Ticket #2017: appleremote.2.patch
File appleremote.2.patch, 17.9 KB (added by , 18 years ago) |
---|
-
libs/libmythui/mythmainwindow.cpp
10 10 #include <qwindowsystem_qws.h> 11 11 #endif 12 12 #ifdef Q_WS_MACX 13 #import <HIToolbox/Menus.h> // For GetMBarHeight() 13 #include <HIToolbox/Menus.h> // For GetMBarHeight() 14 #include <pthread.h> 15 #include "lircevent.h" 16 #include "AppleRemote.h" 17 #include "AppleRemoteListener.h" 14 18 #endif 15 19 16 20 #ifdef USE_LIRC … … 46 50 } 47 51 #endif 48 52 53 #ifdef Q_WS_MACX 54 static void* SpawnAppleRemote(void* param) 55 { 56 MythMainWindow *main_window = (MythMainWindow *)param; 57 AppleRemoteListener *arl = new AppleRemoteListener(main_window); 58 AppleRemote& remote(AppleRemote::instance()); 59 remote.setListener(arl); 60 remote.startListening(); 61 if (!remote.isListeningToRemote()) { 62 return NULL; 63 } 64 remote.runLoop(); 65 return NULL; 66 } 67 #endif 68 49 69 class KeyContext 50 70 { 51 71 public: … … 214 234 pthread_create(&lirc_tid, &attr, SpawnLirc, this); 215 235 #endif 216 236 237 #ifdef Q_WS_MACX 238 pthread_t appleremote_tid; 239 pthread_attr_t arattr; 240 pthread_attr_init(&arattr); 241 pthread_attr_setdetachstate(&arattr, PTHREAD_CREATE_DETACHED); 242 243 pthread_create(&appleremote_tid, &arattr, SpawnAppleRemote, this); 244 #endif 245 217 246 d->keyContexts.setAutoDelete(true); 218 247 219 248 RegisterKey("Global", "UP", "Up Arrow", "Up"); … … 901 930 } 902 931 } 903 932 } 904 #if def USE_LIRC933 #if defined(USE_LIRC) || defined(Q_WS_MACX) 905 934 else if (ce->type() == kLircKeycodeEventType && !d->ignore_lirc_keys) 906 935 { 907 936 LircKeycodeEvent *lke = (LircKeycodeEvent *)ce; -
libs/libmyth/AppleRemote.h
1 #ifndef APPLEREMOTE 2 #define APPLEREMOTE 3 4 #include <string> 5 #include <vector> 6 #include <map> 7 8 #include <IOKit/IOKitLib.h> 9 #include <IOKit/IOCFPlugIn.h> 10 #include <IOKit/hid/IOHIDLib.h> 11 #include <IOKit/hid/IOHIDKeys.h> 12 #include <CoreFoundation/CoreFoundation.h> 13 14 class AppleRemote { 15 public: 16 enum Event { 17 VolumePlus = 0, 18 VolumeMinus, 19 Menu, 20 Play, 21 Right, 22 Left, 23 RightHold, 24 LeftHold, 25 MenuHold, 26 PlaySleep, 27 ControlSwitched 28 }; 29 30 class Listener { 31 public: 32 virtual ~Listener(); 33 virtual void appleRemoteButton(Event button, bool pressedDown) = 0; 34 }; 35 36 static AppleRemote& instance(); 37 ~AppleRemote(); 38 39 bool isRemoteAvailable(); 40 bool isListeningToRemote(); 41 42 void setListener(Listener* listener); 43 Listener* listener() { return _listener; } 44 void setOpenInExclusiveMode(bool in) { openInExclusiveMode = in; }; 45 bool isOpenInExclusiveMode() { return openInExclusiveMode; }; 46 void startListening(); 47 void stopListening(); 48 void runLoop(); 49 50 protected: 51 AppleRemote(); // will be a singleton class 52 53 static AppleRemote* _instance; 54 static const char* const AppleRemoteDeviceName; 55 static const int REMOTE_SWITCH_COOKIE; 56 57 58 private: 59 bool openInExclusiveMode; 60 IOHIDDeviceInterface** hidDeviceInterface; 61 IOHIDQueueInterface** queue; 62 std::vector<int> cookies; 63 std::map< std::string, Event > cookieToButtonMapping; 64 int remoteId; 65 Listener* _listener; 66 67 void _initCookieMap(); 68 io_object_t _findAppleRemoteDevice(); 69 bool _initCookies(); 70 bool _createDeviceInterface(io_object_t hidDevice); 71 bool _openDevice(); 72 73 static void QueueCallbackFunction(void* target, IOReturn result, 74 void* refcon, void* sender); 75 void _queueCallbackFunction(IOReturn result, void* refcon, void* sender); 76 void _handleEventWithCookieString(std::string cookieString, SInt32 sumOfValues); 77 }; 78 79 #endif // APPLEREMOTE -
libs/libmyth/AppleRemoteListener.cpp
1 #include <qapplication.h> 2 #include <qkeysequence.h> 3 #include "lircevent.h" 4 5 #include "AppleRemoteListener.h" 6 7 AppleRemoteListener::AppleRemoteListener(QObject* mainWindow_): mainWindow(mainWindow_) { 8 } 9 10 void 11 AppleRemoteListener::appleRemoteButton(AppleRemote::Event button, bool pressedDown) { 12 char* code = 0; 13 bool separateRelease = false; 14 switch (button) { 15 case AppleRemote::VolumePlus: { 16 code="Up"; 17 separateRelease=true; 18 break; 19 } 20 case AppleRemote::VolumeMinus: { 21 code="Down"; 22 separateRelease=true; 23 break; 24 } 25 case AppleRemote::Menu: { 26 code="Esc"; 27 break; 28 } 29 case AppleRemote::Play: { 30 code="Enter"; 31 break; 32 } 33 case AppleRemote::Right: { 34 code="Right"; 35 break; 36 } 37 case AppleRemote::Left: { 38 code="Left"; 39 break; 40 } 41 case AppleRemote::RightHold: { 42 code="End"; 43 separateRelease=true; 44 break; 45 } 46 case AppleRemote::LeftHold: { 47 code="Home"; 48 separateRelease=true; 49 break; 50 } 51 case AppleRemote::MenuHold: { 52 code="M"; 53 break; 54 } 55 case AppleRemote::PlaySleep: { 56 code="P"; 57 break; 58 } 59 case AppleRemote::ControlSwitched: { 60 return; 61 } 62 } 63 QKeySequence a(code); 64 int keycode = 0; 65 for (unsigned int i = 0; i < a.count(); i++) 66 { 67 keycode = a[i]; 68 69 QApplication::postEvent(mainWindow, new LircKeycodeEvent(code, 70 keycode, pressedDown)); 71 if (!separateRelease) { 72 QApplication::postEvent(mainWindow, new LircKeycodeEvent(code, 73 keycode, false)); 74 } 75 } 76 77 } -
libs/libmyth/AppleRemote.cpp
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <ctype.h> 5 #include <sys/errno.h> 6 #include <sysexits.h> 7 #include <mach/mach.h> 8 #include <mach/mach_error.h> 9 #include <IOKit/IOKitLib.h> 10 #include <IOKit/IOCFPlugIn.h> 11 #include <IOKit/hid/IOHIDLib.h> 12 #include <IOKit/hid/IOHIDKeys.h> 13 #include <CoreFoundation/CoreFoundation.h> 14 15 16 #include <map> 17 #include <sstream> 18 #include <iostream> 19 20 #include "AppleRemote.h" 21 22 // static 23 AppleRemote* AppleRemote::_instance = 0; 24 // static 25 const char* const AppleRemote::AppleRemoteDeviceName = "AppleIRController"; 26 // static 27 const int AppleRemote::REMOTE_SWITCH_COOKIE=19; 28 29 AppleRemote::Listener::~Listener() { 30 } 31 32 // public 33 AppleRemote& 34 AppleRemote::instance() { 35 if (_instance==0) { 36 _instance = new AppleRemote(); 37 } 38 return *_instance; 39 } 40 41 AppleRemote::~AppleRemote() { 42 stopListening(); 43 } 44 45 bool 46 AppleRemote::isRemoteAvailable() { 47 io_object_t hidDevice = _findAppleRemoteDevice(); 48 if (hidDevice != 0) { 49 IOObjectRelease(hidDevice); 50 return true; 51 } 52 return false; 53 } 54 55 bool 56 AppleRemote::isListeningToRemote() { 57 return (hidDeviceInterface != NULL && !cookies.empty() && queue != NULL); 58 } 59 60 void 61 AppleRemote::setListener(AppleRemote::Listener* listener) { 62 _listener = listener; 63 } 64 65 void 66 AppleRemote::startListening() { 67 io_object_t hidDevice = _findAppleRemoteDevice(); 68 if (hidDevice == 0) goto error; 69 if (!_createDeviceInterface(hidDevice)) goto error; 70 if (!_initCookies()) goto error; 71 if (!_openDevice()) goto error; 72 goto cleanup; 73 74 error: 75 stopListening(); 76 77 cleanup: 78 IOObjectRelease(hidDevice); 79 } 80 81 void 82 AppleRemote::stopListening() { 83 if (queue != NULL) { 84 (*queue)->stop(queue); 85 (*queue)->dispose(queue); 86 (*queue)->Release(queue); 87 queue = NULL; 88 } 89 90 if (!cookies.empty()) { 91 cookies.clear(); 92 } 93 94 if (hidDeviceInterface != NULL) { 95 (*hidDeviceInterface)->close(hidDeviceInterface); 96 (*hidDeviceInterface)->Release(hidDeviceInterface); 97 hidDeviceInterface = NULL; 98 } 99 } 100 101 void 102 AppleRemote::runLoop() { 103 CFRunLoopRun(); 104 } 105 106 // protected 107 AppleRemote::AppleRemote(): 108 openInExclusiveMode(true), 109 hidDeviceInterface(0), 110 queue(0), 111 _listener(0) { 112 _initCookieMap(); 113 } 114 115 // private 116 void 117 AppleRemote::_initCookieMap() { 118 cookieToButtonMapping["14_12_11_6_5_"] = VolumePlus; 119 cookieToButtonMapping["14_13_11_6_5_"] = VolumeMinus; 120 cookieToButtonMapping["14_7_6_5_14_7_6_5_"] = Menu; 121 cookieToButtonMapping["14_8_6_5_14_8_6_5_"] = Play; 122 cookieToButtonMapping["14_9_6_5_14_9_6_5_"] = Right; 123 cookieToButtonMapping["14_10_6_5_14_10_6_5_"] = Left; 124 cookieToButtonMapping["14_6_5_4_2_"] = RightHold; 125 cookieToButtonMapping["14_6_5_3_2_"] = LeftHold; 126 cookieToButtonMapping["14_6_5_14_6_5_"] = MenuHold; 127 cookieToButtonMapping["18_14_6_5_18_14_6_5_"] = PlaySleep; 128 cookieToButtonMapping["19_"] = ControlSwitched; 129 } 130 131 // private 132 io_object_t 133 AppleRemote::_findAppleRemoteDevice() { 134 CFMutableDictionaryRef hidMatchDictionary = 0; 135 io_iterator_t hidObjectIterator = 0; 136 io_object_t hidDevice = 0; 137 138 hidMatchDictionary = IOServiceMatching(AppleRemoteDeviceName); 139 140 // check for matching devices 141 IOReturn ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, 142 hidMatchDictionary, 143 &hidObjectIterator); 144 if ((ioReturnValue == kIOReturnSuccess) 145 && (hidObjectIterator != 0)) { 146 hidDevice = IOIteratorNext(hidObjectIterator); 147 } 148 149 // IOServiceGetMatchingServices consumes a reference to the dictionary, so we 150 // don't need to release the dictionary ref. 151 hidMatchDictionary = 0; 152 return hidDevice; 153 } 154 155 // private 156 bool 157 AppleRemote::_initCookies() { 158 IOHIDDeviceInterface122** handle = (IOHIDDeviceInterface122**)hidDeviceInterface; 159 160 CFArrayRef elements; 161 IOReturn success = 162 (*handle)->copyMatchingElements(handle,NULL,(CFArrayRef*)&elements); 163 164 if (success == kIOReturnSuccess) { 165 for (CFIndex i = 0; i < CFArrayGetCount(elements); i++) { 166 CFDictionaryRef element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i); 167 168 CFTypeRef object = CFDictionaryGetValue(element, 169 CFSTR(kIOHIDElementCookieKey)); 170 if (object == 0 || CFGetTypeID(object) != CFNumberGetTypeID()) continue; 171 long number; 172 if (!CFNumberGetValue((CFNumberRef)object, kCFNumberLongType, &number)) { 173 continue; 174 } 175 IOHIDElementCookie cookie = (IOHIDElementCookie)number; 176 177 cookies.push_back((int)cookie); 178 } 179 return true; 180 } 181 return false; 182 } 183 184 // private 185 bool 186 AppleRemote::_createDeviceInterface(io_object_t hidDevice) { 187 SInt32 score = 0; 188 IOCFPlugInInterface** plugInInterface = NULL; 189 190 IOReturn ioReturnValue = IOCreatePlugInInterfaceForService(hidDevice, 191 kIOHIDDeviceUserClientTypeID, 192 kIOCFPlugInInterfaceID, 193 &plugInInterface, 194 &score); 195 if (ioReturnValue == kIOReturnSuccess) { 196 HRESULT plugInResult = (*plugInInterface)->QueryInterface(plugInInterface, 197 CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID), 198 (LPVOID*) (&hidDeviceInterface)); 199 if (plugInResult != S_OK) { 200 std::cerr << "AppleRemote Error: couldn't create device interface " << std::endl; 201 } 202 // Release 203 if (plugInInterface) (*plugInInterface)->Release(plugInInterface); 204 } 205 return hidDeviceInterface != 0; 206 } 207 208 // private 209 bool 210 AppleRemote::_openDevice() { 211 IOHIDOptionsType openMode = kIOHIDOptionsTypeNone; 212 if (openInExclusiveMode) openMode = kIOHIDOptionsTypeSeizeDevice; 213 IOReturn ioReturnValue = (*hidDeviceInterface)->open(hidDeviceInterface, openMode); 214 215 if (ioReturnValue != KERN_SUCCESS) { 216 std::cerr << "AppleRemote Error: when opening device" << std::endl; 217 return false; 218 } 219 queue = (*hidDeviceInterface)->allocQueue(hidDeviceInterface); 220 if (!queue) { 221 std::cerr << "AppleRemote Error allocating queue" << std::endl; 222 return false; 223 } 224 225 HRESULT result = (*queue)->create(queue, 0, 12); 226 if (result != S_OK || !queue) { 227 std::cerr << "AppleRemote Error creating queue" << std::endl; 228 } 229 230 for (std::vector<int>::iterator iter = cookies.begin(); 231 iter != cookies.end(); 232 iter++) { 233 IOHIDElementCookie cookie = (IOHIDElementCookie)(*iter); 234 (*queue)->addElement(queue, cookie, 0); 235 } 236 237 CFRunLoopSourceRef eventSource; 238 ioReturnValue = (*queue)->createAsyncEventSource(queue, &eventSource); 239 if (ioReturnValue != KERN_SUCCESS) { 240 std::cerr << "AppleRemote Error creating async event source" << std::endl; 241 return false; 242 } 243 244 ioReturnValue = (*queue)->setEventCallout(queue,QueueCallbackFunction, this, NULL); 245 if (ioReturnValue != KERN_SUCCESS) { 246 std::cerr << "AppleRemote Error registering callback" << std::endl; 247 return false; 248 } 249 CFRunLoopAddSource(CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode); 250 (*queue)->start(queue); 251 return true; 252 } 253 254 // static 255 void 256 AppleRemote::QueueCallbackFunction(void* target, IOReturn result, 257 void* refcon, void* sender) { 258 AppleRemote* remote = (AppleRemote*)target; 259 remote->_queueCallbackFunction(result,refcon,sender); 260 } 261 262 void 263 AppleRemote::_queueCallbackFunction(IOReturn result, void* /*refcon*/, void* /*sender*/) { 264 AbsoluteTime zeroTime = {0,0}; 265 SInt32 sumOfValues = 0; 266 std::stringstream cookieString; 267 268 while (result == kIOReturnSuccess) { 269 IOHIDEventStruct event; 270 result = (*queue)->getNextEvent(queue, &event, zeroTime, 0); 271 if (result != kIOReturnSuccess) break; 272 273 if (REMOTE_SWITCH_COOKIE == (int)event.elementCookie) { 274 remoteId=event.value; 275 _handleEventWithCookieString("19_",0); 276 } else { 277 sumOfValues+=event.value; 278 cookieString << std::dec << (int)event.elementCookie << "_"; 279 } 280 } 281 282 _handleEventWithCookieString(cookieString.str(), sumOfValues); 283 } 284 285 void 286 AppleRemote::_handleEventWithCookieString(std::string cookieString, 287 SInt32 sumOfValues) { 288 std::map<std::string,AppleRemote::Event>::iterator ii = cookieToButtonMapping.find(cookieString); 289 if (ii != cookieToButtonMapping.end() && _listener) { 290 AppleRemote::Event buttonid = ii->second; 291 if (_listener) _listener->appleRemoteButton(buttonid, sumOfValues>0); 292 } 293 } -
libs/libmyth/mythdialogs.cpp
23 23 using namespace std; 24 24 25 25 #include <pthread.h> 26 #ifdef Q_WS_MACX 27 #include "lircevent.h" 28 #include "AppleRemote.h" 29 #include "AppleRemoteListener.h" 30 #endif 26 31 #ifdef USE_LIRC 27 32 #include "lirc.h" 28 33 #include "lircevent.h" … … 56 61 } 57 62 #endif 58 63 64 #ifdef Q_WS_MACX 65 static void* SpawnAppleRemote(void* param) 66 { 67 MythMainWindow *main_window = (MythMainWindow *)param; 68 AppleRemoteListener *arl = new AppleRemoteListener(main_window); 69 AppleRemote& remote(AppleRemote::instance()); 70 remote.setListener(arl); 71 remote.startListening(); 72 if (!remote.isListeningToRemote()) { 73 return NULL; 74 } 75 remote.runLoop(); 76 return NULL; 77 } 78 #endif 79 59 80 #ifdef USE_JOYSTICK_MENU 60 81 static void *SpawnJoystickMenu(void *param) 61 82 { … … 194 215 pthread_create(&lirc_tid, &attr, SpawnLirc, this); 195 216 #endif 196 217 218 #ifdef Q_WS_MACX 219 pthread_t appleremote_tid; 220 pthread_attr_t arattr; 221 pthread_attr_init(&arattr); 222 pthread_attr_setdetachstate(&arattr, PTHREAD_CREATE_DETACHED); 223 224 pthread_create(&appleremote_tid, &arattr, SpawnAppleRemote, this); 225 #endif 226 197 227 #ifdef USE_JOYSTICK_MENU 198 228 d->ignore_joystick_keys = false; 199 229 pthread_t js_tid; … … 810 840 } 811 841 } 812 842 } 843 #if defined(USE_LIRC) || defined(Q_WS_MACX) 844 else if (ce->type() == kLircKeycodeEventType 813 845 #ifdef USE_LIRC 814 else if (ce->type() == kLircKeycodeEventType && !d->ignore_lirc_keys) 846 && !d->ignore_lirc_keys 847 #endif 848 ) 815 849 { 816 850 LircKeycodeEvent *lke = (LircKeycodeEvent *)ce; 817 851 int keycode = lke->getKeycode(); … … 851 885 " your key mappings.\n"; 852 886 } 853 887 } 888 #endif 889 #ifdef USE_LIRC 854 890 else if (ce->type() == kLircMuteEventType) 855 891 { 856 892 LircMuteEvent *lme = (LircMuteEvent *)ce; -
libs/libmyth/libmyth.pro
75 75 macx { 76 76 HEADERS += audiooutputca.h screensaver-osx.h DisplayResOSX.h 77 77 SOURCES += audiooutputca.cpp screensaver-osx.cpp DisplayResOSX.cpp 78 HEADERS += util-osx.h 79 SOURCES += util-osx.cpp 78 HEADERS += util-osx.h AppleRemote.h AppleRemoteListener.h lircevent.h 79 SOURCES += util-osx.cpp AppleRemote.cpp AppleRemoteListener.cpp lircevent.cpp 80 80 81 81 # Mac OS X Frameworks 82 82 FWKS = ApplicationServices AudioUnit Carbon CoreAudio IOKit -
libs/libmyth/AppleRemoteListener.h
1 #ifndef APPLEREMOTELISTENER 2 #define APPLEREMOTELISTENER 3 4 #include "AppleRemote.h" 5 6 #include <iostream> 7 8 class AppleRemoteListener: public AppleRemote::Listener { 9 public: 10 AppleRemoteListener(QObject* mainWindow_); 11 // virtual 12 void appleRemoteButton(AppleRemote::Event button, bool pressedDown); 13 private: 14 QObject *mainWindow; 15 }; 16 17 #endif // APPLEREMOTELISTENER 18 No newline at end of file