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", | ||||
|             "resolved": "https://registry.npmjs.org/child_process/-/child_process-1.0.2.tgz", | ||||
|             "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", | ||||
|     "license": "ISC", | ||||
|     "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": { | ||||
|         "@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 { Writable } from "stream"; | ||||
| import { IOptions } from "./options"; | ||||
| import { Event } from "common/events"; | ||||
|  | ||||
| const ef1 = "ff"; | ||||
| 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 _childProcess: ChildProcess | undefined; | ||||
|   private _started: boolean; | ||||
| @@ -14,14 +27,20 @@ export class Rtsp extends EventEmitter { | ||||
|   private _options: IOptions; | ||||
|   private _paused: boolean; | ||||
|  | ||||
|   private _dataEvent: Event<this, IStreamEventArgs>; | ||||
|   private _closeEvent: Event<this, ICloseEventArgs>; | ||||
|   private _errorEvent: Event<this, IErrorEventArgs>; | ||||
|  | ||||
|   constructor(connectionString: string, options: IOptions) { | ||||
|     super(); | ||||
|     this._started = false; | ||||
|     this._connecteionString = connectionString; | ||||
|     this._childProcess = undefined; | ||||
|     this._buffer = Buffer.from(""); | ||||
|     this._options = options; | ||||
|     this._paused = false; | ||||
|     this._dataEvent = new Event(); | ||||
|     this._closeEvent = new Event(); | ||||
|     this._errorEvent = new Event(); | ||||
|  | ||||
|     this.onData = this.onData.bind(this); | ||||
|   } | ||||
| @@ -34,6 +53,18 @@ export class Rtsp extends EventEmitter { | ||||
|     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 { | ||||
|     const argStrings = [ | ||||
|       `-i ${this._connecteionString}`, | ||||
| @@ -51,17 +82,24 @@ export class Rtsp extends EventEmitter { | ||||
|     } | ||||
|  | ||||
|     this._childProcess.stdout?.on("data", this.onData); | ||||
|     this._childProcess.on("exit", this.onExit); | ||||
|     this._childProcess.on("error", this.onError); | ||||
|     this._childProcess.on("exit", (code: number, signal: NodeJS.Signals) => | ||||
|       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) { | ||||
|       //   this._childProcess.stderr.on("data", this.onStdErrorData); | ||||
|     //Only register this event if there are subscribers | ||||
|     if (this._childProcess.stderr && this._errorEvent.length > 0) { | ||||
|       this._childProcess.stderr.on("data", this.onStdErrorData); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public close(): void { | ||||
|     this._childProcess && this._childProcess.kill("SIGKILL"); | ||||
|     this.emit("closed"); | ||||
|     this._closeEvent.fire(this, { message: "Process killed by user" }); | ||||
|   } | ||||
|  | ||||
|   public pause(): void { | ||||
| @@ -76,10 +114,6 @@ export class Rtsp extends EventEmitter { | ||||
|     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 => { | ||||
|     if (!this._started) { | ||||
|       this._started = true; | ||||
| @@ -92,13 +126,7 @@ export class Rtsp extends EventEmitter { | ||||
|         msg += `${line}\n`; | ||||
|       }); | ||||
|  | ||||
|     this.emit("error", msg); | ||||
|   }; | ||||
|  | ||||
|   private onExit = (code: number, signal: NodeJS.Signals): void => { | ||||
|     const message = | ||||
|       "FFmpeg exited with code: " + code + " and signal: " + signal; | ||||
|     this.emit("closed", message); | ||||
|     this._errorEvent.fire(this, { message: msg }); | ||||
|   }; | ||||
|  | ||||
|   private onData(data: Buffer): void { | ||||
| @@ -111,7 +139,7 @@ export class Rtsp extends EventEmitter { | ||||
|         data[data.length - 2].toString(16) == ef1 && | ||||
|         data[data.length - 1].toString(16) == ef2 | ||||
|       ) { | ||||
|         this.emit("data", this._buffer); | ||||
|         this._dataEvent.fire(this, { data: this._buffer }); | ||||
|         this._buffer = Buffer.from(""); | ||||
|       } | ||||
|     } | ||||
|   | ||||
							
								
								
									
										121
									
								
								tsconfig.json
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								tsconfig.json
									
									
									
									
									
								
							| @@ -1,60 +1,67 @@ | ||||
| { | ||||
|     "compilerOptions": { | ||||
|         /* Basic Options */ | ||||
|         // "incremental": true,                   /* Enable incremental compilation */ | ||||
|         "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'. */ | ||||
|         // "lib": [],                             /* Specify library files to be included in the compilation. */ | ||||
|         // "allowJs": true,                       /* Allow javascript files to be compiled. */ | ||||
|         // "checkJs": true,                       /* Report errors in .js files. */ | ||||
|         // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ | ||||
|         // "declaration": true,                   /* Generates corresponding '.d.ts' file. */ | ||||
|         // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||||
|         "sourceMap": true, /* Generates corresponding '.map' file. */ | ||||
|         // "outFile": "./",                       /* Concatenate and emit output to single file. */ | ||||
|         "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. */ | ||||
|         "composite": true,                     /* Enable project compilation */ | ||||
|         // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */ | ||||
|         // "removeComments": true,                /* Do not emit comments to output. */ | ||||
|         // "noEmit": true,                        /* Do not emit outputs. */ | ||||
|         // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */ | ||||
|         // "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'). */ | ||||
|         /* 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. */ | ||||
|         // "strictNullChecks": true,              /* Enable strict null checks. */ | ||||
|         "strictFunctionTypes": true, /* Enable strict checking of function types. */ | ||||
|         // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ | ||||
|         // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */ | ||||
|         // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */ | ||||
|         // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */ | ||||
|         /* Additional Checks */ | ||||
|         // "noUnusedLocals": true,                /* Report errors on unused locals. */ | ||||
|         // "noUnusedParameters": true,            /* Report errors on unused parameters. */ | ||||
|         "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ | ||||
|         "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ | ||||
|         /* Module Resolution Options */ | ||||
|         // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||||
|         // "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'. */ | ||||
|         // "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. */ | ||||
|         // "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. */ | ||||
|         "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. */ | ||||
|         // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */ | ||||
|         /* Source Map Options */ | ||||
|         // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */ | ||||
|         // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */ | ||||
|         // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */ | ||||
|         // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||||
|         /* Experimental Options */ | ||||
|         // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */ | ||||
|         // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */ | ||||
|         /* Advanced Options */ | ||||
|         "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ | ||||
|   "compilerOptions": { | ||||
|     /* Basic Options */ | ||||
|     // "incremental": true,                   /* Enable incremental compilation */ | ||||
|     "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'. */, | ||||
|     // "lib": [],                             /* Specify library files to be included in the compilation. */ | ||||
|     // "allowJs": true,                       /* Allow javascript files to be compiled. */ | ||||
|     // "checkJs": true,                       /* Report errors in .js files. */ | ||||
|     // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ | ||||
|     // "declaration": true,                   /* Generates corresponding '.d.ts' file. */ | ||||
|     // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */ | ||||
|     "sourceMap": true /* Generates corresponding '.map' file. */, | ||||
|     // "outFile": "./",                       /* Concatenate and emit output to single file. */ | ||||
|     "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. */, | ||||
|     "composite": true /* Enable project compilation */, | ||||
|     // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */ | ||||
|     // "removeComments": true,                /* Do not emit comments to output. */ | ||||
|     // "noEmit": true,                        /* Do not emit outputs. */ | ||||
|     // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */ | ||||
|     // "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'). */ | ||||
|     /* 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. */, | ||||
|     // "strictNullChecks": true,              /* Enable strict null checks. */ | ||||
|     "strictFunctionTypes": true /* Enable strict checking of function types. */, | ||||
|     // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ | ||||
|     // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */ | ||||
|     // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */ | ||||
|     // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */ | ||||
|     /* Additional Checks */ | ||||
|     // "noUnusedLocals": true,                /* Report errors on unused locals. */ | ||||
|     // "noUnusedParameters": true,            /* Report errors on unused parameters. */ | ||||
|     "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, | ||||
|     "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, | ||||
|     /* Module Resolution Options */ | ||||
|     // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ | ||||
|     "baseUrl": "./" /* Base directory to resolve non-absolute module names. */, | ||||
|     "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. */ | ||||
|     // "typeRoots": [],                       /* List of folders to include type definitions from. */ | ||||
|     // "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. */ | ||||
|     "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. */ | ||||
|     // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */ | ||||
|     /* Source Map Options */ | ||||
|     // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */ | ||||
|     // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */ | ||||
|     // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */ | ||||
|     // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||||
|     /* Experimental Options */ | ||||
|     // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */ | ||||
|     // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */ | ||||
|     /* Advanced Options */ | ||||
|     "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