Merge pull request #26160 from craigrbruce/master

Chromecast CAF Receiver Framework
This commit is contained in:
Armando Aguirre
2018-06-08 11:35:09 -07:00
committed by GitHub
10 changed files with 3751 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
import { Break, BreakClip } from "./cast.framework.messages";
export = cast.framework.breaks;
declare namespace cast.framework.breaks {
class BreakSeekData {
constructor(seekFrom: number, seekTo: number, breaks: Break[]);
/**
* List of breaks
*/
breaks: Break[];
/**
* Current playback time
*/
seekFrom: number;
/**
* The time to seek to
*/
seekTo: number;
}
/** Provide context information for break clip load interceptor. */
class BreakClipLoadInterceptorContext {
constructor(brk: Break);
/**
* The container break for the break clip
*/
break: Break;
}
/** Interface to manage breaks */
interface BreakManager {
/**
* Get current media break by id.
*/
getBreakById(id: string): Break;
/**
* Get current media break clip by id
*/
getBreakClipById(id: string): BreakClip;
/** Get current media break clips. */
getBreakClips(): BreakClip[];
/** Get current media breaks. */
getBreaks(): Break[];
/** Returns true if watched breaks should be played. */
getPlayWatchedBreak(): boolean;
/**
* Provide an interceptor to allow developer to insert more break clips or modify current break clip before a break is started.
* If interceptor is null it will reset the interceptor to default one.
* By default VAST fetching and parsing logic in default interceptor.
* So if customized interceptor is set by developer;
* the VAST logic will be overridden and developers should implement their own VAST fetching and parsing logic in the provided interceptor.
*/
setBreakClipLoadInterceptor(
interceptor: (
breakClip: BreakClip,
breakClipLoaderContext?: BreakClipLoadInterceptorContext
) => void
): void;
/**
* Provide an interceptor for developer to specify what breaks they want to play after seek.
*/
setBreakSeekInterceptor(
seekInterceptor: (breakSeekData: BreakSeekData) => void
): void;
/**
* Set a flag to control if the watched client stitching break should be played.
*/
setPlayWatchedBreak(playWatchedBreak: boolean): void;
/**
* Provide an interceptor to modify VAST tracking URL before it is being sent to server.
* The input of the interceptor is a string of the tracking URL.
* The interceptor can either return a modified string of URL or a Promise of modified string of URL.
* The interceptor can also return null if you want to send the tracking URL by your own code instead of by CAF.
*/
setVastTrackingInterceptor(
interceptor?: (trackingUrl: string) => void
): void;
}
}

View File

@@ -0,0 +1,783 @@
import { EventType } from "./cast.framework.events";
import {
PlayerState,
PlayStringId,
ErrorType,
ErrorReason,
IdleReason,
MessageType,
Track,
TextTrackStyle,
QueueItem,
LoadRequestData,
QueueData,
Break,
LiveSeekableRange,
MediaInformation,
ErrorData,
RequestData
} from "./cast.framework.messages";
import { BreakManager } from "./cast.framework.breaks";
import { EventHandler, RequestHandler, BinaryHandler } from "./index";
import {
EventType as SystemEventType,
ApplicationData,
Sender,
StandbyState,
SystemState
} from "./cast.framework.system";
export = cast.framework;
type HTMLMediaElement = any;
declare namespace cast.framework {
type LoggerLevel =
| "DEBUG"
| "VERBOSE"
| "INFO"
| "WARNING"
| "ERROR"
| "NONE";
type ContentProtection = "NONE" | "CLEARKEY" | "PLAYREADY" | "WIDEVINE";
/**
* Manages text tracks.
*/
class TextTracksManager {
constructor(params?: any);
/**
* Adds text tracks to the list.
*/
addTracks(tracks: Track[]): void;
/**
* Creates a text track.
*/
createTrack(): Track;
/**
* Gets all active text ids.
*/
getActiveIds(): number[];
/**
* Gets all active text tracks.
*/
getActiveTracks(): Track[];
/**
* Returns the current text track style.
*/
getTextTracksStyle(): TextTrackStyle;
/**
* Gets text track by id.
*/
getTrackById(id: number): Track;
/**
* Returns all text tracks.
*/
getTracks(): Track[];
/**
* Gets text tracks by language.
*/
getTracksByLanguage(language: string): Track[];
/**
* Sets text tracks to be active by id.
*/
setActiveByIds(newIds: number[]): void;
/**
* Sets text tracks to be active by language.
*/
setActiveByLanguage(language: string): void;
/**
* Sets text track style.
*/
setTextTrackStyle(style: TextTrackStyle): void;
}
/**
* QueueManager exposes several queue manipulation APIs to developers.
*/
class QueueManager {
constructor(params?: any);
/**
* Returns the current queue item.
*/
getCurrentItem(): QueueItem;
/**
* Returns the index of the current queue item.
*/
getCurrentItemIndex(): number;
/**
* Returns the queue items.
*/
getItems(): QueueItem[];
/**
* Inserts items into the queue.
*/
insertItems(items: QueueItem[], insertBefore?: number): void;
/**
* Removes items from the queue.
*/
removeItems(itemIds: number[]): void;
/**
* Sets whether to limit the number of queue items to be reported in Media Status (default is true).
*/
setQueueStatusLimit(limitQueueItemsInStatus: boolean): void;
/**
* Updates existing queue items by matching itemId.
*/
updateItems(items: QueueItem[]): void;
}
/**
* Base implementation of a queue.
*/
class QueueBase {
/**
* Fetches a window of items using the specified item id as reference; called by the receiver MediaManager when it needs more queue items;
* often as a request from senders. If only one of nextCount and prevCount is non-zero; fetchItems should only return items after or before
* the reference item; if both nextCount and prevCount are non-zero; a window of items including the reference item should be returned.
*/
fetchItems(
itemId: number,
nextCount: number,
prevCount: number
): QueueItem[] | Promise<QueueItem[]>;
/**
* Initializes the queue with the requestData. This is called when a new LOAD request comes in to the receiver.
* If this returns or resolves to null; our default queueing implementation will create a queue based on queueData.items or the single media
* in the load request data.
*/
initialize(
requestData: LoadRequestData
): QueueData | Promise<QueueData>;
/**
* Returns next items after the reference item; often the end of the current queue; called by the receiver MediaManager.
*/
nextItems(itemId?: number): QueueItem[] | Promise<QueueItem[]>;
/**
* Sets the current item with the itemId; called by the receiver MediaManager when it changes the current playing item.
*/
onCurrentItemIdChanged(itemId: number): void;
/**
* A callback for informing the following items have been inserted into the receiver queue in this session.
* A cloud based implementation can optionally choose to update its queue based on the new information.
*/
onItemsInserted(items: QueueItem[], insertBefore?: number): void;
/**
* A callback for informing the following items have been removed from the receiver queue in this session.
* A cloud based implementation can optionally choose to update its queue based on the new information.
*/
onItemsRemoved(itemIds: number[]): void;
/**
* Returns previous items before the reference item; often at the beginning of the queue; called by the receiver MediaManager.
*/
prevItems(itemId?: number): QueueItem[] | Promise<QueueItem[]>;
/**
* Shuffles the queue and returns new queue items. Returns null if the operation is not supported.
*/
shuffle(): QueueItem[] | Promise<QueueItem[]>;
}
/**
* Controls and monitors media playback.
*/
class PlayerManager {
constructor(params?: any);
/**
* Adds an event listener for player event.
*/
addEventListener: (
eventType: EventType | EventType[],
eventListener: EventHandler
) => void;
/**
* Sends a media status message to all senders (broadcast). Applications use this to send a custom state change.
*/
broadcastStatus(
includeMedia?: boolean,
requestId?: number,
customData?: any,
includeQueueItems?: boolean
): void;
getAudioTracksManager(): AudioTracksManager;
/**
* Returns current time in sec in currently-playing break clip.
*/
getBreakClipCurrentTimeSec(): number;
/**
* Returns duration in sec of currently-playing break clip.
*/
getBreakClipDurationSec(): number;
/**
* Obtain the breaks (Ads) manager.
*/
getBreakManager(): BreakManager;
/**
* Returns list of breaks.
*/
getBreaks(): Break[];
/**
* Gets current time in sec of current media.
*/
getCurrentTimeSec(): number;
/**
* Gets duration in sec of currently playing media.
*/
getDurationSec(): number;
/**
* Returns live seekable range with start and end time in seconds. The values are media time based.
*/
getLiveSeekableRange(): LiveSeekableRange;
/**
* Gets media information of current media.
*/
getMediaInformation(): MediaInformation;
/**
* Returns playback configuration.
*/
getPlaybackConfig(): PlaybackConfig;
/**
* Returns current playback rate.
*/
getPlaybackRate(): number;
/**
* Gets player state.
*/
getPlayerState(): PlayerState;
/**
* Get the preferred playback rate. (Can be used on shutdown event to save latest preferred playback rate to a persistent storage;
* so it can be used in next session in the cast options).
*/
getPreferredPlaybackRate(): number;
/**
* Get the preferred text track language.
*/
getPreferredTextLanguage(): string;
/**
* Obtain QueueManager API.
*/
getQueueManager(): QueueManager;
getTextTracksManager(): TextTracksManager;
/**
* Loads media.
*/
load(loadRequest: LoadRequestData): Promise<void>;
/**
* Pauses currently playing media.
*/
pause(): void;
/**
* Plays currently paused media.
*/
play(): void;
/**
* Requests a text string to be played back locally on the receiver device.
*/
playString(stringId: PlayStringId, args?: string[]): Promise<ErrorData>;
/**
* Request Google Assistant to refresh the credentials. Only works if the original credentials came from the assistant.
*/
refreshCredentials(): Promise<void>;
/**
* Removes the event listener added for given player event. If event listener is not added; it will be ignored.
*/
removeEventListener(
eventType: EventType | EventType[],
eventListener: EventHandler
): void;
/**
* Seeks in current media.
*/
seek(seekTime: number): void;
/**
* Sends an error to a specific sender
*/
sendError(
senderId: string,
requestId: number,
type: ErrorType,
reason?: ErrorReason,
customData?: any
): void;
/**
* Send local media request.
*/
sendLocalMediaRequest(request: RequestData): void;
/**
* Sends a media status message to a specific sender.
*/
sendStatus(
senderId: string,
requestId: number,
includeMedia?: boolean,
customData?: any,
includeQueueItems?: boolean
): void;
/**
* Sets the IDLE reason. This allows applications that want to force the IDLE state to indicate the reason that made the player going to IDLE state
* (a custom error; for example). The idle reason will be sent in the next status message. NOTE: Most applications do not need to set this value;
* it is only needed if they want to make the player go to IDLE in special circumstances and the default idleReason does not reflect their intended
* behavior.
*/
setIdleReason(idleReason: IdleReason): void;
/**
* Sets MediaElement to use. If Promise of MediaElement is set; media begins playback after Promise is resolved.
*/
setMediaElement(mediaElement: HTMLMediaElement): void;
/**
* Sets media information.
*/
setMediaInformation(
mediaInformation: MediaInformation,
opt_broadcast?: boolean
): void;
/**
* Sets a handler to return or modify PlaybackConfig; for a specific load request. The handler paramaters are the load request data
* and default playback config for the receiver (provided in the context options). The handler should returns a modified playback config;
* or null to prevent the media from playing. The return value can be a promise to allow waiting for data from the server.
*/
setMediaPlaybackInfoHandler(
handler: (
loadRequestData: LoadRequestData,
playbackConfig: PlaybackConfig
) => void
): void;
/**
* Sets a handler to return the media url for a load request. This handler can be used to avoid having the media content url published as part
* of the media status. By default the media contentId is used as the content url.
*/
setMediaUrlResolver(
resolver: (loadRequestData: LoadRequestData) => void
): void;
/**
* Provide an interceptor of incoming and outgoing messages.
* The interceptor can update the request data; and return updated data; a promise of
* updated data if need to get more data from the server; or null if the request should not be handled.
* Note that if load message interceptor is provided; and no interceptor is provided for preload -
* the load interceptor will be called for preload messages.
*/
setMessageInterceptor(
type: MessageType,
interceptor: (requestData: RequestData) => Promise<any>
): void;
/**
* Sets playback configuration on the PlayerManager.
*/
setPlaybackConfig(playbackConfig: PlaybackConfig): void;
/**
* Set the preferred playback rate for follow up load or media items. The preferred playback rate will be updated automatically to the latest
* playback rate that was provided by a load request or explicit set of playback rate.
*/
setPreferredPlaybackRate(preferredPlaybackRate: number): void;
/**
* Set the preferred text track language. The preferred text track language will be updated automatically to the latest enabled language
* by a load request or explicit change to text tracks. (Should be called only in idle state; and Will only apply to next loaded media).
*/
setPreferredTextLanguage(preferredTextLanguage: string): void;
/**
* Stops currently playing media.
*/
stop(): void;
}
/**
* Configuration to customize playback behavior.
*/
class PlaybackConfig {
/**
* Duration of buffered media in seconds to start buffering.
*/
autoPauseDuration?: number;
/**
* Duration of buffered media in seconds to start/resume playback after auto-paused due to buffering.
*/
autoResumeDuration?: number;
/**
* Minimum number of buffered segments to start/resume playback.
*/
autoResumeNumberOfSegments?: number;
/**
* A function to customize request to get a caption segment.
*/
captionsRequestHandler?: RequestHandler;
/**
* Initial bandwidth in bits in per second.
*/
initialBandwidth?: number;
/**
* Custom license data.
*/
licenseCustomData?: string;
/**
* Handler to process license data. The handler is passed the license data; and returns the modified license data.
*/
licenseHandler?: BinaryHandler;
/**
* A function to customize request to get a license.
*/
licenseRequestHandler?: RequestHandler;
/**
* Url for acquiring the license.
*/
licenseUrl?: string;
/**
* Handler to process manifest data. The handler is passed the manifest; and returns the modified manifest.
*/
manifestHandler?: (manifest: string) => string;
/**
* A function to customize request to get a manifest.
*/
manifestRequestHandler?: RequestHandler;
/**
* Preferred protection system to use for decrypting content.
*/
protectionSystem: ContentProtection;
/**
* Handler to process segment data. The handler is passed the segment data; and returns the modified segment data.
*/
segmentHandler?: BinaryHandler;
/**
* A function to customize request information to get a media segment.
*/
segmentRequestHandler?: RequestHandler;
/**
* Maximum number of times to retry a network request for a segment.
*/
segmentRequestRetryLimit?: number;
}
/**
* HTTP(s) Request/Response information.
*/
class NetworkRequestInfo {
/**
* The content of the request. Can be used to modify license request body.
*/
content: Uint8Array;
/**
* An object containing properties that you would like to send in the header.
*/
headers: any;
/**
* The URL requested.
*/
url: string;
/**
* Indicates whether CORS Access-Control requests should be made using credentials such as cookies or authorization headers.
*/
withCredentials: boolean;
}
/** Cast receiver context options. All options are optionals. */
class CastReceiverOptions {
/**
* Optional map of custom messages namespaces to initialize and their types.
* Custom messages namespaces need to be initiated before the application started;
* so it is best to provide the namespaces in the receiver options.
* (The default type of a message bus is JSON; if not provided here).
*/
customNamespaces?: any;
/**
* Sender id used for local requests. Default value is 'local'.
*/
localSenderId?: string;
/**
* Maximum time in seconds before closing an idle sender connection.
* Setting this value enables a heartbeat message to keep the connection alive.
* Used to detect unresponsive senders faster than typical TCP timeouts.
* The minimum value is 5 seconds; there is no upper bound enforced but practically it's minutes before platform TCP timeouts come into play.
* Default value is 10 seconds.
*/
maxInactivity?: number;
/**
* Optional media element to play content with. Default behavior is to use the first found media element in the page.
*/
mediaElement?: HTMLMediaElement;
/**
* Optional playback configuration.
*/
playbackConfig?: PlaybackConfig;
/**
* If this is true; the watched client stitching break will also be played.
*/
playWatchedBreak?: boolean;
/**
* Preferred value for player playback rate. It is used if playback rate value is not provided in the load request.
*/
preferredPlaybackRate?: number;
/**
* Preferred text track language. It is used if no active track is provided in the load request.
*/
preferredTextLanguage?: string;
/**
* Optional queue implementation.
*/
queue?: QueueBase;
/**
* Text that represents the application status.
* It should meet internationalization rules as may be displayed by the sender application.
*/
statusText?: string;
/**
* A bitmask of media commands supported by the application.
* LOAD; PLAY; STOP; GET_STATUS must always be supported.
* If this value is not provided; then PAUSE; SEEK; STREAM_VOLUME; STREAM_MUTE are assumed to be supported too.
*/
supportedCommands?: number;
/**
* Indicate that MPL should be used for DASH content.
*/
useLegacyDashSupport?: boolean;
/**
* An integer used as an internal version number.
* This number is used only to distinguish between receiver releases and higher numbers do not necessarily have to represent newer releases.
*/
versionCode?: number;
}
/** Manages loading of underlying libraries and initializes underlying cast receiver SDK. */
class CastReceiverContext {
/** Returns the CastReceiverContext singleton instance. */
static getInstance(): CastReceiverContext;
constructor(params: any);
/**
* Sets message listener on custom message channel.
*/
addCustomMessageListener(
namespace: string,
listener: EventHandler
): void;
/**
* Add listener to cast system events.
*/
addEventListener(
type: SystemEventType | SystemEventType[],
handler: EventHandler
): void;
/**
* Checks if the given media params of video or audio streams are supported by the platform.
*/
canDisplayType(
mimeType: string,
codecs?: string,
width?: number,
height?: number,
framerate?: number
): boolean;
/**
* Provides application information once the system is ready; otherwise it will be null.
*/
getApplicationData(): ApplicationData;
/**
* Provides device capabilities information once the system is ready; otherwise it will be null.
* If an empty object is returned; the device does not expose any capabilities information.
*/
getDeviceCapabilities(): any;
/**
* Get Player instance that can control and monitor media playback.
*/
getPlayerManager(): PlayerManager;
/**
* Get a sender by sender id
*/
getSender(senderId: string): Sender;
/**
* Gets a list of currently-connected senders.
*/
getSenders(): Sender[];
/**
* Reports if the cast application's HDMI input is in standby.
*/
getStandbyState(): StandbyState;
/**
* Provides application information about the system state.
*/
getSystemState(): SystemState;
/**
* Reports if the cast application is the HDMI active input.
*/
getVisibilityState(): any;
/**
* When the application calls start; the system will send the ready event to indicate
* that the application information is ready and the application can send messages as soon as there is one sender connected.
*/
isSystemReady(): boolean;
/**
* Start loading player js. This can be used to start loading the players js code in early stage of starting the receiver before calling start.
* This function is a no-op if players were already loaded (start was called).
*/
loadPlayerLibraries(useLegacyDashSupport?: boolean): void;
/**
* Remove a message listener on custom message channel.
*/
removeCustomMessageListener(
namespace: string,
listener: EventHandler
): void;
/**
* Remove listener to cast system events.
*/
removeEventListener(type: EventType, handler: EventHandler): void;
/**
* Sends a message to a specific sender.
*/
sendCustomMessage(
namespace: string,
senderId: string,
message: any
): void;
/**
* This function should be called in response to the feedbackstarted event if the application
* add debug state information to log in the feedback report.
* It takes in a parameter message that is a string that represents the debug information that the application wants to log.
*/
sendFeedbackMessage(feedbackMessage: string): void;
/**
* Sets the application state. The application should call this when its state changes.
* If undefined or set to an empty string; the value of the Application Name established during application
* registration is used for the application state by default.
*/
setApplicationState(statusText: string): void;
/**
* Sets the receiver inactivity timeout.
* It is recommended to set the maximum inactivity value when calling Start and not changing it.
* This API is just provided for development/debugging purposes.
*/
setInactivityTimeout(maxInactivity: number): void;
/**
* Sets the log verbosity level.
*/
setLoggerLevel(level: LoggerLevel): void;
/**
* Initializes system manager and media manager; so that receiver app can receive requests from senders.
*/
start(options?: CastReceiverOptions): CastReceiverContext;
/**
* Shutdown receiver application.
*/
stop(): void;
}
/** Manages audio tracks. */
class AudioTracksManager {
constructor(params: any);
getActiveId(): number;
getActiveTrack(): Track;
getTrackById(id: number): Track;
getTracks(): Track[];
getTracksByLanguage(language: string): Track[];
setActiveById(id: number): void;
setActiveByLanguage(language: string): void;
}
}

View File

@@ -0,0 +1,420 @@
import {
RequestData,
MediaInformation,
Track,
MediaStatus
} from "./cast.framework.messages";
export = cast.framework.events;
declare namespace cast.framework.events {
type EventType =
| "ALL"
| "ABORT"
| "CAN_PLAY"
| "CAN_PLAY_THROUGH"
| "DURATION_CHANGE"
| "EMPTIED"
| "ENDED"
| "LOADED_DATA"
| "LOADED_METADATA"
| "LOAD_START"
| "PAUSE"
| "PLAY"
| "PLAYING"
| "PROGRESS"
| "RATE_CHANGE"
| "SEEKED"
| "SEEKING"
| "STALLED"
| "TIME_UPDATE"
| "SUSPEND"
| "WAITING"
| "BITRATE_CHANGED"
| "BREAK_STARTED"
| "BREAK_ENDED"
| "BREAK_CLIP_LOADING"
| "BREAK_CLIP_STARTED"
| "BREAK_CLIP_ENDED"
| "BUFFERING"
| "CACHE_LOADED"
| "CACHE_HIT"
| "CACHE_INSERTED"
| "CLIP_STARTED"
| "CLIP_ENDED"
| "EMSG"
| "ERROR"
| "ID3"
| "MEDIA_STATUS"
| "MEDIA_FINISHED"
| "PLAYER_PRELOADING"
| "PLAYER_PRELOADING_CANCELLED"
| "PLAYER_LOAD_COMPLETE"
| "PLAYER_LOADING"
| "SEGMENT_DOWNLOADED"
| "REQUEST_SEEK"
| "REQUEST_LOAD"
| "REQUEST_STOP"
| "REQUEST_PAUSE"
| "REQUEST_PLAY"
| "REQUEST_PLAY_AGAIN"
| "REQUEST_PLAYBACK_RATE_CHANGE"
| "REQUEST_SKIP_AD"
| "REQUEST_VOLUME_CHANGE"
| "REQUEST_EDIT_TRACKS_INFO"
| "REQUEST_EDIT_AUDIO_TRACKS"
| "REQUEST_SET_CREDENTIALS"
| "REQUEST_LOAD_BY_ENTITY"
| "REQUEST_USER_ACTION"
| "REQUEST_DISPLAY_STATUS"
| "REQUEST_CUSTOM_COMMAND"
| "REQUEST_FOCUS_STATE"
| "REQUEST_QUEUE_LOAD"
| "REQUEST_QUEUE_INSERT"
| "REQUEST_QUEUE_UPDATE"
| "REQUEST_QUEUE_REMOVE"
| "REQUEST_QUEUE_REORDER"
| "REQUEST_QUEUE_GET_ITEM_RANGE"
| "REQUEST_QUEUE_GET_ITEMS"
| "REQUEST_QUEUE_GET_ITEM_IDS"
| "REQUEST_PRECACHE";
type DetailedErrorCode =
| "MEDIA_UNKNOWN"
| "MEDIA_ABORTED"
| "MEDIA_DECODE"
| "MEDIA_NETWORK"
| "MEDIA_SRC_NOT_SUPPORTED"
| "SOURCE_BUFFER_FAILURE"
| "MEDIAKEYS_UNKNOWN"
| "MEDIAKEYS_NETWORK"
| "MEDIAKEYS_UNSUPPORTED"
| "MEDIAKEYS_WEBCRYPTO"
| "NETWORK_UNKNOWN"
| "SEGMENT_NETWORK"
| "HLS_NETWORK_MASTER_PLAYLIST"
| "HLS_NETWORK_PLAYLIST"
| "HLS_NETWORK_NO_KEY_RESPONSE"
| "HLS_NETWORK_KEY_LOAD"
| "HLS_NETWORK_INVALID_SEGMENT"
| "HLS_SEGMENT_PARSING"
| "DASH_NETWORK"
| "DASH_NO_INIT"
| "SMOOTH_NETWORK"
| "SMOOTH_NO_MEDIA_DATA"
| "MANIFEST_UNKNOWN"
| "HLS_MANIFEST_MASTER"
| "HLS_MANIFEST_PLAYLIST"
| "DASH_MANIFEST_UNKNOWN"
| "DASH_MANIFEST_NO_PERIODS"
| "DASH_MANIFEST_NO_MIMETYPE"
| "DASH_INVALID_SEGMENT_INFO"
| "SMOOTH_MANIFEST"
| "SEGMENT_UNKNOWN"
| "TEXT_UNKNOWN"
| "APP"
| "BREAK_CLIP_LOADING_ERROR"
| "BREAK_SEEK_INTERCEPTOR_ERROR"
| "IMAGE_ERROR"
| "LOAD_INTERRUPTED"
| "GENERIC";
type EndedReason =
| "END_OF_STREAM"
| "ERROR"
| "STOPPED"
| "INTERRUPTED"
| "SKIPPED"
| "BREAK_SWITCH";
/**
* Event data for @see{@link EventType.SEGMENT_DOWNLOADED} event.
*/
class SegmentDownloadedEvent extends Event {
constructor(downloadTime?: number, size?: number);
/**
* The time it took to download the segment; in milliseconds.
*/
downloadTime?: number;
/**
* The number of bytes in the segment.
*/
size?: number;
}
/**
* Event data for all events that represent requests made to the receiver.
*/
class RequestEvent extends Event {
constructor(
type: EventType,
requestData?: RequestData,
senderId?: string
);
/**
* The data that was sent with the request.
*/
requestData?: RequestData;
/**
* The sender id the request came from.
*/
senderId?: string;
}
/**
* Event data superclass for all events dispatched by @see{@link PlayerManager}
*/
class Event {
constructor(type: EventType);
/**
* Type of the event.
*/
type: EventType;
}
/**
* Event data for @see{@link EventType.MEDIA_STATUS} event.
*/
class MediaStatusEvent extends Event {
constructor(type: EventType, mediaStatus?: MediaStatus);
/**
* The media status that was sent.
*/
mediaStatus?: MediaStatus;
}
/**
* Event data for pause events forwarded from the MediaElement.
*/
class MediaPauseEvent extends Event {
constructor(currentMediaTime?: number, ended?: boolean);
/**
* Indicate if the media ended (indicates the pause was fired due to stream reached the end).
*/
ended?: boolean;
}
/**
* Event data for @see{@link EventType.MEDIA_FINISHED} event.
*/
class MediaFinishedEvent extends Event {
constructor(currentMediaTime?: number, endedReason?: EndedReason);
/**
* The time when the media finished (in seconds). For an item in a queue; this value represents the time in the currently playing queue item ( where 0 means the queue item has just started).
*/
currentTime?: number;
/**
* The reason the media finished.
*/
endedReason?: EndedReason;
}
/**
* Event data for all events forwarded from the MediaElement.
*/
class MediaElementEvent extends Event {
constructor(type: EventType, currentMediaTime?: number);
/**
* The time in the currently playing clip when the event was fired (in seconds). Undefined if playback has not started yet.
*/
currentMediaTime?: number;
}
/**
* Event data for all events pertaining to processing a load / preload request. made to the player.
*/
class LoadEvent extends Event {
constructor(type: EventType, media?: MediaInformation);
/**
* Information about the media being loaded.
*/
media: MediaInformation;
}
/**
* Event data for @see{@link EventType.INBAND_TRACK_ADDED} event.
*/
class InbandTrackAddedEvent {
constructor(track: Track);
/**
* Added track.
*/
track: Track;
}
/** Event data for @see{@link EventType.ID3} event. */
class Id3Event extends Event {
constructor(segmentData: Uint8Array);
/**
* The segment data.
*/
segmentData: Uint8Array;
}
/**
* Event data for @see{@link EventType.EMSG} event.
*/
class EmsgEvent extends Event {
constructor(emsgData: any);
/**
* The time that the event ends (in presentation time). Undefined if using legacy Dash support.
*/
endTime: any;
/**
* The duration of the event (in units of timescale). Undefined if using legacy Dash support.
*/
eventDuration: any;
/**
* A field identifying this instance of the message. Undefined if using legacy Dash support.
*/
id: any;
/**
* Body of the message. Undefined if using legacy Dash support.
*/
messageData: any;
/**
* The offset that the event starts; relative to the start of the segment this is contained in (in units of timescale). Undefined if using legacy Dash support.
*/
presentationTimeDelta: any;
/**
* Identifies the message scheme. Undefined if using legacy Dash support.
*/
schemeIdUri: any;
/**
* The segment data. This is only defined if using legacy Dash support.
*/
segmentData: any;
/**
* The time that the event starts (in presentation time). Undefined if using legacy Dash support.
*/
startTime: any;
/**
* Provides the timescale; in ticks per second. Undefined if using legacy Dash support.
*/
timescale: any;
/**
* Specifies the value for the event. Undefined if using legacy Dash support.
*/
value: any;
}
/**
* Event data for @see{@link EventType.CLIP_ENDED} event.
*/
class ClipEndedEvent extends Event {
constructor(currentMediaTime: number, endedReason?: EndedReason);
/**
* The time in media (in seconds) when clip ended.
*/
currentMediaTime: number;
/**
* The reason the clip ended.
*/
endedReason?: EndedReason;
}
/**
* Event data for @see{@link EventType.CACHE_LOADED} event.
*/
class CacheLoadedEvent extends Event {
constructor(media?: MediaInformation);
/**
* Information about the media being cached.
*/
media: MediaInformation;
}
class CacheItemEvent extends Event {
constructor(type: EventType, url: string);
/**
* The URL of data fetched from cache
*/
url: string;
}
class BufferingEvent extends Event {
constructor(isBuffering: boolean);
/**
* True if the player is entering a buffering state.
*/
isBuffering: boolean;
}
class BreaksEvent extends Event {
constructor(
type: EventType,
currentMediaTime?: number,
index?: number,
total?: number,
whenSkippable?: number,
endedReason?: EndedReason,
breakClipId?: string
);
/**
* The break clip's id. Refer to BreakClip.id
*/
breakClipId?: string;
/**
* The time in the currently playing media when the break event occurred.
*/
currentMediaTime?: number;
/**
* The reason the break clip ended.
*/
endedReason?: EndedReason;
/**
* Index of break clip; which starts from 1.
*/
index: number;
/**
* Total number of break clips.
*/
total: number;
/**
* When to skip current break clip in sec; after break clip begins to play.
*/
whenSkippable?: number;
}
/**
* Event data for @see {@link EventType.BITRATE_CHANGED} event.
*/
class BitrateChangedEvent {
constructor(totalBitrate?: number);
/** The bitrate of the media (audio and video) in bits per second. */
totalBitrate: number;
}
class ErrorEvent extends Event {
constructor(detailedErrorCode: DetailedErrorCode, error?: any);
detailedErrorCode: DetailedErrorCode;
error?: any;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,198 @@
import { EventType } from "./cast.framework.events";
export = cast.framework.system;
declare namespace cast.framework.system {
type EventType =
// Fired when the system is ready.
| "READY"
// Fired when the application is terminated
| "SHUTDOWN"
// Fired when a new sender has connected.
| "SENDER_CONNECTED"
// Fired when a sender has disconnected.
| "SENDER_DISCONNECTED"
// Fired when there is a system error.
| "ERROR"
// Fired when the system volume has changed.
| "SYSTEM_VOLUME_CHANGED"
// Fired when the visibility of the application has changed
// (for example after a HDMI Input change or when the TV is turned
// off/on and the cast device is externally powered).
// Note that this API has the same effect as the webkitvisibilitychange event raised
// by your document, we provided it as CastReceiverManager API for convenience and
// to avoid a dependency on a webkit-prefixed event.
| "VISIBILITY_CHANGED"
// Fired when the standby state of the TV has changed.
// This event is related to the visibility chnaged event, as if the TV is in standby
// the visibility will be false, the visibility is more granular
// (as it also detects that the TV has selected a different channel)
// but it is not reliably detected in all TVs,
// standby can be used in those cases as most TVs implement it.
| "STANDBY_CHANGED"
| "MAX_VIDEO_RESOLUTION_CHANGED"
| "FEEDBACK_STARTED";
type SystemState =
| "NOT_STARTED"
| "STARTING_IN_BACKGROUND"
| "STARTING"
| "READY"
| "STOPPING_IN_BACKGROUND"
| "STOPPING";
type StandbyState = "STANDBY" | "NOT_STANDBY" | "UNKNOWN";
type DisconnectReason = "REQUESTED_BY_SENDER" | "ERROR" | "UNKNOWN";
/**
* Event dispatched by @see{@link CastReceiverManager} when the visibility of the application changes (HDMI input change; TV is turned off).
*/
class VisibilityChangedEvent {
constructor(isVisible: boolean);
/**
* Whether the Cast device is the active input or not.
*/
isVisible: boolean;
}
/**
* Represents the system volume data.
*/
interface SystemVolumeData {
/**
* The level (from 0.0 to 1.0) of the system volume
*/
level: number;
/**
* Whether the system volume is muted or not.
*/
muted: boolean;
}
/**
* Event dispatched by @see{CastReceiverManager} when the system volume changes.
*/
class SystemVolumeChangedEvent extends Event {
constructor(volume: SystemVolumeData);
/**
* The system volume data
*/
data: SystemVolumeData;
}
/**
* Event dispatched by @see{@link CastReceiverManager} when the TV enters/leaves the standby state.
*/
class StandbyChangedEvent {
constructor(isStandby: boolean);
isStandby: boolean;
}
/**
* Whether the TV is in standby or not.
*/
interface ShutdownEvent extends Event {
[key: string]: any;
}
/**
* Event dispatched by @see{@link CastReceiverManager} when a sender is disconnected.
*/
class SenderDisconnectedEvent extends Event {
constructor(senderId: string, userAgent: string);
/**
* The ID of the sender connected.
*/
senderId: string;
/**
* The user agent of the sender.
*/
userAgent: string;
/**
* The reason the sender was disconnected.
*/
reason?: DisconnectReason;
}
/**
* Event dispatched by @see{@link CastReceiverManager} when a sender is connected.
*/
class SenderConnectedEvent extends Event {
constructor(senderId: string, userAgent: string);
/**
* The ID of the sender connected.
*/
senderId: string;
/**
* The user agent of the sender.
*/
userAgent: string;
}
/**
* Represents the data of a connected sender device.
*/
interface Sender {
/**
* The sender Id.
*/
id: string;
/**
* Indicate the sender supports large messages (>64KB)
*/
largeMessageSupported?: boolean;
/**
* The userAgent of the sender.
*/
userAgent?: string;
}
/**
* Event dispatched by CastReceiverManager when the system is ready.
*/
class ReadyEvent {
constructor(applicationData: ApplicationData);
/**
* The application data
*/
data: ApplicationData;
}
/**
* Event dispatched by @see{@link CastReceiverManager} when the system needs to update the restriction on maximum video resolution.
*/
class MaxVideoResolutionChangedEvent extends Event {
constructor(height: number);
/**
* Maximum video resolution requested by the system. The value of 0 means there is no restriction.
*/
height: number;
}
/** Event dispatched by @see{@link CastReceiverManager} when the systems starts to create feedback report. */
interface FeedbackStartedEvent extends Event {
[key: string]: any;
}
/** Event dispatched by @see{@link CastReceiverContext} which contains system information. */
class Event {
constructor(type: EventType, data?: any);
type: EventType;
data?: any;
}
/** Represents the data of the launched application. */
interface ApplicationData {
id(): string;
launchingSenderId(): string;
name(): string;
namespaces(): string[];
sessionId(): number;
}
}

View File

@@ -0,0 +1,197 @@
import { PlayerDataEventType } from "./cast.framework.ui";
import { MediaMetadata } from "./cast.framework.messages";
import { PlayerDataChangedEventHandler } from "./index";
export = cast.framework.ui;
declare namespace cast.framework.ui {
type ContentType = "video" | "audio" | "image";
type State =
| "launching"
| "idle"
| "loading"
| "buffering"
| "paused"
| "playing";
type PlayerDataEventType =
| "ANY_CHANGE"
| "STATE_CHANGED"
| "IS_SEEKING_CHANGED"
| "DURATION_CHANGED"
| "CURRENT_TIME_CHANGED"
| "METADATA_CHANGED"
| "TITLE_CHANGED"
| "SUBTITLE_CHANGED"
| "THUMBNAIL_URL_CHANGED"
| "NEXT_TITLE_CHANGED"
| "NEXT_SUBTITLE_CHANGED"
| "NEXT_THUMBNAIL_URL_CHANGED"
| "PRELOADING_NEXT_CHANGED"
| "CONTENT_TYPE_CHANGED"
| "IS_LIVE_CHANGED"
| "BREAK_PERCENTAGE_POSITIONS_CHANGED"
| "IS_PLAYING_BREAK_CHANGED"
| "IS_BREAK_SKIPPABLE_CHANGED"
| "WHEN_SKIPPABLE_CHANGED"
| "NUMBER_BREAK_CLIPS_CHANGED"
| "CURRENT_BREAK_CLIP_NUMBER_CHANGED"
| "DISPLAY_STATUS_CHANGED";
/**
* Player data changed event. Provides the changed field (type); and new value.
*/
class PlayerDataChangedEvent {
constructor(type: PlayerDataEventType, field: string, value: any);
/**
* The field name that was changed.
*/
field: string;
type: PlayerDataEventType;
/**
* The new field value.
*/
value: any;
}
/**
* Player data binder. Bind a player data object to the player state.
* The player data will be updated to reflect correctly the current player state without firing any change event.
*/
class PlayerDataBinder {
constructor(playerData: PlayerData);
/**
* Add listener to player data changes.
*/
addEventListener: (
type: PlayerDataEventType,
listener: PlayerDataChangedEventHandler
) => void;
/**
* Remove listener to player data changes.
*/
removeEventListener: (
type: PlayerDataEventType,
listener: PlayerDataChangedEventHandler
) => void;
}
/**
* Player data. Provide the player media and break state.
*/
interface PlayerData {
/**
* Array of breaks positions in percentage.
*/
breakPercentagePositions: number[];
/**
* Content Type.
*/
contentType: ContentType;
/**
* The number of the current playing break clip in the break.
*/
currentBreakClipNumber: number;
/**
* Media current position in seconds; or break current position if playing break.
*/
currentTime: number;
/**
* Whether the player metadata (ie: title; currentTime) should be displayed.
* This will be true if at least one field in the metadata should be displayed.
* In some cases; displayStatus will be true; but parts of the metadata should be hidden
* (ie: the media title while media is seeking).
* In these cases; additional css can be applied to hide those elements.
* For cases where the media is audio-only; this will almost always be true.
* In cases where the media is video; this will be true when:
* (1) the video is loading; buffering; or seeking
* (2) a play request was made in the last five seconds while media is already playing;
* (3) there is a request made to show the status in the last five seconds; or
* (4) the media was paused in the last five seconds.
*/
displayStatus: boolean;
/**
* Media duration in seconds; Or break duration if playing break.
*/
duration: number;
/**
* Indicate break clip can be skipped.
*/
isBreakSkippable: boolean;
/**
* Indicate if the content is a live stream.
*/
isLive: boolean;
/**
* Indicate that the receiver is playing a break.
*/
isPlayingBreak: boolean;
/**
* Indicate the player is seeking (can be either during playing or pausing).
*/
isSeeking: boolean;
/**
* Media metadata.
*/
metadata: MediaMetadata;
/**
* Next Item subtitle.
*/
nextSubtitle: string;
/**
* Next Item thumbnail url.
*/
nextThumbnailUrl: string;
/**
* Next Item title.
*/
nextTitle: string;
/**
* Number of break clips in current break.
*/
numberBreakClips: number;
/**
* Flag to show/hide next item metadata.
*/
preloadingNext: boolean;
/**
* Current player state.
*/
state: State;
/**
* Content thumbnail url.
*/
thumbnailUrl: string;
/**
* Content title.
*/
title: string;
/**
* Provide the time a break is skipable - relative to current playback time. Undefined if not skippable.
*/
whenSkippable?: number;
}
}

View File

@@ -0,0 +1,106 @@
import {
PlayerData,
PlayerDataBinder
} from "chromecast-caf-receiver/cast.framework.ui";
import {
ReadyEvent,
ApplicationData
} from "chromecast-caf-receiver/cast.framework.system";
import {
RequestEvent,
Event
} from "chromecast-caf-receiver/cast.framework.events";
import {
QueueBase,
TextTracksManager,
QueueManager,
PlayerManager
} from "chromecast-caf-receiver/cast.framework";
import {
BreakSeekData,
BreakClipLoadInterceptorContext,
BreakManager
} from "chromecast-caf-receiver/cast.framework.breaks";
import {
Break,
BreakClip,
LoadRequestData,
Track,
MediaMetadata
} from "chromecast-caf-receiver/cast.framework.messages";
const track = new Track(1, "TEXT");
const breakClip = new BreakClip("id");
const adBreak = new Break("id", ["id"], 1);
const rEvent = new RequestEvent("BITRATE_CHANGED", { requestId: 2 });
const pManager = new PlayerManager();
pManager.addEventListener("STALLED", () => {});
const ttManager = new TextTracksManager();
const qManager = new QueueManager();
const qBase = new QueueBase();
const items = qBase.fetchItems(1, 3, 4);
const breakSeekData = new BreakSeekData(0, 100, []);
const breakClipLoadContext = new BreakClipLoadInterceptorContext(adBreak);
const breakManager: BreakManager = {
getBreakById: () => adBreak,
getBreakClipById: () => breakClip,
getBreakClips: () => [breakClip],
getBreaks: () => [adBreak],
getPlayWatchedBreak: () => true,
setBreakClipLoadInterceptor: () => {},
setBreakSeekInterceptor: () => {},
setPlayWatchedBreak: () => {},
setVastTrackingInterceptor: () => {}
};
const lrd: LoadRequestData = {
requestId: 1,
activeTrackIds: [1, 2],
media: {
tracks: [],
textTrackStyle: {},
streamType: "BUFFERED",
metadata: { metadataType: "GENERIC" },
hlsSegmentFormat: "AAC",
contentId: "id",
contentType: "type",
breakClips: [breakClip],
breaks: [adBreak]
},
queueData: {}
};
const appData: ApplicationData = {
id: () => "id",
launchingSenderId: () => "launch-id",
name: () => "name",
namespaces: () => ["namespace"],
sessionId: () => 1
};
const readyEvent = new ReadyEvent(appData);
const data = readyEvent.data;
const pData: PlayerData = {
breakPercentagePositions: [1],
contentType: "video",
currentBreakClipNumber: 2,
currentTime: 1234,
displayStatus: true,
duration: 222,
isBreakSkippable: false,
isLive: true,
isPlayingBreak: false,
isSeeking: true,
metadata: new MediaMetadata("GENERIC"),
nextSubtitle: "sub",
nextThumbnailUrl: "url",
nextTitle: "title",
numberBreakClips: 3,
preloadingNext: false,
state: "paused",
thumbnailUrl: "url",
title: "title",
whenSkippable: 321
};
const binder = new PlayerDataBinder(pData);
binder.addEventListener("ANY_CHANGE", e => {});

View File

@@ -0,0 +1,24 @@
// Type definitions for chromecast-caf-receiver 3.x
// Project: https://github.com/googlecast
// Definitions by: Craig Bruce <https://github.com/craigrbruce>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.1
/// <reference path="./cast.framework.d.ts" />
/// <reference path="./cast.framework.breaks.d.ts" />
/// <reference path="./cast.framework.events.d.ts" />
/// <reference path="./cast.framework.messages.d.ts" />
/// <reference path="./cast.framework.system.d.ts" />
/// <reference path="./cast.framework.ui.d.ts" />
import { PlayerDataChangedEvent } from './cast.framework.ui';
import { NetworkRequestInfo } from './cast.framework';
import { Event } from './cast.framework.events';
export as namespace cast;
export type EventHandler = (event: Event) => void;
export type PlayerDataChangedEventHandler = (
event: PlayerDataChangedEvent
) => void;
export type RequestHandler = (request: NetworkRequestInfo) => void;
export type BinaryHandler = (data: Uint8Array) => Uint8Array;

View File

@@ -0,0 +1,26 @@
{
"compilerOptions": {
"module": "commonjs",
"lib": ["es6"],
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"baseUrl": "../",
"typeRoots": ["../"],
"types": [],
"noEmit": true,
"forceConsistentCasingInFileNames": true,
"strictFunctionTypes": false,
"esModuleInterop": true
},
"files": [
"index.d.ts",
"chromecast-caf-receiver-tests.ts",
"cast.framework.d.ts",
"cast.framework.breaks.d.ts",
"cast.framework.events.d.ts",
"cast.framework.messages.d.ts",
"cast.framework.system.d.ts",
"cast.framework.ui.d.ts"
]
}

View File

@@ -0,0 +1,5 @@
{
"extends": "dtslint/dt.json",
"rules": {
}
}