HelpBrowser: path box becomes a more conventional search box
[supercollider.git] / SCClassLibrary / Common / Control / HIDDeviceService.sc
bloba1a7c5d1137360a3bfa9eceb793e9b69d519de80
1 HIDInfo{
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;
6         }
8         init{
9         }
11         printOn { | stream |
12                 super.printOn(stream);
13                 stream << $( << name << ", ";
14                 [
15                         bustype,
16                         vendor,
17                         product,
18                         version
19                 ].collect({ | x | "0x" ++ x.asHexString(4) }).printItemsOn(stream);
20                 stream.put($));
21         }
24 HIDDevice {
25         var <manufacturer, < product, <usage, < vendorID, < productID, < locID, < version, < serial;
26         var < elements;
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;
32         }
33         init{
34                 info = HIDInfo.new( product, 0, vendorID, productID, version );
35                 closeAction = {};
36                 elements = Array.new;
37         }
39         value{arg elementNum=0;
40                 ^HIDDeviceService.value(locID,elements.at(elementNum).cookie)
41         }
42         valueByCookie{arg cookie;
43                 ^HIDDeviceService.value(locID,cookie)
44         }
45         setValue{|elementNum, val|
46                 HIDDeviceService.setValue(locID,elements.at(elementNum).cookie, val)
47         }
48         setValueByCookie{|cookie, val|
49                 HIDDeviceService.setValue(locID,cookie, val)
50         }
51         queueDevice{
52                 isQueued = true;
53                 HIDDeviceService.queueDevice(locID);
54         }
56         dequeueDevice{
57                 isQueued = false;
58                 HIDDeviceService.dequeueDevice(locID);
59         }
61         queueElement{arg elementNum=0;
62                 HIDDeviceService.queueElement(locID, elements.at(elementNum).cookie);
63         }
65         dequeueElement{arg elementNum=0;
66                 HIDDeviceService.dequeueElement(locID, elements.at(elementNum).cookie);
67         }
69         wasClosed{
70                 ("WARNING: Device was removed: " + info).postln;
71                 closeAction.value;
72         }
74         //private:
75         prAddElement{arg type, usage, cookie, min, max, ioType, usagePage, usageType;
76                 elements = elements.add(HIDDeviceElement(type, usage, cookie, min, max, ioType, usagePage, usageType));
77         }
80 HIDDeviceElement {
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);
84         }
85 //      value_{|val|
86 //              HIDDeviceService.setValue(locID, cookie, val)
88 //      }
91 HIDDeviceService{
92         classvar < devices, <> action;
93         classvar < initialized = false;
94         classvar < deviceSpecs;
95         classvar < eventLoopIsRunning = false;
96         classvar <> closeAction;
98         *initClass {
99                 deviceSpecs = IdentityDictionary.new;
100                 closeAction = {};
101                 ShutDown.add( { this.releaseDeviceList } );
102         }
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 });
110                 })
111         }
113         *value{arg locID, cookie;
114                 _HIDGetValue
115         }
117         *setValue{arg locID, cookie, value;
118                 _HIDSetValue
119         }
121         *buildDeviceList{arg usagePage=1, usage=4;
122                 var devlist, elelist;
123                 var alreadyOpen;
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;
130                 devices = Array.new;
131                 devlist = this.prbuildDeviceList(usagePage, usage);
132                 devlist ?? {"HIDDeviceService: no devices found".warn; ^nil};
133                 devlist.do({arg dev;
134                         var newdev;
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)));
141                                         elelist.do({arg ele;
142                                                 if(ele.notNil){
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));
144                                                 };
145                                         });
146                                         devices = devices.add(newdev);
147                                         // reopen the device if it already was open
148                                         if ( alreadyOpen.includes( newdev.locID ) ){
149                                                 newdev.queueDevice;     
150                                         }
151                                 });
152                         });
153                 });
154                 initialized = true;
155         }
157         *prbuildDeviceList{arg usagePage=1, usage;
158                 _HIDBuildDeviceList
159                 ^this.primitiveFailed
160         }
161         *prbuildElementList{arg locID;
162                 _HIDBuildElementList
163                 ^this.primitiveFailed
164         }
165         *prGetElementListSize{arg locID;
166                 _HIDGetElementListSize
167                 ^this.primitiveFailed
168         }
169         *releaseDeviceList{
170                 //must be called before closing the program..
171                 if(initialized,{
172                         this.prreleaseDeviceList;
173                         devices = nil;
174                 });
175         }
176         *prreleaseDeviceList{
177                 //must be called before closing the program..
178                 _HIDReleaseDeviceList
179         }
180         *runEventLoop {arg rate=0.002;
181                 eventLoopIsRunning.if({
182                         "META_HIDDeviceService-runEventLoop: \n\t stopping and restarting running eventLoop".warn;
183                 });
184                 this.stopEventLoop;
185                 this.pr_runEventLoop(rate);
186                 eventLoopIsRunning = true;
187         }
189         *pr_runEventLoop{arg rate;
190                 _HIDRunEventLoop
191         }
192         *stopEventLoop{
193                 this.pr_stopEventLoop;
194                 eventLoopIsRunning = false;
195         }
196         *pr_stopEventLoop{
197                 _HIDStopEventLoop
198         }
200         *prHidAction{arg vendorID, productID, locID, cookie, val;
201                 action.value(vendorID, productID, locID, cookie, val);
202         }
204         *prReadError{ arg locID;
205                 var dev;
206                 HIDDeviceService.dequeueDevice( locID );
207                 dev = devices.detect( { |dv| dv.locID == locID } );
208                 dev.wasClosed;
209                 closeAction.value( locID );
210         }
212         *queueDevice{arg locID;
213                 _HIDQueueDevice
214                 ^this.primitiveFailed
215         }
217         *dequeueDevice{arg locID;
218                 _HIDDequeueDevice
219                 ^this.primitiveFailed
220         }
222         *queueElement{arg locID, cookie;
223                 _HIDQueueElement
224                 ^this.primitiveFailed
225         }
227         *dequeueElement{arg locID, cookie;
228                 _HIDDequeueElement
229                 ^this.primitiveFailed
230         }
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:
240 enum
242         kHIDPage_Undefined      = 0x00,
243         kHIDPage_GenericDesktop = 0x01,
244         kHIDPage_Simulation     = 0x02,
245         kHIDPage_VR     = 0x03,
246         kHIDPage_Sport  = 0x04,
247         kHIDPage_Game   = 0x05,
249 most common usage for hid:
251 /* GenericDesktop Page (0x01) */
252 enum
254         kHIDUsage_GD_Pointer    = 0x01, /* Physical Collection */
255         kHIDUsage_GD_Mouse      = 0x02, /* Application Collection */
256         /* 0x03 Reserved */
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. */
266 enum
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) */
290 enum
292         kHIDUsage_Game_3DGameController = 0x01, /* Application Collection */
293         kHIDUsage_Game_PinballDevice    = 0x02, /* Application Collection */
294         kHIDUsage_Game_GunDevice        = 0x03, /* Application Collection */