Using common events
This commit is contained in:
		
							
								
								
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -14,6 +14,10 @@ | |||||||
|             "version": "1.0.2", |             "version": "1.0.2", | ||||||
|             "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", |             "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", | ||||||
|             "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=" |             "integrity": "sha1-sffn/HPSXn/R1FWtyU4UODAYK1o=" | ||||||
|  |         }, | ||||||
|  |         "node-common": { | ||||||
|  |             "version": "git+ssh://git@thebword.ddns.net:3122/watsonb8/node-common.git#3ee1400be94851335e822916861ea2eddb9e344f", | ||||||
|  |             "from": "git+ssh://git@thebword.ddns.net:3122/watsonb8/node-common.git" | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,7 +18,8 @@ | |||||||
|     "author": "Brandon Watson", |     "author": "Brandon Watson", | ||||||
|     "license": "ISC", |     "license": "ISC", | ||||||
|     "dependencies": { |     "dependencies": { | ||||||
|         "child_process": "^1.0.2" |         "child_process": "^1.0.2", | ||||||
|  |         "node-common": "git+ssh://git@thebword.ddns.net:3122/watsonb8/node-common.git" | ||||||
|     }, |     }, | ||||||
|     "devDependencies": { |     "devDependencies": { | ||||||
|         "@types/node": "^14.14.6" |         "@types/node": "^14.14.6" | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								src/index.ts
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								src/index.ts
									
									
									
									
									
								
							| @@ -2,11 +2,24 @@ import { ChildProcess, spawn } from "child_process"; | |||||||
| import { EventEmitter } from "events"; | import { EventEmitter } from "events"; | ||||||
| import { Writable } from "stream"; | import { Writable } from "stream"; | ||||||
| import { IOptions } from "./options"; | import { IOptions } from "./options"; | ||||||
|  | import { Event } from "common/events"; | ||||||
|  |  | ||||||
| const ef1 = "ff"; | const ef1 = "ff"; | ||||||
| const ef2 = "d9"; | const ef2 = "d9"; | ||||||
|  |  | ||||||
| export class Rtsp extends EventEmitter { | export interface IStreamEventArgs { | ||||||
|  |   data: Buffer; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface ICloseEventArgs { | ||||||
|  |   message: string; | ||||||
|  | } | ||||||
|  | export interface IErrorEventArgs { | ||||||
|  |   message?: string; | ||||||
|  |   err?: Error; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export class Rtsp { | ||||||
|   private _connecteionString: string; |   private _connecteionString: string; | ||||||
|   private _childProcess: ChildProcess | undefined; |   private _childProcess: ChildProcess | undefined; | ||||||
|   private _started: boolean; |   private _started: boolean; | ||||||
| @@ -14,14 +27,20 @@ export class Rtsp extends EventEmitter { | |||||||
|   private _options: IOptions; |   private _options: IOptions; | ||||||
|   private _paused: boolean; |   private _paused: boolean; | ||||||
|  |  | ||||||
|  |   private _dataEvent: Event<this, IStreamEventArgs>; | ||||||
|  |   private _closeEvent: Event<this, ICloseEventArgs>; | ||||||
|  |   private _errorEvent: Event<this, IErrorEventArgs>; | ||||||
|  |  | ||||||
|   constructor(connectionString: string, options: IOptions) { |   constructor(connectionString: string, options: IOptions) { | ||||||
|     super(); |  | ||||||
|     this._started = false; |     this._started = false; | ||||||
|     this._connecteionString = connectionString; |     this._connecteionString = connectionString; | ||||||
|     this._childProcess = undefined; |     this._childProcess = undefined; | ||||||
|     this._buffer = Buffer.from(""); |     this._buffer = Buffer.from(""); | ||||||
|     this._options = options; |     this._options = options; | ||||||
|     this._paused = false; |     this._paused = false; | ||||||
|  |     this._dataEvent = new Event(); | ||||||
|  |     this._closeEvent = new Event(); | ||||||
|  |     this._errorEvent = new Event(); | ||||||
|  |  | ||||||
|     this.onData = this.onData.bind(this); |     this.onData = this.onData.bind(this); | ||||||
|   } |   } | ||||||
| @@ -34,6 +53,18 @@ export class Rtsp extends EventEmitter { | |||||||
|     return this._paused; |     return this._paused; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   public get dataEvent(): Event<this, IStreamEventArgs> { | ||||||
|  |     return this._dataEvent; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public get closeEvent(): Event<this, ICloseEventArgs> { | ||||||
|  |     return this._closeEvent; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   public get errorEvent(): Event<this, IErrorEventArgs> { | ||||||
|  |     return this._errorEvent; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   public start(): void { |   public start(): void { | ||||||
|     const argStrings = [ |     const argStrings = [ | ||||||
|       `-i ${this._connecteionString}`, |       `-i ${this._connecteionString}`, | ||||||
| @@ -51,17 +82,24 @@ export class Rtsp extends EventEmitter { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     this._childProcess.stdout?.on("data", this.onData); |     this._childProcess.stdout?.on("data", this.onData); | ||||||
|     this._childProcess.on("exit", this.onExit); |     this._childProcess.on("exit", (code: number, signal: NodeJS.Signals) => | ||||||
|     this._childProcess.on("error", this.onError); |       this._closeEvent.fire(this, { | ||||||
|  |         message: "FFmpeg exited with code: " + code + " and signal: " + signal, | ||||||
|  |       }) | ||||||
|  |     ); | ||||||
|  |     this._childProcess.on("error", (error: Error) => | ||||||
|  |       this._errorEvent.fire(this, { err: error }) | ||||||
|  |     ); | ||||||
|  |  | ||||||
|     if (this._childProcess.stderr) { |     //Only register this event if there are subscribers | ||||||
|       //   this._childProcess.stderr.on("data", this.onStdErrorData); |     if (this._childProcess.stderr && this._errorEvent.length > 0) { | ||||||
|  |       this._childProcess.stderr.on("data", this.onStdErrorData); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public close(): void { |   public close(): void { | ||||||
|     this._childProcess && this._childProcess.kill("SIGKILL"); |     this._childProcess && this._childProcess.kill("SIGKILL"); | ||||||
|     this.emit("closed"); |     this._closeEvent.fire(this, { message: "Process killed by user" }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   public pause(): void { |   public pause(): void { | ||||||
| @@ -76,10 +114,6 @@ export class Rtsp extends EventEmitter { | |||||||
|     return this._childProcess ? this._childProcess.stdin : null; |     return this._childProcess ? this._childProcess.stdin : null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private onError = (err: Error): void => { |  | ||||||
|     this.emit("error", new Error("Failed to start stream: " + err.message)); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   private onStdErrorData = (data: any): void => { |   private onStdErrorData = (data: any): void => { | ||||||
|     if (!this._started) { |     if (!this._started) { | ||||||
|       this._started = true; |       this._started = true; | ||||||
| @@ -92,13 +126,7 @@ export class Rtsp extends EventEmitter { | |||||||
|         msg += `${line}\n`; |         msg += `${line}\n`; | ||||||
|       }); |       }); | ||||||
|  |  | ||||||
|     this.emit("error", msg); |     this._errorEvent.fire(this, { message: msg }); | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   private onExit = (code: number, signal: NodeJS.Signals): void => { |  | ||||||
|     const message = |  | ||||||
|       "FFmpeg exited with code: " + code + " and signal: " + signal; |  | ||||||
|     this.emit("closed", message); |  | ||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   private onData(data: Buffer): void { |   private onData(data: Buffer): void { | ||||||
| @@ -111,7 +139,7 @@ export class Rtsp extends EventEmitter { | |||||||
|         data[data.length - 2].toString(16) == ef1 && |         data[data.length - 2].toString(16) == ef1 && | ||||||
|         data[data.length - 1].toString(16) == ef2 |         data[data.length - 1].toString(16) == ef2 | ||||||
|       ) { |       ) { | ||||||
|         this.emit("data", this._buffer); |         this._dataEvent.fire(this, { data: this._buffer }); | ||||||
|         this._buffer = Buffer.from(""); |         this._buffer = Buffer.from(""); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2,19 +2,19 @@ | |||||||
|   "compilerOptions": { |   "compilerOptions": { | ||||||
|     /* Basic Options */ |     /* Basic Options */ | ||||||
|     // "incremental": true,                   /* Enable incremental compilation */ |     // "incremental": true,                   /* Enable incremental compilation */ | ||||||
|         "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ |     "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, | ||||||
|         "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ |     "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, | ||||||
|     // "lib": [],                             /* Specify library files to be included in the compilation. */ |     // "lib": [],                             /* Specify library files to be included in the compilation. */ | ||||||
|     // "allowJs": true,                       /* Allow javascript files to be compiled. */ |     // "allowJs": true,                       /* Allow javascript files to be compiled. */ | ||||||
|     // "checkJs": true,                       /* Report errors in .js files. */ |     // "checkJs": true,                       /* Report errors in .js files. */ | ||||||
|     // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ |     // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ | ||||||
|     // "declaration": true,                   /* Generates corresponding '.d.ts' file. */ |     // "declaration": true,                   /* Generates corresponding '.d.ts' file. */ | ||||||
|     // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */ |     // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||||||
|         "sourceMap": true, /* Generates corresponding '.map' file. */ |     "sourceMap": true /* Generates corresponding '.map' file. */, | ||||||
|     // "outFile": "./",                       /* Concatenate and emit output to single file. */ |     // "outFile": "./",                       /* Concatenate and emit output to single file. */ | ||||||
|         "outDir": "./lib", /* Redirect output structure to the directory. */ |     "outDir": "./lib" /* Redirect output structure to the directory. */, | ||||||
|         "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ |     "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, | ||||||
|         "composite": true,                     /* Enable project compilation */ |     "composite": true /* Enable project compilation */, | ||||||
|     // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */ |     // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */ | ||||||
|     // "removeComments": true,                /* Do not emit comments to output. */ |     // "removeComments": true,                /* Do not emit comments to output. */ | ||||||
|     // "noEmit": true,                        /* Do not emit outputs. */ |     // "noEmit": true,                        /* Do not emit outputs. */ | ||||||
| @@ -22,10 +22,10 @@ | |||||||
|     // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ |     // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ | ||||||
|     // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ |     // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ | ||||||
|     /* Strict Type-Checking Options */ |     /* Strict Type-Checking Options */ | ||||||
|         "strict": true, /* Enable all strict type-checking options. */ |     "strict": true /* Enable all strict type-checking options. */, | ||||||
|         "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ |     "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */, | ||||||
|     // "strictNullChecks": true,              /* Enable strict null checks. */ |     // "strictNullChecks": true,              /* Enable strict null checks. */ | ||||||
|         "strictFunctionTypes": true, /* Enable strict checking of function types. */ |     "strictFunctionTypes": true /* Enable strict checking of function types. */, | ||||||
|     // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ |     // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ | ||||||
|     // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */ |     // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */ | ||||||
|     // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */ |     // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */ | ||||||
| @@ -33,17 +33,19 @@ | |||||||
|     /* Additional Checks */ |     /* Additional Checks */ | ||||||
|     // "noUnusedLocals": true,                /* Report errors on unused locals. */ |     // "noUnusedLocals": true,                /* Report errors on unused locals. */ | ||||||
|     // "noUnusedParameters": true,            /* Report errors on unused parameters. */ |     // "noUnusedParameters": true,            /* Report errors on unused parameters. */ | ||||||
|         "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ |     "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, | ||||||
|         "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ |     "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, | ||||||
|     /* Module Resolution Options */ |     /* Module Resolution Options */ | ||||||
|     // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ |     // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||||||
|         // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */ |     "baseUrl": "./" /* Base directory to resolve non-absolute module names. */, | ||||||
|         // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ |     "paths": { | ||||||
|  |       "common/*": ["./node_modules/node-common/lib/*"] | ||||||
|  |     } /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */, | ||||||
|     // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */ |     // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */ | ||||||
|     // "typeRoots": [],                       /* List of folders to include type definitions from. */ |     // "typeRoots": [],                       /* List of folders to include type definitions from. */ | ||||||
|     // "types": [],                           /* Type declaration files to be included in compilation. */ |     // "types": [],                           /* Type declaration files to be included in compilation. */ | ||||||
|     // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ |     // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ | ||||||
|         "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ |     "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, | ||||||
|     // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */ |     // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */ | ||||||
|     // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */ |     // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */ | ||||||
|     /* Source Map Options */ |     /* Source Map Options */ | ||||||
| @@ -56,5 +58,10 @@ | |||||||
|     // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */ |     // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */ | ||||||
|     /* Advanced Options */ |     /* Advanced Options */ | ||||||
|     "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ |     "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ | ||||||
|  |   }, | ||||||
|  |   "references": [ | ||||||
|  |     { | ||||||
|  |       "path": "./node_modules/node-common/tsconfig.json" | ||||||
|     } |     } | ||||||
|  |   ] | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user