Overview
The Web Receiver SDK supports queueing with the default queue
provided by the
SDK using QueueData
and QueueManager
or using a custom queue
by
implementing cast.framework.QueueBase
and using QueueManager
for updates.
The Queueing API allows applications to better integrate with Cast by providing the following features:
- Support of Google's and partner's cloud queue implementation so externally stored and created queue can be directly loaded into Cast devices.
- Mechanisms that allows pagination of items in the queue rather than loading everything at once.
- Support for new messaging such as going to the next item, the previous item, fetching a window of items, as well as getting media information related to a set of queue items.
- The
QueueManager
to manage insertion, removal, and update of queue items.
Default queue
The Web Receiver SDK provides limited queue support out of the box in the form of a default queue.
To use the default queue, provide the queueData
in the LoadRequestData
of your sender-side loads or send a local load request
using PlayerManager#load
.
Also see Loading media
.
On the receiver-side, the queue can be modified using the QueueManager
once the initial media has been loaded.
Custom queue
If the default queue does not provide the queueing functionality required for your app, the ability to create a custom queue is available, allowing for more capabilities and flexibility.
Application developers can create a Web Receiver side queue by implementing cast.framework.QueueBase
.
Here is a basic example of a simple queue where the initialize
call is overridden and then a list of queue items along with queue descriptions
are provided to the Cast device.
Also see Loading media .
//
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
;
}
};
In this example, the list of items in the initialize
call is provided in the provider's QueueBase
constructor call. However, for a cloud queue implementation, the custom Web
Receiver logic can fetch the items externally and then return them as part of
the initialize call.
To demonstrate a more comprehensive use of the queueing API, here is a Demo
queue that implements most of the QueueBase
class.
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
);
}
};
In the example above, YourServer
is your cloud queue server and has logic
about how to fetch certain media items.
To use QueueBase
-implemented queueing, one would set the queue option in the CastReceiverContext
:
const
context
=
cast
.
framework
.
CastReceiverContext
.
getInstance
();
context
.
start
({
queue
:
new
DemoQueue
()});
Managing a queue
The QueueManager
gives developers flexibility in developing their queueing solutions by providing
methods to access the currently stored list of queue items as well as the
current playing item. It also provides operations such as insertion, removal,
and update of queueing items. The following snippet shows how to access an
instance of QueueManager
:
const
context
=
cast
.
framework
.
CastReceiverContext
.
getInstance
();
const
queueManager
=
context
.
getPlayerManager
()
.
getQueueManager
();
Default queue management
Once the initial queue has been loaded, the QueueManager
can be used to perform actions such as retrieving the current item, retrieving
all items in the queue, and updating the items in the queue using insertItems
, removeItems
,
and updateItems
.
Custom queue management
Here is an example of a custom queue implementation that uses the insertion and
removal methods based on some event. The example also demonstrates a usage of updateItems
where the developers can modify the queue items in the existing queue, such as
removing ad breaks.
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
;
}));
}
};
Incoming and outgoing messages
To fully support receiver-side queue fetching as the source of truth, the following additional queueing messages are introduced and handled by the CAF Receiver SDK:
Incoming Message | Parameters | Outgoing Response Message | Return |
NEXT | No parameter needed. | MEDIA_STATUS | Receiver will (fetch through nextItems() if necessary) and start playing the next item. |
PREVIOUS | No parameter needed. | MEDIA_STATUS | The Web Receiver will (fetch through prevItems() if necessary) and start playing the previous item. |
FETCH_ITEMS | FetchItemsRequestData | QUEUE_CHANGE | A cast.framework.messages.QueueChange. As an example, for an insert case, the items field in the JSON will contain the list of new items fetched. |
GET_ITEMS_INFO | GetItemsInfoRequestData containing itemIds: Array<number> | ITEMS_INFO | cast.framework.messages.ItemsInfo with queue item information. |
GET_QUEUE_IDS | No parameter needed. | QUEUE_IDS | cast.framework.messages.QueueIds. |
For NEXT
/ PREVIOUS
, if the existing queue representation on the Web Receiver
does not have more items, the QueueBase.nextItems()
or QueueBase.prevItems()
is automatically invoked to receive more items.
For FETCH_ITEM
, the corresponding function fetchItems
in the QueueBase
implementation is called for cloud queues, which retrieves
the relevant data to be returned to the Web Receiver to store.
Whenever more items are fetched, a new message type QUEUE_CHANGE
is triggered
and sent back to the sender. See the various types of queue changes
.
For GET_ITEMS_INFO
, QueueBase
's
implementation is not triggered and the Web Receiver returns media information
already known to the list of ids.
Shuffling a queue
To set the items in your queue to be shuffled, set the shuffle
flag of QueueData
to true
when loading your items into the queue.
If you are using an implementation of QueueBase
, use
the shuffle
method to return a shuffled list of items.
To shuffle an existing queue, use the shuffle
flag of the QUEUE_UPDATE
MessageType
,
rather than the QUEUE_SHUFFLE
command. See QueueUpdateRequestData
for more information.
Repeat mode
To set the items in your queue to be repeated, set the repeatMode
property of QueueData
to the desired RepeatMode
when loading your items into the queue.
To change the RepeatMode
of an existing queue, use the repeatMode
property of the QueueUpdateRequestData
,
which uses the QUEUE_UPDATE
MessageType
.