2 var <name, <bustype=0, <vendor, <product, <version=0;
4 *new{arg product, bustype, vendorID, productID, version;
5 ^super.newCopyArgs( product, bustype, vendorID, productID, version ).init;
12 super.printOn(stream);
13 stream << $( << name << ", ";
19 ].collect({ | x | "0x" ++ x.asHexString(4) }).printItemsOn(stream);
25 var <manufacturer, < product, <usage, < vendorID, < productID, < locID, < version, < serial;
27 var < isQueued = false;
28 var < info, <> closeAction;
30 *new{arg manufacturer, product, usage, vendorID, productID, locID, version, serial;
31 ^super.newCopyArgs(manufacturer, product, usage, vendorID, productID, locID, version, serial).init;
34 info = HIDInfo.new( product, 0, vendorID, productID, version );
39 value{arg elementNum=0;
40 ^HIDDeviceService.value(locID,elements.at(elementNum).cookie)
42 valueByCookie{arg cookie;
43 ^HIDDeviceService.value(locID,cookie)
45 setValue{|elementNum, val|
46 HIDDeviceService.setValue(locID,elements.at(elementNum).cookie, val)
48 setValueByCookie{|cookie, val|
49 HIDDeviceService.setValue(locID,cookie, val)
53 HIDDeviceService.queueDevice(locID);
58 HIDDeviceService.dequeueDevice(locID);
61 queueElement{arg elementNum=0;
62 HIDDeviceService.queueElement(locID, elements.at(elementNum).cookie);
65 dequeueElement{arg elementNum=0;
66 HIDDeviceService.dequeueElement(locID, elements.at(elementNum).cookie);
70 ("WARNING: Device was removed: " + info).postln;
75 prAddElement{arg type, usage, cookie, min, max, ioType, usagePage, usageType;
76 elements = elements.add(HIDDeviceElement(type, usage, cookie, min, max, ioType, usagePage, usageType));
81 var < type, <usage, < cookie, <min, <max, <ioType, <usagePage, < usageType;
82 *new{arg type, usage, cookie, min, max, ioType, usagePage, usageType;
83 ^super.newCopyArgs(type, usage, cookie, min, max, ioType, usagePage, usageType);
86 // HIDDeviceService.setValue(locID, cookie, val)
92 classvar < devices, <> action;
93 classvar < initialized = false;
94 classvar < deviceSpecs;
95 classvar < eventLoopIsRunning = false;
96 classvar <> closeAction;
99 deviceSpecs = IdentityDictionary.new;
101 ShutDown.add( { this.releaseDeviceList } );
104 *keyToIndex { arg key, locID=0;
105 var device, deviceSpec;
106 device = devices.at(locID);
107 ^if(device.isNil, { ^nil }, {
108 deviceSpec = deviceSpecs.at(device.product.asSymbol);
109 if(deviceSpec.notNil, { deviceSpec.at(key) }, { nil });
113 *value{arg locID, cookie;
117 *setValue{arg locID, cookie, value;
121 *buildDeviceList{arg usagePage=1, usage=4;
122 var devlist, elelist;
124 alreadyOpen = devices.select( _.isQueued ).asArray;
125 alreadyOpen.do{ |it| it.dequeueDevice };
126 alreadyOpen = alreadyOpen.collect( _.locID ).asArray;
127 //alreadyOpen.postln;
128 // the following line would solve the bug when rebuilding the device list, but then there is no way to keep track of already opened devices:
129 this.releaseDeviceList;
131 devlist = this.prbuildDeviceList(usagePage, usage);
132 devlist ?? {"HIDDeviceService: no devices found".warn; ^nil};
135 // this is an ugly, ugly workaround:
136 if ( dev.isKindOf( Array ), {
137 if ( dev[0].isKindOf( String ) and: dev[1].isKindOf( String ) and: dev[2].isKindOf( String ) and: dev[7].isKindOf( String ) and: dev[3].isKindOf( Integer ) and: dev[4].isKindOf( Integer ) and: dev[5].isKindOf( Integer ) and: dev[6].isKindOf( Integer ), {
138 newdev = HIDDevice(dev.at(0), dev.at(1), dev.at(2), dev.at(3), dev.at(4), dev.at(5), dev.at(6), dev.at(7));
139 elelist = this.prbuildElementList(newdev.locID,
140 Array.newClear(HIDDeviceService.prGetElementListSize(newdev.locID)));
143 newdev.prAddElement(ele.at(0), ele.at(1), ele.at(2), ele.at(3), ele.at(4), ele.at(5), ele.at(6), ele.at(7));
146 devices = devices.add(newdev);
147 // reopen the device if it already was open
148 if ( alreadyOpen.includes( newdev.locID ) ){
157 *prbuildDeviceList{arg usagePage=1, usage;
159 ^this.primitiveFailed
161 *prbuildElementList{arg locID;
163 ^this.primitiveFailed
165 *prGetElementListSize{arg locID;
166 _HIDGetElementListSize
167 ^this.primitiveFailed
170 //must be called before closing the program..
172 this.prreleaseDeviceList;
176 *prreleaseDeviceList{
177 //must be called before closing the program..
178 _HIDReleaseDeviceList
180 *runEventLoop {arg rate=0.002;
181 eventLoopIsRunning.if({
182 "META_HIDDeviceService-runEventLoop: \n\t stopping and restarting running eventLoop".warn;
185 this.pr_runEventLoop(rate);
186 eventLoopIsRunning = true;
189 *pr_runEventLoop{arg rate;
193 this.pr_stopEventLoop;
194 eventLoopIsRunning = false;
200 *prHidAction{arg vendorID, productID, locID, cookie, val;
201 action.value(vendorID, productID, locID, cookie, val);
204 *prReadError{ arg locID;
206 HIDDeviceService.dequeueDevice( locID );
207 dev = devices.detect( { |dv| dv.locID == locID } );
209 closeAction.value( locID );
212 *queueDevice{arg locID;
214 ^this.primitiveFailed
217 *dequeueDevice{arg locID;
219 ^this.primitiveFailed
222 *queueElement{arg locID, cookie;
224 ^this.primitiveFailed
227 *dequeueElement{arg locID, cookie;
229 ^this.primitiveFailed
233 //HIDDeviceService by jan trutzschler v. falkenstein [10/2003]
235 these are values to pass in buildDeviceList(usagePage, usage);
236 this is an incomplete list.
237 for more look at IOHIDUsageTables.h
239 most common usagePages for hid:
242 kHIDPage_Undefined = 0x00,
243 kHIDPage_GenericDesktop = 0x01,
244 kHIDPage_Simulation = 0x02,
246 kHIDPage_Sport = 0x04,
247 kHIDPage_Game = 0x05,
249 most common usage for hid:
251 /* GenericDesktop Page (0x01) */
254 kHIDUsage_GD_Pointer = 0x01, /* Physical Collection */
255 kHIDUsage_GD_Mouse = 0x02, /* Application Collection */
257 kHIDUsage_GD_Joystick = 0x04, /* Application Collection */
258 kHIDUsage_GD_GamePad = 0x05, /* Application Collection */
259 kHIDUsage_GD_Keyboard = 0x06, /* Application Collection */
260 kHIDUsage_GD_Keypad = 0x07, /* Application Collection */
261 kHIDUsage_GD_MultiAxisController = 0x08, /* Application Collection */
264 /* Simulation Page (0x02) */
265 /* This section provides detailed descriptions of the usages employed by simulation devices. */
268 kHIDUsage_Sim_FlightSimulationDevice = 0x01, /* Application Collection */
269 kHIDUsage_Sim_AutomobileSimulationDevice = 0x02, /* Application Collection */
270 kHIDUsage_Sim_TankSimulationDevice = 0x03, /* Application Collection */
271 kHIDUsage_Sim_SpaceshipSimulationDevice = 0x04, /* Application Collection */
272 kHIDUsage_Sim_SubmarineSimulationDevice = 0x05, /* Application Collection */
273 kHIDUsage_Sim_SailingSimulationDevice = 0x06, /* Application Collection */
274 kHIDUsage_Sim_MotorcycleSimulationDevice = 0x07, /* Application Collection */
275 kHIDUsage_Sim_SportsSimulationDevice = 0x08, /* Application Collection */
276 kHIDUsage_Sim_AirplaneSimulationDevice = 0x09, /* Application Collection */
277 kHIDUsage_Sim_HelicopterSimulationDevice = 0x0A, /* Application Collection */
278 kHIDUsage_Sim_MagicCarpetSimulationDevice = 0x0B, /* Application Collection */
279 kHIDUsage_Sim_BicycleSimulationDevice = 0x0C, /* Application Collection */
280 /* 0x0D - 0x1F Reserved */
281 kHIDUsage_Sim_FlightControlStick = 0x20, /* Application Collection */
282 kHIDUsage_Sim_FlightStick = 0x21, /* Application Collection */
283 kHIDUsage_Sim_CyclicControl = 0x22, /* Physical Collection */
284 kHIDUsage_Sim_CyclicTrim = 0x23, /* Physical Collection */
285 kHIDUsage_Sim_FlightYoke = 0x24, /* Application Collection */
286 kHIDUsage_Sim_TrackControl = 0x25, /* Physical Collection */
289 /* Game Page (0x05) */
292 kHIDUsage_Game_3DGameController = 0x01, /* Application Collection */
293 kHIDUsage_Game_PinballDevice = 0x02, /* Application Collection */
294 kHIDUsage_Game_GunDevice = 0x03, /* Application Collection */