@ceeblue/web-utils 2.5.0 → 2.6.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.
@@ -184,6 +184,55 @@ declare namespace Connect {
184
184
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
185
185
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
186
186
  */
187
+ /**
188
+ * Log interface to deal with log everywhere:
189
+ * - subscribe logs: listen logs to effectuate some specific job related logs
190
+ * - intercept logs: intercept logs to change the default behavior
191
+ * - redirect logs: redirect logs to one other logger engine
192
+ * - redefine logs: change log text like adding a prefix
193
+ *
194
+ * You have 4 {@link LogType} 'error', 'warn', 'info', and 'debug', as commonly managed by browsers.
195
+ *
196
+ * @example
197
+ * // Intercept and redirect all the logs to the console (default behavior)
198
+ * import { log } from '@ceeblue/web-utils';
199
+ * log.on(type:LogType, args:uknown[]) => {
200
+ * console[type](...args.splice(0)); // args is empty after this call = final interception
201
+ * }
202
+ *
203
+ * // Intercept and redirect the logs from Player compoment to the console
204
+ * player.log.on(type:LogType, args:uknown[]) => {
205
+ * console[type](...args.splice(0)); // args is empty after this call = final interception
206
+ * }
207
+ *
208
+ * // Subscribe and redirect all the logs to a file logger
209
+ * log.on(type:LogType, args:uknown[]) => {
210
+ * fileLogger[type](...args); // args stays unchanged to let's continue the default behavior
211
+ * }
212
+ *
213
+ * // Redefine the log to add some prefix indication
214
+ * class Player {
215
+ * connector = new Connector();
216
+ * constructor() {
217
+ * connector.log = this.log.bind(this, "Connector log:");
218
+ * }
219
+ * }
220
+ *
221
+ */
222
+ interface ILog {
223
+ /**
224
+ * Build a log
225
+ */
226
+ (...args: unknown[]): Log;
227
+ /**
228
+ * Intercept, redefine or redirect any log
229
+ * If you clear args you intercept the log and nothing happen more after this call.
230
+ * @param type log level
231
+ * @param args args
232
+ * @returns
233
+ */
234
+ on: (type: LogType, args: unknown[]) => void;
235
+ }
187
236
  /**
188
237
  * Log types
189
238
  */
@@ -207,22 +256,6 @@ declare class Log {
207
256
  constructor(onLog: Function, ...args: unknown[]);
208
257
  private _bind;
209
258
  }
210
- /**
211
- * ILog interface used by log methods
212
- */
213
- interface ILog {
214
- /**
215
- * Build a log
216
- */
217
- (...args: unknown[]): Log;
218
- /**
219
- * Intercept or redefine any log
220
- * @param type log level
221
- * @param args args
222
- * @returns
223
- */
224
- on: (type: LogType, args: unknown[]) => void;
225
- }
226
259
  /**
227
260
  * Inherits from this class to use logs
228
261
  */
@@ -934,6 +967,51 @@ declare class WebSocketReliable extends EventEmitter {
934
967
  private _send;
935
968
  }
936
969
 
970
+ /**
971
+ * Copyright 2024 Ceeblue B.V.
972
+ * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
973
+ * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
974
+ */
975
+ /**
976
+ * Decode the timestamp from a video element and compute the latency between the timestamp and the current date.
977
+ *
978
+ * @param {HTMLVideoElement} sourceEl the video element to get the image from
979
+ * @param {HTMLCanvasElement} canvas
980
+ * @param {CanvasRenderingContext2D} context
981
+ * @param {Date} now current date, new Date() by default
982
+ * @param {Number} blocksPerRow number of blocks in the line, 32 by default
983
+ * @param {Number} tolerance percentage of tolerance for the black and white threshold, 0.2 by default
984
+ * @returns {Number} The latency in millisecond between 'now' and the decoded timestamp, 0 if the timestamp cannot be decoded
985
+ */
986
+ declare function getLatency(sourceEl: HTMLVideoElement, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, now?: Date, blocksPerRow?: number, tolerance?: number): number;
987
+ /**
988
+ * Decode a previously encoded timestamp from a canvas
989
+ *
990
+ * @param {CanvasRenderingContext2D} context
991
+ * @param {Number} lineWidth width of the line in pixels
992
+ * @param {Number} blocksPerRow number of blocks in the line, 32 by default
993
+ * @param {Number} tolerance percentage of tolerance for the black and white threshold, 0.2 by default
994
+ * @returns {Date|null} The Date object representing the timestamp or null if the timestamp cannot be decoded
995
+ */
996
+ declare function decodeTimestamp(context: CanvasRenderingContext2D, lineWidth: number, blocksPerRow?: number, tolerance?: number): Date | undefined;
997
+ /**
998
+ * Encode the current timestamp into a line composed of blocks of black and white pixels
999
+ * written on the top of the canvas.
1000
+ *
1001
+ * @param {CanvasRenderingContext2D} context
1002
+ * @param {Number} lineWidth width of the line in pixels
1003
+ * @param {Number} blocksPerRow number of blocks in the line, 32 by default
1004
+ * @param {Date} now current date, new Date() by default
1005
+ */
1006
+ declare function encodeTimestamp(context: CanvasRenderingContext2D, lineWidth: number, blocksPerRow?: number, now?: Date): void;
1007
+
1008
+ declare const EpochTime_decodeTimestamp: typeof decodeTimestamp;
1009
+ declare const EpochTime_encodeTimestamp: typeof encodeTimestamp;
1010
+ declare const EpochTime_getLatency: typeof getLatency;
1011
+ declare namespace EpochTime {
1012
+ export { EpochTime_decodeTimestamp as decodeTimestamp, EpochTime_encodeTimestamp as encodeTimestamp, EpochTime_getLatency as getLatency };
1013
+ }
1014
+
937
1015
  /**
938
1016
  * Copyright 2024 Ceeblue B.V.
939
1017
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
@@ -942,4 +1020,4 @@ declare class WebSocketReliable extends EventEmitter {
942
1020
 
943
1021
  declare const VERSION: string;
944
1022
 
945
- export { BinaryReader, BinaryWriter, BitReader, ByteRate, Connect, EventEmitter, FixMap, type ILog, Log, LogType, Loggable, NetAddress, Numbers, Queue, SDP, Util, VERSION, WebSocketReliable, type WebSocketReliableError, log };
1023
+ export { BinaryReader, BinaryWriter, BitReader, ByteRate, Connect, EpochTime, EventEmitter, FixMap, type ILog, Log, LogType, Loggable, NetAddress, Numbers, Queue, SDP, Util, VERSION, WebSocketReliable, type WebSocketReliableError, log };
package/dist/web-utils.js CHANGED
@@ -1928,4 +1928,100 @@ class WebSocketReliable extends EventEmitter {
1928
1928
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
1929
1929
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
1930
1930
  */
1931
- const VERSION = '2.5.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EventEmitter,FixMap,Log,LogType,Loggable,NetAddress,Numbers,Queue,SDP,Util,VERSION,WebSocketReliable,log};//# sourceMappingURL=web-utils.js.map
1931
+ /**
1932
+ * Decode the timestamp from a video element and compute the latency between the timestamp and the current date.
1933
+ *
1934
+ * @param {HTMLVideoElement} sourceEl the video element to get the image from
1935
+ * @param {HTMLCanvasElement} canvas
1936
+ * @param {CanvasRenderingContext2D} context
1937
+ * @param {Date} now current date, new Date() by default
1938
+ * @param {Number} blocksPerRow number of blocks in the line, 32 by default
1939
+ * @param {Number} tolerance percentage of tolerance for the black and white threshold, 0.2 by default
1940
+ * @returns {Number} The latency in millisecond between 'now' and the decoded timestamp, 0 if the timestamp cannot be decoded
1941
+ */
1942
+ function getLatency(sourceEl, canvas, context, now = new Date(), blocksPerRow = 32, tolerance = 0.2) {
1943
+ canvas.width = sourceEl.videoWidth;
1944
+ canvas.height = Math.floor(canvas.width / blocksPerRow);
1945
+ if (!canvas.width || !canvas.height) {
1946
+ // No pixel to parse!
1947
+ return 0;
1948
+ }
1949
+ context.drawImage(sourceEl, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height);
1950
+ const timestamp = decodeTimestamp(context, canvas.width, blocksPerRow, tolerance);
1951
+ return timestamp == null ? 0 : now.getTime() - timestamp.getTime();
1952
+ }
1953
+ /**
1954
+ * Decode a previously encoded timestamp from a canvas
1955
+ *
1956
+ * @param {CanvasRenderingContext2D} context
1957
+ * @param {Number} lineWidth width of the line in pixels
1958
+ * @param {Number} blocksPerRow number of blocks in the line, 32 by default
1959
+ * @param {Number} tolerance percentage of tolerance for the black and white threshold, 0.2 by default
1960
+ * @returns {Date|null} The Date object representing the timestamp or null if the timestamp cannot be decoded
1961
+ */
1962
+ function decodeTimestamp(context, lineWidth, blocksPerRow = 32, tolerance = 0.2) {
1963
+ const blockSize = lineWidth / blocksPerRow;
1964
+ let binaryTime = '';
1965
+ let i = blockSize / 2;
1966
+ const data = context.getImageData(0, Math.round(i), lineWidth, 1).data;
1967
+ const pixels = new Uint32Array(data.buffer);
1968
+ const blackThreshold = 0xffffff * tolerance;
1969
+ const whiteThreshold = 0xffffff * (1 - tolerance);
1970
+ while (i < pixels.length) {
1971
+ const pixel = pixels[Math.round(i)] & 0xffffff;
1972
+ pixels[Math.round(i)] = pixel;
1973
+ if (pixel < blackThreshold) {
1974
+ // Black
1975
+ binaryTime += '1';
1976
+ }
1977
+ else if (pixel > whiteThreshold) {
1978
+ // White
1979
+ binaryTime += '0';
1980
+ }
1981
+ else {
1982
+ return;
1983
+ }
1984
+ i += blockSize;
1985
+ }
1986
+ const day = parseInt(binaryTime.slice(0, 5), 2);
1987
+ const hour = parseInt(binaryTime.slice(5, 10), 2);
1988
+ const minute = parseInt(binaryTime.slice(10, 16), 2);
1989
+ const second = parseInt(binaryTime.slice(16, 22), 2);
1990
+ const millisecond = parseInt(binaryTime.slice(22, 32), 2);
1991
+ const now = new Date();
1992
+ return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), day, hour, minute, second, millisecond));
1993
+ }
1994
+ /**
1995
+ * Encode the current timestamp into a line composed of blocks of black and white pixels
1996
+ * written on the top of the canvas.
1997
+ *
1998
+ * @param {CanvasRenderingContext2D} context
1999
+ * @param {Number} lineWidth width of the line in pixels
2000
+ * @param {Number} blocksPerRow number of blocks in the line, 32 by default
2001
+ * @param {Date} now current date, new Date() by default
2002
+ */
2003
+ function encodeTimestamp(context, lineWidth, blocksPerRow = 32, now = new Date()) {
2004
+ const blockSize = Math.floor(lineWidth / blocksPerRow);
2005
+ const day = now.getUTCDate();
2006
+ const hour = now.getUTCHours();
2007
+ const minute = now.getUTCMinutes();
2008
+ const second = now.getUTCSeconds();
2009
+ const millisecond = now.getUTCMilliseconds();
2010
+ const binaryDay = day.toString(2).padStart(5, '0');
2011
+ const binaryHour = hour.toString(2).padStart(5, '0');
2012
+ const binaryMinute = minute.toString(2).padStart(6, '0');
2013
+ const binarySecond = second.toString(2).padStart(6, '0');
2014
+ const binaryMillisecond = millisecond.toString(2).padStart(10, '0');
2015
+ const binaryTime = binaryDay + binaryHour + binaryMinute + binarySecond + binaryMillisecond;
2016
+ for (let i = 0; i < binaryTime.length; i++) {
2017
+ const x = (i % blocksPerRow) * blockSize;
2018
+ const y = Math.floor(i / blocksPerRow) * blockSize;
2019
+ context.fillStyle = binaryTime[i] === '1' ? 'black' : 'white';
2020
+ context.fillRect(x, y, blockSize, blockSize);
2021
+ }
2022
+ }var EpochTime=/*#__PURE__*/Object.freeze({__proto__:null,decodeTimestamp:decodeTimestamp,encodeTimestamp:encodeTimestamp,getLatency:getLatency});/**
2023
+ * Copyright 2024 Ceeblue B.V.
2024
+ * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
2025
+ * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
2026
+ */
2027
+ const VERSION = '2.6.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EpochTime,EventEmitter,FixMap,Log,LogType,Loggable,NetAddress,Numbers,Queue,SDP,Util,VERSION,WebSocketReliable,log};//# sourceMappingURL=web-utils.js.map