summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorder richter <der.richter@gmx.de>2019-11-16 16:54:07 +0100
committerder richter <der.richter@gmx.de>2019-12-15 20:07:31 +0100
commit8a6ee7fe947bb01a49beb38152cedb1e1b206ed2 (patch)
tree6ccead9d45dcc1561601c6d4927c6c71ba528eac
parent1eb6cbd093481517e37b40aec174fc6f4e553bcd (diff)
downloadmpv-8a6ee7fe947bb01a49beb38152cedb1e1b206ed2.tar.bz2
mpv-8a6ee7fe947bb01a49beb38152cedb1e1b206ed2.tar.xz
mac: remove Apple Remote support
the Apple Remote has long been deprecated and abandoned by Apple. current macs don't come with support for it anymore. support might be re-added with the next commit.
-rw-r--r--DOCS/interface-changes.rst3
-rw-r--r--DOCS/man/input.rst3
-rw-r--r--DOCS/man/options.rst4
-rw-r--r--DOCS/mplayer-changes.rst3
-rwxr-xr-xci/build-macos.sh2
-rw-r--r--etc/builtin.conf1
-rw-r--r--etc/input.conf16
-rw-r--r--etc/mplayer-input.conf19
-rw-r--r--input/input.c18
-rw-r--r--input/keycodes.c15
-rw-r--r--input/keycodes.h17
-rw-r--r--osdep/ar/HIDRemote.h378
-rw-r--r--osdep/ar/HIDRemote.m2033
-rw-r--r--osdep/macosx_events.h3
-rw-r--r--osdep/macosx_events.m65
-rw-r--r--osdep/macosx_events_objc.h3
-rw-r--r--wscript5
-rw-r--r--wscript_build.py1
18 files changed, 9 insertions, 2580 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 23e71b3a2d..59e00130c4 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -59,6 +59,9 @@ Interface changes
setting the properties to non-existing tracks may report it as selected
track for a small time window, until it's forced back to "no". The exact
details how this is handled may change in the future.
+ - remove old Apple Remote support, including --input-appleremote
+ - add MediaPlayer support and remove the old Media Key event tap on macOS.
+ this possibly also re-adds the Apple Remote support
--- mpv 0.30.0 ---
- add `--d3d11-output-format` to enable explicit selection of a D3D11
swap chain format.
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 323a961804..3d9263ee3f 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -145,9 +145,6 @@ Comments on some symbolic names:
``GAMEPAD_*``
Keys emitted by the SDL gamepad backend.
-``AR_*``
- Keys emitted by the OSX-only Apple Remote code.
-
``UNMAPPED``
Pseudo-key that matches any unmapped key. (You should probably avoid this
if possible, because it might change behavior or get removed in the future.)
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index c2fd9136a3..be9177b09a 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -3484,10 +3484,6 @@ Input
See `JSON IPC`_ for details.
-``--input-appleremote=<yes|no>``
- (OS X only)
- Enable/disable Apple Remote support. Enabled by default (except for libmpv).
-
``--input-gamepad=<yes|no>``
Enable/disable SDL2 Gamepad support. Disabled by default.
diff --git a/DOCS/mplayer-changes.rst b/DOCS/mplayer-changes.rst
index 66cacb3205..d00b520279 100644
--- a/DOCS/mplayer-changes.rst
+++ b/DOCS/mplayer-changes.rst
@@ -144,7 +144,6 @@ Mac OS X
* Native OpenGL backend.
* Cocoa event loop is independent from MPlayer's event loop, so user
actions like accessing menus and live resizing do not block the playback.
-* Apple Remote support.
* Media Keys support.
* VDA support using libavcodec hwaccel API instead of FFmpeg's decoder with up
to 2-2.5x reduction in CPU usage.
@@ -248,7 +247,7 @@ Command Line Switches
``-msglevel`` ``--msg-level`` (changed semantics)
``-msgmodule`` ``--msg-module``
``-name`` ``--x11-name``
- ``-noar`` ``--no-input-appleremote``
+ ``-noar`` ``(removed; replaced by MediaPlayer framework)``
``-noautosub`` ``--no-sub-auto``
``-noconsolecontrols`` ``--no-input-terminal``
``-nosound`` ``--no-audio``
diff --git a/ci/build-macos.sh b/ci/build-macos.sh
index 4984e3ba81..7b6eda7356 100755
--- a/ci/build-macos.sh
+++ b/ci/build-macos.sh
@@ -19,7 +19,7 @@ PKG_CONFIG_PATH="${FFMPEG_SYSROOT}/lib/pkgconfig/" CC="${CC}" CXX="${CXX}" pytho
--variant="${MPV_VARIANT}" \
--prefix="${MPV_INSTALL_PREFIX}" \
--enable-{gl,iconv,lcms2,libass,libass-osd,libmpv-shared,lua,jpeg,plain-gl,zlib} \
- --enable-{apple-remote,cocoa,coreaudio,gl-cocoa,macos-cocoa-cb,macos-touchbar,videotoolbox-gl}
+ --enable-{cocoa,coreaudio,gl-cocoa,macos-cocoa-cb,macos-touchbar,videotoolbox-gl}
python3 ./waf build --variant="${MPV_VARIANT}" -j4
diff --git a/etc/builtin.conf b/etc/builtin.conf
index a5e174e964..6984d57769 100644
--- a/etc/builtin.conf
+++ b/etc/builtin.conf
@@ -27,7 +27,6 @@ osc=no
input-default-bindings=no
input-vo-keyboard=no
# OSX/Cocoa global input hooks
-input-appleremote=no
input-media-keys=no
[encoding]
diff --git a/etc/input.conf b/etc/input.conf
index f60ed51bd4..9c870ea42b 100644
--- a/etc/input.conf
+++ b/etc/input.conf
@@ -168,22 +168,6 @@
#F8 show_text ${playlist} # show playlist
#F9 show_text ${track-list} # show list of audio/sub streams
-# Apple Remote section
-#AR_PLAY cycle pause
-#AR_PLAY_HOLD quit
-#AR_CENTER cycle pause
-#AR_CENTER_HOLD quit
-#AR_NEXT seek 10
-#AR_NEXT_HOLD seek 120
-#AR_PREV seek -10
-#AR_PREV_HOLD seek -120
-#AR_MENU show-progress
-#AR_MENU_HOLD cycle mute
-#AR_VUP add volume 2
-#AR_VUP_HOLD add chapter 1
-#AR_VDOWN add volume -2
-#AR_VDOWN_HOLD add chapter -1
-
#
# Legacy bindings (may or may not be removed in the future)
#
diff --git a/etc/mplayer-input.conf b/etc/mplayer-input.conf
index 742913c0fe..2d23e47477 100644
--- a/etc/mplayer-input.conf
+++ b/etc/mplayer-input.conf
@@ -74,25 +74,6 @@ l cycle tv-channel -1
n cycle tv-norm
#b tv_step_chanlist
-##
-## Apple Remote section
-##
-## To use OSD menu with Apple Remote, set key AR_MENU to any OSD menu command,
-## or just comment out the 'AR_MENU osd' line and uncomment the line after it.
-##
-
-AR_PLAY cycle pause
-AR_PLAY_HOLD quit
-AR_NEXT seek 30
-AR_NEXT_HOLD seek 120
-AR_PREV seek -10
-AR_PREV_HOLD seek -120
-#AR_MENU menu up
-#AR_MENU menu cancel
-AR_MENU_HOLD cycle mute
-AR_VUP add volume 1
-AR_VDOWN add volume -1
-
#? add chapter -1 # skip to previous dvd chapter
#? add chapter +1 # next
diff --git a/input/input.c b/input/input.c
index 084a61a2eb..1bc8e303f6 100644
--- a/input/input.c
+++ b/input/input.c
@@ -196,14 +196,14 @@ const struct m_sub_options input_config = {
OPT_FLAG("input-cursor", enable_mouse_movements, 0),
OPT_FLAG("input-vo-keyboard", vo_key_input, 0),
OPT_FLAG("input-media-keys", use_media_keys, 0),
-#if HAVE_COCOA
- OPT_FLAG("input-appleremote", use_appleremote, 0),
-#endif
#if HAVE_SDL2_GAMEPAD
OPT_FLAG("input-gamepad", use_gamepad, 0),
#endif
OPT_FLAG("window-dragging", allow_win_drag, 0),
OPT_REPLACED("input-x11-keyboard", "input-vo-keyboard"),
+#if HAVE_COCOA
+ OPT_REMOVED("input-appleremote", "replaced by MediaPlayer support"),
+#endif
{0}
},
.size = sizeof(struct input_opts),
@@ -215,9 +215,6 @@ const struct m_sub_options input_config = {
.use_alt_gr = 1,
.enable_mouse_movements = 1,
.use_media_keys = 1,
-#if HAVE_COCOA
- .use_appleremote = 1,
-#endif
.default_bindings = 1,
.vo_key_input = 1,
.allow_win_drag = 1,
@@ -1335,15 +1332,6 @@ static void reload_opts(struct input_ctx *ictx, bool shutdown)
#if HAVE_COCOA
struct input_opts *opts = ictx->opts;
- if (ictx->using_ar != (opts->use_appleremote && !shutdown)) {
- ictx->using_ar = !ictx->using_ar;
- if (ictx->using_ar) {
- cocoa_init_apple_remote();
- } else {
- cocoa_uninit_apple_remote();
- }
- }
-
if (ictx->using_cocoa_media_keys != (opts->use_media_keys && !shutdown)) {
ictx->using_cocoa_media_keys = !ictx->using_cocoa_media_keys;
if (ictx->using_cocoa_media_keys) {
diff --git a/input/keycodes.c b/input/keycodes.c
index 3d7fd09d11..bcf59c74a1 100644
--- a/input/keycodes.c
+++ b/input/keycodes.c
@@ -102,21 +102,6 @@ static const struct key_name key_names[] = {
{ MP_MBTN_MID_DBL, "MBTN_MID_DBL" },
{ MP_MBTN_RIGHT_DBL, "MBTN_RIGHT_DBL" },
- { MP_AR_PLAY, "AR_PLAY" },
- { MP_AR_PLAY_HOLD, "AR_PLAY_HOLD" },
- { MP_AR_CENTER, "AR_CENTER" },
- { MP_AR_CENTER_HOLD, "AR_CENTER_HOLD" },
- { MP_AR_NEXT, "AR_NEXT" },
- { MP_AR_NEXT_HOLD, "AR_NEXT_HOLD" },
- { MP_AR_PREV, "AR_PREV" },
- { MP_AR_PREV_HOLD, "AR_PREV_HOLD" },
- { MP_AR_MENU, "AR_MENU" },
- { MP_AR_MENU_HOLD, "AR_MENU_HOLD" },
- { MP_AR_VUP, "AR_VUP" },
- { MP_AR_VUP_HOLD, "AR_VUP_HOLD" },
- { MP_AR_VDOWN, "AR_VDOWN" },
- { MP_AR_VDOWN_HOLD, "AR_VDOWN_HOLD" },
-
{ MP_KEY_GAMEPAD_ACTION_DOWN, "GAMEPAD_ACTION_DOWN" },
{ MP_KEY_GAMEPAD_ACTION_RIGHT, "GAMEPAD_ACTION_RIGHT" },
{ MP_KEY_GAMEPAD_ACTION_LEFT, "GAMEPAD_ACTION_LEFT" },
diff --git a/input/keycodes.h b/input/keycodes.h
index 65c31b4d61..a75099f2f2 100644
--- a/input/keycodes.h
+++ b/input/keycodes.h
@@ -141,23 +141,6 @@
#define MP_KEY_MOUSE_BTN_COUNT (MP_MBTN_END - MP_MBTN_BASE)
-// Apple Remote input module
-#define MP_AR_BASE (MP_KEY_BASE+0xE0)
-#define MP_AR_PLAY (MP_AR_BASE + 0)
-#define MP_AR_PLAY_HOLD (MP_AR_BASE + 1)
-#define MP_AR_CENTER (MP_AR_BASE + 2)
-#define MP_AR_CENTER_HOLD (MP_AR_BASE + 3)
-#define MP_AR_NEXT (MP_AR_BASE + 4)
-#define MP_AR_NEXT_HOLD (MP_AR_BASE + 5)
-#define MP_AR_PREV (MP_AR_BASE + 6)
-#define MP_AR_PREV_HOLD (MP_AR_BASE + 7)
-#define MP_AR_MENU (MP_AR_BASE + 8)
-#define MP_AR_MENU_HOLD (MP_AR_BASE + 9)
-#define MP_AR_VUP (MP_AR_BASE + 10)
-#define MP_AR_VUP_HOLD (MP_AR_BASE + 11)
-#define MP_AR_VDOWN (MP_AR_BASE + 12)
-#define MP_AR_VDOWN_HOLD (MP_AR_BASE + 13)
-
/* game controller keys */
#define MP_KEY_GAMEPAD (MP_KEY_BASE+0xF0)
#define MP_KEY_GAMEPAD_ACTION_DOWN (MP_KEY_GAMEPAD+0)
diff --git a/osdep/ar/HIDRemote.h b/osdep/ar/HIDRemote.h
deleted file mode 100644
index 35db408b40..0000000000
--- a/osdep/ar/HIDRemote.h
+++ /dev/null
@@ -1,378 +0,0 @@
-//
-// HIDRemote.h
-// HIDRemote V1.2
-//
-// Created by Felix Schwarz on 06.04.07.
-// Copyright 2007-2011 IOSPIRIT GmbH. All rights reserved.
-//
-// The latest version of this class is available at
-// http://www.iospirit.com/developers/hidremote/
-//
-// ** LICENSE *************************************************************************
-//
-// Copyright (c) 2007-2011 IOSPIRIT GmbH (http://www.iospirit.com/)
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice, this list
-// of conditions and the following disclaimer.
-//
-// * Redistributions in binary form must reproduce the above copyright notice, this
-// list of conditions and the following disclaimer in the documentation and/or other
-// materials provided with the distribution.
-//
-// * Neither the name of IOSPIRIT GmbH nor the names of its contributors may be used to
-// endorse or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-// DAMAGE.
-//
-// ************************************************************************************
-
-
-// ************************************************************************************
-// ********************************** DOCUMENTATION ***********************************
-// ************************************************************************************
-//
-// - a reference is available at http://www.iospirit.com/developers/hidremote/reference/
-// - for a guide, please see http://www.iospirit.com/developers/hidremote/guide/
-//
-// ************************************************************************************
-
-
-#import <Cocoa/Cocoa.h>
-
-#include <Carbon/Carbon.h>
-
-#include <unistd.h>
-#include <mach/mach.h>
-#include <sys/types.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/IOMessage.h>
-#include <IOKit/hid/IOHIDKeys.h>
-#include <IOKit/hid/IOHIDLib.h>
-#include <IOKit/hid/IOHIDUsageTables.h>
-#include <IOKit/hidsystem/IOHIDLib.h>
-#include <IOKit/hidsystem/IOHIDParameter.h>
-#include <IOKit/hidsystem/IOHIDShared.h>
-
-#pragma mark -- Enums / Codes --
-
-typedef enum
-{
- kHIDRemoteModeNone = 0L,
- kHIDRemoteModeShared, // Share the remote with others - let's you listen to the remote control events as long as no one has an exclusive lock on it
- // (RECOMMENDED ONLY FOR SPECIAL PURPOSES)
-
- kHIDRemoteModeExclusive, // Try to acquire an exclusive lock on the remote (NOT RECOMMENDED)
-
- kHIDRemoteModeExclusiveAuto // Try to acquire an exclusive lock on the remote whenever the application has focus. Temporarily release control over the
- // remote when another application has focus (RECOMMENDED)
-} HIDRemoteMode;
-
-typedef enum
-{
- /* A code reserved for "no button" (needed for tracking) */
- kHIDRemoteButtonCodeNone = 0L,
-
- /* Standard codes - available for white plastic and aluminum remote */
- kHIDRemoteButtonCodeUp,
- kHIDRemoteButtonCodeDown,
- kHIDRemoteButtonCodeLeft,
- kHIDRemoteButtonCodeRight,
- kHIDRemoteButtonCodeCenter,
- kHIDRemoteButtonCodeMenu,
-
- /* Extra codes - Only available for the new aluminum version of the remote */
- kHIDRemoteButtonCodePlay,
-
- /* Masks */
- kHIDRemoteButtonCodeCodeMask = 0xFFL,
- kHIDRemoteButtonCodeHoldMask = (1L << 16L),
- kHIDRemoteButtonCodeSpecialMask = (1L << 17L),
- kHIDRemoteButtonCodeAluminumMask = (1L << 21L), // PRIVATE - only used internally
-
- /* Hold button standard codes - available for white plastic and aluminum remote */
- kHIDRemoteButtonCodeUpHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeUp),
- kHIDRemoteButtonCodeDownHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeDown),
- kHIDRemoteButtonCodeLeftHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeLeft),
- kHIDRemoteButtonCodeRightHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeRight),
- kHIDRemoteButtonCodeCenterHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeCenter),
- kHIDRemoteButtonCodeMenuHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodeMenu),
-
- /* Hold button extra codes - Only available for aluminum version of the remote */
- kHIDRemoteButtonCodePlayHold = (kHIDRemoteButtonCodeHoldMask|kHIDRemoteButtonCodePlay),
-
- /* DEPRECATED codes - compatibility with HIDRemote 1.0 */
- kHIDRemoteButtonCodePlus = kHIDRemoteButtonCodeUp,
- kHIDRemoteButtonCodePlusHold = kHIDRemoteButtonCodeUpHold,
- kHIDRemoteButtonCodeMinus = kHIDRemoteButtonCodeDown,
- kHIDRemoteButtonCodeMinusHold = kHIDRemoteButtonCodeDownHold,
- kHIDRemoteButtonCodePlayPause = kHIDRemoteButtonCodeCenter,
- kHIDRemoteButtonCodePlayPauseHold = kHIDRemoteButtonCodeCenterHold,
-
- /* Special purpose codes */
- kHIDRemoteButtonCodeIDChanged = (kHIDRemoteButtonCodeSpecialMask|(1L << 18L)), // (the ID of the connected remote has changed, you can safely ignore this)
- #ifdef _HIDREMOTE_EXTENSIONS
- #define _HIDREMOTE_EXTENSIONS_SECTION 1
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-} HIDRemoteButtonCode;
-
-typedef enum
-{
- kHIDRemoteModelUndetermined = 0L, // Assume a white plastic remote
- kHIDRemoteModelWhitePlastic, // Signal *likely* to be coming from a white plastic remote
- kHIDRemoteModelAluminum // Signal *definitely* coming from an aluminum remote
-} HIDRemoteModel;
-
-typedef enum
-{
- kHIDRemoteAluminumRemoteSupportLevelNone = 0L, // This system has no support for the Aluminum Remote at all
- kHIDRemoteAluminumRemoteSupportLevelEmulation, // This system possibly has support for the Aluminum Remote (via emulation)
- kHIDRemoteAluminumRemoteSupportLevelNative // This system has native support for the Aluminum Remote
-} HIDRemoteAluminumRemoteSupportLevel;
-
-@class HIDRemote;
-
-#pragma mark -- Delegate protocol (mandatory) --
-@protocol HIDRemoteDelegate
-
-// Notification of button events
-- (void)hidRemote:(HIDRemote *)hidRemote // The instance of HIDRemote sending this
- eventWithButton:(HIDRemoteButtonCode)buttonCode // Event for the button specified by code
- isPressed:(BOOL)isPressed // The button was pressed (YES) / released (NO)
- fromHardwareWithAttributes:(NSMutableDictionary *)attributes; // Information on the device this event comes from
-
-@optional
-
-// Notification of ID changes
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when the user switched to a remote control with a different ID
- remoteIDChangedOldID:(SInt32)old
- newID:(SInt32)newID
- forHardwareWithAttributes:(NSMutableDictionary *)attributes;
-
-// Notification about hardware additions/removals
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware was found / added to HIDRemote's pool
- foundNewHardwareWithAttributes:(NSMutableDictionary *)attributes;
-
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when initialization of new hardware as requested failed
- failedNewHardwareWithError:(NSError *)error;
-
-- (void)hidRemote:(HIDRemote *)hidRemote // Invoked when hardware was removed from HIDRemote's pool
- releasedHardwareWithAttributes:(NSMutableDictionary *)attributes;
-
-// ### WARNING: Unless you know VERY PRECISELY what you are doing, do not implement any of the delegate methods below. ###
-
-// Matching of newly found receiver hardware
-- (BOOL)hidRemote:(HIDRemote *)hidRemote // Invoked when new hardware is inspected
- inspectNewHardwareWithService:(io_service_t)service //
- prematchResult:(BOOL)prematchResult; // Return YES if HIDRemote should go on with this hardware and try
- // to use it, or NO if it should not be pursued further.
-
-// Exlusive lock lending
-- (BOOL)hidRemote:(HIDRemote *)hidRemote
- lendExclusiveLockToApplicationWithInfo:(NSDictionary *)applicationInfo;
-
-- (void)hidRemote:(HIDRemote *)hidRemote
- exclusiveLockReleasedByApplicationWithInfo:(NSDictionary *)applicationInfo;
-
-- (BOOL)hidRemote:(HIDRemote *)hidRemote
- shouldRetryExclusiveLockWithInfo:(NSDictionary *)applicationInfo;
-
-@end
-
-
-#pragma mark -- Actual header file for class --
-
-@interface HIDRemote : NSObject
-{
- // IOMasterPort
- mach_port_t _masterPort;
-
- // Notification ports
- IONotificationPortRef _notifyPort;
- CFRunLoopSourceRef _notifyRLSource;
-
- // Matching iterator
- io_iterator_t _matchingServicesIterator;
-
- // SecureInput notification
- io_object_t _secureInputNotification;
-
- // Service attributes
- NSMutableDictionary *_serviceAttribMap;
-
- // Mode
- HIDRemoteMode _mode;
- BOOL _autoRecover;
- NSTimer *_autoRecoveryTimer;
-
- // Delegate
- NSObject <HIDRemoteDelegate> *_delegate;
-
- // Last seen ID and remote model
- SInt32 _lastSeenRemoteID;
- HIDRemoteModel _lastSeenModel;
- SInt32 _lastSeenModelRemoteID;
-
- // Unused button codes
- NSArray *_unusedButtonCodes;
-
- // Simulate Plus/Minus Hold
- BOOL _simulateHoldEvents;
-
- // SecureEventInput workaround
- BOOL _secureEventInputWorkAround;
- UInt64 _lastSecureEventInputPIDSum;
- uid_t _lastFrontUserSession;
-
- // Exclusive lock lending
- BOOL _exclusiveLockLending;
- BOOL _sendExclusiveResourceReuseNotification;
- NSNumber *_waitForReturnByPID;
- NSNumber *_returnToPID;
- BOOL _isRestarting;
-
- // Status notifications
- BOOL _sendStatusNotifications;
- NSString *_pidString;
-
- // Status
- BOOL _applicationIsTerminating;
- BOOL _isStopping;
-
- // Thread safety
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING /* #define HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING if you're running your HIDRemote instance on a background thread (requires OS X 10.5 or later) */
- NSThread *_runOnThread;
- #endif
-}
-
-#pragma mark -- PUBLIC: Shared HID Remote --
-+ (HIDRemote *)sharedHIDRemote;
-
-#pragma mark -- PUBLIC: System Information --
-+ (BOOL)isCandelairInstalled;
-+ (BOOL)isCandelairInstallationRequiredForRemoteMode:(HIDRemoteMode)remoteMode;
-- (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel;
-
-#pragma mark -- PUBLIC: Interface / API --
-- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode;
-- (void)stopRemoteControl;
-
-- (BOOL)isStarted;
-- (HIDRemoteMode)startedInMode;
-
-- (unsigned)activeRemoteControlCount;
-
-- (SInt32)lastSeenRemoteControlID;
-
-- (void)setLastSeenModel:(HIDRemoteModel)aModel;
-- (HIDRemoteModel)lastSeenModel;
-
-- (void)setDelegate:(NSObject <HIDRemoteDelegate> *)newDelegate;
-- (NSObject <HIDRemoteDelegate> *)delegate;
-
-- (void)setSimulateHoldEvents:(BOOL)newSimulateHoldEvents;
-- (BOOL)simulateHoldEvents;
-
-- (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers;
-- (NSArray *)unusedButtonCodes;
-
-#pragma mark -- PUBLIC: Expert APIs --
-- (void)setEnableSecureEventInputWorkaround:(BOOL)newEnableSecureEventInputWorkaround;
-- (BOOL)enableSecureEventInputWorkaround;
-
-- (void)setExclusiveLockLendingEnabled:(BOOL)newExclusiveLockLendingEnabled;
-- (BOOL)exclusiveLockLendingEnabled;
-
-- (BOOL)isApplicationTerminating;
-- (BOOL)isStopping;
-
-#pragma mark -- PRIVATE: HID Event handling --
-- (void)_handleButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict;
-- (void)_sendButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict;
-- (void)_hidEventFor:(io_service_t)hidDevice from:(IOHIDQueueInterface **)interface withResult:(IOReturn)result;
-
-#pragma mark -- PRIVATE: Service setup and destruction --
-- (BOOL)_prematchService:(io_object_t)service;
-- (HIDRemoteButtonCode)buttonCodeForUsage:(unsigned int)usage usagePage:(unsigned int)usagePage;
-- (BOOL)_setupService:(io_object_t)service;
-- (void)_destructService:(io_object_t)service;
-
-#pragma mark -- PRIVATE: Distributed notifiations handling --
-- (void)_postStatusWithAction:(NSString *)action;
-- (void)_handleNotifications:(NSNotification *)notification;
-- (void)_setSendStatusNotifications:(BOOL)doSend;
-- (BOOL)_sendStatusNotifications;
-
-#pragma mark -- PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto --
-- (void)_appStatusChanged:(NSNotification *)notification;
-- (void)_delayedAutoRecovery:(NSTimer *)aTimer;
-
-#pragma mark -- PRIVATE: Notification handling --
-- (void)_serviceMatching:(io_iterator_t)iterator;
-- (void)_serviceNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument;
-- (void)_updateSessionInformation;
-- (void)_secureInputNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument;
-
-@end
-
-#pragma mark -- Information attribute keys --
-extern NSString *kHIDRemoteManufacturer;
-extern NSString *kHIDRemoteProduct;
-extern NSString *kHIDRemoteTransport;
-
-#pragma mark -- Internal/Expert attribute keys (AKA: don't touch these unless you really, really, REALLY know what you do) --
-extern NSString *kHIDRemoteCFPluginInterface;
-extern NSString *kHIDRemoteHIDDeviceInterface;
-extern NSString *kHIDRemoteCookieButtonCodeLUT;
-extern NSString *kHIDRemoteHIDQueueInterface;
-extern NSString *kHIDRemoteServiceNotification;
-extern NSString *kHIDRemoteCFRunLoopSource;
-extern NSString *kHIDRemoteLastButtonPressed;
-extern NSString *kHIDRemoteService;
-extern NSString *kHIDRemoteSimulateHoldEventsTimer;
-extern NSString *kHIDRemoteSimulateHoldEventsOriginButtonCode;
-extern NSString *kHIDRemoteAluminumRemoteSupportLevel;
-extern NSString *kHIDRemoteAluminumRemoteSupportOnDemand;
-
-#pragma mark -- Distributed notifications --
-extern NSString *kHIDRemoteDNHIDRemotePing;
-extern NSString *kHIDRemoteDNHIDRemoteRetry;
-extern NSString *kHIDRemoteDNHIDRemoteStatus;
-
-extern NSString *kHIDRemoteDNHIDRemoteRetryGlobalObject;
-
-#pragma mark -- Distributed notifications userInfo keys and values --
-extern NSString *kHIDRemoteDNStatusHIDRemoteVersionKey;
-extern NSString *kHIDRemoteDNStatusPIDKey;
-extern NSString *kHIDRemoteDNStatusModeKey;
-extern NSString *kHIDRemoteDNStatusUnusedButtonCodesKey;
-extern NSString *kHIDRemoteDNStatusRemoteControlCountKey;
-extern NSString *kHIDRemoteDNStatusReturnToPIDKey;
-extern NSString *kHIDRemoteDNStatusActionKey;
-extern NSString *kHIDRemoteDNStatusActionStart;
-extern NSString *kHIDRemoteDNStatusActionStop;
-extern NSString *kHIDRemoteDNStatusActionUpdate;
-extern NSString *kHIDRemoteDNStatusActionNoNeed;
-
-#pragma mark -- Driver compatibility flags --
-typedef enum
-{
- kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice = 1L,
-} HIDRemoteCompatibilityFlags;
diff --git a/osdep/ar/HIDRemote.m b/osdep/ar/HIDRemote.m
deleted file mode 100644
index 8e6c913d46..0000000000
--- a/osdep/ar/HIDRemote.m
+++ /dev/null
@@ -1,2033 +0,0 @@
-//
-// HIDRemote.m
-// HIDRemote V1.2 (27th May 2011)
-//
-// Created by Felix Schwarz on 06.04.07.
-// Copyright 2007-2011 IOSPIRIT GmbH. All rights reserved.
-//
-// The latest version of this class is available at
-// http://www.iospirit.com/developers/hidremote/
-//
-// ** LICENSE *************************************************************************
-//
-// Copyright (c) 2007-2011 IOSPIRIT GmbH (http://www.iospirit.com/)
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without modification,
-// are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice, this list
-// of conditions and the following disclaimer.
-//
-// * Redistributions in binary form must reproduce the above copyright notice, this
-// list of conditions and the following disclaimer in the documentation and/or other
-// materials provided with the distribution.
-//
-// * Neither the name of IOSPIRIT GmbH nor the names of its contributors may be used to
-// endorse or promote products derived from this software without specific prior
-// written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
-// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
-// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
-// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
-// DAMAGE.
-//
-// ************************************************************************************
-
-// ************************************************************************************
-// ********************************** DOCUMENTATION ***********************************
-// ************************************************************************************
-//
-// - a reference is available at http://www.iospirit.com/developers/hidremote/reference/
-// - for a guide, please see http://www.iospirit.com/developers/hidremote/guide/
-//
-// ************************************************************************************
-
-#import "HIDRemote.h"
-
-// Callback Prototypes
-static void HIDEventCallback( void * target,
- IOReturn result,
- void * refcon,
- void * sender);
-
-static void ServiceMatchingCallback( void *refCon,
- io_iterator_t iterator);
-
-static void ServiceNotificationCallback(void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument);
-
-static void SecureInputNotificationCallback( void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument);
-
-// Shared HIDRemote instance
-static HIDRemote *sHIDRemote = nil;
-
-@implementation HIDRemote
-
-#pragma mark -- Init, dealloc & shared instance --
-
-+ (HIDRemote *)sharedHIDRemote
-{
- if (sHIDRemote==nil)
- {
- sHIDRemote = [[HIDRemote alloc] init];
- }
-
- return (sHIDRemote);
-}
-
-- (id)init
-{
- if ((self = [super init]) != nil)
- {
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- _runOnThread = [[NSThread currentThread] retain];
- #endif
-
- // Detect application becoming active/inactive
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationDidBecomeActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillResignActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appStatusChanged:) name:NSApplicationWillTerminateNotification object:NSApp];
-
- // Handle distributed notifications
- _pidString = [[NSString alloc] initWithFormat:@"%d", getpid()];
-
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemotePing object:nil];
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject];
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteRetry object:_pidString];
-
- // Enabled by default: simulate hold events for plus/minus
- _simulateHoldEvents = YES;
-
- // Enabled by default: work around for a locking issue introduced with Security Update 2008-004 / 10.4.9 and beyond (credit for finding this workaround goes to Martin Kahr)
- _secureEventInputWorkAround = YES;
- _secureInputNotification = 0;
-
- // Initialize instance variables
- _lastSeenRemoteID = -1;
- _lastSeenModel = kHIDRemoteModelUndetermined;
- _unusedButtonCodes = [[NSMutableArray alloc] init];
- _exclusiveLockLending = NO;
- _sendExclusiveResourceReuseNotification = YES;
- _applicationIsTerminating = NO;
-
- // Send status notifications
- _sendStatusNotifications = YES;
- }
-
- return (self);
-}
-
-- (void)dealloc
-{
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillTerminateNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationWillResignActiveNotification object:NSApp];
- [[NSNotificationCenter defaultCenter] removeObserver:self name:NSApplicationDidBecomeActiveNotification object:NSApp];
-
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemotePing object:nil];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:kHIDRemoteDNHIDRemoteRetryGlobalObject];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteRetry object:_pidString];
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:nil object:nil]; /* As demanded by the documentation for -[NSDistributedNotificationCenter removeObserver:name:object:] */
-
- [self stopRemoteControl];
-
- [self setExclusiveLockLendingEnabled:NO];
-
- [self setDelegate:nil];
-
- if (_unusedButtonCodes != nil)
- {
- [_unusedButtonCodes release];
- _unusedButtonCodes = nil;
- }
-
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- [_runOnThread release];
- _runOnThread = nil;
- #endif
-
- [_pidString release];
- _pidString = nil;
-
- [super dealloc];
-}
-
-#pragma mark -- PUBLIC: System Information --
-+ (BOOL)isCandelairInstalled
-{
- mach_port_t masterPort = 0;
- kern_return_t kernResult;
- io_service_t matchingService = 0;
- BOOL isInstalled = NO;
-
- kernResult = IOMasterPort(MACH_PORT_NULL, &masterPort);
- if ((kernResult!=kIOReturnSuccess) || (masterPort==0)) { return(NO); }
-
- if ((matchingService = IOServiceGetMatchingService(masterPort, IOServiceMatching("IOSPIRITIRController"))) != 0)
- {
- isInstalled = YES;
- IOObjectRelease((io_object_t) matchingService);
- }
-
- mach_port_deallocate(mach_task_self(), masterPort);
-
- return (isInstalled);
-}
-
-+ (BOOL)isCandelairInstallationRequiredForRemoteMode:(HIDRemoteMode)remoteMode
-{
- return (NO);
-}
-
-- (HIDRemoteAluminumRemoteSupportLevel)aluminiumRemoteSystemSupportLevel
-{
- HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone;
- NSEnumerator *attribDictsEnum;
- NSDictionary *hidAttribsDict;
-
- attribDictsEnum = [_serviceAttribMap objectEnumerator];
-
- while ((hidAttribsDict = [attribDictsEnum nextObject]) != nil)
- {
- NSNumber *deviceSupportLevel;
-
- if ((deviceSupportLevel = [hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel]) != nil)
- {
- if ([deviceSupportLevel intValue] > (int)supportLevel)
- {
- supportLevel = [deviceSupportLevel intValue];
- }
- }
- }
-
- return (supportLevel);
-}
-
-#pragma mark -- PUBLIC: Interface / API --
-- (BOOL)startRemoteControl:(HIDRemoteMode)hidRemoteMode
-{
- if ((_mode == kHIDRemoteModeNone) && (hidRemoteMode != kHIDRemoteModeNone))
- {
- kern_return_t kernReturn;
- CFMutableDictionaryRef matchDict=NULL;
- io_service_t rootService;
-
- do
- {
- // Get IOKit master port
- kernReturn = IOMasterPort(bootstrap_port, &_masterPort);
- if ((kernReturn!=kIOReturnSuccess) || (_masterPort==0)) { break; }
-
- // Setup notification port
- _notifyPort = IONotificationPortCreate(_masterPort);
-
- if ((_notifyRLSource = IONotificationPortGetRunLoopSource(_notifyPort)) != NULL)
- {
- CFRunLoopAddSource( CFRunLoopGetCurrent(),
- _notifyRLSource,
- kCFRunLoopCommonModes);
- }
- else
- {
- break;
- }
-
- // Setup SecureInput notification
- if ((hidRemoteMode == kHIDRemoteModeExclusive) || (hidRemoteMode == kHIDRemoteModeExclusiveAuto))
- {
- if ((rootService = IORegistryEntryFromPath(_masterPort, kIOServicePlane ":/")) != 0)
- {
- kernReturn = IOServiceAddInterestNotification( _notifyPort,
- rootService,
- kIOBusyInterest,
- SecureInputNotificationCallback,
- (void *)self,
- &_secureInputNotification);
- if (kernReturn != kIOReturnSuccess) { break; }
-
- [self _updateSessionInformation];
- }
- else
- {
- break;
- }
- }
-
- // Setup notification matching dict
- matchDict = IOServiceMatching(kIOHIDDeviceKey);
- CFRetain(matchDict);
-
- // Actually add notification
- kernReturn = IOServiceAddMatchingNotification( _notifyPort,
- kIOFirstMatchNotification,
- matchDict, // one reference count consumed by this call
- ServiceMatchingCallback,
- (void *) self,
- &_matchingServicesIterator);
- if (kernReturn != kIOReturnSuccess) { break; }
-
- // Setup serviceAttribMap
- _serviceAttribMap = [[NSMutableDictionary alloc] init];
- if (_serviceAttribMap==nil) { break; }
-
- // Phew .. everything went well!
- _mode = hidRemoteMode;
- CFRelease(matchDict);
-
- [self _serviceMatching:_matchingServicesIterator];
-
- [self _postStatusWithAction:kHIDRemoteDNStatusActionStart];
-
- return (YES);
-
- }while(0);
-
- // An error occurred. Do necessary clean up.
- if (matchDict!=NULL)
- {
- CFRelease(matchDict);
- matchDict = NULL;
- }
-
- [self stopRemoteControl];
- }
-
- return (NO);
-}
-
-- (void)stopRemoteControl
-{
- UInt32 serviceCount = 0;
-
- _autoRecover = NO;
- _isStopping = YES;
-
- if (_autoRecoveryTimer!=nil)
- {
- [_autoRecoveryTimer invalidate];
- [_autoRecoveryTimer release];
- _autoRecoveryTimer = nil;
- }
-
- if (_serviceAttribMap!=nil)
- {
- NSDictionary *cloneDict = [[NSDictionary alloc] initWithDictionary:_serviceAttribMap];
-
- if (cloneDict!=nil)
- {
- NSEnumerator *mapKeyEnum = [cloneDict keyEnumerator];
- NSNumber *serviceValue;
-
- while ((serviceValue = [mapKeyEnum nextObject]) != nil)
- {
- [self _destructService:(io_object_t)[serviceValue unsignedIntValue]];
- serviceCount++;
- };
-
- [cloneDict release];
- cloneDict = nil;
- }
-
- [_serviceAttribMap release];
- _serviceAttribMap = nil;
- }
-
- if (_matchingServicesIterator!=0)
- {
- IOObjectRelease((io_object_t) _matchingServicesIterator);
- _matchingServicesIterator = 0;
- }
-
- if (_secureInputNotification!=0)
- {
- IOObjectRelease((io_object_t) _secureInputNotification);
- _secureInputNotification = 0;
- }
-
- if (_notifyRLSource!=NULL)
- {
- CFRunLoopSourceInvalidate(_notifyRLSource);
- _notifyRLSource = NULL;
- }
-
- if (_notifyPort!=NULL)
- {
- IONotificationPortDestroy(_notifyPort);
- _notifyPort = NULL;
- }
-
- if (_masterPort!=0)
- {
- mach_port_deallocate(mach_task_self(), _masterPort);
- _masterPort = 0;
- }
-
- if (_returnToPID!=nil)
- {
- [_returnToPID release];
- _returnToPID = nil;
- }
-
- if (_mode!=kHIDRemoteModeNone)
- {
- // Post status
- [self _postStatusWithAction:kHIDRemoteDNStatusActionStop];
-
- if (_sendStatusNotifications)
- {
- // In case we were not ready to lend it earlier, tell other HIDRemote apps that the resources (if any were used) are now again available for use by other applications
- if (((_mode==kHIDRemoteModeExclusive) || (_mode==kHIDRemoteModeExclusiveAuto)) && (_sendExclusiveResourceReuseNotification==YES) && (_exclusiveLockLending==NO) && (serviceCount>0))
- {
- _mode = kHIDRemoteModeNone;
-
- if (!_isRestarting)
- {
- [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry
- object:kHIDRemoteDNHIDRemoteRetryGlobalObject
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
- [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
- nil]
- deliverImmediately:YES];
- }
- }
- }
- }
-
- _mode = kHIDRemoteModeNone;
- _isStopping = NO;
-}
-
-- (BOOL)isStarted
-{
- return (_mode != kHIDRemoteModeNone);
-}
-
-- (HIDRemoteMode)startedInMode
-{
- return (_mode);
-}
-
-- (unsigned)activeRemoteControlCount
-{
- return ([_serviceAttribMap count]);
-}
-
-- (SInt32)lastSeenRemoteControlID
-{
- return (_lastSeenRemoteID);
-}
-
-- (HIDRemoteModel)lastSeenModel
-{
- return (_lastSeenModel);
-}
-
-- (void)setLastSeenModel:(HIDRemoteModel)aModel
-{
- _lastSeenModel = aModel;
-}
-
-- (void)setSimulateHoldEvents:(BOOL)newSimulateHoldEvents
-{
- _simulateHoldEvents = newSimulateHoldEvents;
-}
-
-- (BOOL)simulateHoldEvents
-{
- return (_simulateHoldEvents);
-}
-
-- (NSArray *)unusedButtonCodes
-{
- return (_unusedButtonCodes);
-}
-
-- (void)setUnusedButtonCodes:(NSArray *)newArrayWithUnusedButtonCodesAsNSNumbers
-{
- [newArrayWithUnusedButtonCodesAsNSNumbers retain];
- [_unusedButtonCodes release];
-
- _unusedButtonCodes = newArrayWithUnusedButtonCodesAsNSNumbers;
-
- [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate];
-}
-
-- (void)setDelegate:(NSObject <HIDRemoteDelegate> *)newDelegate
-{
- _delegate = newDelegate;
-}
-
-- (NSObject <HIDRemoteDelegate> *)delegate
-{
- return (_delegate);
-}
-
-#pragma mark -- PUBLIC: Expert APIs --
-- (void)setEnableSecureEventInputWorkaround:(BOOL)newEnableSecureEventInputWorkaround
-{
- _secureEventInputWorkAround = newEnableSecureEventInputWorkaround;
-}
-
-- (BOOL)enableSecureEventInputWorkaround
-{
- return (_secureEventInputWorkAround);
-}
-
-- (void)setExclusiveLockLendingEnabled:(BOOL)newExclusiveLockLendingEnabled
-{
- if (newExclusiveLockLendingEnabled != _exclusiveLockLending)
- {
- _exclusiveLockLending = newExclusiveLockLendingEnabled;
-
- if (_exclusiveLockLending)
- {
- [[NSDistributedNotificationCenter defaultCenter] addObserver:self selector:@selector(_handleNotifications:) name:kHIDRemoteDNHIDRemoteStatus object:nil];
- }
- else
- {
- [[NSDistributedNotificationCenter defaultCenter] removeObserver:self name:kHIDRemoteDNHIDRemoteStatus object:nil];
-
- [_waitForReturnByPID release];
- _waitForReturnByPID = nil;
- }
- }
-}
-
-- (BOOL)exclusiveLockLendingEnabled
-{
- return (_exclusiveLockLending);
-}
-
-- (void)setSendExclusiveResourceReuseNotification:(BOOL)newSendExclusiveResourceReuseNotification
-{
- _sendExclusiveResourceReuseNotification = newSendExclusiveResourceReuseNotification;
-}
-
-- (BOOL)sendExclusiveResourceReuseNotification
-{
- return (_sendExclusiveResourceReuseNotification);
-}
-
-- (BOOL)isApplicationTerminating
-{
- return (_applicationIsTerminating);
-}
-
-- (BOOL)isStopping
-{
- return (_isStopping);
-}
-
-#pragma mark -- PRIVATE: Application becomes active / inactive handling for kHIDRemoteModeExclusiveAuto --
-- (void)_appStatusChanged:(NSNotification *)notification
-{
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only
- {
- if ([NSThread currentThread] != _runOnThread)
- {
- if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification])
- {
- if (!_autoRecover)
- {
- return;
- }
- }
-
- if ([[notification name] isEqual:NSApplicationWillResignActiveNotification])
- {
- if (_mode != kHIDRemoteModeExclusiveAuto)
- {
- return;
- }
- }
-
- [self performSelector:@selector(_appStatusChanged:) onThread:_runOnThread withObject:notification waitUntilDone:[[notification name] isEqual:NSApplicationWillTerminateNotification]];
- return;
- }
- }
- #endif
-
- if (notification!=nil)
- {
- if (_autoRecoveryTimer!=nil)
- {
- [_autoRecoveryTimer invalidate];
- [_autoRecoveryTimer release];
- _autoRecoveryTimer = nil;
- }
-
- if ([[notification name] isEqual:NSApplicationDidBecomeActiveNotification])
- {
- if (_autoRecover)
- {
- // Delay autorecover by 0.1 to avoid race conditions
- if ((_autoRecoveryTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.1] interval:0.1 target:self selector:@selector(_delayedAutoRecovery:) userInfo:nil repeats:NO]) != nil)
- {
- // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes.
- // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code
- // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0.
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)_autoRecoveryTimer, kCFRunLoopCommonModes);
- }
- }
- }
-
- if ([[notification name] isEqual:NSApplicationWillResignActiveNotification])
- {
- if (_mode == kHIDRemoteModeExclusiveAuto)
- {
- [self stopRemoteControl];
- _autoRecover = YES;
- }
- }
-
- if ([[notification name] isEqual:NSApplicationWillTerminateNotification])
- {
- _applicationIsTerminating = YES;
-
- if ([self isStarted])
- {
- [self stopRemoteControl];
- }
- }
- }
-}
-
-- (void)_delayedAutoRecovery:(NSTimer *)aTimer
-{
- [_autoRecoveryTimer invalidate];
- [_autoRecoveryTimer release];
- _autoRecoveryTimer = nil;
-
- if (_autoRecover)
- {
- [self startRemoteControl:kHIDRemoteModeExclusiveAuto];
- _autoRecover = NO;
- }
-}
-
-
-#pragma mark -- PRIVATE: Distributed notifiations handling --
-- (void)_postStatusWithAction:(NSString *)action
-{
- if (_sendStatusNotifications)
- {
- [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteStatus
- object:((_pidString!=nil) ? _pidString : [NSString stringWithFormat:@"%d",getpid()])
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInt:1], kHIDRemoteDNStatusHIDRemoteVersionKey,
- [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
- [NSNumber numberWithInt:(int)_mode], kHIDRemoteDNStatusModeKey,
- [NSNumber numberWithUnsignedInt:(unsigned int)[self activeRemoteControlCount]], kHIDRemoteDNStatusRemoteControlCountKey,
- ((_unusedButtonCodes!=nil) ? _unusedButtonCodes : [NSArray array]), kHIDRemoteDNStatusUnusedButtonCodesKey,
- action, kHIDRemoteDNStatusActionKey,
- [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
- _returnToPID, kHIDRemoteDNStatusReturnToPIDKey,
- nil]
- deliverImmediately:YES
- ];
- }
-}
-
-- (void)_handleNotifications:(NSNotification *)notification
-{
- NSString *notificationName;
-
- #ifdef HIDREMOTE_THREADSAFETY_HARDENED_NOTIFICATION_HANDLING
- if ([self respondsToSelector:@selector(performSelector:onThread:withObject:waitUntilDone:)]) // OS X 10.5+ only
- {
- if ([NSThread currentThread] != _runOnThread)
- {
- [self performSelector:@selector(_handleNotifications:) onThread:_runOnThread withObject:notification waitUntilDone:NO];
- return;
- }
- }
- #endif
-
- if ((notification!=nil) && ((notificationName = [notification name]) != nil))
- {
- if ([notificationName isEqual:kHIDRemoteDNHIDRemotePing])
- {
- [self _postStatusWithAction:kHIDRemoteDNStatusActionUpdate];
- }
-
- if ([notificationName isEqual:kHIDRemoteDNHIDRemoteRetry])
- {
- if ([self isStarted])
- {
- BOOL retry = YES;
-
- // Ignore our own global retry broadcasts
- if ([[notification object] isEqual:kHIDRemoteDNHIDRemoteRetryGlobalObject])
- {
- NSNumber *fromPID;
-
- if ((fromPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil)
- {
- if (getpid() == (int)[fromPID unsignedIntValue])
- {
- retry = NO;
- }
- }
- }
-
- if (retry)
- {
- if (([self delegate] != nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:shouldRetryExclusiveLockWithInfo:)]))
- {
- retry = [[self delegate] hidRemote:self shouldRetryExclusiveLockWithInfo:[notification userInfo]];
- }
- }
-
- if (retry)
- {
- HIDRemoteMode restartInMode = _mode;
-
- if (restartInMode != kHIDRemoteModeNone)
- {
- _isRestarting = YES;
- [self stopRemoteControl];
-
- [_returnToPID release];
- _returnToPID = nil;
-
- [self startRemoteControl:restartInMode];
- _isRestarting = NO;
-
- if (restartInMode != kHIDRemoteModeShared)
- {
- _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain];
- }
- }
- }
- else
- {
- NSNumber *cacheReturnPID = _returnToPID;
-
- _returnToPID = [[[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey] retain];
- [self _postStatusWithAction:kHIDRemoteDNStatusActionNoNeed];
- [_returnToPID release];
-
- _returnToPID = cacheReturnPID;
- }
- }
- }
-
- if (_exclusiveLockLending)
- {
- if ([notificationName isEqual:kHIDRemoteDNHIDRemoteStatus])
- {
- NSString *action;
-
- if ((action = [[notification userInfo] objectForKey:kHIDRemoteDNStatusActionKey]) != nil)
- {
- if ((_mode == kHIDRemoteModeNone) && (_waitForReturnByPID!=nil))
- {
- NSNumber *pidNumber, *returnToPIDNumber;
-
- if ((pidNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey]) != nil)
- {
- returnToPIDNumber = [[notification userInfo] objectForKey:kHIDRemoteDNStatusReturnToPIDKey];
-
- if ([action isEqual:kHIDRemoteDNStatusActionStart])
- {
- if ([pidNumber isEqual:_waitForReturnByPID])
- {
- NSNumber *startMode;
-
- if ((startMode = [[notification userInfo] objectForKey:kHIDRemoteDNStatusModeKey]) != nil)
- {
- if ([startMode intValue] == kHIDRemoteModeShared)
- {
- returnToPIDNumber = [NSNumber numberWithInt:getpid()];
- action = kHIDRemoteDNStatusActionNoNeed;
- }
- }
- }
- }
-
- if (returnToPIDNumber != nil)
- {
- if ([action isEqual:kHIDRemoteDNStatusActionStop] || [action isEqual:kHIDRemoteDNStatusActionNoNeed])
- {
- if ([pidNumber isEqual:_waitForReturnByPID] && ([returnToPIDNumber intValue] == getpid()))
- {
- [_waitForReturnByPID release];
- _waitForReturnByPID = nil;
-
- if (([self delegate] != nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:exclusiveLockReleasedByApplicationWithInfo:)]))
- {
- [[self delegate] hidRemote:self exclusiveLockReleasedByApplicationWithInfo:[notification userInfo]];
- }
- else
- {
- [self startRemoteControl:kHIDRemoteModeExclusive];
- }
- }
- }
- }
- }
- }
-
- if (_mode==kHIDRemoteModeExclusive)
- {
- if ([action isEqual:kHIDRemoteDNStatusActionStart])
- {
- NSNumber *originPID = [[notification userInfo] objectForKey:kHIDRemoteDNStatusPIDKey];
- BOOL lendLock = YES;
-
- if ([originPID intValue] != getpid())
- {
- if (([self delegate] != nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:lendExclusiveLockToApplicationWithInfo:)]))
- {
- lendLock = [[self delegate] hidRemote:self lendExclusiveLockToApplicationWithInfo:[notification userInfo]];
- }
-
- if (lendLock)
- {
- [_waitForReturnByPID release];
- _waitForReturnByPID = [originPID retain];
-
- if (_waitForReturnByPID != nil)
- {
- [self stopRemoteControl];
-
- [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kHIDRemoteDNHIDRemoteRetry
- object:[NSString stringWithFormat:@"%d", [_waitForReturnByPID intValue]]
- userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithUnsignedInt:(unsigned int)getpid()], kHIDRemoteDNStatusPIDKey,
- [[NSBundle mainBundle] bundleIdentifier], (NSString *)kCFBundleIdentifierKey,
- nil]
- deliverImmediately:YES];
- }
- }
- }
- }
- }
- }
- }
- }
- }
-}
-
-- (void)_setSendStatusNotifications:(BOOL)doSend
-{
- _sendStatusNotifications = doSend;
-}
-
-- (BOOL)_sendStatusNotifications
-{
- return (_sendStatusNotifications);
-}
-
-#pragma mark -- PRIVATE: Service setup and destruction --
-- (BOOL)_prematchService:(io_object_t)service
-{
- BOOL serviceMatches = NO;
- NSString *ioClass;
- NSNumber *candelairHIDRemoteCompatibilityMask;
-
- if (service != 0)
- {
- // IOClass matching
- if ((ioClass = (NSString *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
- CFSTR(kIOClassKey),
- kCFAllocatorDefault,
- 0)) != nil)
- {
- // Match on Apple's AppleIRController and old versions of the Remote Buddy IR Controller
- if ([ioClass isEqual:@"AppleIRController"] || [ioClass isEqual:@"RBIOKitAIREmu"])
- {
- CFTypeRef candelairHIDRemoteCompatibilityDevice;
-
- serviceMatches = YES;
-
- if ((candelairHIDRemoteCompatibilityDevice = IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityDevice"), kCFAllocatorDefault, 0)) != NULL)
- {
- if (CFEqual(kCFBooleanTrue, candelairHIDRemoteCompatibilityDevice))
- {
- serviceMatches = NO;
- }
-
- CFRelease (candelairHIDRemoteCompatibilityDevice);
- }
- }
-
- // Match on the virtual IOSPIRIT IR Controller
- if ([ioClass isEqual:@"IOSPIRITIRController"])
- {
- serviceMatches = YES;
- }
-
- CFRelease((CFTypeRef)ioClass);
- }
-
- // Match on services that claim compatibility with the HID Remote class (Candelair or third-party) by having a property of CandelairHIDRemoteCompatibilityMask = 1 <Type: Number>
- if ((candelairHIDRemoteCompatibilityMask = (NSNumber *)IORegistryEntryCreateCFProperty((io_registry_entry_t)service, CFSTR("CandelairHIDRemoteCompatibilityMask"), kCFAllocatorDefault, 0)) != nil)
- {
- if ([candelairHIDRemoteCompatibilityMask isKindOfClass:[NSNumber class]])
- {
- if ([candelairHIDRemoteCompatibilityMask unsignedIntValue] & kHIDRemoteCompatibilityFlagsStandardHIDRemoteDevice)
- {
- serviceMatches = YES;
- }
- else
- {
- serviceMatches = NO;
- }
- }
-
- CFRelease((CFTypeRef)candelairHIDRemoteCompatibilityMask);
- }
- }
-
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:inspectNewHardwareWithService:prematchResult:)]))
- {
- serviceMatches = [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self inspectNewHardwareWithService:service prematchResult:serviceMatches];
- }
-
- return (serviceMatches);
-}
-
-- (HIDRemoteButtonCode)buttonCodeForUsage:(unsigned int)usage usagePage:(unsigned int)usagePage
-{
- HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone;
-
- switch (usagePage)
- {
- case kHIDPage_Consumer:
- switch (usage)
- {
- case kHIDUsage_Csmr_MenuPick:
- // Aluminum Remote: Center
- buttonCode = (kHIDRemoteButtonCodeCenter|kHIDRemoteButtonCodeAluminumMask);
- break;
-
- case kHIDUsage_Csmr_ModeStep:
- // Aluminium Remote: Center Hold
- buttonCode = (kHIDRemoteButtonCodeCenterHold|kHIDRemoteButtonCodeAluminumMask);
- break;
-
- case kHIDUsage_Csmr_PlayOrPause:
- // Aluminum Remote: Play/Pause
- buttonCode = (kHIDRemoteButtonCodePlay|kHIDRemoteButtonCodeAluminumMask);
- break;
-
- case kHIDUsage_Csmr_Rewind:
- buttonCode = kHIDRemoteButtonCodeLeftHold;
- break;
-
- case kHIDUsage_Csmr_FastForward:
- buttonCode = kHIDRemoteButtonCodeRightHold;
- break;
-
- case kHIDUsage_Csmr_Menu:
- buttonCode = kHIDRemoteButtonCodeMenuHold;
- break;
-
- case kHIDUsage_Csmr_VolumeIncrement:
- buttonCode = kHIDRemoteButtonCodeUp;
- break;
-
- case kHIDUsage_Csmr_VolumeDecrement:
- buttonCode = kHIDRemoteButtonCodeDown;
- break;
- }
- break;
-
- case kHIDPage_GenericDesktop:
- switch (usage)
- {
- case kHIDUsage_GD_SystemAppMenu:
- buttonCode = kHIDRemoteButtonCodeMenu;
- break;
-
- case kHIDUsage_GD_SystemMenu:
- buttonCode = kHIDRemoteButtonCodeCenter;
- break;
-
- case kHIDUsage_GD_SystemMenuRight:
- buttonCode = kHIDRemoteButtonCodeRight;
- break;
-
- case kHIDUsage_GD_SystemMenuLeft:
- buttonCode = kHIDRemoteButtonCodeLeft;
- break;
-
- case kHIDUsage_GD_SystemMenuUp:
- buttonCode = kHIDRemoteButtonCodeUp;
- break;
-
- case kHIDUsage_GD_SystemMenuDown:
- buttonCode = kHIDRemoteButtonCodeDown;
- break;
- }
- break;
-
- case 0x06: /* Reserved */
- switch (usage)
- {
- case 0x22:
- buttonCode = kHIDRemoteButtonCodeIDChanged;
- break;
- }
- break;
-
- case 0xFF01: /* Vendor specific */
- switch (usage)
- {
- case 0x23:
- buttonCode = kHIDRemoteButtonCodeCenterHold;
- break;
-
- #ifdef _HIDREMOTE_EXTENSIONS
- #define _HIDREMOTE_EXTENSIONS_SECTION 2
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
- }
- break;
- }
-
- return (buttonCode);
-}
-
-- (BOOL)_setupService:(io_object_t)service
-{
- kern_return_t kernResult;
- IOReturn returnCode;
- HRESULT hResult;
- SInt32 score;
- BOOL opened = NO, queueStarted = NO;
- IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
- IOCFPlugInInterface **cfPluginInterface = NULL;
- IOHIDQueueInterface **hidQueueInterface = NULL;
- io_object_t serviceNotification = 0;
- CFRunLoopSourceRef queueEventSource = NULL;
- NSMutableDictionary *hidAttribsDict = nil;
- CFArrayRef hidElements = NULL;
- NSError *error = nil;
- UInt32 errorCode = 0;
-
- if (![self _prematchService:service])
- {
- return (NO);
- }
-
- do
- {
- // Create a plugin interface ..
- kernResult = IOCreatePlugInInterfaceForService( service,
- kIOHIDDeviceUserClientTypeID,
- kIOCFPlugInInterfaceID,
- &cfPluginInterface,
- &score);
-
- if (kernResult != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:kernResult userInfo:nil];
- errorCode = 1;
- break;
- }
-
-
- // .. use it to get the HID interface ..
- hResult = (*cfPluginInterface)->QueryInterface( cfPluginInterface,
- CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID122),
- (LPVOID)&hidDeviceInterface);
-
- if ((hResult!=S_OK) || (hidDeviceInterface==NULL))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil];
- errorCode = 2;
- break;
- }
-
-
- // .. then open it ..
- switch (_mode)
- {
- case kHIDRemoteModeShared:
- hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeNone);
- break;
-
- case kHIDRemoteModeExclusive:
- case kHIDRemoteModeExclusiveAuto:
- hResult = (*hidDeviceInterface)->open(hidDeviceInterface, kIOHIDOptionsTypeSeizeDevice);
- break;
-
- default:
- goto cleanUp; // Ugh! But there are no "double breaks" available in C AFAIK ..
- break;
- }
-
- if (hResult!=S_OK)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:hResult userInfo:nil];
- errorCode = 3;
- break;
- }
-
- opened = YES;
-
- // .. query the HID elements ..
- returnCode = (*hidDeviceInterface)->copyMatchingElements(hidDeviceInterface,
- NULL,
- &hidElements);
- if ((returnCode != kIOReturnSuccess) || (hidElements==NULL))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 4;
-
- break;
- }
-
- // Setup an event queue for HID events!
- hidQueueInterface = (*hidDeviceInterface)->allocQueue(hidDeviceInterface);
- if (hidQueueInterface == NULL)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 5;
-
- break;
- }
-
- returnCode = (*hidQueueInterface)->create(hidQueueInterface, 0, 32);
- if (returnCode != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 6;
-
- break;
- }
-
-
- // Setup of attributes stored for this HID device
- hidAttribsDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
- [NSValue valueWithPointer:(const void *)cfPluginInterface], kHIDRemoteCFPluginInterface,
- [NSValue valueWithPointer:(const void *)hidDeviceInterface], kHIDRemoteHIDDeviceInterface,
- [NSValue valueWithPointer:(const void *)hidQueueInterface], kHIDRemoteHIDQueueInterface,
- nil];
-
- {
- UInt32 i, hidElementCnt = CFArrayGetCount(hidElements);
- NSMutableDictionary *cookieButtonCodeLUT = [[NSMutableDictionary alloc] init];
- NSMutableDictionary *cookieCount = [[NSMutableDictionary alloc] init];
-
- if ((cookieButtonCodeLUT==nil) || (cookieCount==nil))
- {
- [cookieButtonCodeLUT release];
- cookieButtonCodeLUT = nil;
-
- [cookieCount release];
- cookieCount = nil;
-
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 7;
-
- break;
- }
-
- // Analyze the HID elements and find matching elements
- for (i=0;i<hidElementCnt;i++)
- {
- CFDictionaryRef hidDict;
- NSNumber *usage, *usagePage, *cookie;
- HIDRemoteButtonCode buttonCode = kHIDRemoteButtonCodeNone;
-
- hidDict = CFArrayGetValueAtIndex(hidElements, i);
-
- usage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsageKey));
- usagePage = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementUsagePageKey));
- cookie = (NSNumber *) CFDictionaryGetValue(hidDict, CFSTR(kIOHIDElementCookieKey));
-
- if ((usage!=nil) && (usagePage!=nil) && (cookie!=nil))
- {
- // Find the button codes for the ID combos
- buttonCode = [self buttonCodeForUsage:[usage unsignedIntValue] usagePage:[usagePage unsignedIntValue]];
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 3
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- // Did record match?
- if (buttonCode != kHIDRemoteButtonCodeNone)
- {
- NSString *pairString = [[NSString alloc] initWithFormat:@"%u_%u", [usagePage unsignedIntValue], [usage unsignedIntValue]];
- NSNumber *buttonCodeNumber = [[NSNumber alloc] initWithUnsignedInt:(unsigned int)buttonCode];
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 4
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- [cookieCount setObject:buttonCodeNumber forKey:pairString];
- [cookieButtonCodeLUT setObject:buttonCodeNumber forKey:cookie];
-
- (*hidQueueInterface)->addElement(hidQueueInterface,
- (IOHIDElementCookie) [cookie unsignedIntValue],
- 0);
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Get current Apple Remote ID value
- #define _HIDREMOTE_EXTENSIONS_SECTION 7
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- [buttonCodeNumber release];
- [pairString release];
- }
- }
- }
-
- // Compare number of *unique* matches (thus the cookieCount dictionary) with required minimum
- if ([cookieCount count] < 10)
- {
- [cookieButtonCodeLUT release];
- cookieButtonCodeLUT = nil;
-
- [cookieCount release];
- cookieCount = nil;
-
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 8;
-
- break;
- }
-
- [hidAttribsDict setObject:cookieButtonCodeLUT forKey:kHIDRemoteCookieButtonCodeLUT];
-
- [cookieButtonCodeLUT release];
- cookieButtonCodeLUT = nil;
-
- [cookieCount release];
- cookieCount = nil;
- }
-
- // Finish setup of IOHIDQueueInterface with CFRunLoop
- returnCode = (*hidQueueInterface)->createAsyncEventSource(hidQueueInterface, &queueEventSource);
- if ((returnCode != kIOReturnSuccess) || (queueEventSource == NULL))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 9;
- break;
- }
-
- returnCode = (*hidQueueInterface)->setEventCallout(hidQueueInterface, HIDEventCallback, (void *)((intptr_t)service), (void *)self);
- if (returnCode != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 10;
- break;
- }
-
- CFRunLoopAddSource( CFRunLoopGetCurrent(),
- queueEventSource,
- kCFRunLoopCommonModes);
- [hidAttribsDict setObject:[NSValue valueWithPointer:(const void *)queueEventSource] forKey:kHIDRemoteCFRunLoopSource];
-
- returnCode = (*hidQueueInterface)->start(hidQueueInterface);
- if (returnCode != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 11;
- break;
- }
-
- queueStarted = YES;
-
- // Setup device notifications
- returnCode = IOServiceAddInterestNotification( _notifyPort,
- service,
- kIOGeneralInterest,
- ServiceNotificationCallback,
- self,
- &serviceNotification);
- if ((returnCode != kIOReturnSuccess) || (serviceNotification==0))
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:returnCode userInfo:nil];
- errorCode = 12;
- break;
- }
-
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)serviceNotification] forKey:kHIDRemoteServiceNotification];
-
- // Retain service
- if (IOObjectRetain(service) != kIOReturnSuccess)
- {
- error = [NSError errorWithDomain:NSMachErrorDomain code:kIOReturnError userInfo:nil];
- errorCode = 13;
- break;
- }
-
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:(unsigned int)service] forKey:kHIDRemoteService];
-
- // Get some (somewhat optional) infos on the device
- {
- CFStringRef product, manufacturer, transport;
-
- if ((product = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- (CFStringRef) @"Product",
- kCFAllocatorDefault,
- 0)) != NULL)
- {
- if (CFGetTypeID(product) == CFStringGetTypeID())
- {
- [hidAttribsDict setObject:(NSString *)product forKey:kHIDRemoteProduct];
- }
-
- CFRelease(product);
- }
-
- if ((manufacturer = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- (CFStringRef) @"Manufacturer",
- kCFAllocatorDefault,
- 0)) != NULL)
- {
- if (CFGetTypeID(manufacturer) == CFStringGetTypeID())
- {
- [hidAttribsDict setObject:(NSString *)manufacturer forKey:kHIDRemoteManufacturer];
- }
-
- CFRelease(manufacturer);
- }
-
- if ((transport = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- (CFStringRef) @"Transport",
- kCFAllocatorDefault,
- 0)) != NULL)
- {
- if (CFGetTypeID(transport) == CFStringGetTypeID())
- {
- [hidAttribsDict setObject:(NSString *)transport forKey:kHIDRemoteTransport];
- }
-
- CFRelease(transport);
- }
- }
-
- // Determine Aluminum Remote support
- {
- CFNumberRef aluSupport;
- HIDRemoteAluminumRemoteSupportLevel supportLevel = kHIDRemoteAluminumRemoteSupportLevelNone;
-
- if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto))
- {
- // Determine if this driver offers on-demand support for the Aluminum Remote (only relevant under OS versions < 10.6.2)
- if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
- (CFStringRef) @"AluminumRemoteSupportLevelOnDemand",
- kCFAllocatorDefault,
- 0)) != nil)
- {
- // There is => request the driver to enable it for us
- if (IORegistryEntrySetCFProperty((io_registry_entry_t)service,
- CFSTR("EnableAluminumRemoteSupportForMe"),
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithLongLong:(long long)getpid()], @"pid",
- [NSNumber numberWithLongLong:(long long)getuid()], @"uid",
- nil]) == kIOReturnSuccess)
- {
- if (CFGetTypeID(aluSupport) == CFNumberGetTypeID())
- {
- supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue];
- }
-
- [hidAttribsDict setObject:[NSNumber numberWithBool:YES] forKey:kHIDRemoteAluminumRemoteSupportOnDemand];
- }
-
- CFRelease(aluSupport);
- }
- }
-
- if (supportLevel == kHIDRemoteAluminumRemoteSupportLevelNone)
- {
- if ((aluSupport = IORegistryEntryCreateCFProperty((io_registry_entry_t)service,
- (CFStringRef) @"AluminumRemoteSupportLevel",
- kCFAllocatorDefault,
- 0)) != nil)
- {
- if (CFGetTypeID(aluSupport) == CFNumberGetTypeID())
- {
- supportLevel = (HIDRemoteAluminumRemoteSupportLevel) [(NSNumber *)aluSupport intValue];
- }
-
- CFRelease(aluSupport);
- }
- else
- {
- CFStringRef ioKitClassName;
-
- if ((ioKitClassName = IORegistryEntryCreateCFProperty( (io_registry_entry_t)service,
- CFSTR(kIOClassKey),
- kCFAllocatorDefault,
- 0)) != nil)
- {
- if ([(NSString *)ioKitClassName isEqual:@"AppleIRController"])
- {
- supportLevel = kHIDRemoteAluminumRemoteSupportLevelNative;
- }
-
- CFRelease(ioKitClassName);
- }
- }
- }
-
- [hidAttribsDict setObject:(NSNumber *)[NSNumber numberWithInt:(int)supportLevel] forKey:kHIDRemoteAluminumRemoteSupportLevel];
- }
-
- // Add it to the serviceAttribMap
- [_serviceAttribMap setObject:hidAttribsDict forKey:[NSNumber numberWithUnsignedInt:(unsigned int)service]];
-
- // And we're done with setup ..
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:foundNewHardwareWithAttributes:)]))
- {
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self foundNewHardwareWithAttributes:hidAttribsDict];
- }
-
- [hidAttribsDict release];
- hidAttribsDict = nil;
-
- return(YES);
-
- }while(0);
-
- cleanUp:
-
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:failedNewHardwareWithError:)]))
- {
- if (error!=nil)
- {
- error = [NSError errorWithDomain:[error domain]
- code:[error code]
- userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:errorCode] forKey:@"InternalErrorCode"]
- ];
- }
-
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self failedNewHardwareWithError:error];
- }
-
- // An error occurred or this device is not of interest .. cleanup ..
- if (serviceNotification!=0)
- {
- IOObjectRelease(serviceNotification);
- serviceNotification = 0;
- }
-
- if (queueEventSource!=NULL)
- {
- CFRunLoopSourceInvalidate(queueEventSource);
- queueEventSource=NULL;
- }
-
- if (hidQueueInterface!=NULL)
- {
- if (queueStarted)
- {
- (*hidQueueInterface)->stop(hidQueueInterface);
- }
- (*hidQueueInterface)->dispose(hidQueueInterface);
- (*hidQueueInterface)->Release(hidQueueInterface);
- hidQueueInterface = NULL;
- }
-
- if (hidAttribsDict!=nil)
- {
- [hidAttribsDict release];
- hidAttribsDict = nil;
- }
-
- if (hidElements!=NULL)
- {
- CFRelease(hidElements);
- hidElements = NULL;
- }
-
- if (hidDeviceInterface!=NULL)
- {
- if (opened)
- {
- (*hidDeviceInterface)->close(hidDeviceInterface);
- }
- (*hidDeviceInterface)->Release(hidDeviceInterface);
- // opened = NO;
- hidDeviceInterface = NULL;
- }
-
- if (cfPluginInterface!=NULL)
- {
- IODestroyPlugInInterface(cfPluginInterface);
- cfPluginInterface = NULL;
- }
-
- return (NO);
-}
-
-- (void)_destructService:(io_object_t)service
-{
- NSNumber *serviceValue;
- NSMutableDictionary *serviceDict = NULL;
-
- if ((serviceValue = [NSNumber numberWithUnsignedInt:(unsigned int)service]) == nil)
- {
- return;
- }
-
- serviceDict = [_serviceAttribMap objectForKey:serviceValue];
-
- if (serviceDict!=nil)
- {
- IOHIDDeviceInterface122 **hidDeviceInterface = NULL;
- IOCFPlugInInterface **cfPluginInterface = NULL;
- IOHIDQueueInterface **hidQueueInterface = NULL;
- io_object_t serviceNotification = 0;
- CFRunLoopSourceRef queueEventSource = NULL;
- io_object_t theService = 0;
- NSMutableDictionary *cookieButtonMap = nil;
- NSTimer *simulateHoldTimer = nil;
-
- serviceNotification = (io_object_t) ([serviceDict objectForKey:kHIDRemoteServiceNotification] ? [[serviceDict objectForKey:kHIDRemoteServiceNotification] unsignedIntValue] : 0);
- theService = (io_object_t) ([serviceDict objectForKey:kHIDRemoteService] ? [[serviceDict objectForKey:kHIDRemoteService] unsignedIntValue] : 0);
- queueEventSource = (CFRunLoopSourceRef) ([serviceDict objectForKey:kHIDRemoteCFRunLoopSource] ? [[serviceDict objectForKey:kHIDRemoteCFRunLoopSource] pointerValue] : NULL);
- hidQueueInterface = (IOHIDQueueInterface **) ([serviceDict objectForKey:kHIDRemoteHIDQueueInterface] ? [[serviceDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue] : NULL);
- hidDeviceInterface = (IOHIDDeviceInterface122 **) ([serviceDict objectForKey:kHIDRemoteHIDDeviceInterface] ? [[serviceDict objectForKey:kHIDRemoteHIDDeviceInterface] pointerValue] : NULL);
- cfPluginInterface = (IOCFPlugInInterface **) ([serviceDict objectForKey:kHIDRemoteCFPluginInterface] ? [[serviceDict objectForKey:kHIDRemoteCFPluginInterface] pointerValue] : NULL);
- cookieButtonMap = (NSMutableDictionary *) [serviceDict objectForKey:kHIDRemoteCookieButtonCodeLUT];
- simulateHoldTimer = (NSTimer *) [serviceDict objectForKey:kHIDRemoteSimulateHoldEventsTimer];
-
- [serviceDict retain];
- [_serviceAttribMap removeObjectForKey:serviceValue];
-
- if (([serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand]!=nil) && [[serviceDict objectForKey:kHIDRemoteAluminumRemoteSupportOnDemand] boolValue] && (theService != 0))
- {
- // We previously requested the driver to enable Aluminum Remote support for us. Tell it to turn it off again - now that we no longer need it
- IORegistryEntrySetCFProperty( (io_registry_entry_t)theService,
- CFSTR("DisableAluminumRemoteSupportForMe"),
- [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithLongLong:(long long)getpid()], @"pid",
- [NSNumber numberWithLongLong:(long long)getuid()], @"uid",
- nil]);
- }
-
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:releasedHardwareWithAttributes:)]))
- {
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self releasedHardwareWithAttributes:serviceDict];
- }
-
- if (simulateHoldTimer!=nil)
- {
- [simulateHoldTimer invalidate];
- }
-
- if (serviceNotification!=0)
- {
- IOObjectRelease(serviceNotification);
- }
-
- if (queueEventSource!=NULL)
- {
- CFRunLoopRemoveSource( CFRunLoopGetCurrent(),
- queueEventSource,
- kCFRunLoopCommonModes);
- }
-
- if ((hidQueueInterface!=NULL) && (cookieButtonMap!=nil))
- {
- NSEnumerator *cookieEnum = [cookieButtonMap keyEnumerator];
- NSNumber *cookie;
-
- while ((cookie = [cookieEnum nextObject]) != nil)
- {
- if ((*hidQueueInterface)->hasElement(hidQueueInterface, (IOHIDElementCookie) [cookie unsignedIntValue]))
- {
- (*hidQueueInterface)->removeElement(hidQueueInterface,
- (IOHIDElementCookie) [cookie unsignedIntValue]);
- }
- };
- }
-
- if (hidQueueInterface!=NULL)
- {
- (*hidQueueInterface)->stop(hidQueueInterface);
- (*hidQueueInterface)->dispose(hidQueueInterface);
- (*hidQueueInterface)->Release(hidQueueInterface);
- }
-
- if (hidDeviceInterface!=NULL)
- {
- (*hidDeviceInterface)->close(hidDeviceInterface);
- (*hidDeviceInterface)->Release(hidDeviceInterface);
- }
-
- if (cfPluginInterface!=NULL)
- {
- IODestroyPlugInInterface(cfPluginInterface);
- }
-
- if (theService!=0)
- {
- IOObjectRelease(theService);
- }
-
- [serviceDict release];
- }
-}
-
-
-#pragma mark -- PRIVATE: HID Event handling --
-- (void)_simulateHoldEvent:(NSTimer *)aTimer
-{
- NSMutableDictionary *hidAttribsDict;
- NSTimer *shTimer;
- NSNumber *shButtonCode;
-
- if ((hidAttribsDict = (NSMutableDictionary *)[aTimer userInfo]) != nil)
- {
- if (((shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer]) != nil) &&
- ((shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode]) != nil))
- {
- [shTimer invalidate];
- [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer];
-
- [self _sendButtonCode:(((HIDRemoteButtonCode)[shButtonCode unsignedIntValue])|kHIDRemoteButtonCodeHoldMask) isPressed:YES hidAttribsDict:hidAttribsDict];
- }
- }
-}
-
-- (void)_handleButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict
-{
- switch (buttonCode)
- {
- case kHIDRemoteButtonCodeIDChanged:
- // Do nothing, this is handled separately
- break;
-
- case kHIDRemoteButtonCodeUp:
- case kHIDRemoteButtonCodeDown:
- if (_simulateHoldEvents)
- {
- NSTimer *shTimer = nil;
- NSNumber *shButtonCode = nil;
-
- [[hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer] invalidate];
-
- if (isPressed)
- {
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:buttonCode] forKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
-
- if ((shTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:0.7] interval:0.1 target:self selector:@selector(_simulateHoldEvent:) userInfo:hidAttribsDict repeats:NO]) != nil)
- {
- [hidAttribsDict setObject:shTimer forKey:kHIDRemoteSimulateHoldEventsTimer];
-
- // Using CFRunLoopAddTimer instead of [[NSRunLoop currentRunLoop] addTimer:.. for consistency with run loop modes.
- // The kCFRunLoopCommonModes counterpart NSRunLoopCommonModes is only available in 10.5 and later, whereas this code
- // is designed to be also compatible with 10.4. CFRunLoopTimerRef is "toll-free-bridged" with NSTimer since 10.0.
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), (CFRunLoopTimerRef)shTimer, kCFRunLoopCommonModes);
-
- [shTimer release];
-
- break;
- }
- }
- else
- {
- shTimer = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsTimer];
- shButtonCode = [hidAttribsDict objectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
-
- if ((shTimer!=nil) && (shButtonCode!=nil))
- {
- [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:YES hidAttribsDict:hidAttribsDict];
- [self _sendButtonCode:(HIDRemoteButtonCode)[shButtonCode unsignedIntValue] isPressed:NO hidAttribsDict:hidAttribsDict];
- }
- else
- {
- if (shButtonCode!=nil)
- {
- [self _sendButtonCode:(((HIDRemoteButtonCode)[shButtonCode unsignedIntValue])|kHIDRemoteButtonCodeHoldMask) isPressed:NO hidAttribsDict:hidAttribsDict];
- }
- }
- }
-
- [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsTimer];
- [hidAttribsDict removeObjectForKey:kHIDRemoteSimulateHoldEventsOriginButtonCode];
-
- break;
- }
-
- default:
- [self _sendButtonCode:buttonCode isPressed:isPressed hidAttribsDict:hidAttribsDict];
- break;
- }
-}
-
-- (void)_sendButtonCode:(HIDRemoteButtonCode)buttonCode isPressed:(BOOL)isPressed hidAttribsDict:(NSMutableDictionary *)hidAttribsDict
-{
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:eventWithButton:isPressed:fromHardwareWithAttributes:)]))
- {
- switch (buttonCode & (~kHIDRemoteButtonCodeAluminumMask))
- {
- case kHIDRemoteButtonCodePlay:
- case kHIDRemoteButtonCodeCenter:
- if (buttonCode & kHIDRemoteButtonCodeAluminumMask)
- {
- _lastSeenModel = kHIDRemoteModelAluminum;
- _lastSeenModelRemoteID = _lastSeenRemoteID;
- }
- else
- {
- switch ((HIDRemoteAluminumRemoteSupportLevel)[[hidAttribsDict objectForKey:kHIDRemoteAluminumRemoteSupportLevel] intValue])
- {
- case kHIDRemoteAluminumRemoteSupportLevelNone:
- case kHIDRemoteAluminumRemoteSupportLevelEmulation:
- // Remote type can't be determined by just the Center button press
- break;
-
- case kHIDRemoteAluminumRemoteSupportLevelNative:
- // Remote type can be safely determined by just the Center button press
- if (((_lastSeenModel == kHIDRemoteModelAluminum) && (_lastSeenModelRemoteID != _lastSeenRemoteID)) ||
- (_lastSeenModel == kHIDRemoteModelUndetermined))
- {
- _lastSeenModel = kHIDRemoteModelWhitePlastic;
- }
- break;
- }
- }
- break;
- }
-
- // As soon as we have received a code that's unique to the Aluminum Remote, we can tell kHIDRemoteButtonCodePlayHold and kHIDRemoteButtonCodeCenterHold apart.
- // Prior to that, a long press of the new "Play" button will be submitted as a "kHIDRemoteButtonCodeCenterHold", not a "kHIDRemoteButtonCodePlayHold" code.
- if ((buttonCode == kHIDRemoteButtonCodeCenterHold) && (_lastSeenModel == kHIDRemoteModelAluminum))
- {
- buttonCode = kHIDRemoteButtonCodePlayHold;
- }
-
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self eventWithButton:(buttonCode & (~kHIDRemoteButtonCodeAluminumMask)) isPressed:isPressed fromHardwareWithAttributes:hidAttribsDict];
- }
-}
-
-- (void)_hidEventFor:(io_service_t)hidDevice from:(IOHIDQueueInterface **)interface withResult:(IOReturn)result
-{
- NSMutableDictionary *hidAttribsDict = [[[_serviceAttribMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int)hidDevice]] retain] autorelease];
-
- if (hidAttribsDict!=nil)
- {
- IOHIDQueueInterface **queueInterface = NULL;
-
- queueInterface = [[hidAttribsDict objectForKey:kHIDRemoteHIDQueueInterface] pointerValue];
-
- if (interface == queueInterface)
- {
- NSNumber *lastButtonPressedNumber = nil;
- HIDRemoteButtonCode lastButtonPressed = kHIDRemoteButtonCodeNone;
- NSMutableDictionary *cookieButtonMap = nil;
-
- cookieButtonMap = [hidAttribsDict objectForKey:kHIDRemoteCookieButtonCodeLUT];
-
- if ((lastButtonPressedNumber = [hidAttribsDict objectForKey:kHIDRemoteLastButtonPressed]) != nil)
- {
- lastButtonPressed = [lastButtonPressedNumber unsignedIntValue];
- }
-
- while (result == kIOReturnSuccess)
- {
- IOHIDEventStruct hidEvent;
- AbsoluteTime supportedTime = { 0,0 };
-
- result = (*queueInterface)->getNextEvent( queueInterface,
- &hidEvent,
- supportedTime,
- 0);
-
- if (result == kIOReturnSuccess)
- {
- NSNumber *buttonCodeNumber = [cookieButtonMap objectForKey:[NSNumber numberWithUnsignedInt:(unsigned int) hidEvent.elementCookie]];
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 5
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
-
- if (buttonCodeNumber!=nil)
- {
- HIDRemoteButtonCode buttonCode = [buttonCodeNumber unsignedIntValue];
-
- if (hidEvent.value == 0)
- {
- if (buttonCode == lastButtonPressed)
- {
- [self _handleButtonCode:lastButtonPressed isPressed:NO hidAttribsDict:hidAttribsDict];
- lastButtonPressed = kHIDRemoteButtonCodeNone;
- }
- }
-
- if (hidEvent.value != 0)
- {
- if (lastButtonPressed != kHIDRemoteButtonCodeNone)
- {
- [self _handleButtonCode:lastButtonPressed isPressed:NO hidAttribsDict:hidAttribsDict];
- // lastButtonPressed = kHIDRemoteButtonCodeNone;
- }
-
- if (buttonCode == kHIDRemoteButtonCodeIDChanged)
- {
- if (([self delegate]!=nil) &&
- ([[self delegate] respondsToSelector:@selector(hidRemote:remoteIDChangedOldID:newID:forHardwareWithAttributes:)]))
- {
- [((NSObject <HIDRemoteDelegate> *)[self delegate]) hidRemote:self remoteIDChangedOldID:_lastSeenRemoteID newID:hidEvent.value forHardwareWithAttributes:hidAttribsDict];
- }
-
- _lastSeenRemoteID = hidEvent.value;
- _lastSeenModel = kHIDRemoteModelUndetermined;
- }
-
- [self _handleButtonCode:buttonCode isPressed:YES hidAttribsDict:hidAttribsDict];
- lastButtonPressed = buttonCode;
- }
- }
- }
- };
-
- [hidAttribsDict setObject:[NSNumber numberWithUnsignedInt:lastButtonPressed] forKey:kHIDRemoteLastButtonPressed];
- }
-
- #ifdef _HIDREMOTE_EXTENSIONS
- // Debug logging code
- #define _HIDREMOTE_EXTENSIONS_SECTION 6
- #include "HIDRemoteAdditions.h"
- #undef _HIDREMOTE_EXTENSIONS_SECTION
- #endif /* _HIDREMOTE_EXTENSIONS */
- }
-}
-
-#pragma mark -- PRIVATE: Notification handling --
-- (void)_serviceMatching:(io_iterator_t)iterator
-{
- io_object_t matchingService = 0;
-
- while ((matchingService = IOIteratorNext(iterator)) != 0)
- {
- [self _setupService:matchingService];
-
- IOObjectRelease(matchingService);
- };
-}
-
-- (void)_serviceNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument
-{
- if (messageType == kIOMessageServiceIsTerminated)
- {
- [self _destructService:service];
- }
-}
-
-- (void)_updateSessionInformation
-{
- NSArray *consoleUsersArray;
- io_service_t rootService;
-
- if (_masterPort==0) { return; }
-
- if ((rootService = IORegistryGetRootEntry(_masterPort)) != 0)
- {
- if ((consoleUsersArray = (NSArray *)IORegistryEntryCreateCFProperty((io_registry_entry_t)rootService, CFSTR("IOConsoleUsers"), kCFAllocatorDefault, 0)) != nil)
- {
- if ([consoleUsersArray isKindOfClass:[NSArray class]]) // Be careful - ensure this really is an array
- {
- NSEnumerator *consoleUsersEnum; // I *love* Obj-C2's fast enumerators, but we need to stay compatible with 10.4 :-/
-
- if ((consoleUsersEnum = [consoleUsersArray objectEnumerator]) != nil)
- {
- UInt64 secureEventInputPIDSum = 0;
- uid_t frontUserSession = 0;
- NSDictionary *consoleUserDict;
-
- while ((consoleUserDict = [consoleUsersEnum nextObject]) != nil)
- {
- if ([consoleUserDict isKindOfClass:[NSDictionary class]]) // Be careful - ensure this really is a dictionary
- {
- NSNumber *secureInputPID;
- NSNumber *onConsole;
- NSNumber *userID;
-
- if ((secureInputPID = [consoleUserDict objectForKey:@"kCGSSessionSecureInputPID"]) != nil)
- {
- if ([secureInputPID isKindOfClass:[NSNumber class]])
- {
- secureEventInputPIDSum += ((UInt64) [secureInputPID intValue]);
- }
- }
-
- if (((onConsole = [consoleUserDict objectForKey:@"kCGSSessionOnConsoleKey"]) != nil) &&
- ((userID = [consoleUserDict objectForKey:@"kCGSSessionUserIDKey"]) != nil))
- {
- if ([onConsole isKindOfClass:[NSNumber class]] && [userID isKindOfClass:[NSNumber class]])
- {
- if ([onConsole boolValue])
- {
- frontUserSession = (uid_t) [userID intValue];
- }
- }
- }
- }
- }
-
- _lastSecureEventInputPIDSum = secureEventInputPIDSum;
- _lastFrontUserSession = frontUserSession;
- }
- }
-
- CFRelease((CFTypeRef)consoleUsersArray);
- }
-
- IOObjectRelease((io_object_t) rootService);
- }
-}
-
-- (void)_secureInputNotificationFor:(io_service_t)service messageType:(natural_t)messageType messageArgument:(void *)messageArgument
-{
- if (messageType == kIOMessageServiceBusyStateChange)
- {
- UInt64 old_lastSecureEventInputPIDSum = _lastSecureEventInputPIDSum;
- uid_t old_lastFrontUserSession = _lastFrontUserSession;
-
- [self _updateSessionInformation];
-
- if (((old_lastSecureEventInputPIDSum != _lastSecureEventInputPIDSum) || (old_lastFrontUserSession != _lastFrontUserSession)) && _secureEventInputWorkAround)
- {
- if ((_mode == kHIDRemoteModeExclusive) || (_mode == kHIDRemoteModeExclusiveAuto))
- {
- HIDRemoteMode restartInMode = _mode;
-
- _isRestarting = YES;
- [self stopRemoteControl];
- [self startRemoteControl:restartInMode];
- _isRestarting = NO;
- }
- }
- }
-}
-
-@end
-
-#pragma mark -- PRIVATE: IOKitLib Callbacks --
-
-static void HIDEventCallback( void * target,
- IOReturn result,
- void * refCon,
- void * sender)
-{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [hidRemote _hidEventFor:(io_service_t)((intptr_t)target) from:(IOHIDQueueInterface**)sender withResult:(IOReturn)result];
-
- [pool release];
-}
-
-
-static void ServiceMatchingCallback( void *refCon,
- io_iterator_t iterator)
-{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [hidRemote _serviceMatching:iterator];
-
- [pool release];
-}
-
-static void ServiceNotificationCallback(void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument)
-{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [hidRemote _serviceNotificationFor:service
- messageType:messageType
- messageArgument:messageArgument];
-
- [pool release];
-}
-
-static void SecureInputNotificationCallback( void * refCon,
- io_service_t service,
- natural_t messageType,
- void * messageArgument)
-{
- HIDRemote *hidRemote = (HIDRemote *)refCon;
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-
- [hidRemote _secureInputNotificationFor:service
- messageType:messageType
- messageArgument:messageArgument];
-
- [pool release];
-}
-
-// Attribute dictionary keys
-NSString *kHIDRemoteCFPluginInterface = @"CFPluginInterface";
-NSString *kHIDRemoteHIDDeviceInterface = @"HIDDeviceInterface";
-NSString *kHIDRemoteCookieButtonCodeLUT = @"CookieButtonCodeLUT";
-NSString *kHIDRemoteHIDQueueInterface = @"HIDQueueInterface";
-NSString *kHIDRemoteServiceNotification = @"ServiceNotification";
-NSString *kHIDRemoteCFRunLoopSource = @"CFRunLoopSource";
-NSString *kHIDRemoteLastButtonPressed = @"LastButtonPressed";
-NSString *kHIDRemoteService = @"Service";
-NSString *kHIDRemoteSimulateHoldEventsTimer = @"SimulateHoldEventsTimer";
-NSString *kHIDRemoteSimulateHoldEventsOriginButtonCode = @"SimulateHoldEventsOriginButtonCode";
-NSString *kHIDRemoteAluminumRemoteSupportLevel = @"AluminumRemoteSupportLevel";
-NSString *kHIDRemoteAluminumRemoteSupportOnDemand = @"AluminumRemoteSupportLevelOnDemand";
-
-NSString *kHIDRemoteManufacturer = @"Manufacturer";
-NSString *kHIDRemoteProduct = @"Product";
-NSString *kHIDRemoteTransport = @"Transport";
-
-// Distributed notifications
-NSString *kHIDRemoteDNHIDRemotePing = @"com.candelair.ping";
-NSString *kHIDRemoteDNHIDRemoteRetry = @"com.candelair.retry";
-NSString *kHIDRemoteDNHIDRemoteStatus = @"com.candelair.status";
-
-NSString *kHIDRemoteDNHIDRemoteRetryGlobalObject = @"global";
-
-// Distributed notifications userInfo keys and values
-NSString *kHIDRemoteDNStatusHIDRemoteVersionKey = @"HIDRemoteVersion";
-NSString *kHIDRemoteDNStatusPIDKey = @"PID";
-NSString *kHIDRemoteDNStatusModeKey = @"Mode";
-NSString *kHIDRemoteDNStatusUnusedButtonCodesKey = @"UnusedButtonCodes";
-NSString *kHIDRemoteDNStatusActionKey = @"Action";
-NSString *kHIDRemoteDNStatusRemoteControlCountKey = @"RemoteControlCount";
-NSString *kHIDRemoteDNStatusReturnToPIDKey = @"ReturnToPID";
-NSString *kHIDRemoteDNStatusActionStart = @"start";
-NSString *kHIDRemoteDNStatusActionStop = @"stop";
-NSString *kHIDRemoteDNStatusActionUpdate = @"update";
-NSString *kHIDRemoteDNStatusActionNoNeed = @"noneed";
diff --git a/osdep/macosx_events.h b/osdep/macosx_events.h
index 17adaf9ae5..9188c8bee2 100644
--- a/osdep/macosx_events.h
+++ b/osdep/macosx_events.h
@@ -27,9 +27,6 @@ struct mpv_handle;
void cocoa_put_key(int keycode);
void cocoa_put_key_with_modifiers(int keycode, int modifiers);
-void cocoa_init_apple_remote(void);
-void cocoa_uninit_apple_remote(void);
-
void cocoa_init_media_keys(void);
void cocoa_uninit_media_keys(void);
diff --git a/osdep/macosx_events.m b/osdep/macosx_events.m
index 68956de43e..14aa7063fb 100644
--- a/osdep/macosx_events.m
+++ b/osdep/macosx_events.m
@@ -50,17 +50,12 @@
BOOL _is_application;
NSCondition *_input_lock;
CFMachPortRef _mk_tap_port;
-#if HAVE_APPLE_REMOTE
- HIDRemote *_remote;
-#endif
}
- (BOOL)handleMediaKey:(NSEvent *)event;
- (NSEvent *)handleKey:(NSEvent *)event;
- (BOOL)setMpvHandle:(struct mpv_handle *)ctx;
- (void)readEvents;
-- (void)startAppleRemote;
-- (void)stopAppleRemote;
- (void)startMediaKeys;
- (void)restartMediaKeys;
- (void)stopMediaKeys;
@@ -126,16 +121,6 @@ static int convert_key(unsigned key, unsigned charcode)
return charcode;
}
-void cocoa_init_apple_remote(void)
-{
- [[EventsResponder sharedInstance] startAppleRemote];
-}
-
-void cocoa_uninit_apple_remote(void)
-{
- [[EventsResponder sharedInstance] stopAppleRemote];
-}
-
static int mk_code(NSEvent *event)
{
return (([event data1] & 0xFFFF0000) >> 16);
@@ -352,29 +337,6 @@ void cocoa_set_mpv_handle(struct mpv_handle *ctx)
}
}
-- (void)startAppleRemote
-{
-#if HAVE_APPLE_REMOTE
- dispatch_async(dispatch_get_main_queue(), ^{
- self->_remote = [[HIDRemote alloc] init];
- if (self->_remote) {
- [self->_remote setDelegate:self];
- [self->_remote startRemoteControl:kHIDRemoteModeExclusiveAuto];
- }
- });
-#endif
-}
-
-- (void)stopAppleRemote
-{
-#if HAVE_APPLE_REMOTE
- dispatch_async(dispatch_get_main_queue(), ^{
- [self->_remote stopRemoteControl];
- [self->_remote release];
- });
-#endif
-}
-
- (void)restartMediaKeys
{
if (self->_mk_tap_port)
@@ -448,33 +410,6 @@ void cocoa_set_mpv_handle(struct mpv_handle *ctx)
andMapping:keymapd];
}
-- (void)hidRemote:(HIDRemote *)remote
- eventWithButton:(HIDRemoteButtonCode)buttonCode
- isPressed:(BOOL)isPressed
- fromHardwareWithAttributes:(NSMutableDictionary *)attributes
-{
- if (!isPressed) return;
-
- NSDictionary *keymapd = @{
- @(kHIDRemoteButtonCodePlay): @(MP_AR_PLAY),
- @(kHIDRemoteButtonCodePlayHold): @(MP_AR_PLAY_HOLD),
- @(kHIDRemoteButtonCodeCenter): @(MP_AR_CENTER),
- @(kHIDRemoteButtonCodeCenterHold): @(MP_AR_CENTER_HOLD),
- @(kHIDRemoteButtonCodeLeft): @(MP_AR_PREV),
- @(kHIDRemoteButtonCodeLeftHold): @(MP_AR_PREV_HOLD),
- @(kHIDRemoteButtonCodeRight): @(MP_AR_NEXT),
- @(kHIDRemoteButtonCodeRightHold): @(MP_AR_NEXT_HOLD),
- @(kHIDRemoteButtonCodeMenu): @(MP_AR_MENU),
- @(kHIDRemoteButtonCodeMenuHold): @(MP_AR_MENU_HOLD),
- @(kHIDRemoteButtonCodeUp): @(MP_AR_VUP),
- @(kHIDRemoteButtonCodeUpHold): @(MP_AR_VUP_HOLD),
- @(kHIDRemoteButtonCodeDown): @(MP_AR_VDOWN),
- @(kHIDRemoteButtonCodeDownHold): @(MP_AR_VDOWN_HOLD),
- };
-
- [self handleKey:buttonCode withMask:0 andMapping:keymapd];
-}
-
- (int)mapKeyModifiers:(int)cocoaModifiers
{
int mask = 0;
diff --git a/osdep/macosx_events_objc.h b/osdep/macosx_events_objc.h
index 79ace0a909..42f6ee234a 100644
--- a/osdep/macosx_events_objc.h
+++ b/osdep/macosx_events_objc.h
@@ -18,12 +18,11 @@
*/
#import <Cocoa/Cocoa.h>
-#import "ar/HIDRemote.h"
#include "osdep/macosx_events.h"
struct input_ctx;
-@interface EventsResponder : NSObject <HIDRemoteDelegate>
+@interface EventsResponder : NSObject
+ (EventsResponder *)sharedInstance;
- (void)setInputContext:(struct input_ctx *)ctx;
diff --git a/wscript b/wscript
index 7af97dd894..3aa1376995 100644
--- a/wscript
+++ b/wscript
@@ -905,11 +905,6 @@ standalone_features = [
'deps': 'os-win32 || !(!(os-cygwin))',
'func': check_ctx_vars('WINDRES')
}, {
- 'name': '--apple-remote',
- 'desc': 'Apple Remote support',
- 'deps': 'cocoa',
- 'func': check_true
- }, {
'name': '--macos-touchbar',
'desc': 'macOS Touch Bar support',
'deps': 'cocoa',
diff --git a/wscript_build.py b/wscript_build.py
index 383e1df6f6..3ad85fd3b5 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -544,7 +544,6 @@ def build(ctx):
( "osdep/android/posix-spawn.c", "android"),
( "osdep/android/strnlen.c", "android"),
- ( "osdep/ar/HIDRemote.m", "apple-remote" ),
( "osdep/glob-win.c", "glob-win32" ),
( "osdep/macosx_application.m", "cocoa" ),
( "osdep/macosx_events.m", "cocoa" ),