supernova: fix for small audio vector sizes
[supercollider.git] / lang / LangPrimSource / SC_LID.cpp
blob43c05762d28bbe0f7db8cec067365cdf2e2cc38d
1 /*
2 Linux Input Device support.
3 Copyright (c) 2004 stefan kersten.
4 modifications by Marije Baalman 2006-9
6 ====================================================================
8 SuperCollider real time audio synthesis system
9 Copyright (c) 2002 James McCartney. All rights reserved.
10 http://www.audiosynth.com
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 Linux Input Device interface, 2004 <sk>
29 #include "SCBase.h"
30 #include "VMGlobals.h"
31 #include "PyrSymbolTable.h"
32 #include "PyrInterpreter.h"
33 #include "PyrKernel.h"
35 #include "PyrPrimitive.h"
36 #include "PyrObjectProto.h"
37 #include "PyrPrimitiveProto.h"
38 #include "PyrKernelProto.h"
39 #include "SC_InlineUnaryOp.h"
40 #include "SC_InlineBinaryOp.h"
41 #include "PyrSched.h"
42 #include "GC.h"
44 #if HAVE_LID
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <linux/input.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <sys/select.h>
51 #include <sys/types.h>
52 #include <unistd.h>
54 #define BITS_PER_LONG (sizeof(long) * 8)
55 #define NBITS(x) ((((x) - 1) / BITS_PER_LONG) + 1)
56 #define OFF(x) ((x) % BITS_PER_LONG)
57 #define BIT(x) (1UL << OFF(x))
58 #define LONG(x) ((x) / BITS_PER_LONG)
59 #define TEST_BIT(array, bit) (((array)[LONG(bit)] >> OFF(bit)) & 1)
61 extern bool compiledOK;
63 static PyrSymbol* s_inputDeviceClass = 0;
64 static PyrSymbol* s_inputDeviceInfoClass = 0;
65 static PyrSymbol* s_absInfoClass = 0;
66 static PyrSymbol* s_handleEvent = 0;
67 static PyrSymbol* s_readError = 0;
69 // =====================================================================
70 // SC_LID
72 struct SC_LID
74 SC_LID(PyrObject *obj);
75 ~SC_LID();
77 int open(const char *path);
78 int close();
80 bool isEventTypeSupported(int evtType);
81 bool isEventCodeSupported(int evtType, int evtCode);
83 int getName(char* buf, size_t size);
84 int getInfo(struct input_id *info, char *bufPhys, size_t sizePhys, char *bufUniq, size_t sizeUniq);
85 int getKeyState(int evtCode);
86 int getAbsInfo(int evtCode, struct input_absinfo *info);
88 int setLedState( int evtCode, int evtValue, int evtType );
90 int grab(int flag);
91 void handleEvent(struct input_event& evt);
92 void readError();
94 static PyrObject* getObject(PyrSlot* slot)
96 return isKindOfSlot(slot, s_inputDeviceClass->u.classobj) ? slotRawObject(slot) : 0;
99 static SC_LID* getDevice(PyrObject* obj)
101 return (SC_LID*)slotRawPtr(&obj->slots[0]);
104 SC_LID* m_next;
105 PyrObject* m_obj;
106 int m_fd;
107 int m_lastEventType;
108 unsigned long m_eventTypeCaps[NBITS(EV_MAX)];
109 unsigned long m_eventCodeCaps[NBITS(KEY_MAX)];
110 unsigned long m_keyState[NBITS(KEY_MAX)];
113 // =====================================================================
114 // SC_LIDManager
116 struct SC_LIDManager
118 public:
119 static SC_LIDManager& instance();
121 int start();
122 int stop();
124 int add(SC_LID *dev);
125 int remove(SC_LID *dev);
127 private:
128 SC_LIDManager();
129 ~SC_LIDManager();
131 enum
133 kStop,
134 kAdd,
135 kRemove
138 struct Command
140 int id;
141 union
143 SC_LID* dev;
144 } arg;
147 int sendCommand(const Command& cmd);
148 void devicesChanged();
149 bool asyncAddDevice(SC_LID *dev);
150 bool asyncRemoveDevice(SC_LID *dev);
151 void loop();
153 static void* threadFunc(void*);
155 pthread_t m_thread;
156 pthread_mutex_t m_mutex;
157 bool m_running;
158 int m_cmdFifo[2];
159 int m_nfds;
160 fd_set m_fds;
161 SC_LID* m_devices;
164 // =====================================================================
165 // SC_LID
167 SC_LID::SC_LID(PyrObject* obj)
168 : m_next(0),
169 m_obj(obj),
170 m_fd(-1),
171 m_lastEventType(-1)
173 SetPtr(obj->slots+0, this);
176 SC_LID::~SC_LID()
178 if (m_fd != -1) ::close(m_fd);
181 int SC_LID::open(const char* path)
183 m_fd = ::open(path, O_RDWR);
185 if (m_fd == -1) {
186 error("LID (1): %s\n", strerror(errno));
187 return errFailed;
190 memset(m_eventTypeCaps, 0, sizeof(m_eventTypeCaps));
191 if (ioctl(m_fd, EVIOCGBIT(0, EV_MAX), m_eventTypeCaps) == -1) {
192 error("LID (2): %s\n", strerror(errno));
193 return errFailed;
196 memset(m_keyState, 0, sizeof(m_keyState));
197 if (ioctl(m_fd, EVIOCGKEY(sizeof(m_keyState)), m_keyState) == -1) {
198 error("LID (3): %s\n", strerror(errno));
199 return errFailed;
202 return SC_LIDManager::instance().add(this);
205 int SC_LID::close()
207 SetNil(m_obj->slots+0);
208 return SC_LIDManager::instance().remove(this);
211 bool SC_LID::isEventTypeSupported(int evtType)
213 return TEST_BIT(m_eventTypeCaps, evtType);
216 bool SC_LID::isEventCodeSupported(int evtType, int evtCode)
218 if (evtType != m_lastEventType) {
219 m_lastEventType = evtType;
220 memset(m_eventCodeCaps, 0, sizeof(m_eventCodeCaps));
221 if (ioctl(m_fd, EVIOCGBIT(evtType, KEY_MAX), m_eventCodeCaps) == -1) {
222 post("LID failed to check event code (error %s)\n", strerror(errno));
223 return false;
226 return TEST_BIT(m_eventCodeCaps, evtCode);
229 int SC_LID::getName(char* buf, size_t size)
231 if (ioctl(m_fd, EVIOCGNAME(size), buf) == -1) {
232 error("LID (5): %s\n", strerror(errno));
233 return errFailed;
235 return errNone;
238 int SC_LID::getInfo(struct input_id *info, char *bufPhys, size_t sizePhys, char *bufUniq, size_t sizeUniq)
240 if (ioctl(m_fd, EVIOCGID, info) == -1) {
241 error("LID (6): %s\n", strerror(errno));
242 return errFailed;
244 if (ioctl(m_fd, EVIOCGPHYS(sizePhys), bufPhys) == -1) {
245 // strcpy( sizePhys, strerror(errno));
246 post("LID could not retrieve physical location (error: %s)\n", strerror(errno));
247 // return errFailed;
249 if (ioctl(m_fd, EVIOCGUNIQ(sizeUniq), bufUniq) == -1) {
250 // strcpy( strerror(errno), sizeof( strerror(errno)), sizeUniq );
251 post("LID could not get unique identifier (error: %s)\n", strerror(errno));
252 // return errFailed;
255 return errNone;
258 int SC_LID::getKeyState(int evtCode)
260 return TEST_BIT(m_keyState, evtCode);
263 int SC_LID::getAbsInfo(int evtCode, struct input_absinfo* info)
265 if (ioctl(m_fd, EVIOCGABS(evtCode), info) == -1) {
266 error("LID (9): %s\n", strerror(errno));
267 return errFailed;
269 return errNone;
272 int SC_LID::setLedState( int evtCode, int evtValue, int evtType )
273 { // added by marije baalman
274 struct input_event ev;
275 // post( "set led state called, putting event" );
276 ev.code = evtCode;
277 ev.value = evtValue;
278 ev.type = evtType;
279 // post( "m_fd %i", m_fd );
280 // post( "code %i, value %i ", evtCode, evtValue );
281 if ( write(m_fd, &ev, sizeof(struct input_event)) == -1 )
283 // post( "error writing event" );
284 return errFailed;
286 return errNone;
289 int SC_LID::grab(int flag)
291 if (ioctl(m_fd, EVIOCGRAB, flag) == -1) {
292 error("LID (10): %s\n", strerror(errno));
293 return errFailed;
295 return errNone;
298 void SC_LID::handleEvent(struct input_event& evt)
300 if (evt.type != EV_SYN) {
301 pthread_mutex_lock(&gLangMutex);
302 if (compiledOK) {
303 VMGlobals* g = gMainVMGlobals;
304 g->canCallOS = false;
305 ++g->sp; SetObject(g->sp, m_obj);
306 ++g->sp; SetInt(g->sp, evt.type);
307 ++g->sp; SetInt(g->sp, evt.code);
308 ++g->sp; SetInt(g->sp, evt.value);
309 runInterpreter(g, s_handleEvent, 4);
310 g->canCallOS = false;
312 pthread_mutex_unlock(&gLangMutex);
316 void SC_LID::readError()
318 pthread_mutex_lock(&gLangMutex);
319 if (compiledOK) {
320 VMGlobals* g = gMainVMGlobals;
321 g->canCallOS = false;
322 ++g->sp; SetObject(g->sp, m_obj);
323 runInterpreter(g, s_readError, 1);
324 g->canCallOS = false;
326 pthread_mutex_unlock(&gLangMutex);
329 // =====================================================================
330 // SC_LIDManager
332 SC_LIDManager& SC_LIDManager::instance()
334 static SC_LIDManager instance;
335 return instance;
338 SC_LIDManager::SC_LIDManager()
339 : m_running(false),
340 m_devices(0)
342 if (pipe(m_cmdFifo) == -1) {
343 m_cmdFifo[0] = m_cmdFifo[1] = -1;
345 devicesChanged();
348 SC_LIDManager::~SC_LIDManager()
350 close(m_cmdFifo[0]);
351 close(m_cmdFifo[1]);
354 int SC_LIDManager::start()
356 int err;
357 err = pthread_create(&m_thread, 0, &threadFunc, this);
358 if (err != 0) return errFailed;
359 return errNone;
362 int SC_LIDManager::stop()
364 if (m_running == false)
365 return errNone;
367 Command cmd;
369 cmd.id = kStop;
370 int err = sendCommand(cmd);
371 if (err) return err;
373 err = pthread_join(m_thread, 0);
374 if (err != 0) return errFailed;
376 return errNone;
379 int SC_LIDManager::add(SC_LID* dev)
381 Command cmd;
382 cmd.id = kAdd;
383 cmd.arg.dev = dev;
384 return sendCommand(cmd);
387 int SC_LIDManager::remove(SC_LID* dev)
389 Command cmd;
390 cmd.id = kRemove;
391 cmd.arg.dev = dev;
392 return sendCommand(cmd);
395 int SC_LIDManager::sendCommand(const Command& cmd)
397 return write(m_cmdFifo[1], &cmd, sizeof(cmd)) == sizeof(cmd) ? errNone : errFailed;
400 void SC_LIDManager::devicesChanged()
402 int fdMax = m_cmdFifo[0];
404 FD_ZERO(&m_fds);
405 FD_SET(fdMax, &m_fds);
407 SC_LID *dev = m_devices;
408 while (dev) {
409 int fd = dev->m_fd;
410 if (fd != -1) {
411 FD_SET(fd, &m_fds);
412 if (fd > fdMax) fdMax = fd;
414 dev = dev->m_next;
417 m_nfds = fdMax + 1;
420 bool SC_LIDManager::asyncAddDevice(SC_LID* dev)
422 if (dev->m_next) return false;
423 dev->m_next = m_devices;
424 m_devices = dev;
425 devicesChanged();
426 return true;
429 bool SC_LIDManager::asyncRemoveDevice(SC_LID* dev)
431 SC_LID *prev = 0, *cur = m_devices;
433 while (cur) {
434 if (cur == dev) {
435 if (prev) prev->m_next = dev->m_next;
436 else m_devices = dev->m_next;
437 dev->m_next = 0;
438 delete dev;
439 devicesChanged();
440 return true;
442 prev = cur;
443 cur = cur->m_next;
446 return false;
449 void* SC_LIDManager::threadFunc(void* arg)
451 ((SC_LIDManager*)arg)->loop();
452 return 0;
455 void SC_LIDManager::loop()
457 m_running = true;
458 post("LID: event loop started\n");
460 while (true) {
461 fd_set fds;
462 memcpy(&fds, &m_fds, sizeof(fd_set));
463 int n = select(m_nfds, &fds, 0, 0, 0);
464 if (n == -1) {
465 if( errno == EINTR ) continue;
466 post("LID: error in input handler: %s\n", strerror(errno));
467 goto quit;
468 } else if (n > 0) {
469 if (FD_ISSET(m_cmdFifo[0], &fds)) {
470 Command cmd;
471 --n;
472 int err = read(m_cmdFifo[0], &cmd, sizeof(cmd));
473 if (err == -1) {
474 if( errno != EINTR ) {
475 post("LID: error in input handler: %s\n", strerror(errno));
476 goto quit;
479 else {
480 switch (cmd.id) {
481 case kStop:
482 goto quit;
483 case kAdd:
484 if (asyncAddDevice(cmd.arg.dev)) {
485 post("LID: added device %p\n", cmd.arg);
486 } else {
487 post("LID: cannot add device\n");
489 break;
490 case kRemove:
491 if (asyncRemoveDevice(cmd.arg.dev)) {
492 post("LID: removed device %p\n", cmd.arg);
493 } else {
494 post("LID: couldn't remove device\n");
496 break;
497 default:
498 post("LID: unknown command in input handler\n");
502 if (n > 0) {
503 SC_LID *dev = m_devices;
504 while (dev) {
505 int fd = dev->m_fd;
506 if (FD_ISSET(fd, &fds)) {
507 struct input_event evt;
508 if (read(fd, &evt, sizeof(evt)) == sizeof(evt)) {
509 dev->handleEvent(evt);
511 else {
512 dev->readError();
515 dev = dev->m_next;
521 quit:
522 m_running = false;
523 post("LID: event loop stopped\n");
526 // =====================================================================
527 // Primitive Interface
529 int prLID_Open(VMGlobals *g, int numArgsPushed)
531 PyrSlot* args = g->sp - 1;
532 int err;
534 PyrObject* obj = SC_LID::getObject(args+0);
535 if (!obj) return errWrongType;
537 char path[PATH_MAX];
538 err = slotStrVal(args+1, path, sizeof(path));
539 if (err) return err;
541 SC_LID* dev = new SC_LID(obj);
542 err = dev->open(path);
543 if (err) {
544 delete dev;
545 return err;
548 return errNone;
551 int prLID_Close(VMGlobals *g, int numArgsPushed)
553 PyrSlot* args = g->sp;
555 PyrObject* obj = SC_LID::getObject(args+0);
556 if (!obj) return errWrongType;
558 SC_LID* dev = SC_LID::getDevice(obj);
559 if (!dev) return errFailed;
561 return dev->close();
564 int prLID_EventTypeSupported(VMGlobals *g, int numArgsPushed)
566 PyrSlot* args = g->sp - 1;
567 int evtType;
568 int err;
570 if (!g->canCallOS) return errCantCallOS;
572 PyrObject* obj = SC_LID::getObject(args+0);
573 if (!obj) return errWrongType;
575 err = slotIntVal(args+1, &evtType);
576 if (err) return err;
578 SC_LID* dev = SC_LID::getDevice(obj);
579 if (!dev) return errFailed;
581 SetBool(args, dev->isEventTypeSupported(evtType));
583 return errNone;
586 int prLID_EventCodeSupported(VMGlobals *g, int numArgsPushed)
588 PyrSlot* args = g->sp - 2;
589 int evtType, evtCode;
590 int err;
592 if (!g->canCallOS) return errCantCallOS;
594 PyrObject* obj = SC_LID::getObject(args+0);
595 if (!obj) return errWrongType;
597 err = slotIntVal(args+1, &evtType);
598 if (err) return err;
600 err = slotIntVal(args+2, &evtCode);
601 if (err) return err;
603 SC_LID* dev = SC_LID::getDevice(obj);
604 if (!dev) return errFailed;
606 SetBool(args, dev->isEventCodeSupported(evtType, evtCode));
608 return errNone;
611 int prLID_GetInfo(VMGlobals* g, int numArgsPushed)
613 PyrSlot* args = g->sp - 1;
614 int err;
616 PyrObject* obj = SC_LID::getObject(args+0);
617 if (!obj) return errWrongType;
619 if (!isKindOfSlot(args+1, s_inputDeviceInfoClass->u.classobj))
620 return errWrongType;
621 PyrObject* infoObj = slotRawObject(&args[1]);
623 SC_LID* dev = SC_LID::getDevice(obj);
624 if (!dev) return errFailed;
626 char name[128];
627 err = dev->getName(name, sizeof(name));
628 if (err) return err;
630 struct input_id info;
631 char namePhys[128];
632 char nameUniq[128];
633 err = dev->getInfo(&info, namePhys, sizeof( namePhys ), nameUniq, sizeof( nameUniq ) );
634 if (err) return err;
636 SetSymbol(infoObj->slots+0, getsym(name));
637 SetInt(infoObj->slots+1, info.bustype);
638 SetInt(infoObj->slots+2, info.vendor);
639 SetInt(infoObj->slots+3, info.product);
640 SetInt(infoObj->slots+4, info.version);
641 SetSymbol(infoObj->slots+5, getsym(namePhys));
642 SetSymbol(infoObj->slots+6, getsym(nameUniq));
644 slotCopy(&args[0], &args[1]);
646 return errNone;
649 int prLID_GetKeyState(VMGlobals *g, int numArgsPushed)
651 PyrSlot* args = g->sp - 1;
652 int evtCode;
653 int err;
655 PyrObject* obj = SC_LID::getObject(args+0);
656 if (!obj) return errWrongType;
658 err = slotIntVal(args+1, &evtCode);
659 if (err) return err;
661 SC_LID* dev = SC_LID::getDevice(obj);
662 if (!dev) return errFailed;
664 SetInt(args, dev->getKeyState(evtCode));
666 return errNone;
669 int prLID_GetAbsInfo(VMGlobals *g, int numArgsPushed)
671 PyrSlot* args = g->sp - 2;
672 int evtCode;
673 int err;
675 PyrObject* obj = SC_LID::getObject(args+0);
676 if (!obj) return errWrongType;
678 err = slotIntVal(args+1, &evtCode);
679 if (err) return err;
681 if (!isKindOfSlot(args+2, s_absInfoClass->u.classobj))
682 return errWrongType;
683 PyrObject* infoObj = slotRawObject(&args[2]);
685 SC_LID* dev = SC_LID::getDevice(obj);
686 if (!dev) return errFailed;
688 struct input_absinfo info;
689 err = dev->getAbsInfo(evtCode, &info);
690 if (err) return err;
692 SetInt(infoObj->slots+0, info.value);
693 SetInt(infoObj->slots+1, info.minimum);
694 SetInt(infoObj->slots+2, info.maximum);
695 SetInt(infoObj->slots+3, info.fuzz);
696 SetInt(infoObj->slots+4, info.flat);
698 slotCopy(&args[0], &args[2]);
700 return errNone;
703 int prLID_Grab(VMGlobals *g, int numArgsPushed)
705 PyrSlot* args = g->sp - 1;
707 PyrObject* obj = SC_LID::getObject(args+0);
708 if (!obj) return errWrongType;
710 SC_LID* dev = SC_LID::getDevice(obj);
711 if (!dev) return errFailed;
713 return dev->grab(IsTrue(args+1));
716 int prLID_Start(VMGlobals* g, int numArgsPushed)
718 // if (!g->canCallOS) return errCantCallOS;
719 return SC_LIDManager::instance().start();
722 int prLID_Stop(VMGlobals* g, int numArgsPushed)
724 // if (!g->canCallOS) return errCantCallOS;
725 return SC_LIDManager::instance().stop();
728 int prLID_SetLedState(VMGlobals *g, int numArgsPushed)
730 // post( "set led state primitive called" );
731 PyrSlot* args = g->sp - 2;
732 int evtCode, evtValue;
733 int err;
735 PyrObject* obj = SC_LID::getObject(args+0);
736 if (!obj) return errWrongType;
738 err = slotIntVal(args+1, &evtCode);
739 if (err) return err;
741 err = slotIntVal(args+2, &evtValue);
742 if (err) return err;
744 SC_LID* dev = SC_LID::getDevice(obj);
745 if (!dev) return errFailed;
747 SetInt(args, dev->setLedState(evtCode,evtValue, EV_LED));
748 return errNone;
751 int prLID_SetMscState(VMGlobals *g, int numArgsPushed)
753 // post( "set msc state primitive called\n" );
754 PyrSlot* args = g->sp - 2;
755 int evtCode, evtValue;
756 int err;
758 PyrObject* obj = SC_LID::getObject(args+0);
759 if (!obj) return errWrongType;
761 err = slotIntVal(args+1, &evtCode);
762 if (err) return err;
764 err = slotIntVal(args+2, &evtValue);
765 if (err) return err;
767 SC_LID* dev = SC_LID::getDevice(obj);
768 if (!dev) return errFailed;
770 SetInt(args, dev->setLedState(evtCode,evtValue, EV_MSC));
771 return errNone;
774 void SC_LIDInit()
776 int base, index;
778 s_inputDeviceClass = getsym("LID");
779 s_inputDeviceInfoClass = getsym("LIDInfo");
780 s_absInfoClass = getsym("LIDAbsInfo");
781 s_handleEvent = getsym("prHandleEvent");
782 s_readError = getsym("prReadError");
784 base = nextPrimitiveIndex();
785 index = 0;
787 definePrimitive(base, index++, "_LID_Open", prLID_Open, 2, 0);
788 definePrimitive(base, index++, "_LID_Close", prLID_Close, 1, 0);
789 definePrimitive(base, index++, "_LID_EventTypeSupported", prLID_EventTypeSupported, 2, 0);
790 definePrimitive(base, index++, "_LID_EventCodeSupported", prLID_EventCodeSupported, 3, 0);
791 definePrimitive(base, index++, "_LID_GetInfo", prLID_GetInfo, 2, 0);
792 definePrimitive(base, index++, "_LID_GetKeyState", prLID_GetKeyState, 2, 0);
793 definePrimitive(base, index++, "_LID_GetAbsInfo", prLID_GetAbsInfo, 3, 0);
794 definePrimitive(base, index++, "_LID_Grab", prLID_Grab, 2, 0);
795 definePrimitive(base, index++, "_LID_Start", prLID_Start, 1, 0);
796 definePrimitive(base, index++, "_LID_Stop", prLID_Stop, 1, 0);
797 definePrimitive(base, index++, "_LID_SetLedState", prLID_SetLedState, 3, 0); // added by Marije Baalman
798 definePrimitive(base, index++, "_LID_SetMscState", prLID_SetMscState, 3, 0);
800 #else // !HAVE_LID
801 int prLID_Start(VMGlobals* g, int numArgsPushed)
803 return errNone;
806 int prLID_Stop(VMGlobals* g, int numArgsPushed)
808 return errNone;
811 void SC_LIDInit()
813 int base, index;
815 base = nextPrimitiveIndex();
816 index = 0;
818 definePrimitive(base, index++, "_LID_Start", prLID_Start, 1, 0);
819 definePrimitive(base, index++, "_LID_Stop", prLID_Stop, 1, 0);
821 #endif // HAVE_LID
823 void initHIDPrimitives()
825 SC_LIDInit();
828 // EOF