Обзор
 Пакет SDK веб-приемника поддерживает очередь с использованием очереди по умолчанию , предоставленной пакетом SDK, с использованием QueueData и QueueManager , или использование пользовательской очереди путем реализации cast.framework.QueueBase и использования QueueManager для обновлений.
Queuing API позволяет приложениям лучше интегрироваться с Cast, предоставляя следующие функции:
- Поддержка реализации облачной очереди Google и ее партнеров, позволяющая напрямую загружать сохраненную и созданную извне очередь на устройства Cast.
- Механизмы, позволяющие разбивать элементы в очереди на страницы, а не загружать все сразу.
- Поддержка новых сообщений, таких как переход к следующему элементу, предыдущему элементу, выборка окна элементов, а также получение мультимедийной информации, связанной с набором элементов очереди.
-  QueueManagerдля управления вставкой, удалением и обновлением элементов очереди.
Очередь по умолчанию
Web Receiver SDK обеспечивает ограниченную поддержку очередей «из коробки» в виде очереди по умолчанию.
 Чтобы использовать очередь по умолчанию, укажите queueData в LoadRequestData загрузок на стороне отправителя или отправьте локальный запрос на загрузку с помощью PlayerManager#load . Также см. Загрузка носителя .
 На стороне получателя очередь можно изменить с помощью QueueManager после загрузки исходного носителя.
Пользовательская очередь
Если очередь по умолчанию не обеспечивает функции организации очередей, необходимые для вашего приложения, доступна возможность создания пользовательской очереди, обеспечивающая больше возможностей и гибкости.
 Разработчики приложений могут создать боковую очередь веб-приемника, реализовав cast.framework.QueueBase .
 Вот базовый пример простой очереди, в которой вызов initialize переопределяется, а затем на устройство Cast передается список элементов очереди вместе с описаниями.
Также см. Загрузка носителя .
// Creates a simple queue with a combination of contents.
const DemoQueue = class extends cast.framework.QueueBase {
 constructor() {
   super();
   /**
    * List of media urls.
    * @private @const {!Array<string>}
    */
   this.myMediaUrls_ = [...];
 }
 /**
  * Provide a list of items.
  * @param {!cast.framework.messages.LoadRequestData} loadRequestData
  * @return {!cast.framework.messages.QueueData}
  */
 initialize(loadRequestData) {
   const items = [];
   for (const mediaUrl of this.myMediaUrls_) {
     const item = new cast.framework.messages.QueueItem();
     item.media = new cast.framework.messages.MediaInformation();
     item.media.contentId = mediaUrl;
     items.push(item);
   }
   let queueData = loadRequestData.queueData;
   // Create a new queue with media from the load request if one doesn't exist.
   if (!queueData) {
     queueData = new cast.framework.messages.QueueData();
     queueData.name = 'Your Queue Name';
     queueData.description = 'Your Queue Description';
     queueData.items = items;
     // Start with the first item in the playlist.
     queueData.startIndex = 0;
     // Start from 10 seconds into the first item.
     queueData.currentTime = 10;
   }
   return queueData;
 }
};
 В этом примере список элементов в вызове initialize предоставляется в вызове конструктора QueueBase поставщика. Однако для реализации облачной очереди пользовательская логика веб-приемника может получать элементы извне, а затем возвращать их как часть вызова инициализации.
 Чтобы продемонстрировать более полное использование API очередей, ниже представлена демонстрационная очередь, реализующая большую часть класса QueueBase .
const DemoQueue = class extends cast.framework.QueueBase {
 constructor() {
   /** @private {} */
   super();
   YourServer.onSomeEvent = this.updateEntireQueue_;
 }
 /**
  * Initializes the queue.
  * @param {!cast.framework.messages.LoadRequestData} loadRequestData
  * @return {!cast.framework.messages.QueueData}
  */
 initialize(loadRequestData) {
   let queueData = loadRequestData.queueData;
   // Create a new queue with media from the load request if one doesn't exist.
   if (!queueData) {
     queueData = new cast.framework.messages.QueueData();
     queueData.name = 'Your Queue Name';
     queueData.description = 'Your Queue Description';
     // Put the first set of items into the queue
     const items = this.nextItems();
     queueData.items = items;
     // Start with the first item in the playlist.
     queueData.startIndex = 0;
     // Start from 10 seconds into the first item.
     queueData.currentTime = 10;
   }
   return queueData;
 }
 /**
  * Picks a set of items from remote server after the reference item id and
  * return as the next items to be inserted into the queue. When
  * referenceItemId is omitted, items are simply appended to the end of the
  * queue.
  * @param {number} referenceItemId
  * @return {!Array<cast.framework.QueueItem>}
  */
 nextItems(referenceItemId) {
   // Assume your media has a itemId and the media url
   return this.constructQueueList_(YourServer.getNextMedias(referenceItemId));
 }
 /**
  * Picks a set of items from remote server before the reference item id and
  * return as the items to be inserted into the queue. When
  * referenceItemId is omitted, items are simply appended to beginning of the
  * queue.
  * @param {number} referenceItemId
  * @return {!Array<cast.framework.QueueItem>}
  */
 prevItems(referenceItemId) {
   return this.constructQueueList_(YourServer.getPrevMedias(referenceItemId));
 }
 /**
  * Constructs a list of QueueItems based on the media information containing
  * the item id and the media url.
  * @param {number} referenceItemId
  * @return {!Array<cast.framework.QueueItem>}
  */
 constructQueueList_(medias) {
   const items = [];
   for (media of medias) {
     const item = new cast.framework.messages.QueueItem(media.itemId);
     item.media = new cast.framework.messages.MediaInformation();
     item.media.contentId = media.url;
     items.push(item);
   }
   return items;
 }
 /**
  * Logs the currently playing item.
  * @param {number} itemId The unique id for the item.
  * @export
  */
 onCurrentItemIdChanged(itemId) {
   console.log('We are now playing video ' + itemId);
   YourServer.trackUsage(itemId);
 }
};
 В приведенном выше примере YourServer — это ваш сервер облачной очереди, у которого есть логика получения определенных медиа-элементов.
 Чтобы использовать очередь, реализованную QueueBase , нужно установить параметр очереди в CastReceiverContext :
const context = cast.framework.CastReceiverContext.getInstance();
context.start({queue: new DemoQueue()});
Управление очередью
 QueueManager дает разработчикам гибкость в разработке решений для организации очередей, предоставляя методы доступа к сохраненному в данный момент списку элементов очереди, а также к текущему воспроизводимому элементу. Он также обеспечивает такие операции, как вставка, удаление и обновление элементов очереди. В следующем фрагменте показано, как получить доступ к экземпляру QueueManager :
const context = cast.framework.CastReceiverContext.getInstance();
const queueManager = context.getPlayerManager().getQueueManager();
Управление очередью по умолчанию
 После загрузки исходной очереди QueueManager можно использовать для выполнения таких действий, как получение текущего элемента, получение всех элементов в очереди и обновление элементов в очереди с помощью insertItems , removeItems и updateItems .
Пользовательское управление очередью
 Ниже приведен пример реализации пользовательской очереди, в которой используются методы вставки и удаления на основе некоторого события. В примере также показано использование updateItems , где разработчики могут изменять элементы очереди в существующей очереди, например удалять рекламные паузы.
const DemoQueue = class extends cast.framework.QueueBase {
  constructor() {
    super();
    /** @private @const {!cast.framework.QueueManager} */
    this.queueManager_ = context.getPlayerManager().getQueueManager();
  }
  /**
   * Provide a list of items.
   * @param {!cast.framework.messages.LoadRequestData} loadRequestData
   * @return {!cast.framework.messages.QueueData}
   */
  initialize(loadRequestData) {
    // Your normal initialization; see examples above.
    return queueData;
  }
  /** Inserts items to the queue. */
  onSomeEventTriggeringInsertionToQueue() {
    const twoMoreUrls = ['http://url1', 'http://url2'];
    const items = [];
    for (const mediaUrl of twoMoreUrls) {
      const item = new cast.framework.QueueItem();
      item.media = new cast.framework.messages.MediaInformation();
      item.media.contentId = mediaUrl;
      items.push(item);
    }
    // Insert two more items after the current playing item.
    const allItems = this.queueManager_.getItems();
    const currentItemIndex = this.queueManager_.getCurrentItemIndex();
    const nextItemIndex = currentItemIndex + 1;
    let insertBefore = undefined;
    if (currentItemIndex >= 0 &&
        currentItemIndex < allItems.length - 1) {
      insertBefore = allItems[nextItemIndex].itemId;
    }
    this.queueManager_.insertItems(items, insertBefore);
  }
  /** Removes a particular item from the queue. */
  onSomeEventTriggeringRemovalFromQueue() {
    this.queueManager_.removeItems([2]);
  }
  /** Removes all the ads from all the items across the entire queue. */
  onUserBoughtAdFreeVersion() {
    const items = this.queueManager_.getItems();
    this.queueManager_.updateItems(items.map(item => {
      item.media.breaks = undefined;
      return item;
    }));
  }
};
Входящие и исходящие сообщения
Для полной поддержки выборки очереди на стороне получателя как источника достоверной информации в CAF Receiver SDK вводятся и обрабатываются следующие дополнительные сообщения очередей:
| Входящее сообщение | Параметры | Исходящее ответное сообщение | Возвращаться | 
| СЛЕДУЮЩИЙ | Никакой параметр не требуется. | МЕДИА_СТАТУС | Получатель выполнит (при необходимости вызовет через nextItems()) и начнет воспроизведение следующего элемента. | 
| ПРЕДЫДУЩИЙ | Никакой параметр не требуется. | МЕДИА_СТАТУС | Веб-приемник выполнит (при необходимости вызов через prevItems()) и начнет воспроизведение предыдущего элемента. | 
| FETCH_ITEMS | FetchItemsRequestData | QUEUE_CHANGE | Cast.framework.messages.QueueChange. Например, для вставки поле items в JSON будет содержать список полученных новых элементов. | 
| GET_ITEMS_INFO | GetItemsInfoRequestData, содержащий идентификаторы элементов : Array<number> | ITEMS_INFO | cast.framework.messages.ItemsInfo с информацией об элементе очереди. | 
| GET_QUEUE_IDS | Никакой параметр не требуется. | QUEUE_IDS | cast.framework.messages.QueueIds. | 
 Для NEXT / PREVIOUS , если существующее представление очереди в веб-приемнике не содержит дополнительных элементов, QueueBase.nextItems() или QueueBase.prevItems() автоматически вызывается для получения дополнительных элементов.
 Для FETCH_ITEM соответствующая функция fetchItems в реализации QueueBase вызывается для облачных очередей, которая извлекает соответствующие данные, которые должны быть возвращены веб-приемнику для хранения.
 Всякий раз, когда извлекается больше элементов, запускается новый тип сообщения QUEUE_CHANGE , который отправляется обратно отправителю. Ознакомьтесь с различными типами изменений очереди .
 Для GET_ITEMS_INFO реализация QueueBase не запускается, и веб-приемник возвращает медиа-информацию, уже известную списку идентификаторов.
Перетасовка очереди
 Чтобы элементы в очереди перемешивались, установите для флага shuffle QueueData значение true при загрузке элементов в очередь.
 Если вы используете реализацию QueueBase , используйте метод shuffle , чтобы вернуть перетасованный список элементов.
 Чтобы перетасовать существующую очередь, используйте флаг shuffle QUEUE_UPDATE MessageType , а не команду QUEUE_SHUFFLE . Дополнительные сведения см. в разделе QueueUpdateRequestData .
Режим повтора
 Чтобы элементы в очереди повторялись, установите для свойства repeatMode QueueData желаемый RepeatMode при загрузке элементов в очередь.
 Чтобы изменить RepeatMode существующей очереди, используйте свойство repeatMode QueueUpdateRequestData , которое использует QUEUE_UPDATE MessageType .