diff --git a/types/chromecast-caf-sender/chromecast-caf-sender-tests.ts b/types/chromecast-caf-sender/chromecast-caf-sender-tests.ts new file mode 100644 index 0000000000..49e2bf5fee --- /dev/null +++ b/types/chromecast-caf-sender/chromecast-caf-sender-tests.ts @@ -0,0 +1,134 @@ +cast.framework.VERSION === "1.0.06"; +cast.framework.setLoggerLevel(cast.framework.LoggerLevel.DEBUG); + +const context = cast.framework.CastContext.getInstance(); +context.getCastState() === cast.framework.CastState.CONNECTED; +context.getSessionState() === cast.framework.SessionState.NO_SESSION; + +context.setOptions({ + autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED, + language: "en-US", + receiverApplicationId: "test", + resumeSavedSession: true +}); + +context.addEventListener( + cast.framework.CastContextEventType.CAST_STATE_CHANGED, + event => { + const { castState } = event; + } +); +context.addEventListener( + cast.framework.CastContextEventType.SESSION_STATE_CHANGED, + event => { + const { sessionState } = event; + } +); + +const handleSessionStateChange = ( + event: cast.framework.SessionStateEventData +) => {}; +context.removeEventListener( + cast.framework.CastContextEventType.SESSION_STATE_CHANGED, + handleSessionStateChange +); + +context.requestSession().then(err => { + if (err === chrome.cast.ErrorCode.CHANNEL_ERROR) return; + + const session = cast.framework.CastContext.getInstance().getCurrentSession(); + if (!session) return; + + const handleError = (err?: chrome.cast.ErrorCode) => {}; + + session.getSessionObj().sessionId === session.getSessionId(); + session.getSessionState() === cast.framework.SessionState.SESSION_STARTED; + session.getCastDevice().name; + session.getApplicationMetadata().applicationId; + session.getApplicationStatus() === ""; + session.getActiveInputState() === + cast.framework.ActiveInputState.ACTIVE_INPUT_STATE_UNKNOWN; + session.endSession(false); + session.setVolume(0.5).then(handleError); + session.getVolume() === 0.5; + session.setMute(true).then(handleError); + session.isMute(); + session.sendMessage("namespace", { obj: 1 }).then(handleError); + session.sendMessage("namespace", "string"); + session.sendMessage("namespace", 2); + + session.addMessageListener("namespace", (namespace, message) => {}); + session.removeMessageListener("namespace", (namespace, message) => {}); + + const req = new chrome.cast.media.LoadRequest( + new chrome.cast.media.MediaInfo("id", "type") + ); + session.loadMedia(req); + + const media = session.getMediaSession(); + if (media && media.sessionId) { + } + + session.addEventListener( + cast.framework.SessionEventType.ACTIVE_INPUT_STATE_CHANGED, + ({ activeInputState }) => {} + ); + session.addEventListener( + cast.framework.SessionEventType.APPLICATION_METADATA_CHANGED, + ({ metadata }) => {} + ); + session.addEventListener( + cast.framework.SessionEventType.APPLICATION_STATUS_CHANGED, + ({ status }) => {} + ); + session.addEventListener( + cast.framework.SessionEventType.MEDIA_SESSION, + ({ mediaSession }) => {} + ); + session.addEventListener( + cast.framework.SessionEventType.VOLUME_CHANGED, + ({ volume }) => {} + ); + session.removeEventListener( + cast.framework.SessionEventType.VOLUME_CHANGED, + ({ volume }) => {} + ); +}); + +const player = new cast.framework.RemotePlayer(); +{ + const bool: boolean = + player.isConnected && + player.isMediaLoaded && + player.canControlVolume && + player.isPaused && + player.isMuted && + player.canPause && + player.canSeek; + const sum: number = player.duration + player.currentTime + player.volumeLevel; + const str: string = + player.displayName + player.statusText + player.title + player.displayName; +} +player.mediaInfo && player.mediaInfo.contentId; +player.imageUrl && player.imageUrl === ""; +player.playerState && player.playerState === chrome.cast.media.PlayerState.IDLE; +player.savedPlayerState && player.savedPlayerState.currentTime; +player.controller === null; + +const playerCtrl = new cast.framework.RemotePlayerController(player); +player.controller === playerCtrl; +playerCtrl.playOrPause(); +playerCtrl.stop(); +playerCtrl.seek(); +playerCtrl.muteOrUnmute(); +playerCtrl.setVolumeLevel(); +playerCtrl.getFormattedTime(60); +playerCtrl.getSeekPosition(1, 60) === playerCtrl.getSeekTime(1, 60); +playerCtrl.addEventListener( + cast.framework.RemotePlayerEventType.ANY_CHANGE, + () => {} +); +playerCtrl.removeEventListener( + cast.framework.RemotePlayerEventType.ANY_CHANGE, + () => {} +); diff --git a/types/chromecast-caf-sender/index.d.ts b/types/chromecast-caf-sender/index.d.ts new file mode 100644 index 0000000000..e1e5c8ae65 --- /dev/null +++ b/types/chromecast-caf-sender/index.d.ts @@ -0,0 +1,306 @@ +// Type definitions for Cast Application Framework Sender API 1.0 +// Project: https://developers.google.com/cast/docs/caf_receiver_overview +// Definitions by: Samuel Maddock +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +// TypeScript Version: 2.4 + +/// +/// + +//////////////////// +// Global object +//////////////////// +interface Window { + cast: typeof cast; +} + +//////////////////// +// Framework +//////////////////// +/** + * Cast Application Framework + * @see https://developers.google.com/cast/docs/reference/chrome/cast.framework + */ +declare namespace cast.framework { + enum LoggerLevel { + DEBUG, + INFO, + WARNING, + ERROR, + NONE + } + + enum CastState { + NO_DEVICES_AVAILABLE = "NO_DEVICES_AVAILABLE", + NOT_CONNECTED = "NOT_CONNECTED", + CONNECTING = "CONNECTING", + CONNECTED = "CONNECTED" + } + + enum SessionState { + NO_SESSION = "NO_SESSION", + SESSION_STARTING = "SESSION_STARTING", + SESSION_STARTED = "SESSION_STARTED", + SESSION_START_FAILED = "SESSION_START_FAILED", + SESSION_ENDING = "SESSION_ENDING", + SESSION_ENDED = "SESSION_ENDED", + SESSION_RESUMED = "SESSION_RESUMED" + } + enum CastContextEventType { + CAST_STATE_CHANGED = "caststatechanged", + SESSION_STATE_CHANGED = "sessionstatechanged" + } + enum SessionEventType { + APPLICATION_STATUS_CHANGED = "applicationstatuschanged", + APPLICATION_METADATA_CHANGED = "applicationmetadatachanged", + ACTIVE_INPUT_STATE_CHANGED = "activeinputstatechanged", + VOLUME_CHANGED = "volumechanged", + MEDIA_SESSION = "mediasession" + } + enum RemotePlayerEventType { + ANY_CHANGE = "anyChanged", + IS_CONNECTED_CHANGED = "isConnectedChanged", + IS_MEDIA_LOADED_CHANGED = "isMediaLoadedChanged", + DURATION_CHANGED = "durationChanged", + CURRENT_TIME_CHANGED = "currentTimeChanged", + IS_PAUSED_CHANGED = "isPausedChanged", + VOLUME_LEVEL_CHANGED = "volumeLevelChanged", + CAN_CONTROL_VOLUME_CHANGED = "canControlVolumeChanged", + IS_MUTED_CHANGED = "isMutedChanged", + CAN_PAUSE_CHANGED = "canPauseChanged", + CAN_SEEK_CHANGED = "canSeekChanged", + DISPLAY_NAME_CHANGED = "displayNameChanged", + STATUS_TEXT_CHANGED = "statusTextChanged", + TITLE_CHANGED = "titleChanged", + DISPLAY_STATUS_CHANGED = "displayStatusChanged", + MEDIA_INFO_CHANGED = "mediaInfoChanged", + IMAGE_URL_CHANGED = "imageUrlChanged", + PLAYER_STATE_CHANGED = "playerStateChanged" + } + + enum ActiveInputState { + ACTIVE_INPUT_STATE_UNKNOWN = -1, + ACTIVE_INPUT_STATE_NO = 0, + ACTIVE_INPUT_STATE_YES = 1 + } + + interface CastOptions { + autoJoinPolicy: chrome.cast.AutoJoinPolicy; + language?: string; + receiverApplicationId?: string; + resumeSavedSession?: boolean; + } + + const VERSION: string; + function setLoggerLevel(level: LoggerLevel): void; + + class CastContext { + static getInstance(): CastContext; + setOptions(options: CastOptions): void; + getCastState(): CastState; + getSessionState(): SessionState; + requestSession(): Promise; + getCurrentSession(): CastSession | null; + endCurrentSession(stopCasting: boolean): void; + + addEventListener( + type: CastContextEventType.CAST_STATE_CHANGED, + handler: (event: CastStateEventData) => void + ): void; + addEventListener( + type: CastContextEventType.SESSION_STATE_CHANGED, + handler: (event: SessionStateEventData) => void + ): void; + removeEventListener( + type: CastContextEventType.CAST_STATE_CHANGED, + handler: (event: CastStateEventData) => void + ): void; + removeEventListener( + type: CastContextEventType.SESSION_STATE_CHANGED, + handler: (event: SessionStateEventData) => void + ): void; + } + + class CastSession { + constructor(sessionObj: chrome.cast.Session, state: SessionState); + getSessionObj(): chrome.cast.Session; + getSessionId(): string; + getSessionState(): SessionState; + getCastDevice(): chrome.cast.Receiver; + getApplicationMetadata(): ApplicationMetadata; + getApplicationStatus(): string; + getActiveInputState(): ActiveInputState; + endSession(stopCasting: boolean): void; + setVolume(volume: number): Promise; + getVolume(): number; + setMute(mute: boolean): Promise; + isMute(): boolean; + sendMessage( + namespace: string, + data: any + ): Promise; + addMessageListener( + namespace: string, + listener: (namespace: string, message: string) => void + ): void; + removeMessageListener( + namespace: string, + listener: (namespace: string, message: string) => void + ): void; + loadMedia( + request: chrome.cast.media.LoadRequest + ): Promise; + getMediaSession(): chrome.cast.media.Media | null; + + addEventListener( + type: SessionEventType.ACTIVE_INPUT_STATE_CHANGED, + handler: (event: ActiveInputStateEventData) => void + ): void; + addEventListener( + type: SessionEventType.APPLICATION_METADATA_CHANGED, + handler: (event: ApplicationMetadataEventData) => void + ): void; + addEventListener( + type: SessionEventType.APPLICATION_STATUS_CHANGED, + handler: (event: ApplicationStatusEventData) => void + ): void; + addEventListener( + type: SessionEventType.MEDIA_SESSION, + handler: (event: MediaSessionEventData) => void + ): void; + addEventListener( + type: SessionEventType.VOLUME_CHANGED, + handler: (event: VolumeEventData) => void + ): void; + removeEventListener( + type: SessionEventType.ACTIVE_INPUT_STATE_CHANGED, + handler: (event: ActiveInputStateEventData) => void + ): void; + removeEventListener( + type: SessionEventType.APPLICATION_METADATA_CHANGED, + handler: (event: ApplicationMetadataEventData) => void + ): void; + removeEventListener( + type: SessionEventType.APPLICATION_STATUS_CHANGED, + handler: (event: ApplicationStatusEventData) => void + ): void; + removeEventListener( + type: SessionEventType.MEDIA_SESSION, + handler: (event: MediaSessionEventData) => void + ): void; + removeEventListener( + type: SessionEventType.VOLUME_CHANGED, + handler: (event: VolumeEventData) => void + ): void; + } + + class RemotePlayerController { + constructor(player: RemotePlayer); + playOrPause(): void; + stop(): void; + seek(): void; + muteOrUnmute(): void; + setVolumeLevel(): void; + getFormattedTime(timeInSec: number): string; + getSeekPosition(currentTime: number, duration: number): number; + getSeekTime(currentPosition: number, duration: number): number; + + addEventListener( + type: RemotePlayerEventType, + handler: (event: RemotePlayerChangedEvent) => void + ): void; + removeEventListener( + type: RemotePlayerEventType, + handler: (event: RemotePlayerChangedEvent) => void + ): void; + } + + interface SavedPlayerState { + mediaInfo: chrome.cast.media.PlayerState | null; + currentTime: number; + isPaused: boolean; + } + + class RemotePlayer { + isConnected: boolean; + isMediaLoaded: boolean; + duration: number; + currentTime: number; + volumeLevel: number; + canControlVolume: boolean; + isPaused: boolean; + isMuted: boolean; + canPause: boolean; + canSeek: boolean; + displayName: string; + statusText: string; + title: string; + displayStatus: string; + mediaInfo?: chrome.cast.media.MediaInfo; + imageUrl: string | null; + playerState: chrome.cast.media.PlayerState | null; + savedPlayerState: SavedPlayerState | null; + controller: RemotePlayerController | null; + } + + class ApplicationMetadata { + constructor(sessionObj: chrome.cast.Session); + applicationId: string; + images: chrome.cast.Image[]; + name: string; + namespaces: string[]; + } + + abstract class EventData { + constructor(type: string); + type: string; + } + + class ActiveInputStateEventData extends EventData { + constructor(activeInputState: ActiveInputState); + activeInputState: ActiveInputState; + } + + class ApplicationMetadataEventData extends EventData { + constructor(metadata: ApplicationMetadata); + metadata: ApplicationMetadata; + } + + class ApplicationStatusEventData extends EventData { + constructor(status: string); + status: string; + } + + class CastStateEventData extends EventData { + constructor(castState: CastState); + castState: CastState; + } + + class MediaSessionEventData extends EventData { + constructor(mediaSession: chrome.cast.media.Media); + mediaSession: chrome.cast.media.Media; + } + + class RemotePlayerChangedEvent extends EventData { + constructor(type: RemotePlayerEventType, field: string, value: T); + field: string; + value: T; + } + + class SessionStateEventData extends EventData { + constructor( + session: CastSession, + sessionState: SessionState, + opt_errorCode: chrome.cast.ErrorCode + ); + errorCode: chrome.cast.ErrorCode; + session: CastSession; + sessionState: SessionState; + } + + class VolumeEventData extends EventData { + constructor(volume: number, isMute: boolean); + isMute: boolean; + volume: number; + } +} diff --git a/types/chromecast-caf-sender/tsconfig.json b/types/chromecast-caf-sender/tsconfig.json new file mode 100644 index 0000000000..0d8a0cad6e --- /dev/null +++ b/types/chromecast-caf-sender/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "chromecast-caf-sender-tests.ts" + ] +} diff --git a/types/chromecast-caf-sender/tslint.json b/types/chromecast-caf-sender/tslint.json new file mode 100644 index 0000000000..3db14f85ea --- /dev/null +++ b/types/chromecast-caf-sender/tslint.json @@ -0,0 +1 @@ +{ "extends": "dtslint/dt.json" }