diff --git a/lib/Application.js b/lib/Application.js index 3b56fe9..0ebdaff 100644 --- a/lib/Application.js +++ b/lib/Application.js @@ -3,6 +3,13 @@ const Client = require("./Client.js"); const Emitter = require("medooze-event-emitter"); const SharedPointer = require("./SharedPointer.js") +/** + * @typedef {Object} ApplicationEvents + * @property {(self: Application) => void} stopped + * @property {(client: Client) => void} connect + */ + +/** @extends {Emitter} */ class Application extends Emitter { constructor() @@ -14,16 +21,21 @@ class Application extends Emitter this.application = new Native.RTMPApplicationImpl(this); //Client map - this.clients = new Map(); + this.clients = /** @type {Map} */ (new Map()); //The event handler - this.onconnect = (peerIp,peerPort,appName,conn) =>{ + this.onconnect = ( + /** @type {string} */ peerIp, + /** @type {number} */ peerPort, + /** @type {string} */ appName, + /** @type {Native.RTMPNetConnectionImplShared} */ conn, + ) =>{ //Create new connection const client = new Client(SharedPointer(conn),peerIp,peerPort,appName); //Add to client list this.clients.set(client.getId(),client); //event handlers - client.once("stopped",(client)=>{ + client.once("stopped",()=>{ //Remove client from map this.clients.delete(client.getId()); }); diff --git a/lib/Client.js b/lib/Client.js index 4a78531..beb7356 100644 --- a/lib/Client.js +++ b/lib/Client.js @@ -1,11 +1,24 @@ -const uuidV4 = require("uuid/v4"); +const { v4: uuidV4 } = require("uuid"); const Emitter = require("medooze-event-emitter"); const Stream = require("./Stream"); -const SharedPointer = require("./SharedPointer.js") +const SharedPointer = require("./SharedPointer.js"); +const Native = require("./Native"); + +/** + * @typedef {Object} ClientEvents + * @property {(self: Client) => void} stopped + * @property {(stream: Stream) => void} stream + */ + +/** @extends {Emitter} */ class Client extends Emitter { - constructor(connection,peerIp,peerPort,appName) + constructor( + /** @type {Native.RTMPNetConnectionImpl} */ connection, + /** @type {string} */ peerIp, + /** @type {number} */ peerPort, + /** @type {string} */ appName) { //Init emitter super(); @@ -19,12 +32,12 @@ class Client extends Emitter //Store native connection this.connection = connection; //Map of streams - this.streams = new Map(); + this.streams = /** @type {Map} */ (new Map()); //Ids this.maxId = 0; //Events - this.onstream = (netstream)=>{ + this.onstream = (/** @type {Native.RTMPNetStreamImplShared} */ netstream)=>{ //Create stream wrapper const stream = new Stream(SharedPointer(netstream)); //New id @@ -41,6 +54,7 @@ class Client extends Emitter }; this.ondisconnect = ()=>{ //NO connection anymore + //@ts-expect-error this.connection = false; //Stop us this.stop(); @@ -96,7 +110,9 @@ class Client extends Emitter //Stop emitter super.stop(); //Release mem + //@ts-expect-error this.connection = null; + //@ts-expect-error this.streams = null; } } diff --git a/lib/IncomingStreamBridge.js b/lib/IncomingStreamBridge.js index f30a8c0..f9bb157 100644 --- a/lib/IncomingStreamBridge.js +++ b/lib/IncomingStreamBridge.js @@ -1,21 +1,30 @@ -const uuidV4 = require("uuid/v4"); +const { v4: uuidV4 } = require("uuid"); const Native = require("./Native"); const Emitter = require("medooze-event-emitter"); const SharedPointer = require("./SharedPointer"); const IncomingStreamTrackBridge = require("./IncomingStreamTrackBridge"); +//@ts-expect-error +const parseInt = /** @type {(x: number) => number} */ (global.parseInt); + +/** @typedef {IncomingStreamTrackBridge.TrackStats} TrackStats */ +/** @typedef {{ [trackId: string]: TrackStats }} StreamStats */ + +/** + * @typedef {Object} IncomingStreamBridgeEvents + * @property {(self: IncomingStreamBridge) => void} stopped + * @property {(config: string) => void} aacconfig aac specific config received + */ /** * The incoming streams represent the recived media stream from a remote peer. + * @extends {Emitter} */ class IncomingStreamBridge extends Emitter { - /** - * @ignore - * @hideconstructor - * private constructor - */ - constructor(maxLateOffset, maxBufferingTime) + constructor( + /** @type {number} */ maxLateOffset, + /** @type {number} */ maxBufferingTime) { //Init emitter super(); @@ -26,27 +35,19 @@ class IncomingStreamBridge extends Emitter this.bridge = new Native.IncomingStreamBridge(this, parseInt(maxLateOffset), parseInt(maxBufferingTime)); //Store sources - this.tracks = new Map(); + this.tracks = /** @type {Map} */ (new Map()); //Create audio and video tracks this.tracks.set("audio",new IncomingStreamTrackBridge("audio","audio",SharedPointer(this.bridge.GetAudio()))); this.tracks.set("video",new IncomingStreamTrackBridge("video","video",SharedPointer(this.bridge.GetVideo()))); //Listen for aac config - this.onaacconfig = (config)=>{ - /** - * IncomingStreamBridge aac specific config received - * - * @name aacconfig - * @memberof IncomingStreamBridge - * @kind event - * @argument {String} config - */ + this.onaacconfig = (/** @type {string} */ config)=>{ this.emit("aacconfig", config); }; //Event listeners - this.onstreamstopped = (stream)=>{ + this.onstreamstopped = (/** @type {import("./Stream")} */ stream)=>{ //If it is the same as ours if (this.stream===stream) //Dettach @@ -67,12 +68,10 @@ class IncomingStreamBridge extends Emitter * Get statistics for all tracks in the stream * * See OutgoingStreamTrack.getStats for information about the stats returned by each track. - * - * @returns {Map,Object} Map with stats by trackId */ getStats() { - const stats = {}; + const stats = /** @type {StreamStats} */ ({}); //for each track for (let track of this.tracks.values()) @@ -85,7 +84,7 @@ class IncomingStreamBridge extends Emitter /** * Get track by id * @param {String} trackId - The track id - * @returns {IncomingStreamTrack} - requested track or null + * @returns {IncomingStreamTrackBridge | undefined} */ getTrack(trackId) { @@ -95,7 +94,7 @@ class IncomingStreamBridge extends Emitter /** * Get all the tracks - * @returns {Array} - Array of tracks + * @returns {Array} - Array of tracks */ getTracks() { @@ -104,11 +103,11 @@ class IncomingStreamBridge extends Emitter } /** * Get an array of the media stream audio tracks - * @returns {Array} - Array of tracks + * @returns {Array} - Array of tracks */ getAudioTracks() { - var audio = []; + var audio = /** @type {IncomingStreamTrackBridge[]} */ ([]); //For each track for (let track of this.tracks.values()) @@ -122,11 +121,11 @@ class IncomingStreamBridge extends Emitter /** * Get an array of the media stream video tracks - * @returns {Array} - Array of tracks + * @returns {Array} - Array of tracks */ getVideoTracks() { - var video = []; + var video = /** @type {IncomingStreamTrackBridge[]} */ ([]); //For each track for (let track of this.tracks.values()) @@ -152,7 +151,7 @@ class IncomingStreamBridge extends Emitter this.stream = null; } - attachTo(stream) + attachTo(/** @type {import("./Stream")} */ stream) { //Dettach just in case this.dettach(); @@ -207,6 +206,7 @@ class IncomingStreamBridge extends Emitter super.stop(); //Remove brdige reference, so destructor is called on GC + //@ts-expect-error this.bridge = null; } } diff --git a/lib/RTMPServer.js b/lib/RTMPServer.js index 23d282d..9797bf2 100644 --- a/lib/RTMPServer.js +++ b/lib/RTMPServer.js @@ -3,8 +3,13 @@ const Server = require("./Server.js"); const Application = require("./Application.js"); const Status = require("./Status.js"); const IncomingStreamBridge = require("./IncomingStreamBridge"); + +/** @typedef {import("./Status").Status} Status */ + /** @namespace */ -const RTMPServer = Status; +const RTMPServer = {}; +RTMPServer.NetStream = Status.NetStream; +RTMPServer.NetConnection = Status.NetConnection; //INitialize Stuff Native.RTMPServerModule.Initialize(); @@ -49,7 +54,7 @@ RTMPServer.enableDebug = function(flag) * @memberof RTMPServer * @param {Boolean} flag */ -RTMPServer.enableUltraDebug = function(flag) +RTMPServer.enableUltraDebug = function(/** @type {boolean} */ flag) { //Set flag Native.RTMPServerModule.EnableUltraDebug(flag); @@ -82,7 +87,7 @@ RTMPServer.createIncomingStreamBridge = function() /** * Create a new application * @memberof RTMPServer - * @returns {Applicaton} The new created application + * @returns {Application} The new created application */ RTMPServer.createApplication = function() { diff --git a/lib/Server.js b/lib/Server.js index c82dfc1..8bd520e 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -1,5 +1,7 @@ const Native = require("./Native.js"); +/** @typedef {import("./Application")} Application */ + class Server { constructor() @@ -8,13 +10,15 @@ class Server this.server = new Native.RTMPServerFacade(this); } - start(port) + start(/** @type {number} */ port) { //Create native server this.server.Start(port); } - addApplication(name,app) + addApplication( + /** @type {string} */ name, + /** @type {Application} */ app) { //Add to server this.server.AddApplication(name,app.application); @@ -26,6 +30,7 @@ class Server this.server.Stop(); //Release mem + //@ts-expect-error this.server = null; } } diff --git a/lib/Status.js b/lib/Status.js index 20ea283..ba3768d 100644 --- a/lib/Status.js +++ b/lib/Status.js @@ -1,6 +1,8 @@ class Status { - constructor(code,level) + constructor( + /** @type {string} */ code, + /** @type {string} */ level) { this.code = code; this.level = level; @@ -10,6 +12,7 @@ class Status module.exports = { + Status, NetConnection: { Call: diff --git a/lib/Stream.js b/lib/Stream.js index 44f1bc6..0620d1c 100644 --- a/lib/Stream.js +++ b/lib/Stream.js @@ -1,11 +1,29 @@ const Emitter = require("medooze-event-emitter"); const Status = require("./Status"); -const IncomingStreamBridge = require("./IncomingStreamBridge") +const IncomingStreamBridge = require("./IncomingStreamBridge"); +const Native = require("./Native"); +/** + * @typedef {unknown} AMFData + * a serialized AMF value (see toJson in C++ code) + */ +/** + * @typedef {Object} Command + * @property {string} name + * @property {AMFData} params + */ + +/** + * @typedef {Object} StreamEvents + * @property {(self: Stream) => void} stopped + * @property {(cmd: Command, transId: number, ...extra: AMFData[]) => void} cmd + */ + +/** @extends {Emitter} */ class Stream extends Emitter { - constructor(stream) + constructor(/** @type {Native.RTMPNetStreamImpl} */ stream) { //Intit emitted super(); @@ -15,7 +33,12 @@ class Stream extends Emitter this.stream = stream; //On command listener - this.oncmd = (name,params,...extra) => { + this.oncmd = ( + /** @type {string} */ name, + /** @type {AMFData} */ params, + /** @type {number} */ transId, + /** @type {AMFData[]} */ ...extra + ) => { //Launch async so we can set listeners safely setTimeout(()=>{ try @@ -26,7 +49,7 @@ class Stream extends Emitter this.emit("cmd",{ name : name, params : params - },...extra); + },transId,...extra); } catch(e){ //Ignore } @@ -47,13 +70,18 @@ class Stream extends Emitter return this.id; } - sendStatus(transId, status,desc) + sendStatus( + /** @type {number} */ transId, + /** @type {import("./Status").Status} */ status, + /** @type {string | undefined} */ desc = undefined) { //Send it this.stream.SendStatus(transId,status.code,status.level,desc || status.code); } - createIncomingStreamBridge(maxLateOffset, maxBufferingTime) + createIncomingStreamBridge( + /** @type {number | undefined} */ maxLateOffset = undefined, + /** @type {number | undefined} */ maxBufferingTime = undefined) { if (maxLateOffset === undefined) maxLateOffset = 200; if (maxBufferingTime === undefined) maxBufferingTime = 600; @@ -80,14 +108,6 @@ class Stream extends Emitter //Remove us as listener this.stream.ResetListener(); - /** - * IncomingStream stopped event - * - * @name stopped - * @memberof IncomingStream - * @kind event - * @argument {IncomingStream} incomingStream - */ this.emit("stopped", this); //Stop stream @@ -97,6 +117,7 @@ class Stream extends Emitter super.stop(); //Stop listener + //@ts-expect-error this.stream = null; } }