Skip to content

Commit

Permalink
feat: add a streamState and fix streamMetadataError
Browse files Browse the repository at this point in the history
  • Loading branch information
MathieuPOUX committed Sep 25, 2024
1 parent 8a82854 commit e884225
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 6 deletions.
2 changes: 1 addition & 1 deletion index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export { IStats } from './src/stats/IStats';
export { StreamerStats } from './src/stats/StreamerStats';
// Metadata
export { Metadata, MSource, MTrack, MType } from './src/metadata/Metadata';
export { StreamMetadata, StreamMetadataError } from './src/metadata/StreamMetadata';
export { StreamState, StreamMetadata, StreamMetadataError } from './src/metadata/StreamMetadata';
// Timed metadata
export { IStreamData } from './src/metadata/IStreamData';
export { WSStreamData } from './src/metadata/WSStreamData';
Expand Down
29 changes: 27 additions & 2 deletions src/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
*/

import { StreamMetadata, StreamMetadataError } from './metadata/StreamMetadata';
import { StreamMetadata, StreamMetadataError, StreamState } from './metadata/StreamMetadata';
import { ILog, Connect, Util, EventEmitter, WebSocketReliableError } from '@ceeblue/web-utils';
import { ConnectionInfos, ConnectorError, IConnector } from './connectors/IConnector';
import { IController, IsController, PlayingInfos } from './connectors/IController';
Expand Down Expand Up @@ -91,6 +91,14 @@ export class Player extends EventEmitter {
}
}

/**
* Event fired when stream state is changing
* @param state
*/
onState(state: StreamState) {
this.log('onState', state).info();
}

/**
* Event fired every second to report information while content plays
* @param playing
Expand Down Expand Up @@ -157,6 +165,13 @@ export class Player extends EventEmitter {
return this._connector;
}

/**
* State of the stream as indicated by the server
*/
get streamState(): StreamState {
return this._streamMetadata?.streamState || StreamState.UNKNOWN;
}

/**
* Returns the {@link Metadata} object description
*/
Expand Down Expand Up @@ -383,7 +398,16 @@ export class Player extends EventEmitter {
// reset to release resources!
mbr?.reset();
// Stop the player if signaling fails!
this.stop(error);
if (this.streamState === StreamState.OFFLINE) {
// if stream-state was offine on disconnection, shows this error!
this.stop({
type: 'StreamMetadataError',
name: this.streamState,
stream: (params as Connect.Params).streamName
});
} else {
this.stop(error);
}
};

// Timed Metadatas
Expand Down Expand Up @@ -518,6 +542,7 @@ export class Player extends EventEmitter {
private _initStreamMetadata(params: Connect.Params, streamMetadata: StreamMetadata) {
this._streamMetadata = streamMetadata;
streamMetadata.log = this.log.bind(this, 'StreamMetadata:') as ILog;
streamMetadata.onState = (state: StreamState) => this.onState(state);
streamMetadata.onMetadata = metadata => {
if (!this._connector || !this._connector.opened) {
return;
Expand Down
47 changes: 44 additions & 3 deletions src/metadata/StreamMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ import { MTrack, MType, Metadata } from './Metadata';

const sortByMAXBPS = (track1: MTrack, track2: MTrack) => track2.maxbps - track1.maxbps;

export enum StreamState {
UNKNOWN = '',
ONLINE = 'Stream is online',
OFFLINE = 'Stream is offline',
LOADING = 'Stream is initializing',
BOOTING = 'Stream is booting',
WAITING = 'Stream is waiting for data'
}

export type StreamMetadataError =
/**
* Represents a Connection error.
Expand All @@ -18,7 +27,6 @@ export type StreamMetadataError =
* Represents a {@link WebSocketReliableError} error
*/
| WebSocketReliableError;

/**
* Use StreamMetadata to get real-time information on a server stream, including:
* - the list of tracks and their properties,
Expand All @@ -28,8 +36,16 @@ export type StreamMetadataError =
* streamMetadata.onMetadata = metadata => {
* console.log(metadata);
* }
*
*/
export class StreamMetadata extends EventEmitter {
/**
* Event fired when stream state is changing
* @param state
*/
onState(state: StreamState) {
this.log('onState', state).info();
}
/**
* Event fired when the stream is closed
* @param error error description on an improper closure
Expand All @@ -55,6 +71,13 @@ export class StreamMetadata extends EventEmitter {
return this._ws.url;
}

/**
* State of the stream as indicated by the server
*/
get streamState(): StreamState {
return this._streamState;
}

/**
* Returns the {@link Connect.Params} object containing the connection parameters
*/
Expand All @@ -78,24 +101,40 @@ export class StreamMetadata extends EventEmitter {
private _ws: WebSocketReliable;
private _metadata?: Metadata;
private _connectParams: Connect.Params;
private _streamState: StreamState;
/**
* Create a new StreamMetadata instance, connects to the server using WebSocket and
* listen to metadata events.
*/
constructor(connectParams: Connect.Params) {
super();

const states = new Map<string, StreamState>();
for (const state of Object.values(StreamState)) {
states.set(state, state);
}
// Server can server the following text to indicate a unknown status
states.set('Stream status is unknown?!', StreamState.UNKNOWN);

this._connectParams = connectParams;
this._streamState = StreamState.UNKNOWN;
this._ws = new WebSocketReliable(Connect.buildURL(Connect.Type.META, connectParams));
this._ws.onClose = (error?: WebSocketReliableError) => this.close(error);
this._ws.onMessage = (message: string) => {
try {
const data = JSON.parse(message);
if (data.error) {
// Unrecoverable issue!
this.close({ type: 'StreamMetadataError', name: data.error, stream: connectParams.streamName });
const state = states.get(data.error);
if (state) {
this.onState((this._streamState = state));
} else {
// Unrecoverable issue!
this.close({ type: 'StreamMetadataError', name: data.error, stream: connectParams.streamName });
}
return;
}

// Metadata
this._metadata = new Metadata();
this._metadata.type = data.type;
this._metadata.width = data.width;
Expand Down Expand Up @@ -135,6 +174,8 @@ export class StreamMetadata extends EventEmitter {
for (const track of tracks) {
this._metadata.tracks.set(track.idx, track);
}
// SUCCESS
this.onState((this._streamState = StreamState.ONLINE));
} catch (e) {
this.log(Util.stringify(e)).error();
return;
Expand Down

0 comments on commit e884225

Please sign in to comment.