sane-wasm 0.3.0 → 0.3.2

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.
Binary file
@@ -27,23 +27,15 @@ if (ENVIRONMENT_IS_NODE) {
27
27
 
28
28
  Object.assign(global, {
29
29
  self: global,
30
- require: require,
31
- Module: Module,
30
+ require,
31
+ Module,
32
32
  location: {
33
33
  href: __filename
34
34
  },
35
35
  Worker: nodeWorkerThreads.Worker,
36
- importScripts: function(f) {
37
- (0, eval)(fs.readFileSync(f, 'utf8') + '//# sourceURL=' + f);
38
- },
39
- postMessage: function(msg) {
40
- parentPort.postMessage(msg);
41
- },
42
- performance: global.performance || {
43
- now: function() {
44
- return Date.now();
45
- }
46
- },
36
+ importScripts: (f) => (0, eval)(fs.readFileSync(f, 'utf8') + '//# sourceURL=' + f),
37
+ postMessage: (msg) => parentPort.postMessage(msg),
38
+ performance: global.performance || { now: Date.now },
47
39
  });
48
40
  }
49
41
 
@@ -65,7 +57,7 @@ function threadPrintErr() {
65
57
  }
66
58
  function threadAlert() {
67
59
  var text = Array.prototype.slice.call(arguments).join(' ');
68
- postMessage({cmd: 'alert', text: text, threadId: Module['_pthread_self']()});
60
+ postMessage({cmd: 'alert', text, threadId: Module['_pthread_self']()});
69
61
  }
70
62
  // We don't need out() for now, but may need to add it if we want to use it
71
63
  // here. Or, if this code all moves into the main JS, that problem will go
@@ -73,6 +65,7 @@ function threadAlert() {
73
65
  var out = () => { throw 'out() is not defined in worker.js.'; }
74
66
  var err = threadPrintErr;
75
67
  self.alert = threadAlert;
68
+ var dbg = threadPrintErr;
76
69
 
77
70
  Module['instantiateWasm'] = (info, receiveInstance) => {
78
71
  // Instantiate from the module posted from the main thread.
@@ -90,7 +83,7 @@ Module['instantiateWasm'] = (info, receiveInstance) => {
90
83
  // Turn unhandled rejected promises into errors so that the main thread will be
91
84
  // notified about them.
92
85
  self.onunhandledrejection = (e) => {
93
- throw e.reason ?? e;
86
+ throw e.reason || e;
94
87
  };
95
88
 
96
89
  function handleMessage(e) {
@@ -120,8 +113,8 @@ function handleMessage(e) {
120
113
  // Use `const` here to ensure that the variable is scoped only to
121
114
  // that iteration, allowing safe reference from a closure.
122
115
  for (const handler of e.data.handlers) {
123
- Module[handler] = function() {
124
- postMessage({ cmd: 'callHandler', handler, args: [...arguments] });
116
+ Module[handler] = (...args) => {
117
+ postMessage({ cmd: 'callHandler', handler, args: args });
125
118
  }
126
119
  }
127
120
 
@@ -143,7 +136,7 @@ function handleMessage(e) {
143
136
  LibSANE(Module);
144
137
  } else if (e.data.cmd === 'run') {
145
138
  // Pass the thread address to wasm to store it for fast access.
146
- Module['__emscripten_thread_init'](e.data.pthread_ptr, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0, /*canBlock=*/1);
139
+ Module['__emscripten_thread_init'](e.data.pthread_ptr, /*is_main=*/0, /*is_runtime=*/0, /*can_block=*/1);
147
140
 
148
141
  // Await mailbox notifications with `Atomics.waitAsync` so we can start
149
142
  // using the fast `Atomics.notify` notification path.
@@ -186,11 +179,11 @@ function handleMessage(e) {
186
179
  // The received message looks like something that should be handled by this message
187
180
  // handler, (since there is a e.data.cmd field present), but is not one of the
188
181
  // recognized commands:
189
- err('worker.js received unknown command ' + e.data.cmd);
182
+ err(`worker.js received unknown command ${e.data.cmd}`);
190
183
  err(e.data);
191
184
  }
192
185
  } catch(ex) {
193
- err('worker.js onmessage() captured an uncaught exception: ' + ex);
186
+ err(`worker.js onmessage() captured an uncaught exception: ${ex}`);
194
187
  if (ex && ex.stack) err(ex.stack);
195
188
  if (Module['__emscripten_thread_crashed']) {
196
189
  Module['__emscripten_thread_crashed']();
@@ -200,5 +193,3 @@ function handleMessage(e) {
200
193
  };
201
194
 
202
195
  self.onmessage = handleMessage;
203
-
204
-
package/dist/index.d.ts CHANGED
@@ -497,3 +497,5 @@ export declare const libsane: LibSANEFactory;
497
497
  * Use the 'libsane' named export.
498
498
  */
499
499
  export default libsane;
500
+ export * from './options';
501
+ export * from './readers';
package/dist/index.js CHANGED
@@ -1,4 +1,18 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
2
16
  Object.defineProperty(exports, "__esModule", { value: true });
3
17
  exports.libsane = exports.SANEFrame = exports.SANEConstraintType = exports.SANEUnit = exports.SANEValueType = exports.SANEStatus = void 0;
4
18
  /**
@@ -79,3 +93,5 @@ exports.libsane = require('../lib');
79
93
  * Use the 'libsane' named export.
80
94
  */
81
95
  exports.default = exports.libsane;
96
+ __exportStar(require("./options"), exports);
97
+ __exportStar(require("./readers"), exports);
@@ -0,0 +1,127 @@
1
+ import { LibSANE, SANEOptionDescriptor, SANEStatus } from ".";
2
+ export interface ScanOption<T = any> {
3
+ index: number;
4
+ descriptor: SANEOptionDescriptor;
5
+ value: T;
6
+ }
7
+ export interface IScanOptions extends Iterable<ScanOption> {
8
+ /**
9
+ * List of all SANE options.
10
+ */
11
+ readonly options: ReadonlyArray<ScanOption>;
12
+ /**
13
+ * Well-known SANE option index zero (total number of options).
14
+ *
15
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
16
+ */
17
+ readonly zero: ScanOption<number>;
18
+ /**
19
+ * Well-known SANE option `resolution`.
20
+ *
21
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
22
+ */
23
+ readonly resolution: ScanOption<number> | null;
24
+ /**
25
+ * Well-known SANE option `preview`.
26
+ *
27
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
28
+ */
29
+ readonly preview: ScanOption<boolean> | null;
30
+ /**
31
+ * Well-known SANE option `tl-x`.
32
+ *
33
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
34
+ */
35
+ readonly tlX: ScanOption<number> | null;
36
+ /**
37
+ * Well-known SANE option `tl-y`.
38
+ *
39
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
40
+ */
41
+ readonly tlY: ScanOption<number> | null;
42
+ /**
43
+ * Well-known SANE option `br-x`.
44
+ *
45
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
46
+ */
47
+ readonly brX: ScanOption<number> | null;
48
+ /**
49
+ * Well-known SANE option `br-y`.
50
+ *
51
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#well-known-options}
52
+ */
53
+ readonly brY: ScanOption<number> | null;
54
+ }
55
+ /**
56
+ * @private
57
+ */
58
+ export declare abstract class ScanOptionsBase implements IScanOptions {
59
+ protected _lib: LibSANE;
60
+ readonly options: ReadonlyArray<ScanOption>;
61
+ readonly zero: ScanOption<number>;
62
+ readonly resolution: ScanOption<number> | null;
63
+ readonly preview: ScanOption<boolean> | null;
64
+ readonly tlX: ScanOption<number> | null;
65
+ readonly tlY: ScanOption<number> | null;
66
+ readonly brX: ScanOption<number> | null;
67
+ readonly brY: ScanOption<number> | null;
68
+ [Symbol.iterator](): IterableIterator<ScanOption>;
69
+ protected static _getOpts(lib: LibSANE): Promise<ScanOption<any>[]>;
70
+ protected constructor(lib: LibSANE, opts: Array<ScanOption>);
71
+ protected _setOpts(this: {
72
+ -readonly [K in keyof ScanOptionsBase]: ScanOptionsBase[K];
73
+ }, opts: Array<ScanOption>): void;
74
+ protected _setValue(index: number, value: any): Promise<{
75
+ status: SANEStatus.UNSUPPORTED | SANEStatus.CANCELLED | SANEStatus.DEVICE_BUSY | SANEStatus.INVAL | SANEStatus.EOF | SANEStatus.JAMMED | SANEStatus.NO_DOCS | SANEStatus.COVER_OPEN | SANEStatus.IO_ERROR | SANEStatus.NO_MEM | SANEStatus.ACCESS_DENIED;
76
+ info: null;
77
+ opts: null;
78
+ } | {
79
+ status: SANEStatus.GOOD;
80
+ info: import(".").SANEInfo;
81
+ opts: ScanOption<any>[];
82
+ }>;
83
+ /**
84
+ * Get class instance (with all scanning options).
85
+ */
86
+ static get: (lib: LibSANE) => Promise<IScanOptions>;
87
+ /**
88
+ * Set option value. Use `null` as `value` for automatic.
89
+ *
90
+ * @see {@link https://sane-project.gitlab.io/standard/1.06/api.html#sane-control-option}
91
+ */
92
+ abstract setValue(index: number, value: any): any;
93
+ }
94
+ /**
95
+ * Helper class for getting/setting scan options.
96
+ *
97
+ * Any changes (i.e. calls to {@link ScanOptionsMutable.setValue}) affect the
98
+ * internal state.
99
+ */
100
+ export declare class ScanOptionsMutable extends ScanOptionsBase {
101
+ static get(lib: LibSANE): Promise<ScanOptionsMutable>;
102
+ setValue(index: number, value: any): Promise<{
103
+ status: SANEStatus.GOOD;
104
+ info: import(".").SANEInfo;
105
+ } | {
106
+ status: SANEStatus.UNSUPPORTED | SANEStatus.CANCELLED | SANEStatus.DEVICE_BUSY | SANEStatus.INVAL | SANEStatus.EOF | SANEStatus.JAMMED | SANEStatus.NO_DOCS | SANEStatus.COVER_OPEN | SANEStatus.IO_ERROR | SANEStatus.NO_MEM | SANEStatus.ACCESS_DENIED;
107
+ info: null;
108
+ }>;
109
+ }
110
+ /**
111
+ * Helper class for getting/setting scan options.
112
+ *
113
+ * Any changes (i.e. calls to {@link ScanOptions.setValue}) return a
114
+ * new class instance.
115
+ */
116
+ export declare class ScanOptions extends ScanOptionsBase {
117
+ static get(lib: LibSANE): Promise<ScanOptions>;
118
+ setValue(index: number, value: any): Promise<{
119
+ status: SANEStatus.GOOD;
120
+ info: import(".").SANEInfo;
121
+ updated: ScanOptions;
122
+ } | {
123
+ status: SANEStatus.UNSUPPORTED | SANEStatus.CANCELLED | SANEStatus.DEVICE_BUSY | SANEStatus.INVAL | SANEStatus.EOF | SANEStatus.JAMMED | SANEStatus.NO_DOCS | SANEStatus.COVER_OPEN | SANEStatus.IO_ERROR | SANEStatus.NO_MEM | SANEStatus.ACCESS_DENIED;
124
+ info: null;
125
+ updated: null;
126
+ }>;
127
+ }
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.ScanOptions = exports.ScanOptionsMutable = exports.ScanOptionsBase = void 0;
13
+ const _1 = require(".");
14
+ /**
15
+ * @private
16
+ */
17
+ class ScanOptionsBase {
18
+ [Symbol.iterator]() {
19
+ return this.options[Symbol.iterator]();
20
+ }
21
+ static _getOpts(lib) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const opts = [];
24
+ let desc = null;
25
+ for (let i = 0, n = -1; desc || i === 0; i++) {
26
+ ({ option_descriptor: desc } = lib.sane_get_option_descriptor(i));
27
+ if (desc) {
28
+ if (!desc.cap.INACTIVE && desc.cap.SOFT_DETECT && desc.type !== _1.SANEValueType.BUTTON) {
29
+ const { status, value } = yield lib.sane_control_option_get_value(i);
30
+ if (status !== _1.SANEStatus.GOOD) {
31
+ throw new Error(`Unexpected status ${_1.SANEStatus[status]} while getting option value.`);
32
+ }
33
+ opts.push({ index: i, descriptor: desc, value });
34
+ if (i === 0) {
35
+ n = value; // option 0 contains total number of options
36
+ }
37
+ }
38
+ else {
39
+ opts.push({ index: i, descriptor: desc, value: null });
40
+ }
41
+ }
42
+ else if (!desc && i !== n) {
43
+ throw new Error('Unexpected number of options.');
44
+ }
45
+ }
46
+ return opts;
47
+ });
48
+ }
49
+ constructor(lib, opts) {
50
+ this.resolution = null;
51
+ this.preview = null;
52
+ this.tlX = null;
53
+ this.tlY = null;
54
+ this.brX = null;
55
+ this.brY = null;
56
+ this._lib = lib;
57
+ this._setOpts(opts);
58
+ }
59
+ _setOpts(opts) {
60
+ this.options = opts;
61
+ this.zero = this.options[0];
62
+ for (let i = 0; i < this.options.length; i++) {
63
+ if (this.options[i].index !== i) {
64
+ throw new Error(`Option index mismatch ${this.options[i].index} != ${i}.`);
65
+ }
66
+ switch (this.options[i].descriptor.name) {
67
+ case 'resolution':
68
+ this.resolution = this.options[i];
69
+ break;
70
+ case 'preview':
71
+ this.preview = this.options[i];
72
+ break;
73
+ case 'tl-x':
74
+ this.tlX = this.options[i];
75
+ break;
76
+ case 'tl-y':
77
+ this.tlY = this.options[i];
78
+ break;
79
+ case 'br-x':
80
+ this.brX = this.options[i];
81
+ break;
82
+ case 'br-y':
83
+ this.brY = this.options[i];
84
+ break;
85
+ }
86
+ }
87
+ }
88
+ _setValue(index, value) {
89
+ return __awaiter(this, void 0, void 0, function* () {
90
+ const auto = value === null; // null means auto
91
+ const { status, info } = auto ? yield this._lib.sane_control_option_set_auto(index) : yield this._lib.sane_control_option_set_value(index, value);
92
+ if (status !== _1.SANEStatus.GOOD) {
93
+ return { status, info, opts: null };
94
+ }
95
+ if (info.RELOAD_OPTIONS) {
96
+ return { status, info, opts: yield ScanOptionsBase._getOpts(this._lib) };
97
+ }
98
+ if (info.INEXACT || typeof value === 'number' || auto) {
99
+ // auto triggers get value... ok
100
+ // number triggers get value... this is a quirk for fixed numbers
101
+ // because the conversion from floating to fixed point happens
102
+ // on the library side, we might get INEXACT == false but in
103
+ // reality there were some small difference
104
+ // XXX: this could probably be fixed on the C side
105
+ const { status, value: v } = yield this._lib.sane_control_option_get_value(index);
106
+ if (status !== _1.SANEStatus.GOOD) {
107
+ throw new Error(`Unexpected status ${_1.SANEStatus[status]} while getting option value.`);
108
+ }
109
+ value = v;
110
+ }
111
+ // update value
112
+ const opts = [...this.options];
113
+ opts[index] = Object.assign(Object.assign({}, opts[index]), { value });
114
+ return { status, info, opts };
115
+ });
116
+ }
117
+ }
118
+ exports.ScanOptionsBase = ScanOptionsBase;
119
+ /**
120
+ * Helper class for getting/setting scan options.
121
+ *
122
+ * Any changes (i.e. calls to {@link ScanOptionsMutable.setValue}) affect the
123
+ * internal state.
124
+ */
125
+ class ScanOptionsMutable extends ScanOptionsBase {
126
+ static get(lib) {
127
+ return __awaiter(this, void 0, void 0, function* () {
128
+ return new this(lib, yield this._getOpts(lib));
129
+ });
130
+ }
131
+ setValue(index, value) {
132
+ return __awaiter(this, void 0, void 0, function* () {
133
+ const { status, info, opts } = yield this._setValue(index, value);
134
+ if (status == _1.SANEStatus.GOOD) {
135
+ this._setOpts(opts);
136
+ return { status, info };
137
+ }
138
+ return { status, info };
139
+ });
140
+ }
141
+ }
142
+ exports.ScanOptionsMutable = ScanOptionsMutable;
143
+ /**
144
+ * Helper class for getting/setting scan options.
145
+ *
146
+ * Any changes (i.e. calls to {@link ScanOptions.setValue}) return a
147
+ * new class instance.
148
+ */
149
+ class ScanOptions extends ScanOptionsBase {
150
+ static get(lib) {
151
+ return __awaiter(this, void 0, void 0, function* () {
152
+ return new this(lib, yield this._getOpts(lib));
153
+ });
154
+ }
155
+ setValue(index, value) {
156
+ return __awaiter(this, void 0, void 0, function* () {
157
+ const { status, info, opts } = yield this._setValue(index, value);
158
+ if (status == _1.SANEStatus.GOOD) {
159
+ return { status, info, updated: new ScanOptions(this._lib, opts) };
160
+ }
161
+ return { status, info, updated: null };
162
+ });
163
+ }
164
+ }
165
+ exports.ScanOptions = ScanOptions;
@@ -0,0 +1,108 @@
1
+ import { LibSANE, SANEParameters, SANEStatus } from ".";
2
+ declare abstract class EventBaseClass<T extends Record<keyof T, any[]>> {
3
+ private _firing;
4
+ private _listeners;
5
+ /**
6
+ * Add event listener.
7
+ */
8
+ on<K extends keyof T>(type: K, listener: (...args: T[K]) => void): void;
9
+ /**
10
+ * Fire event.
11
+ */
12
+ protected fire<K extends keyof T>(type: K, ...args: T[K]): Promise<null> | null;
13
+ }
14
+ /**
15
+ * @private Events types for {@link ScanDataReader}.
16
+ */
17
+ export interface ScanDataReaderEventMap extends Record<string, any[]> {
18
+ /**
19
+ * Scanning stop event.
20
+ */
21
+ start: [parameters: SANEParameters];
22
+ /**
23
+ * Scanning start event.
24
+ */
25
+ stop: [parameters: SANEParameters, error: Error | null];
26
+ /**
27
+ * Raw image data event.
28
+ */
29
+ data: [parameters: SANEParameters, data: Uint8Array];
30
+ }
31
+ /**
32
+ * Raw data reader that automatically handles SANE's read code flow.
33
+ *
34
+ * Use {@link ScanDataReader.on} to listen to events, available event types
35
+ * are declared on {@link ScanDataReaderEventMap}.
36
+ *
37
+ * A device should already be open with sane_open(), the reader will call
38
+ * sane_start() do the scanning and call sane_stop().
39
+ *
40
+ * Other SANE functions cannot be used while scanning.
41
+ *
42
+ * Scan readers are single use.
43
+ *
44
+ * {@link https://sane-project.gitlab.io/standard/1.06/api.html#code-flow}
45
+ */
46
+ export declare class ScanDataReader<T extends ScanDataReaderEventMap = ScanDataReaderEventMap> extends EventBaseClass<T> {
47
+ private _lib;
48
+ private _used;
49
+ private _killed;
50
+ constructor(lib: LibSANE);
51
+ private _readPromise;
52
+ /**
53
+ * Start scanning operation.
54
+ */
55
+ start(): {
56
+ status: SANEStatus.UNSUPPORTED | SANEStatus.CANCELLED | SANEStatus.DEVICE_BUSY | SANEStatus.INVAL | SANEStatus.EOF | SANEStatus.JAMMED | SANEStatus.NO_DOCS | SANEStatus.COVER_OPEN | SANEStatus.IO_ERROR | SANEStatus.NO_MEM | SANEStatus.ACCESS_DENIED;
57
+ parameters: null;
58
+ promise: Promise<void>;
59
+ } | {
60
+ status: SANEStatus.GOOD;
61
+ parameters: SANEParameters;
62
+ promise: Promise<void>;
63
+ };
64
+ /**
65
+ * Cancel scanning operation.
66
+ */
67
+ cancel(): void;
68
+ }
69
+ /**
70
+ * @private Events types for {@link ScanImageReader}.
71
+ */
72
+ export interface ScanImageReaderEventMap extends ScanDataReaderEventMap {
73
+ /**
74
+ * Image line event, one or more full lines of RGBA data.
75
+ */
76
+ line: [parameters: SANEParameters, data: Uint8ClampedArray, line: number];
77
+ /**
78
+ * Full image event (end of scan), RGBA data.
79
+ */
80
+ image: [parameters: SANEParameters, data: Uint8ClampedArray];
81
+ }
82
+ /**
83
+ * Image reader that automatically generates RGBA data while reading from
84
+ * SANE's API using {@link ScanDataReader}. It supports the most common scan
85
+ * modes and image formats. More formats can be added in the future.
86
+ *
87
+ * Use {@link ScanImageReader.on} to listen to events, available event types
88
+ * are declared on {@link ScanImageReaderEventMap}.
89
+ *
90
+ * A device should already be open with sane_open(), the reader will call
91
+ * sane_start() do the scanning and call sane_stop().
92
+ *
93
+ * Other SANE functions cannot be used while scanning.
94
+ *
95
+ * Scan readers are single use.
96
+ *
97
+ * {@link https://sane-project.gitlab.io/standard/1.06/api.html#code-flow}
98
+ */
99
+ export declare class ScanImageReader<T extends ScanImageReaderEventMap = ScanImageReaderEventMap> extends ScanDataReader<T> {
100
+ private _line;
101
+ private _allData;
102
+ private _remainder;
103
+ constructor(lib: LibSANE);
104
+ private _onStart;
105
+ private _onData;
106
+ private _onStop;
107
+ }
108
+ export {};