The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
8.6KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. // (This file gets included by juce_mac_NativeCode.mm, rather than being
  24. // compiled on its own).
  25. #ifdef JUCE_INCLUDED_FILE
  26. //==============================================================================
  27. AppleRemoteDevice::AppleRemoteDevice()
  28. : device (0),
  29. queue (0),
  30. remoteId (0)
  31. {
  32. }
  33. AppleRemoteDevice::~AppleRemoteDevice()
  34. {
  35. stop();
  36. }
  37. static io_object_t getAppleRemoteDevice() throw()
  38. {
  39. CFMutableDictionaryRef dict = IOServiceMatching ("AppleIRController");
  40. io_iterator_t iter = 0;
  41. io_object_t iod = 0;
  42. if (IOServiceGetMatchingServices (kIOMasterPortDefault, dict, &iter) == kIOReturnSuccess
  43. && iter != 0)
  44. {
  45. iod = IOIteratorNext (iter);
  46. }
  47. IOObjectRelease (iter);
  48. return iod;
  49. }
  50. static bool createAppleRemoteInterface (io_object_t iod, void** device) throw()
  51. {
  52. jassert (*device == 0);
  53. io_name_t classname;
  54. if (IOObjectGetClass (iod, classname) == kIOReturnSuccess)
  55. {
  56. IOCFPlugInInterface** cfPlugInInterface = 0;
  57. SInt32 score = 0;
  58. if (IOCreatePlugInInterfaceForService (iod,
  59. kIOHIDDeviceUserClientTypeID,
  60. kIOCFPlugInInterfaceID,
  61. &cfPlugInInterface,
  62. &score) == kIOReturnSuccess)
  63. {
  64. HRESULT hr = (*cfPlugInInterface)->QueryInterface (cfPlugInInterface,
  65. CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID),
  66. device);
  67. (void) hr;
  68. (*cfPlugInInterface)->Release (cfPlugInInterface);
  69. }
  70. }
  71. return *device != 0;
  72. }
  73. bool AppleRemoteDevice::start (const bool inExclusiveMode) throw()
  74. {
  75. if (queue != 0)
  76. return true;
  77. stop();
  78. bool result = false;
  79. io_object_t iod = getAppleRemoteDevice();
  80. if (iod != 0)
  81. {
  82. if (createAppleRemoteInterface (iod, &device) && open (inExclusiveMode))
  83. result = true;
  84. else
  85. stop();
  86. IOObjectRelease (iod);
  87. }
  88. return result;
  89. }
  90. void AppleRemoteDevice::stop() throw()
  91. {
  92. if (queue != 0)
  93. {
  94. (*(IOHIDQueueInterface**) queue)->stop ((IOHIDQueueInterface**) queue);
  95. (*(IOHIDQueueInterface**) queue)->dispose ((IOHIDQueueInterface**) queue);
  96. (*(IOHIDQueueInterface**) queue)->Release ((IOHIDQueueInterface**) queue);
  97. queue = 0;
  98. }
  99. if (device != 0)
  100. {
  101. (*(IOHIDDeviceInterface**) device)->close ((IOHIDDeviceInterface**) device);
  102. (*(IOHIDDeviceInterface**) device)->Release ((IOHIDDeviceInterface**) device);
  103. device = 0;
  104. }
  105. }
  106. bool AppleRemoteDevice::isActive() const throw()
  107. {
  108. return queue != 0;
  109. }
  110. static void appleRemoteQueueCallback (void* const target, const IOReturn result, void*, void*)
  111. {
  112. if (result == kIOReturnSuccess)
  113. ((AppleRemoteDevice*) target)->handleCallbackInternal();
  114. }
  115. bool AppleRemoteDevice::open (const bool openInExclusiveMode) throw()
  116. {
  117. #if ! MACOS_10_2_OR_EARLIER
  118. Array <int> cookies;
  119. CFArrayRef elements;
  120. IOHIDDeviceInterface122** const device122 = (IOHIDDeviceInterface122**) device;
  121. if ((*device122)->copyMatchingElements (device122, 0, &elements) != kIOReturnSuccess)
  122. return false;
  123. for (int i = 0; i < CFArrayGetCount (elements); ++i)
  124. {
  125. CFDictionaryRef element = (CFDictionaryRef) CFArrayGetValueAtIndex (elements, i);
  126. // get the cookie
  127. CFTypeRef object = CFDictionaryGetValue (element, CFSTR (kIOHIDElementCookieKey));
  128. if (object == 0 || CFGetTypeID (object) != CFNumberGetTypeID())
  129. continue;
  130. long number;
  131. if (! CFNumberGetValue ((CFNumberRef) object, kCFNumberLongType, &number))
  132. continue;
  133. cookies.add ((int) number);
  134. }
  135. CFRelease (elements);
  136. if ((*(IOHIDDeviceInterface**) device)
  137. ->open ((IOHIDDeviceInterface**) device,
  138. openInExclusiveMode ? kIOHIDOptionsTypeSeizeDevice
  139. : kIOHIDOptionsTypeNone) == KERN_SUCCESS)
  140. {
  141. queue = (*(IOHIDDeviceInterface**) device)->allocQueue ((IOHIDDeviceInterface**) device);
  142. if (queue != 0)
  143. {
  144. (*(IOHIDQueueInterface**) queue)->create ((IOHIDQueueInterface**) queue, 0, 12);
  145. for (int i = 0; i < cookies.size(); ++i)
  146. {
  147. IOHIDElementCookie cookie = (IOHIDElementCookie) cookies.getUnchecked(i);
  148. (*(IOHIDQueueInterface**) queue)->addElement ((IOHIDQueueInterface**) queue, cookie, 0);
  149. }
  150. CFRunLoopSourceRef eventSource;
  151. if ((*(IOHIDQueueInterface**) queue)
  152. ->createAsyncEventSource ((IOHIDQueueInterface**) queue, &eventSource) == KERN_SUCCESS)
  153. {
  154. if ((*(IOHIDQueueInterface**) queue)->setEventCallout ((IOHIDQueueInterface**) queue,
  155. appleRemoteQueueCallback, this, 0) == KERN_SUCCESS)
  156. {
  157. CFRunLoopAddSource (CFRunLoopGetCurrent(), eventSource, kCFRunLoopDefaultMode);
  158. (*(IOHIDQueueInterface**) queue)->start ((IOHIDQueueInterface**) queue);
  159. return true;
  160. }
  161. }
  162. }
  163. }
  164. #endif
  165. return false;
  166. }
  167. void AppleRemoteDevice::handleCallbackInternal()
  168. {
  169. #if ! MACOS_10_2_OR_EARLIER
  170. int totalValues = 0;
  171. AbsoluteTime nullTime = { 0, 0 };
  172. char cookies [12];
  173. int numCookies = 0;
  174. while (numCookies < numElementsInArray (cookies))
  175. {
  176. IOHIDEventStruct e;
  177. if ((*(IOHIDQueueInterface**) queue)->getNextEvent ((IOHIDQueueInterface**) queue, &e, nullTime, 0) != kIOReturnSuccess)
  178. break;
  179. if ((int) e.elementCookie == 19)
  180. {
  181. remoteId = e.value;
  182. buttonPressed (switched, false);
  183. }
  184. else
  185. {
  186. totalValues += e.value;
  187. cookies [numCookies++] = (char) (pointer_sized_int) e.elementCookie;
  188. }
  189. }
  190. cookies [numCookies++] = 0;
  191. //DBG (String::toHexString ((uint8*) cookies, numCookies, 1) + " " + String (totalValues));
  192. static const char buttonPatterns[] =
  193. {
  194. 0x1f, 0x14, 0x12, 0x1f, 0x14, 0x12, 0,
  195. 0x1f, 0x15, 0x12, 0x1f, 0x15, 0x12, 0,
  196. 0x1f, 0x1d, 0x1c, 0x12, 0,
  197. 0x1f, 0x1e, 0x1c, 0x12, 0,
  198. 0x1f, 0x16, 0x12, 0x1f, 0x16, 0x12, 0,
  199. 0x1f, 0x17, 0x12, 0x1f, 0x17, 0x12, 0,
  200. 0x1f, 0x12, 0x04, 0x02, 0,
  201. 0x1f, 0x12, 0x03, 0x02, 0,
  202. 0x1f, 0x12, 0x1f, 0x12, 0,
  203. 0x23, 0x1f, 0x12, 0x23, 0x1f, 0x12, 0,
  204. 19, 0
  205. };
  206. int buttonNum = (int) menuButton;
  207. int i = 0;
  208. while (i < numElementsInArray (buttonPatterns))
  209. {
  210. if (strcmp (cookies, buttonPatterns + i) == 0)
  211. {
  212. buttonPressed ((ButtonType) buttonNum, totalValues > 0);
  213. break;
  214. }
  215. i += strlen (buttonPatterns + i) + 1;
  216. ++buttonNum;
  217. }
  218. #endif
  219. }
  220. #endif