docs: public synchronized List<Message> renderMenuItems(Message.MenuIdentifier targetMenu, CdjStatus.TrackSourceSlot slot,
                                                        CdjStatus.TrackType trackType, int offset, int count)
              throws IOException {
  
          if (!menuLock.isHeldByCurrentThread()) {
              throw new IllegalStateException("renderMenuItems() cannot be called without first successfully calling tryLockingForMenuOperation()");
          }
          if (offset < 0) {
              throw new IllegalArgumentException("offset must be nonnegative");
          }
          if (count < 1) {
              throw new IllegalArgumentException("count must be positive");
          }
  
          final ArrayList<Message> results = new ArrayList<Message>(count);
          int gathered = 0;
          while (gathered < count) {
              final long batchSize = (Math.min(count - gathered, menuBatchSize.get()));
              final NumberField transaction = assignTransactionNumber();
              final NumberField limit = new NumberField(batchSize);
              final NumberField total = new NumberField(count);
              final Message request = new Message(transaction,
                      new NumberField(Message.KnownType.RENDER_MENU_REQ.protocolValue, 2),
                      buildRMST(targetMenu, slot, trackType), new NumberField(offset), limit, NumberField.WORD_0, total, NumberField.WORD_0);
  
              sendMessage(request);
              Message response = Message.read(is);
  
              if (response.transaction.getValue() != transaction.getValue()) {
                  throw new IOException("Received response with wrong transaction ID. Expected: " + transaction.getValue() +
                          ", got: " + response);
              }
              if (response.knownType != Message.KnownType.MENU_HEADER) {
                  throw new IOException("Expecting MENU_HEADER, instead got: " + response);
              }
              response = Message.read(is);
  
              while (response.knownType == Message.KnownType.MENU_ITEM) {
                  results.add(response);
                  response = Message.read(is);
              }
  
              if (response.knownType != Message.KnownType.MENU_FOOTER) {
                  throw new IOException("Expecting MENU_ITEM or MENU_FOOTER, instead got: " + response);
              }
  
              offset += batchSize;
              gathered += batchSize;
          }
          return Collections.unmodifiableList(results);
      }