aes70
Version:
A controller library for the AES70 protocol.
193 lines (157 loc) • 4.49 kB
JavaScript
import { OcaPropertyID } from '../types/OcaPropertyID.js';
import { error } from '../log.js';
/*eslint no-constant-condition: ["error", { "checkLoops": false }]*/
/**
* Describes an AES70 property. Simplifies getting or setting properties
* and listening to property changes.
*/
export class Property {
constructor(
name,
type,
level,
index,
readonly,
is_static,
aliases,
accessors
) {
this.name = name;
this.type = type;
this.level = level;
this.index = index;
this.readonly = readonly;
this.static = is_static;
this.aliases = aliases;
if (!aliases && !accessors && !is_static) {
accessors = { get: 'Get' + name };
}
this.accessors = accessors;
}
/**
* Returns the OcaPropertyID of this property.
*/
GetPropertyID() {
return new OcaPropertyID(this.level, this.index);
}
/**
* Returns the name of this property.
*/
GetName() {
return this.name;
}
/**
* Returns the getter for this property in o.
*
* @param {Object} o - The remote object.
* @param {boolean} [no_bind=false] - If true, the returned function is not
* bound to the object o.
* @returns {Function} The getter. If none could be found, null is returned.
*/
getter(o, no_bind) {
const name = this.name;
const aliases = this.aliases;
const accessors = this.accessors;
if (accessors) {
const get = accessors.get;
if (!get) return null;
let fun;
if (typeof get === 'string') {
fun = o[get];
} else if (typeof get === 'object') {
const { name, index } = get;
if (index >= 0) {
fun = function (callback) {
if (typeof callback === 'function') {
this[name]((ok, result) => {
if (ok) {
result = result.item(index);
}
callback(ok, result);
});
} else {
return this[name]().then((result) => result.item(index));
}
};
} else {
fun = o[name];
}
} else {
throw new Error(`Unexpected accessor.`);
}
if (!fun) return null;
return no_bind ? fun : fun.bind(o);
}
// iterate all possible names
const possibleNames = aliases ? [name, ...aliases] : [name];
for (const possibleName of possibleNames) {
if (this.static) {
const c = o.constructor;
const v = c[possibleName];
if (v !== void 0) {
return function () {
return Promise.resolve(v);
};
}
} else {
const fun = o['Get' + possibleName];
if (fun) return no_bind ? fun : fun.bind(o);
}
}
return null;
}
/**
* Returns the setter for this property in o.
*
* @param {Object} o - The remote object.
* @param {boolean} [no_bind=false] - If true, the returned function is not
* bound to the object o.
* @returns {Function} The setter. If none could be found, null is returned.
*/
setter(o, no_bind) {
if (this.readonly || this.static) return null;
const name = this.name;
const aliases = this.aliases;
const possibleNames = aliases ? [name, ...aliases] : [name];
for (const possibleName of possibleNames) {
const fun = o['Set' + possibleName];
if (fun) return no_bind ? fun : fun.bind(o);
}
return null;
}
/**
* Returns the event for this property in o.
*
* @returns {PropertyEvent} The event.
*/
event(o) {
let name = this.name,
i = 0;
const aliases = this.aliases;
do {
const event = o['On' + name + 'Changed'];
if (event) return event;
if (aliases && i < aliases.length) {
name = aliases[i++];
continue;
}
} while (false);
return null;
}
/**
* Subscribe to changes of this property in o. If successful, the callback will be called at least
* once with the initial value.
*
* @param {Object} o - The remote object.
* @param {Function} cb - The callback.
* @returns {boolean} Returns true if the property could be subscribed.
*/
subscribe(o, cb) {
const event = this.event(o);
const getter = this.getter(o);
if (event) event.subscribe(cb).catch(error);
if (getter) getter().then(cb, error);
if (event) return event;
return !!getter;
}
}