UNPKG

webmonome

Version:

communicate with devices beyond a translator

17 lines (16 loc) 7 kB
'use strict';Object.defineProperty(exports,"__esModule",{value:!0});let MSG_PREFIX="WebMonome: ",ERR_NOT_SUPPORTED="device type not yet supported",ERR_WRITE="write error",ERR_WRITE_MISSING_BYTES="write is missing bytes",WARN_NO_USB="this browser does not support WebUsb.",USB_XFER_STATUS_OK="ok";function clamp(a,b,c){return Math.max(Math.min(a,c),b)}function packLineData(a){let b=0;for(let c=0;c<Math.min(8,a.length);c++)b|=clamp(a[c],0,1)<<c;return b}function err(a){throw Error(MSG_PREFIX+a);} function log(a,b=0){console[["log","warn","error"][b]](MSG_PREFIX+a)} class Monome extends EventTarget{constructor(a){super();this.device=a;this.callbacks={};this.endpointIn=getEndpoint(a,"in");this.endpointOut=getEndpoint(a,"out")}async listen(){if(this.isConnected){var a=await this.read(64);"ok"===a.status&&0<a.data.byteLength&&this.processData(a.data,0);await this.listen()}}async read(a){if(this.isConnected)return this.device.transferIn(this.endpointIn,a)}async write(a){a=new Uint8Array(a);let b=await this.device.transferOut(this.endpointOut,a);b.status!==USB_XFER_STATUS_OK&& err(ERR_WRITE);b.bytesWritten!==a.byteLength&&err(ERR_WRITE_MISSING_BYTES);return b}get isConnected(){return!(!this.device||!this.device.opened)}emit(a,b){a=new CustomEvent(a,{detail:b});this.dispatchEvent(a);return a}} let getEndpointsForDevice=a=>a.configuration.interfaces[getInterfaceForVendor(a.vendorId)].alternates[0].endpoints,getEndpoint=(a,b)=>{const c={in:1,out:2};let d;try{d=getEndpointsForDevice(a).find(({direction:e})=>e===b)}catch(e){log(e,2)}return d?d.endpointNumber:c[b]},ADDR_SYSTEM=0,ADDR_LED_GRID=1,ADDR_KEY_GRID=2,SYS_QUERY=0,SYS_GET_ID=1,SYS_GET_GRID_SIZES=5,SYS_QUERY_RESPONSE=0,SYS_ID=1,SYS_GRID_SIZE=3,CMD_LED_OFF=0,CMD_LED_ON=1,CMD_LED_ALL_OFF=2,CMD_LED_ALL_ON=3,CMD_LED_MAP=4,CMD_LED_ROW=5,CMD_LED_COLUMN= 6,CMD_LED_INTENSITY=7,CMD_LED_LEVEL_SET=8,CMD_LED_LEVEL_ALL=9,CMD_LED_LEVEL_MAP=10,CMD_LED_LEVEL_ROW=11,CMD_LED_LEVEL_COLUMN=12,CMD_KEY_UP=0,CMD_KEY_DOWN=1,packHeader=(a,b)=>(a&15)<<4|b&15,packBuffer=([a,b,...c])=>[packHeader(a,b),...(Array.isArray(c)?c:[])],packIntensityData=(a,b)=>{const c=[];for(var d=0;d<Math.ceil(b/2);d++)c[d]=0;for(d=0;d<Math.min(b,a.length);d++){const e=Math.floor(d/2),f=0===d%2?4:0;"number"!==typeof c[e]&&(c[e]=0);c[e]|=clamp(a[d],0,15)<<f}return c}; class Mext extends Monome{constructor(a){super(a)}processData(a,b){switch(a.getUint8(b++)){case packHeader(ADDR_SYSTEM,SYS_QUERY_RESPONSE):this.emit("query",{type:a.getUint8(b++),count:a.getUint8(b++)});break;case packHeader(ADDR_SYSTEM,SYS_ID):let c="";for(let d=0;32>d;d++)c+=String.fromCharCode(a.getUint8(b++));this.emit("getId",c);break;case packHeader(ADDR_SYSTEM,SYS_GRID_SIZE):this.emit("getGridSize",{x:a.getUint8(b++),y:a.getUint8(b++)});break;case packHeader(ADDR_KEY_GRID,CMD_KEY_DOWN):this.emit("gridKeyDown", {x:a.getUint8(b++),y:a.getUint8(b++)});break;case packHeader(ADDR_KEY_GRID,CMD_KEY_UP):this.emit("gridKeyUp",{x:a.getUint8(b++),y:a.getUint8(b++)})}a.byteLength>b+1&&this.processData(a,b)}query(){return this.writeBuffer(ADDR_SYSTEM,SYS_QUERY)}getId(){return this.writeBuffer(ADDR_SYSTEM,SYS_GET_ID)}getGridSize(){return this.writeBuffer(ADDR_SYSTEM,SYS_GET_GRID_SIZES)}gridLed(a,b,c){return this.writeBuffer(ADDR_LED_GRID,c?CMD_LED_ON:CMD_LED_OFF,a,b)}gridLedAll(a){return this.writeBuffer(ADDR_LED_GRID, a?CMD_LED_ALL_ON:CMD_LED_ALL_OFF)}gridLedCol(a,b,c){if(Array.isArray(c))return this.writeBuffer(ADDR_LED_GRID,CMD_LED_COLUMN,a,b,packLineData(c))}gridLedRow(a,b,c){if(Array.isArray(c))return this.writeBuffer(ADDR_LED_GRID,CMD_LED_ROW,a,b,packLineData(c))}gridLedMap(a,b,c){if(Array.isArray(c)){var d=[0,0,0,0,0,0,0,0];for(let e=0;e<Math.min(64,c.length);e++){let f=Math.floor(e/8),g=e%8;d[f]|=clamp(c[e],0,1)<<g}return this.writeBuffer(ADDR_LED_GRID,CMD_LED_MAP,a,b,...d)}}gridLedIntensity(a){return this.writeBuffer(ADDR_LED_GRID, CMD_LED_INTENSITY,clamp(a,0,15))}gridLedLevel(a,b,c){return this.writeBuffer(ADDR_LED_GRID,CMD_LED_LEVEL_SET,a,b,clamp(c,0,15))}gridLedLevelAll(a){return this.writeBuffer(ADDR_LED_GRID,CMD_LED_LEVEL_ALL,clamp(a,0,15))}gridLedLevelCol(a,b,c){if(Array.isArray(c))return this.writeBuffer(ADDR_LED_GRID,CMD_LED_LEVEL_COLUMN,a,b,...packIntensityData(c,8))}gridLedLevelRow(a,b,c){if(Array.isArray(c))return this.writeBuffer(ADDR_LED_GRID,CMD_LED_LEVEL_ROW,a,b,...packIntensityData(c,8))}gridLedLevelMap(a,b, c){if(Array.isArray(c))return this.writeBuffer(ADDR_LED_GRID,CMD_LED_LEVEL_MAP,a,b,...packIntensityData(c,64))}writeBuffer(){return this.write(packBuffer(Array.from(arguments)))}}let PROTO_SERIES_BUTTON_DOWN=0,PROTO_SERIES_BUTTON_UP=16,PROTO_SERIES_LED_ON=32,PROTO_SERIES_LED_OFF=48,PROTO_SERIES_LED_ROW_8=64,PROTO_SERIES_LED_COL_8=80,PROTO_SERIES_LED_ROW_16=96,PROTO_SERIES_LED_COL_16=112,PROTO_SERIES_CLEAR=144,PROTO_SERIES_INTENSITY=160; class Series extends Monome{constructor(a){super(a)}processData(a,b){let c;switch(a.getUint8(b++)){case PROTO_SERIES_BUTTON_DOWN:var d=a.getUint8(b++);[d,c]=[d>>4,d&15];this.emit("gridKeyDown",{x:d,y:c});break;case PROTO_SERIES_BUTTON_UP:d=a.getUint8(b++),[d,c]=[d>>4,d&15],this.emit("gridKeyUp",{x:d,y:c})}a.byteLength>b+1&&this.processData(a,b)}query(){}getId(){}getGridSize(){let [,a]=this.device.serialNumber.match(/^m(64|128|256)/);this.emit("getGridSize",{64:{x:8,y:8},128:{x:16,y:8},256:{x:16,y:16}}[a])}gridLed(a, b,c){return this.write([c?PROTO_SERIES_LED_ON:PROTO_SERIES_LED_OFF,a<<4|b])}gridLedAll(a){return this.write([PROTO_SERIES_CLEAR|a&1])}gridLedCol(a,b,c){if(Array.isArray(c))return this.write([(8===c.length?PROTO_SERIES_LED_COL_8:PROTO_SERIES_LED_COL_16)|a&15,packLineData(c)])}gridLedRow(a,b,c){if(Array.isArray(c))return this.write([(8===c.length?PROTO_SERIES_LED_ROW_8:PROTO_SERIES_LED_ROW_16)|b&15,packLineData(c)])}gridLedMap(a,b,c){}gridLedIntensity(a){return this.write([PROTO_SERIES_INTENSITY|clamp(a, 0,15)&15])}gridLedLevel(a,b,c){return this.gridLed(a,b,7<c)}gridLedLevelAll(a){return this.gridLedIntensity(a)}gridLedLevelCol(a,b,c){return this.gridLedCol(a,b,c.map(d=>7<d))}gridLedLevelRow(a,b,c){return this.gridLedRow(a,b,c.map(d=>7<d))}gridLedLevelMap(a,b,c){}}let VENDOR_ID_GENESIS=1027,VENDOR_ID_2021=1155,interfaceMap={[VENDOR_ID_GENESIS]:0,[VENDOR_ID_2021]:1},getInterfaceForVendor=a=>interfaceMap[a]||0,hasUsb="navigator"in window&&"usb"in navigator; var webmonome={async connect(){if(!hasUsb)return log(WARN_NO_USB,1);let a;try{a=await navigator.usb.requestDevice({filters:[{vendorId:VENDOR_ID_GENESIS},{vendorId:VENDOR_ID_2021}]});await a.open();null===a.configuration&&await a.selectConfiguration(1);await a.claimInterface(getInterfaceForVendor(a.vendorId));let b=factory(a);b.listen();return b}catch(b){throw b;}}};function factory(a){return new ({mext:Mext,series:Series}[deviceType(a)])(a)} function deviceType(a){if(/^m(64|128|256)/.test(a.serialNumber)||/^mk/.test(a.serialNumber))return"series";if(/^[Mm]\d+/.test(a.serialNumber))return"mext";err(ERR_NOT_SUPPORTED)}exports.default=webmonome;exports.getInterfaceForVendor=getInterfaceForVendor