camstreamerlib 3.2.4 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CamOverlayPainter/Frame.d.ts +43 -16
- package/CamOverlayPainter/Frame.js +160 -51
- package/CamOverlayPainter/Painter.d.ts +13 -10
- package/CamOverlayPainter/Painter.js +90 -29
- package/CameraVapix.d.ts +3 -3
- package/CameraVapix.js +30 -49
- package/DefaultAgent.js +1 -1
- package/README.md +1 -1
- package/package.json +1 -1
|
@@ -1,50 +1,74 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import { CamOverlayDrawingAPI, TAlign, TCairoCreateResponse, TUploadImageResponse } from '../CamOverlayDrawingAPI';
|
|
2
4
|
import ResourceManager from './ResourceManager';
|
|
3
5
|
export type TRgb = [number, number, number];
|
|
4
6
|
export type TRgba = [number, number, number, number];
|
|
5
7
|
export type TTmf = 'TFM_OVERFLOW' | 'TFM_SCALE' | 'TFM_TRUNCATE';
|
|
6
8
|
export type TObjectFitType = 'fill' | 'fit' | 'none';
|
|
7
|
-
export type
|
|
9
|
+
export type TFrameOptions = {
|
|
10
|
+
enabled?: boolean;
|
|
8
11
|
x: number;
|
|
9
12
|
y: number;
|
|
10
13
|
width: number;
|
|
11
14
|
height: number;
|
|
12
|
-
enabled?: boolean;
|
|
13
|
-
bgImage?: string;
|
|
14
15
|
text?: string;
|
|
15
16
|
fontColor?: TRgb;
|
|
17
|
+
font?: string;
|
|
16
18
|
bgColor?: TRgba;
|
|
19
|
+
bgImage?: string;
|
|
17
20
|
bgType?: TObjectFitType;
|
|
21
|
+
borderRadius?: number;
|
|
22
|
+
borderWidth?: number;
|
|
23
|
+
borderColor?: TRgba;
|
|
24
|
+
customDraw?: TDrawingCallback;
|
|
25
|
+
layer?: number;
|
|
18
26
|
};
|
|
19
27
|
export type TFrameInfo = {
|
|
20
28
|
width: number;
|
|
21
29
|
height: number;
|
|
22
30
|
};
|
|
23
31
|
export type TDrawingCallback = (cod: CamOverlayDrawingAPI, cairo: string, info: TFrameInfo) => Promise<void>;
|
|
24
|
-
export
|
|
25
|
-
|
|
32
|
+
export interface Frame {
|
|
33
|
+
on(event: 'layoutChanged', listener: () => void): this;
|
|
34
|
+
emit(event: 'layoutChanged'): boolean;
|
|
35
|
+
}
|
|
36
|
+
export declare class Frame extends EventEmitter {
|
|
37
|
+
protected enabled: boolean;
|
|
26
38
|
protected posX: number;
|
|
27
39
|
protected posY: number;
|
|
28
40
|
protected width: number;
|
|
29
41
|
protected height: number;
|
|
30
|
-
protected enabled: boolean;
|
|
31
42
|
private text;
|
|
43
|
+
private fontColor;
|
|
44
|
+
private font?;
|
|
32
45
|
private align;
|
|
33
46
|
private textType;
|
|
34
|
-
private fontColor;
|
|
35
|
-
private fontName?;
|
|
36
47
|
private bgColor?;
|
|
37
48
|
private bgImage?;
|
|
38
49
|
private bgType?;
|
|
50
|
+
private borderRadius;
|
|
51
|
+
private borderWidth;
|
|
52
|
+
private borderColor;
|
|
53
|
+
private customDraw?;
|
|
54
|
+
private layer;
|
|
39
55
|
protected children: Frame[];
|
|
40
|
-
constructor(opt:
|
|
56
|
+
constructor(opt: TFrameOptions);
|
|
57
|
+
enable(): void;
|
|
58
|
+
disable(): void;
|
|
41
59
|
setFramePosition(x: number, y: number): void;
|
|
42
60
|
setFrameSize(width: number, height: number): void;
|
|
43
|
-
setText(text: string, align: TAlign, textType?: TTmf,
|
|
61
|
+
setText(text: string, align: TAlign, textType?: TTmf, fontColor?: TRgb): void;
|
|
62
|
+
setFontColor(fontColor: TRgb): void;
|
|
44
63
|
setFont(fontName: string): void;
|
|
64
|
+
setFontData(fontData: TCairoCreateResponse): void;
|
|
45
65
|
setBgColor(color: TRgba): void;
|
|
46
66
|
setBgImage(imageName: string, type?: TObjectFitType): void;
|
|
47
67
|
setBgImageData(imageData: TUploadImageResponse, type?: TObjectFitType): void;
|
|
68
|
+
setBgType(type: TObjectFitType): void;
|
|
69
|
+
setBorderRadius(radius: number): void;
|
|
70
|
+
setBorderWidth(width: number): void;
|
|
71
|
+
setBorderColor(color: TRgba): void;
|
|
48
72
|
setCustomDraw(customDraw: TDrawingCallback): void;
|
|
49
73
|
resetFont(): void;
|
|
50
74
|
resetBgColor(): void;
|
|
@@ -52,12 +76,15 @@ export default class Frame {
|
|
|
52
76
|
resetCustomDraw(): void;
|
|
53
77
|
clear(): void;
|
|
54
78
|
insert(...frames: Frame[]): void;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
displayImage(cod: CamOverlayDrawingAPI,
|
|
58
|
-
|
|
79
|
+
getLayers(): Set<number>;
|
|
80
|
+
protected layoutChanged(): void;
|
|
81
|
+
displayImage(cod: CamOverlayDrawingAPI, resourceManager: ResourceManager, cairo: string, ppX: number, ppY: number, scale: number, layer: number): Promise<void>;
|
|
82
|
+
private prepareResources;
|
|
83
|
+
protected displayOwnImage(cod: CamOverlayDrawingAPI, cairo: string, ppX: number, ppY: number, scale: number): Promise<void>;
|
|
84
|
+
private clipDrawing;
|
|
59
85
|
private drawFrame;
|
|
60
86
|
private drawImage;
|
|
61
87
|
private drawText;
|
|
88
|
+
private drawBorder;
|
|
89
|
+
private drawRectPath;
|
|
62
90
|
}
|
|
63
|
-
export { Frame };
|
|
@@ -10,24 +10,37 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.Frame = void 0;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const events_1 = require("events");
|
|
14
|
+
class Frame extends events_1.EventEmitter {
|
|
15
|
+
constructor(opt) {
|
|
16
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
17
|
+
super();
|
|
17
18
|
this.text = '';
|
|
18
19
|
this.align = 'A_LEFT';
|
|
19
20
|
this.textType = 'TFM_OVERFLOW';
|
|
20
21
|
this.children = new Array();
|
|
22
|
+
this.enabled = (_a = opt.enabled) !== null && _a !== void 0 ? _a : true;
|
|
21
23
|
this.posX = opt.x;
|
|
22
24
|
this.posY = opt.y;
|
|
23
25
|
this.width = opt.width;
|
|
24
26
|
this.height = opt.height;
|
|
25
|
-
this.enabled = (_a = opt.enabled) !== null && _a !== void 0 ? _a : true;
|
|
26
27
|
this.setText((_b = opt.text) !== null && _b !== void 0 ? _b : '', 'A_LEFT');
|
|
27
28
|
this.fontColor = (_c = opt.fontColor) !== null && _c !== void 0 ? _c : [1.0, 1.0, 1.0];
|
|
29
|
+
this.font = opt.font;
|
|
28
30
|
this.bgColor = opt.bgColor;
|
|
29
31
|
this.bgImage = opt.bgImage;
|
|
30
32
|
this.bgType = opt.bgType;
|
|
33
|
+
this.borderRadius = (_d = opt.borderRadius) !== null && _d !== void 0 ? _d : 0;
|
|
34
|
+
this.borderWidth = (_e = opt.borderWidth) !== null && _e !== void 0 ? _e : 0;
|
|
35
|
+
this.borderColor = (_f = opt.borderColor) !== null && _f !== void 0 ? _f : [1, 1, 1, 1];
|
|
36
|
+
this.customDraw = opt.customDraw;
|
|
37
|
+
this.layer = (_g = opt.layer) !== null && _g !== void 0 ? _g : 0;
|
|
38
|
+
}
|
|
39
|
+
enable() {
|
|
40
|
+
this.enabled = true;
|
|
41
|
+
}
|
|
42
|
+
disable() {
|
|
43
|
+
this.enabled = false;
|
|
31
44
|
}
|
|
32
45
|
setFramePosition(x, y) {
|
|
33
46
|
this.posX = x;
|
|
@@ -37,16 +50,22 @@ class Frame {
|
|
|
37
50
|
this.width = width;
|
|
38
51
|
this.height = height;
|
|
39
52
|
}
|
|
40
|
-
setText(text, align, textType = 'TFM_OVERFLOW',
|
|
53
|
+
setText(text, align, textType = 'TFM_OVERFLOW', fontColor) {
|
|
41
54
|
this.text = text;
|
|
42
55
|
this.align = align;
|
|
43
56
|
this.textType = textType;
|
|
44
|
-
if (
|
|
45
|
-
this.fontColor =
|
|
57
|
+
if (fontColor) {
|
|
58
|
+
this.fontColor = fontColor;
|
|
46
59
|
}
|
|
47
60
|
}
|
|
61
|
+
setFontColor(fontColor) {
|
|
62
|
+
this.fontColor = fontColor;
|
|
63
|
+
}
|
|
48
64
|
setFont(fontName) {
|
|
49
|
-
this.
|
|
65
|
+
this.font = fontName;
|
|
66
|
+
}
|
|
67
|
+
setFontData(fontData) {
|
|
68
|
+
this.font = fontData;
|
|
50
69
|
}
|
|
51
70
|
setBgColor(color) {
|
|
52
71
|
this.bgColor = color;
|
|
@@ -59,11 +78,23 @@ class Frame {
|
|
|
59
78
|
this.bgImage = imageData;
|
|
60
79
|
this.bgType = type;
|
|
61
80
|
}
|
|
81
|
+
setBgType(type) {
|
|
82
|
+
this.bgType = type;
|
|
83
|
+
}
|
|
84
|
+
setBorderRadius(radius) {
|
|
85
|
+
this.borderRadius = radius;
|
|
86
|
+
}
|
|
87
|
+
setBorderWidth(width) {
|
|
88
|
+
this.borderWidth = width;
|
|
89
|
+
}
|
|
90
|
+
setBorderColor(color) {
|
|
91
|
+
this.borderColor = color;
|
|
92
|
+
}
|
|
62
93
|
setCustomDraw(customDraw) {
|
|
63
94
|
this.customDraw = customDraw;
|
|
64
95
|
}
|
|
65
96
|
resetFont() {
|
|
66
|
-
this.
|
|
97
|
+
this.font = undefined;
|
|
67
98
|
}
|
|
68
99
|
resetBgColor() {
|
|
69
100
|
this.bgColor = undefined;
|
|
@@ -80,7 +111,7 @@ class Frame {
|
|
|
80
111
|
this.align = 'A_LEFT';
|
|
81
112
|
this.textType = 'TFM_OVERFLOW';
|
|
82
113
|
this.fontColor = [1.0, 1.0, 1.0];
|
|
83
|
-
this.
|
|
114
|
+
this.font = undefined;
|
|
84
115
|
this.bgColor = undefined;
|
|
85
116
|
this.bgImage = undefined;
|
|
86
117
|
this.bgType = undefined;
|
|
@@ -88,55 +119,96 @@ class Frame {
|
|
|
88
119
|
}
|
|
89
120
|
insert(...frames) {
|
|
90
121
|
this.children.push(...frames);
|
|
122
|
+
for (const frame of frames) {
|
|
123
|
+
frame.on('layoutChanged', () => this.layoutChanged());
|
|
124
|
+
}
|
|
125
|
+
this.layoutChanged();
|
|
91
126
|
}
|
|
92
|
-
|
|
93
|
-
|
|
127
|
+
getLayers() {
|
|
128
|
+
const uniqueLayers = new Set();
|
|
129
|
+
uniqueLayers.add(this.layer);
|
|
130
|
+
for (const child of this.children) {
|
|
131
|
+
for (const layer of child.getLayers()) {
|
|
132
|
+
uniqueLayers.add(layer);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return uniqueLayers;
|
|
94
136
|
}
|
|
95
|
-
|
|
96
|
-
this.
|
|
137
|
+
layoutChanged() {
|
|
138
|
+
this.emit('layoutChanged');
|
|
97
139
|
}
|
|
98
|
-
displayImage(cod,
|
|
140
|
+
displayImage(cod, resourceManager, cairo, ppX, ppY, scale, layer) {
|
|
99
141
|
return __awaiter(this, void 0, void 0, function* () {
|
|
100
142
|
if (this.enabled) {
|
|
101
143
|
ppX += this.posX;
|
|
102
144
|
ppY += this.posY;
|
|
103
|
-
yield this.
|
|
145
|
+
yield this.prepareResources(resourceManager);
|
|
146
|
+
yield cod.cairo('cairo_save', cairo);
|
|
147
|
+
yield this.clipDrawing(cod, cairo, scale, ppX, ppY);
|
|
148
|
+
if (this.layer === layer) {
|
|
149
|
+
yield this.displayOwnImage(cod, cairo, ppX, ppY, scale);
|
|
150
|
+
}
|
|
104
151
|
for (const child of this.children) {
|
|
105
|
-
yield child.displayImage(cod,
|
|
152
|
+
yield child.displayImage(cod, resourceManager, cairo, ppX, ppY, scale, layer);
|
|
106
153
|
}
|
|
154
|
+
yield cod.cairo('cairo_restore', cairo);
|
|
107
155
|
}
|
|
108
156
|
});
|
|
109
157
|
}
|
|
110
|
-
|
|
158
|
+
prepareResources(resourceManager) {
|
|
111
159
|
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
-
if (this.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
promises.push(cod.cairo('cairo_set_font_face', cairo, 'NULL'));
|
|
120
|
-
}
|
|
121
|
-
if (this.bgColor !== undefined) {
|
|
122
|
-
promises.push(this.drawFrame(cod, cairo, scale, ppX, ppY));
|
|
123
|
-
}
|
|
124
|
-
if (this.bgImage !== undefined) {
|
|
125
|
-
promises.push(this.drawImage(cod, rm, cairo, scale, ppX, ppY));
|
|
126
|
-
}
|
|
127
|
-
if (this.text) {
|
|
128
|
-
promises.push(this.drawText(cod, cairo, scale, ppX, ppY));
|
|
129
|
-
}
|
|
130
|
-
if (this.customDraw) {
|
|
131
|
-
promises.push(cod.cairo('cairo_identity_matrix', cairo));
|
|
132
|
-
promises.push(cod.cairo('cairo_translate', cairo, scale * ppX, scale * ppY));
|
|
133
|
-
promises.push(cod.cairo('cairo_scale', cairo, scale, scale));
|
|
134
|
-
promises.push(this.customDraw(cod, cairo, { width: this.width, height: this.height }));
|
|
135
|
-
}
|
|
136
|
-
yield Promise.all(promises);
|
|
160
|
+
if (typeof this.bgImage === 'string') {
|
|
161
|
+
this.bgImage = yield resourceManager.image(this.bgImage);
|
|
162
|
+
}
|
|
163
|
+
if (typeof this.font === 'string') {
|
|
164
|
+
this.font = yield resourceManager.font(this.font);
|
|
137
165
|
}
|
|
138
166
|
});
|
|
139
167
|
}
|
|
168
|
+
displayOwnImage(cod, cairo, ppX, ppY, scale) {
|
|
169
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
170
|
+
if (!this.enabled) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const promises = new Array();
|
|
174
|
+
if (this.font !== undefined && typeof this.font !== 'string') {
|
|
175
|
+
promises.push(cod.cairo('cairo_set_font_face', cairo, this.font.var));
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
promises.push(cod.cairo('cairo_set_font_face', cairo, 'NULL'));
|
|
179
|
+
}
|
|
180
|
+
if (this.bgColor !== undefined) {
|
|
181
|
+
promises.push(this.drawFrame(cod, cairo, scale, ppX, ppY));
|
|
182
|
+
}
|
|
183
|
+
if (this.bgImage !== undefined) {
|
|
184
|
+
promises.push(this.drawImage(cod, cairo, scale, ppX, ppY));
|
|
185
|
+
}
|
|
186
|
+
if (this.borderWidth > 0) {
|
|
187
|
+
promises.push(this.drawBorder(cod, cairo, scale, ppX, ppY));
|
|
188
|
+
}
|
|
189
|
+
if (this.text) {
|
|
190
|
+
promises.push(this.drawText(cod, cairo, scale, ppX, ppY));
|
|
191
|
+
}
|
|
192
|
+
if (this.customDraw) {
|
|
193
|
+
promises.push(cod.cairo('cairo_identity_matrix', cairo));
|
|
194
|
+
promises.push(cod.cairo('cairo_translate', cairo, scale * ppX, scale * ppY));
|
|
195
|
+
promises.push(cod.cairo('cairo_scale', cairo, scale, scale));
|
|
196
|
+
promises.push(this.customDraw(cod, cairo, { width: this.width, height: this.height }));
|
|
197
|
+
}
|
|
198
|
+
yield Promise.all(promises);
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
clipDrawing(cod, cairo, scale, ppX, ppY) {
|
|
202
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
203
|
+
if (this.borderRadius === 0) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
yield Promise.all([
|
|
207
|
+
this.drawRectPath(cod, cairo, scale, ppX, ppY, this.borderRadius),
|
|
208
|
+
cod.cairo('cairo_clip', cairo),
|
|
209
|
+
]);
|
|
210
|
+
});
|
|
211
|
+
}
|
|
140
212
|
drawFrame(cod, cairo, scale, ppX, ppY) {
|
|
141
213
|
return __awaiter(this, void 0, void 0, function* () {
|
|
142
214
|
if (this.bgColor) {
|
|
@@ -152,16 +224,18 @@ class Frame {
|
|
|
152
224
|
yield Promise.all(promises);
|
|
153
225
|
}
|
|
154
226
|
else {
|
|
155
|
-
throw new Error('
|
|
227
|
+
throw new Error('Color of the frame is undefined.');
|
|
156
228
|
}
|
|
157
229
|
});
|
|
158
230
|
}
|
|
159
|
-
drawImage(cod,
|
|
231
|
+
drawImage(cod, cairo, scale, ppX, ppY) {
|
|
160
232
|
return __awaiter(this, void 0, void 0, function* () {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
233
|
+
if (this.bgImage === undefined || typeof this.bgImage === 'string') {
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const bgImage = this.bgImage.var;
|
|
237
|
+
const bgWidth = this.bgImage.width;
|
|
238
|
+
const bgHeight = this.bgImage.height;
|
|
165
239
|
const promises = new Array();
|
|
166
240
|
promises.push(cod.cairo('cairo_identity_matrix', cairo));
|
|
167
241
|
promises.push(cod.cairo('cairo_translate', cairo, scale * ppX, scale * ppY));
|
|
@@ -194,6 +268,41 @@ class Frame {
|
|
|
194
268
|
yield Promise.all(promises);
|
|
195
269
|
});
|
|
196
270
|
}
|
|
271
|
+
drawBorder(cod, cairo, scale, ppX, ppY) {
|
|
272
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
273
|
+
yield Promise.all([
|
|
274
|
+
this.drawRectPath(cod, cairo, scale, ppX, ppY, this.borderRadius),
|
|
275
|
+
cod.cairo('cairo_set_source_rgba', cairo, this.borderColor[0], this.borderColor[1], this.borderColor[2], this.borderColor[3]),
|
|
276
|
+
cod.cairo('cairo_set_line_width', cairo, this.borderWidth),
|
|
277
|
+
cod.cairo('cairo_stroke', cairo),
|
|
278
|
+
]);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
drawRectPath(cod, cairo, scale, ppX, ppY, radius) {
|
|
282
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
283
|
+
if (radius === 0) {
|
|
284
|
+
return yield Promise.all([
|
|
285
|
+
cod.cairo('cairo_identity_matrix', cairo),
|
|
286
|
+
cod.cairo('cairo_translate', cairo, scale * ppX, scale * ppY),
|
|
287
|
+
cod.cairo('cairo_scale', cairo, scale, scale),
|
|
288
|
+
cod.cairo('cairo_rectangle', cairo, 0, 0, this.width, this.height),
|
|
289
|
+
]);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
const degrees = Math.PI / 180;
|
|
293
|
+
return yield Promise.all([
|
|
294
|
+
cod.cairo('cairo_identity_matrix', cairo),
|
|
295
|
+
cod.cairo('cairo_translate', cairo, scale * ppX, scale * ppY),
|
|
296
|
+
cod.cairo('cairo_scale', cairo, scale, scale),
|
|
297
|
+
cod.cairo('cairo_new_sub_path', cairo),
|
|
298
|
+
cod.cairo('cairo_arc', cairo, this.width - radius, radius, radius, -90 * degrees, 0 * degrees),
|
|
299
|
+
cod.cairo('cairo_arc', cairo, this.width - radius, this.height - radius, radius, 0 * degrees, 90 * degrees),
|
|
300
|
+
cod.cairo('cairo_arc', cairo, radius, this.height - radius, radius, 90 * degrees, 180 * degrees),
|
|
301
|
+
cod.cairo('cairo_arc', cairo, radius, radius, radius, 180 * degrees, 270 * degrees),
|
|
302
|
+
cod.cairo('cairo_close_path', cairo),
|
|
303
|
+
]);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
197
307
|
}
|
|
198
|
-
exports.default = Frame;
|
|
199
308
|
exports.Frame = Frame;
|
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
import { CamOverlayDrawingAPI, CamOverlayDrawingOptions } from '../CamOverlayDrawingAPI';
|
|
2
2
|
import ResourceManager from './ResourceManager';
|
|
3
|
-
import { Frame,
|
|
3
|
+
import { Frame, TFrameOptions } from './Frame';
|
|
4
4
|
export declare const COORD: Record<string, [number, number]>;
|
|
5
|
-
export type
|
|
5
|
+
export type TPainterOptions = TFrameOptions & {
|
|
6
6
|
screenWidth: number;
|
|
7
7
|
screenHeight: number;
|
|
8
8
|
coAlignment: string;
|
|
9
9
|
};
|
|
10
|
-
export
|
|
10
|
+
export declare class Painter extends Frame {
|
|
11
11
|
private screenWidth;
|
|
12
12
|
private screenHeight;
|
|
13
13
|
private coAlignment;
|
|
14
|
-
private surface?;
|
|
15
|
-
private cairo?;
|
|
16
14
|
private cod;
|
|
17
15
|
private rm;
|
|
16
|
+
private refreshLayers;
|
|
17
|
+
private layers;
|
|
18
|
+
constructor(opt: TPainterOptions, coopt: CamOverlayDrawingOptions);
|
|
18
19
|
get camOverlayDrawingAPI(): CamOverlayDrawingAPI;
|
|
19
20
|
get resourceManager(): ResourceManager;
|
|
20
|
-
constructor(opt: PainterOptions, coopt: CamOverlayDrawingOptions);
|
|
21
21
|
connect(): void;
|
|
22
22
|
disconnect(): void;
|
|
23
23
|
isConnected(): boolean;
|
|
24
24
|
registerImage(moniker: string, fileName: string): void;
|
|
25
25
|
registerFont(moniker: string, fileName: string): void;
|
|
26
26
|
setScreenSize(sw: number, sh: number): void;
|
|
27
|
-
setCoAlignment(
|
|
27
|
+
setCoAlignment(coAlignment: string): void;
|
|
28
|
+
protected layoutChanged(): void;
|
|
28
29
|
display(scale?: number): Promise<void>;
|
|
29
30
|
hide(): Promise<void>;
|
|
31
|
+
invalidateLayer(layer: number): Promise<void>;
|
|
32
|
+
private prepareLayers;
|
|
33
|
+
private prepareSurface;
|
|
34
|
+
private cleanupSurface;
|
|
30
35
|
private positionConvertor;
|
|
31
|
-
private prepareDrawing;
|
|
32
|
-
private destroy;
|
|
33
36
|
}
|
|
34
|
-
export {
|
|
37
|
+
export { Frame, TFrameOptions as FrameOptions, ResourceManager, CamOverlayDrawingOptions };
|
|
@@ -27,20 +27,22 @@ exports.COORD = {
|
|
|
27
27
|
bottom_right: [1, 1],
|
|
28
28
|
};
|
|
29
29
|
class Painter extends Frame_1.Frame {
|
|
30
|
-
get camOverlayDrawingAPI() {
|
|
31
|
-
return this.cod;
|
|
32
|
-
}
|
|
33
|
-
get resourceManager() {
|
|
34
|
-
return this.rm;
|
|
35
|
-
}
|
|
36
30
|
constructor(opt, coopt) {
|
|
37
31
|
super(opt);
|
|
32
|
+
this.refreshLayers = true;
|
|
33
|
+
this.layers = [];
|
|
38
34
|
this.coAlignment = exports.COORD[opt.coAlignment];
|
|
39
35
|
this.screenWidth = opt.screenWidth;
|
|
40
36
|
this.screenHeight = opt.screenHeight;
|
|
41
37
|
this.cod = new CamOverlayDrawingAPI_1.CamOverlayDrawingAPI(coopt);
|
|
42
38
|
this.rm = new ResourceManager_1.default(this.cod);
|
|
43
39
|
}
|
|
40
|
+
get camOverlayDrawingAPI() {
|
|
41
|
+
return this.cod;
|
|
42
|
+
}
|
|
43
|
+
get resourceManager() {
|
|
44
|
+
return this.rm;
|
|
45
|
+
}
|
|
44
46
|
connect() {
|
|
45
47
|
this.cod.on('open', () => {
|
|
46
48
|
this.rm.clear();
|
|
@@ -66,19 +68,45 @@ class Painter extends Frame_1.Frame {
|
|
|
66
68
|
this.screenWidth = sw;
|
|
67
69
|
this.screenHeight = sh;
|
|
68
70
|
}
|
|
69
|
-
setCoAlignment(
|
|
70
|
-
this.coAlignment = exports.COORD[
|
|
71
|
+
setCoAlignment(coAlignment) {
|
|
72
|
+
this.coAlignment = exports.COORD[coAlignment];
|
|
71
73
|
}
|
|
72
|
-
|
|
74
|
+
layoutChanged() {
|
|
75
|
+
this.refreshLayers = true;
|
|
76
|
+
}
|
|
77
|
+
display(scale = 1.0) {
|
|
73
78
|
return __awaiter(this, void 0, void 0, function* () {
|
|
74
79
|
if (this.enabled) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
if (this.refreshLayers) {
|
|
81
|
+
this.refreshLayers = false;
|
|
82
|
+
yield this.prepareLayers();
|
|
83
|
+
}
|
|
84
|
+
let cairo;
|
|
85
|
+
let surface;
|
|
86
|
+
let lastCachedLayer;
|
|
87
|
+
for (let i = 0; i < this.layers.length; i++) {
|
|
88
|
+
const layer = this.layers[i];
|
|
89
|
+
if (layer.cairoCache !== undefined &&
|
|
90
|
+
layer.surfaceCache !== undefined &&
|
|
91
|
+
surface === undefined &&
|
|
92
|
+
cairo === undefined) {
|
|
93
|
+
lastCachedLayer = layer;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (surface === undefined || cairo === undefined) {
|
|
97
|
+
[surface, cairo] = yield this.prepareSurface(scale, lastCachedLayer === null || lastCachedLayer === void 0 ? void 0 : lastCachedLayer.surfaceCache, lastCachedLayer === null || lastCachedLayer === void 0 ? void 0 : lastCachedLayer.cairoCache);
|
|
98
|
+
}
|
|
99
|
+
yield this.displayImage(this.cod, this.rm, cairo, 0, 0, scale, layer.layer);
|
|
100
|
+
if (i < this.layers.length - 1) {
|
|
101
|
+
const [surfaceToCache, cairoToCache] = yield this.prepareSurface(scale, surface, cairo);
|
|
102
|
+
layer.surfaceCache = surfaceToCache;
|
|
103
|
+
layer.cairoCache = cairoToCache;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (surface !== undefined && cairo !== undefined) {
|
|
107
|
+
yield this.cod.showCairoImage(surface, this.positionConvertor(this.coAlignment[0], this.screenWidth, this.posX, scale * this.width), this.positionConvertor(this.coAlignment[1], this.screenHeight, this.posY, scale * this.height));
|
|
108
|
+
yield this.cleanupSurface(surface, cairo);
|
|
79
109
|
}
|
|
80
|
-
yield this.cod.showCairoImage(this.surface, this.positionConvertor(this.coAlignment[0], this.screenWidth, this.posX, scale * this.width), this.positionConvertor(this.coAlignment[1], this.screenHeight, this.posY, scale * this.height));
|
|
81
|
-
yield this.destroy();
|
|
82
110
|
}
|
|
83
111
|
});
|
|
84
112
|
}
|
|
@@ -87,6 +115,53 @@ class Painter extends Frame_1.Frame {
|
|
|
87
115
|
yield this.cod.removeImage();
|
|
88
116
|
});
|
|
89
117
|
}
|
|
118
|
+
invalidateLayer(layer) {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const layerIdx = this.layers.findIndex((l) => l.layer === layer);
|
|
121
|
+
if (layerIdx === -1) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
for (let i = layerIdx; i < this.layers.length; i++) {
|
|
125
|
+
const layer = this.layers[i];
|
|
126
|
+
if (layer.surfaceCache !== undefined && layer.cairoCache !== undefined) {
|
|
127
|
+
yield this.cleanupSurface(layer.surfaceCache, layer.cairoCache);
|
|
128
|
+
layer.surfaceCache = undefined;
|
|
129
|
+
layer.cairoCache = undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
prepareLayers() {
|
|
135
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
for (const layer of this.layers) {
|
|
137
|
+
if (layer.surfaceCache !== undefined && layer.cairoCache !== undefined) {
|
|
138
|
+
yield this.cleanupSurface(layer.surfaceCache, layer.cairoCache);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const uniqueLayers = this.getLayers();
|
|
142
|
+
const sortedLayers = Array.from(uniqueLayers).sort((a, b) => a - b);
|
|
143
|
+
this.layers = sortedLayers.map((layer) => {
|
|
144
|
+
return { layer };
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
prepareSurface(scale, cachedSurface, cachedCairo) {
|
|
149
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
+
const surface = (yield this.cod.cairo('cairo_image_surface_create', 'CAIRO_FORMAT_ARGB32', Math.floor(this.width * scale), Math.floor(this.height * scale)));
|
|
151
|
+
const cairo = (yield this.cod.cairo('cairo_create', surface.var));
|
|
152
|
+
if (cachedSurface !== undefined && cachedCairo !== undefined) {
|
|
153
|
+
yield this.cod.cairo('cairo_set_source_surface', cairo.var, cachedSurface, 0, 0);
|
|
154
|
+
yield this.cod.cairo('cairo_paint', cairo.var);
|
|
155
|
+
}
|
|
156
|
+
return [surface.var, cairo.var];
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
cleanupSurface(surface, cairo) {
|
|
160
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
161
|
+
yield this.cod.cairo('cairo_surface_destroy', surface);
|
|
162
|
+
yield this.cod.cairo('cairo_destroy', cairo);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
90
165
|
positionConvertor(alignment, screenSize, position, graphicsSize) {
|
|
91
166
|
switch (alignment) {
|
|
92
167
|
case -1:
|
|
@@ -99,19 +174,5 @@ class Painter extends Frame_1.Frame {
|
|
|
99
174
|
throw new Error('Invalid graphics alignment.');
|
|
100
175
|
}
|
|
101
176
|
}
|
|
102
|
-
prepareDrawing(scale) {
|
|
103
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
-
const surface = (yield this.cod.cairo('cairo_image_surface_create', 'CAIRO_FORMAT_ARGB32', Math.floor(this.width * scale), Math.floor(this.height * scale)));
|
|
105
|
-
const cairo = (yield this.cod.cairo('cairo_create', surface.var));
|
|
106
|
-
return [surface.var, cairo.var];
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
destroy() {
|
|
110
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
-
yield this.cod.cairo('cairo_surface_destroy', this.surface);
|
|
112
|
-
yield this.cod.cairo('cairo_destroy', this.cairo);
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
177
|
}
|
|
116
|
-
exports.default = Painter;
|
|
117
178
|
exports.Painter = Painter;
|
package/CameraVapix.d.ts
CHANGED
|
@@ -78,13 +78,13 @@ export declare class CameraVapix {
|
|
|
78
78
|
getTimezone(): Promise<string>;
|
|
79
79
|
getHeaders(): Promise<Record<string, string>>;
|
|
80
80
|
setHeaders(headers: Record<string, string>): Promise<Response>;
|
|
81
|
-
private
|
|
81
|
+
private parseParameters;
|
|
82
82
|
getParameterGroup(groupNames: string): Promise<Record<string, string>>;
|
|
83
83
|
setParameter(params: Record<string, string>): Promise<Response>;
|
|
84
84
|
getGuardTourList(): Promise<TGuardTour[]>;
|
|
85
|
-
setGuardTourEnabled(
|
|
85
|
+
setGuardTourEnabled(guardTourID: string, enable: boolean): Promise<Response>;
|
|
86
86
|
private parsePtz;
|
|
87
|
-
private
|
|
87
|
+
private parseCameraPtzResponse;
|
|
88
88
|
getPTZPresetList(channel: number): Promise<string[]>;
|
|
89
89
|
listPtzVideoSourceOverview(): Promise<TPtzOverview>;
|
|
90
90
|
goToPreset(channel: number, presetName: string): Promise<Response>;
|
package/CameraVapix.js
CHANGED
|
@@ -46,8 +46,7 @@ class CameraVapix {
|
|
|
46
46
|
}
|
|
47
47
|
getCameraImage(camera, compression, resolution, outputStream) {
|
|
48
48
|
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
-
const
|
|
50
|
-
const res = yield this.vapixGet(path);
|
|
49
|
+
const res = yield this.vapixGet('/axis-cgi/jpg/image.cgi', { resolution, compression, camera });
|
|
51
50
|
if (res.body) {
|
|
52
51
|
void res.body.pipeTo(outputStream);
|
|
53
52
|
}
|
|
@@ -181,40 +180,26 @@ class CameraVapix {
|
|
|
181
180
|
return this.vapixPost('/axis-cgi/customhttpheader.cgi', data);
|
|
182
181
|
});
|
|
183
182
|
}
|
|
184
|
-
|
|
183
|
+
parseParameters(response) {
|
|
185
184
|
const params = {};
|
|
186
185
|
const lines = response.split(/[\r\n]/);
|
|
187
186
|
for (let i = 0; i < lines.length; i++) {
|
|
188
|
-
if (lines[i].substring(0, 7) === '# Error') {
|
|
187
|
+
if (lines[i].length === 0 || lines[i].substring(0, 7) === '# Error') {
|
|
189
188
|
continue;
|
|
190
189
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
else if (p[0].substring(0, 7) !== '# Error') {
|
|
198
|
-
params[p[0].slice(0, -1)] = '';
|
|
199
|
-
}
|
|
190
|
+
const delimiterPos = lines[i].indexOf('=');
|
|
191
|
+
if (delimiterPos !== -1) {
|
|
192
|
+
const paramName = lines[i].substring(0, delimiterPos);
|
|
193
|
+
const paramValue = lines[i].substring(delimiterPos + 1);
|
|
194
|
+
params[paramName] = paramValue;
|
|
200
195
|
}
|
|
201
196
|
}
|
|
202
197
|
return params;
|
|
203
198
|
}
|
|
204
199
|
getParameterGroup(groupNames) {
|
|
205
200
|
return __awaiter(this, void 0, void 0, function* () {
|
|
206
|
-
const response = yield
|
|
207
|
-
|
|
208
|
-
const lines = response.split(/[\r\n]/);
|
|
209
|
-
for (let i = 0; i < lines.length; i++) {
|
|
210
|
-
if (lines[i].length) {
|
|
211
|
-
const p = lines[i].split('=');
|
|
212
|
-
if (p.length >= 2) {
|
|
213
|
-
params[p[0]] = p[1];
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return params;
|
|
201
|
+
const response = yield this.vapixGet('/axis-cgi/param.cgi', { action: 'list', group: groupNames });
|
|
202
|
+
return this.parseParameters(yield response.text());
|
|
218
203
|
});
|
|
219
204
|
}
|
|
220
205
|
setParameter(params) {
|
|
@@ -263,26 +248,26 @@ class CameraVapix {
|
|
|
263
248
|
return gTourList;
|
|
264
249
|
});
|
|
265
250
|
}
|
|
266
|
-
setGuardTourEnabled(
|
|
251
|
+
setGuardTourEnabled(guardTourID, enable) {
|
|
267
252
|
const options = {};
|
|
268
|
-
options[
|
|
253
|
+
options[guardTourID + '.Running'] = enable ? 'yes' : 'no';
|
|
269
254
|
return this.setParameter(options);
|
|
270
255
|
}
|
|
271
256
|
parsePtz(parsed) {
|
|
272
257
|
const res = [];
|
|
273
258
|
parsed.forEach((value) => {
|
|
274
|
-
const
|
|
275
|
-
if (
|
|
259
|
+
const delimiterPos = value.indexOf('=');
|
|
260
|
+
if (delimiterPos === -1) {
|
|
276
261
|
return;
|
|
277
262
|
}
|
|
278
|
-
if (!
|
|
263
|
+
if (!value.startsWith('presetposno')) {
|
|
279
264
|
return;
|
|
280
265
|
}
|
|
281
|
-
const id = Number(
|
|
266
|
+
const id = Number(value.substring(11, delimiterPos));
|
|
282
267
|
if (Number.isNaN(id)) {
|
|
283
268
|
return;
|
|
284
269
|
}
|
|
285
|
-
const data =
|
|
270
|
+
const data = value.substring(delimiterPos + 1).split(':');
|
|
286
271
|
const getValue = (valueName) => {
|
|
287
272
|
for (const d of data) {
|
|
288
273
|
const p = d.split('=');
|
|
@@ -304,7 +289,7 @@ class CameraVapix {
|
|
|
304
289
|
});
|
|
305
290
|
return res;
|
|
306
291
|
}
|
|
307
|
-
|
|
292
|
+
parseCameraPtzResponse(response) {
|
|
308
293
|
const json = JSON.parse(response);
|
|
309
294
|
const parsed = {};
|
|
310
295
|
Object.keys(json).forEach((key) => {
|
|
@@ -320,7 +305,7 @@ class CameraVapix {
|
|
|
320
305
|
}
|
|
321
306
|
getPTZPresetList(channel) {
|
|
322
307
|
return __awaiter(this, void 0, void 0, function* () {
|
|
323
|
-
const response = yield (yield this.vapixGet(
|
|
308
|
+
const response = yield (yield this.vapixGet('/axis-cgi/com/ptz.cgi', { query: 'presetposcam', camera: channel.toString() })).text();
|
|
324
309
|
const positions = [];
|
|
325
310
|
const lines = response.split(/[\r\n]/);
|
|
326
311
|
for (const line of lines) {
|
|
@@ -338,11 +323,11 @@ class CameraVapix {
|
|
|
338
323
|
listPtzVideoSourceOverview() {
|
|
339
324
|
return __awaiter(this, void 0, void 0, function* () {
|
|
340
325
|
try {
|
|
341
|
-
const response = yield this.vapixGet(
|
|
326
|
+
const response = yield this.vapixGet('/axis-cgi/com/ptz.cgi', {
|
|
342
327
|
query: 'presetposall',
|
|
343
328
|
format: 'json',
|
|
344
329
|
});
|
|
345
|
-
const data = this.
|
|
330
|
+
const data = this.parseCameraPtzResponse(yield response.text());
|
|
346
331
|
const res = {};
|
|
347
332
|
Object.keys(data).forEach((camera) => {
|
|
348
333
|
res[Number(camera) - 1] = data[Number(camera)].map((_a) => {
|
|
@@ -358,40 +343,36 @@ class CameraVapix {
|
|
|
358
343
|
});
|
|
359
344
|
}
|
|
360
345
|
goToPreset(channel, presetName) {
|
|
361
|
-
return this.
|
|
346
|
+
return this.vapixGet('/axis-cgi/com/ptz.cgi', { camera: channel.toString(), gotoserverpresetname: presetName });
|
|
362
347
|
}
|
|
363
348
|
getPtzPosition(camera) {
|
|
364
349
|
return __awaiter(this, void 0, void 0, function* () {
|
|
365
350
|
try {
|
|
366
|
-
const res = yield this.vapixGet(
|
|
351
|
+
const res = yield this.vapixGet('/axis-cgi/com/ptz.cgi', {
|
|
367
352
|
query: 'position',
|
|
368
353
|
camera: camera.toString(),
|
|
369
354
|
});
|
|
370
|
-
const
|
|
355
|
+
const params = this.parseParameters(yield res.text());
|
|
371
356
|
return {
|
|
372
|
-
pan: Number(
|
|
373
|
-
tilt: Number(
|
|
374
|
-
zoom: Number(
|
|
357
|
+
pan: Number(params.pan),
|
|
358
|
+
tilt: Number(params.tilt),
|
|
359
|
+
zoom: Number(params.zoom),
|
|
375
360
|
};
|
|
376
361
|
}
|
|
377
362
|
catch (err) {
|
|
378
|
-
return {
|
|
379
|
-
pan: 0,
|
|
380
|
-
tilt: 0,
|
|
381
|
-
zoom: 0,
|
|
382
|
-
};
|
|
363
|
+
return { pan: 0, tilt: 0, zoom: 0 };
|
|
383
364
|
}
|
|
384
365
|
});
|
|
385
366
|
}
|
|
386
367
|
getInputState(port) {
|
|
387
368
|
return __awaiter(this, void 0, void 0, function* () {
|
|
388
|
-
const response = yield (yield this.
|
|
369
|
+
const response = yield (yield this.vapixGet('/axis-cgi/io/port.cgi', { checkactive: port.toString() })).text();
|
|
389
370
|
return response.split('=')[1].indexOf('active') === 0;
|
|
390
371
|
});
|
|
391
372
|
}
|
|
392
373
|
setOutputState(port, active) {
|
|
393
374
|
return __awaiter(this, void 0, void 0, function* () {
|
|
394
|
-
return this.
|
|
375
|
+
return this.vapixGet('/axis-cgi/io/port.cgi', { action: active ? `${port}:/` : `${port}:\\` });
|
|
395
376
|
});
|
|
396
377
|
}
|
|
397
378
|
getApplicationList() {
|
package/DefaultAgent.js
CHANGED
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Node.js helper library for CamStreamer ACAP applications.
|
|
4
4
|
|
|
5
|
-
The library is primarily developed for CamScripter
|
|
5
|
+
The library is primarily developed for the CamScripter ACAP application running directly in Axis cameras.
|
|
6
6
|
Examples of CamScripter packages can be found at https://github.com/CamStreamer/CamScripterApp_examples
|
|
7
7
|
|
|
8
8
|
## Installation
|