274 lines
9.0 KiB
TypeScript
274 lines
9.0 KiB
TypeScript
/// <reference types="node" />
|
|
import { CancelTokenSession } from 'jibo-cai-utils';
|
|
import { Event } from 'jibo-typed-events';
|
|
import { EventEmitter } from 'events';
|
|
import HLS = require('hls.js');
|
|
import { Log } from 'jibo-log';
|
|
/**
|
|
* Enum of radio media types.
|
|
* @typedef MediaType
|
|
* @prop Music
|
|
* @prop Talk
|
|
* @prop Other
|
|
*/
|
|
export declare enum MediaType {
|
|
Music = "Music",
|
|
Talk = "Talk",
|
|
Other = "Other",
|
|
}
|
|
/**
|
|
* @interface SongData
|
|
* @prop [mediaType] {MediaType}
|
|
* @prop [artist] {string}
|
|
* @prop [title] {string}
|
|
* @prop [artworkUrl] {string}
|
|
* @prop [length] {string}
|
|
*/
|
|
export interface SongData {
|
|
mediaType?: MediaType;
|
|
artist?: string;
|
|
title?: string;
|
|
artworkUrl?: string;
|
|
length?: string;
|
|
}
|
|
/**
|
|
* @interface StationData
|
|
* @prop band {string}
|
|
* @prop callLetters {string}
|
|
* @prop description {string}
|
|
* @prop frequency {string}
|
|
* @prop logoUrl {string}
|
|
* @prop name {string}
|
|
* @prop website {string}
|
|
*/
|
|
export interface StationData {
|
|
band: string;
|
|
callLetters: string;
|
|
description: string;
|
|
frequency: string;
|
|
logoUrl: string;
|
|
name: string;
|
|
website: string;
|
|
}
|
|
/**
|
|
* Enum of radio-play modes
|
|
* @typedef Mode
|
|
* @prop HLS
|
|
* @prop Shoutcast
|
|
* @prop PLS
|
|
* @intdocs
|
|
*/
|
|
export declare enum Mode {
|
|
HLS = "HLS",
|
|
Shoutcast = "Shoutcast",
|
|
PLS = "PLS",
|
|
}
|
|
/**
|
|
* Enum of supported localities when searching for live stations
|
|
* @typedef Locality
|
|
* @prop Local
|
|
* @prop National
|
|
*/
|
|
export declare enum Locality {
|
|
Local = "Local",
|
|
National = "National",
|
|
}
|
|
/**
|
|
* Options provided to RadioPlayer#getStations
|
|
* @interface GetStationsOptions
|
|
* @prop [genreName] {string} The name of the genre for filteriing the station results
|
|
* @prop [locality] {Locality} Limit the results to national or local stations
|
|
* @prop [limit] {number} Limit the results to this amount
|
|
* @prop [preferredStation] {string} The call letters of the station preferred by the end-user, or the default station for the genre
|
|
*/
|
|
export interface GetStationsOptions {
|
|
genreName?: string;
|
|
locality?: Locality;
|
|
limit?: number;
|
|
preferredStation?: string;
|
|
}
|
|
/**
|
|
* Generic interface of jibo.volume properties that we use
|
|
* @interface VolumePlugin
|
|
* @prop currentVolume {number}
|
|
* @intdocs
|
|
*/
|
|
export interface VolumePlugin extends EventEmitter {
|
|
currentVolume: number;
|
|
}
|
|
/**
|
|
* Generic interface of websocket responses emitted from jibo.gl.events.noMatch
|
|
* @interface WSResponse<T = any>
|
|
* @prop status {string}
|
|
* @prop message {string}
|
|
* @prop id {string}
|
|
* @prop result {T}
|
|
* @prop moreinfo {string}
|
|
* @intdocs
|
|
*/
|
|
export interface WSResponse<T = any> {
|
|
status: string;
|
|
message: string;
|
|
id: string;
|
|
result: T;
|
|
moreinfo: string;
|
|
}
|
|
/**
|
|
* Generic interface of the jibo.jetstream.events and jibo.globalEvents used in RadioPlayer
|
|
* @interface ListenEvents
|
|
* @prop hjHeard {Event<void>}
|
|
* @prop hjOnly {Event<void>}
|
|
* @prop noMatch {Event<WSResponse<jibo.gl.NoMatchResults>>}
|
|
* @prop noGlobalMatch {Event<any>}
|
|
* @prop nonInterruptingGlobal {Event<void>}
|
|
* @intdocs
|
|
*/
|
|
export interface ListenEvents {
|
|
hjHeard: Event<void>;
|
|
hjOnly: Event<any>;
|
|
noGlobalMatch: Event<any>;
|
|
nonInterruptingGlobal: Event<void>;
|
|
}
|
|
/**
|
|
* This is an abstract base class, which cannot be instantiated directly;
|
|
* instead, use an implementation of this class, like IHeartPlayer
|
|
* @class RadioPlayer
|
|
*/
|
|
export default abstract class RadioPlayer extends EventEmitter {
|
|
protected static _hash(name: string): string;
|
|
private static _songDataDifferent(left, right);
|
|
private static _promiseTimeout<T>(promise, millis);
|
|
protected _deviceId: string;
|
|
protected _lat: number;
|
|
protected _lng: number;
|
|
protected _log: Log;
|
|
protected _mediaTagPlayPromise: Promise<void>;
|
|
protected _mode: Mode;
|
|
protected _promises: CancelTokenSession;
|
|
protected _releaseVersion: string;
|
|
private _audio;
|
|
private _country;
|
|
private _hls;
|
|
private _hlsURI;
|
|
private _icecastClient;
|
|
private _isCurrentlySpeaking;
|
|
private _lastSongData;
|
|
private _listenEvents;
|
|
private _playPromise;
|
|
private _playReject;
|
|
private _playResolve;
|
|
private _plsStreams;
|
|
private _plsStreamFirstIndex;
|
|
private _plsStreamIndex;
|
|
private _pollSongData;
|
|
private _recoveringMedia;
|
|
private _shoutcastServer;
|
|
private _songDataSession;
|
|
private _songDataTimers;
|
|
private _swappingAudioCodec;
|
|
private _video;
|
|
private _volumePlugin;
|
|
constructor();
|
|
/**
|
|
* Initialize the RadioPlayer: implementations can override this, but must
|
|
* call super.init() to ensure this code runs
|
|
* @param {string} serialNumber Pass in the result from jibo.systemManager.getIdentity()
|
|
* @param {string} releaseVersion Pass in jibo.versions.release
|
|
* @param {string} country Pass in jibo.utils.Location.jiboHome.country;
|
|
* @param {number} lat Pass in jibo.utils.Location.jiboHome.lat
|
|
* @param {number} lng Pass in jibo.utils.Location.jiboHome.lng
|
|
* @param {ListenEvents} listenEvents Pass in jibo.gl.events
|
|
* @param {VolumePlugin} volumePlugin Pass in jibo.volume
|
|
* @return {Promise<void>} Resolves when all init steps are complete
|
|
*/
|
|
init(serialNumber: string, releaseVersion: string, country: string, lat: number, lng: number, listenEvents: ListenEvents, volumePlugin: VolumePlugin): Promise<void>;
|
|
getCountry(): Promise<string>;
|
|
/**
|
|
* Get a list of stations matching the options provided
|
|
* @method RadioPlayer#getStations
|
|
* @param {GetStationsOptions} options The search options to use
|
|
* @return {Promise<StationData[]>} Resolves to a list of stations matching the options provided
|
|
*/
|
|
abstract getStations(options: GetStationsOptions): Promise<StationData[]>;
|
|
/**
|
|
* Play the provided radio station; call letters may be retrieved from
|
|
* getStations() results. Abstract method must be implemented;
|
|
* implementations must call _streamHLS, _streamShoutcast, or _streamPLS
|
|
* @method RadioPlayer#play
|
|
* @param {string} callLetters The call letters of the station to play
|
|
* @return {Promise<void>} Resolves when the station actually starts streaming
|
|
*/
|
|
abstract play(callLetters: string): Promise<void>;
|
|
/**
|
|
* Replace a URL to artwork with one that will resize the artwork to the
|
|
* dimension provided. Implementations can override this; the default
|
|
* behavior simply returns the provided URL back, unaltered.
|
|
* @method RadioPlayer#resizeArtwork
|
|
* @param {string} url
|
|
* @param {number} width
|
|
* @return {string}
|
|
*/
|
|
resizeArtwork(uri: string, width: number): string;
|
|
/**
|
|
* Pauses the current stream; not expected to be overridden
|
|
* @method RadioPlayer#pause
|
|
* @return {Promise<void>}
|
|
*/
|
|
pause(): Promise<void>;
|
|
/**
|
|
* Begin playing the current stream, or resume the paused stream
|
|
* @method RadioPlayer#resume
|
|
* @return {Promise<void>}
|
|
*/
|
|
resume(): Promise<void>;
|
|
/**
|
|
* Stop a stream, cancel related Promises and timers, remove related event
|
|
* listeners, and release all related resources for garbage collection.
|
|
* An implementation may override this, but must await super.stop().
|
|
* @method RadioPlayer#stop
|
|
* @return {Promise<void>}
|
|
*/
|
|
stop(): Promise<void>;
|
|
/**
|
|
* Cancel all Promises and event listenrs and release all used memory
|
|
* @method RadioPlayer#destroy
|
|
* @return {void}
|
|
*/
|
|
destroy(): void;
|
|
/**
|
|
* Stop any current stream, cancel Promises and event listeners, and
|
|
* release all memory used by the RadioPlayer for garbage collection
|
|
* @method RadioPlayer#stopAndDestroy
|
|
* @return {Promise<void>}
|
|
*/
|
|
stopAndDestroy(): Promise<void>;
|
|
protected abstract _processHLSMetadata(titleField: string): SongData;
|
|
protected abstract _processShoutcastMetadata(titleField: string): SongData;
|
|
protected abstract _getSidebandData: () => Promise<SongData>;
|
|
protected _handleStreamError(err?: any): void;
|
|
protected _streamHLS(uri: string, config?: HLS.OptionalConfig, failover?: boolean): Promise<void>;
|
|
private _fillMissingSongData(songData);
|
|
private _emitSongData(songData, fromSideband?);
|
|
protected _streamShoutcast(uri: string, failover?: boolean): Promise<void>;
|
|
protected _streamPLS(uri: string, failover?: boolean): Promise<void>;
|
|
protected _streamStarted(): void;
|
|
setCurrentlySpeaking(isCurrentlySpeaking: boolean): void;
|
|
private _volume;
|
|
private _hjHeard;
|
|
private _listenFinished;
|
|
private _volumeChanged;
|
|
private _playPLSStream();
|
|
private _nextPLSStream(data?);
|
|
private _hlsMediaAttached;
|
|
private _hlsManifestParsed;
|
|
private _hlsFragParsing;
|
|
private _handleHLSErrors;
|
|
private _handleMediaPlaying;
|
|
private _handleAudioError;
|
|
private _handleVideoError;
|
|
private static _getMediaError(code);
|
|
private _setStreamPromiseHandlers(startStream);
|
|
private _resolveStreamPromise();
|
|
private _rejectOrEmit(reason?);
|
|
}
|