cmake build system: visiblity support for clang
[supercollider.git] / SCClassLibrary / Common / Control / GeneralHID.sc
blobd65fc0831fa277339f65c3891f6d0ea1bed2ba8c
1 GeneralHID{
2         classvar <>all, <>verbose=false;
3         classvar <scheme, <schemes;
5         *initClass {
6                 schemes = IdentityDictionary.new;
7         }
9         *new { arg key; ^scheme.perform( key )}
11         *current {
12                 ^scheme;
13         }
15         *get { arg id;
16                 ^schemes[ id.asSymbol ];
17         }
19         *set { arg aScheme;
20                 scheme = aScheme;
21         }
23         *use { arg aScheme, func;
24                 var recent      = scheme;
25                 scheme          = aScheme;
26                 ^func.protect({ scheme = recent });
27         }
29         *useID { arg id, func;
30                 ^this.use( schemes[ id.asSymbol ], func );
31         }
33         *open { |dev| ^scheme.open(dev); }
35                 // maybe better define interface here instead,
36                 // rather than doesNotUnderstand.
37         *doesNotUnderstand { arg selector ... args;
38                 //      ["GeneralHID forwarding to scheme:", selector, args].postln;
39                 ^scheme.performList( selector, args );
40         }
42         /*      *deviceList {
43                 ^scheme.deviceList;
44                 }*/
46         *add { arg aScheme;
47                 schemes.put( aScheme.id, aScheme );
48                 if( scheme.isNil, {                             // first registration = first default kit
49                         scheme = aScheme;
50                 }, {
51                         scheme = schemes[ scheme.id ];  // in case we are updating an existing scheme
52                 });
53         }
55         *fromID { arg id;
56                 var newScheme = schemes[ id.asSymbol ];
57                 if( newScheme.notNil, {
58                         scheme = newScheme;
59                 }, {
60                         if(thisProcess.platform.name != \windows){ // on win we know it's not yet supported
61                                 ("GeneralHID.fromID : The HID scheme '" ++ id ++ "' is not installed\n" ++
62                                 "The current scheme is still '" ++ if( scheme.notNil, { scheme.id }) ++ "'!").warn;
63                         }
64                 });
65                 ^scheme;
66         }
67                 // find a device by its info properties
68         *findBy { |vendorID, productID, locID, versionID|
69                 if ( locID.isKindOf( String ), { locID = locID.asSymbol } );
70                 ^this.deviceList.detect { |pair|
71                         var dev, info; #dev, info = pair;
72                         (info.vendor == vendorID)
73                         and: { productID.isNil or: { info.product == productID } }
74                         and: { locID.isNil or: { info.physical == locID } }
75                         and: { versionID.isNil or: { info.version == versionID } }
76                 };
77         }
80 GeneralHIDInfo{
81         var <name, <bustype, <vendor, <product, <version, <physical, <unique;
83         *new{arg  name="", bustype=0, vendor=0, product=0, version=0, physical=0, unique=0;
84                 ^super.newCopyArgs( name, bustype, vendor, product, version, physical, unique ).init;
85         }
87         init{
88         }
90         findArgs{
91                 ^[ vendor, product, physical, version ];
92         }
94         printOn { | stream |
95                 super.printOn(stream);
96                 stream << $( << name << ", ";
97                 // " VendorID: " << vendor << ", ProductID: " << product << ", locID: " << physical << ", version: " << version << $);
98                 [
99                         bustype,
100                         vendor,
101                         product,
102                         version
103                 ].collect({ | x | "0x" ++ x.asHexString(4) }).printItemsOn(stream);
104                 stream << ", " << physical << ", " << unique;
105                 stream.put($));
106         }
109 GeneralHIDDevice{
110         classvar all;
111         var <slots, <spec;
112         var <device, <info;
114         *initClass {
115                 all = [];
116                 //      specs = IdentityDictionary.new;
117         }
118         *all {
119                 ^all.copy
120         }
121         *closeAll {
122                 all.copy.do({ | dev | dev.close });
123         }
124         /*      *register { | name, spec |
125                 specs[name] = spec;
126                 }*/
127         *new { |newDevice|
128                 ^all.detect({ | dev | dev.device == newDevice }) ?? { super.new.init(newDevice) }
129         }
130         init{ |newDevice|
131                 device = newDevice;
132                 slots = device.getSlots;
133                 info = device.getInfo;
134                 spec = GeneralHIDSpec.new( this );
135         }
136         close{
137                 device.close;
138         }
139         isOpen{
140                 ^device.isOpen;
141         }
142         /*      info{
143                 ^device.info;
144                 }
145         */
146         debug_{ |onoff,allslots=true|
147                 device.class.debug_( onoff );
148                 // is this necessary? to also turn on/off all the slot debugging?
149                 if ( allslots ){
150                         slots.do{ |sl|
151                                 sl.do{ |slt| slt.debug_( onoff ) } 
152                         };
153                 };
154         }
155         caps{
156                 slots.do{ |sl|
157                         "".postln;
158                         sl.do{ |slt| "\t".post; slt.asString.postln; } };
159         }
160         grab{
161                 device.grab;
162         }
163         ungrab{
164                 device.ungrab;
165         }
166         
167         hidDeviceAction_{ |func|
168                 device.hidDeviceAction = func;  
169         }
171         hidDeviceAction{ 
172                 ^device.hidDeviceAction;        
173         }
175         // spec support
176         findSpec{
177                 ^spec.find;
178         }
180         setSpec{ |name|
181                 spec.fromFile( name );
182         }
184         add{ |key, slot|
185                 spec.add( key, slot );
186         }
188         at{ |key|
189                 ^spec.at( key );
190         }
192         value{ |key|
193                 ^spec.value( key );
194         }
196         bus{ |key|
197                 ^spec.bus( key );
198         }
200         value_{ |key,value|
201                 spec.value_( key, value );
202         }
204         action_{ |key,action|
205                 if ( (key.class == Function) and: action.isNil,{
206                         device.action = key;
207                 },{
208                         spec.action_( key, action );
209                 });
210         }
212         createBus{ |name,server|
213                 spec.createBus( name, server );
214         }
216         freeBus{ |name|
217                 spec.freeBus( name );
218         }
220         createAllBuses{ |server|
221                 spec.createAllBuses( server );
222         }
224         freeAllBuses{
225                 spec.freeAllBuses;
226         }
228         makeGui{
229                 ^GeneralHIDDeviceGUI.new( this );
230         }
235 GeneralHIDSlot{
236         var <type, <id, <device, <devSlot;
237         classvar <typeMap;
238         var <action;
239         var <bus, <busAction;
240         var <debugAction;
241         var <>key;
243         *initClass{
244                 // typeMap is modeled after Linux input system.
245                 // to get the Mac work in a similar way, some tricks will be needed
246                 typeMap = IdentityDictionary.new.addAll([
247                         0x0000 -> "Syn",
248                         0x0001 -> "Button",
249                         0x0002 -> "Relative",
250                         0x0003 -> "Absolute",
251                         0x0004 -> "Miscellaneous",
252                         0x0011 -> "LED",
253                         0x0012 -> "Sound",
254                         0x0014 -> "Rep",
255                         0x0015 -> "Force Feedback",
256                         0x0016 -> "Power",
257                         0x0017 -> "Force Feedback Status",
258                         0x0FFF -> "Linear"
259                 ]);
260         }
262         *new{ |type,id,device,devSlot|
263                 ^super.newCopyArgs( type, id, device, devSlot ).init;
264         }
266         init{
267                 busAction = {};
268                 debugAction = {};
269                 action = {};
270                 devSlot.action = { |v| this.debugAction.value(v); this.busAction.value(v); this.action.value(v) };
271         }
273         value {
274                 ^devSlot.value;
275         }
277         rawValue {
278                 ^devSlot.rawValue;
279         }
281         value_ { |v|
282                 devSlot.value_( v );
283         }
285         debug_{ |onoff|
286                 if ( onoff, {
287                         //      this.action_({ |slot| [ slot.type, slot.code, slot.value, key ].postln; });
288                         this.debugAction_({ |slot| [ slot.type, slot.code, slot.value, key ].postln; });
289                 },{
290                         //      this.action_({});
291                         this.debugAction_({});
292                 });
293         }
295         debugAction_{ |actionFunc|
296                 debugAction = actionFunc;
297         }
299         action_{ |actionFunc|
300                 action = actionFunc;
301                 //      devSlot.action = { |v| this.action.value(v); this.busAction.value(v); this.debugAction.value(v) };
302         }
304         createBus{ |s|
305                 s = s ? Server.default;
306                 if ( bus.isNil, {
307                         bus = Bus.control( s, 1 );
308                 },{
309                         if ( bus.index.isNil, {
310                                 bus = Bus.control( s, 1 );
311                         });
312                 });
313                 /*              if ( s.serverRunning.not and: s.isLocal, {
314                         "Server seems not running, so bus will be invalid".warn;
315                         });*/
316                 busAction = { |v| bus.set( v.value ); };
317                 //      devSlot.action = { |v| action.value(v); busAction.value(v); };
318         }
320         freeBus{
321                 busAction = {};
322                 bus.free;
323         }
325         printOn { | stream |
326                 stream
327                 << this.class.name << $(
328                 << this.class.typeMap[type] << ", "
329                 << "type: " << type << ", "
330                 << "id: " << id << ", "
331                 << "value: " << this.value << $)
332         }
334 // JITLib support
335         kr{
336                 this.createBus;
337                 ^In.kr( bus );
338         }
340 }