diff options
-rw-r--r-- | .travis.yml | 1 | ||||
-rw-r--r-- | DOCS/man/en/options.rst | 3 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | core/defaultopts.c | 3 | ||||
-rw-r--r-- | core/input/input.c | 39 | ||||
-rw-r--r-- | core/input/input.h | 2 | ||||
-rw-r--r-- | core/input/keycodes.h | 17 | ||||
-rw-r--r-- | core/m_option.c | 7 | ||||
-rw-r--r-- | core/mplayer.c | 3 | ||||
-rw-r--r-- | core/options.h | 3 | ||||
-rw-r--r-- | demux/demux.c | 2 | ||||
-rw-r--r-- | demux/demux_mkv.c | 2 | ||||
-rw-r--r-- | etc/input.conf | 23 | ||||
-rw-r--r-- | osdep/ar/HIDRemote.h | 378 | ||||
-rw-r--r-- | osdep/ar/HIDRemote.m | 2068 | ||||
-rw-r--r-- | osdep/macosx_application.h | 3 | ||||
-rw-r--r-- | osdep/macosx_application.m | 200 | ||||
-rw-r--r-- | osdep/macosx_application_objc.h | 21 | ||||
-rw-r--r-- | osdep/macosx_events.h | 29 | ||||
-rw-r--r-- | osdep/macosx_events.m | 218 | ||||
-rw-r--r-- | stream/stream_dvd.c | 1 | ||||
-rw-r--r-- | video/out/cocoa_common.h | 2 | ||||
-rw-r--r-- | video/out/cocoa_common.m | 788 | ||||
-rw-r--r-- | video/out/gl_video.c | 13 | ||||
-rw-r--r-- | video/out/gl_video_shaders.glsl | 1 | ||||
-rw-r--r-- | video/out/osx_common.h | 28 | ||||
-rw-r--r-- | video/out/osx_common.m | 181 |
27 files changed, 3315 insertions, 728 deletions
diff --git a/.travis.yml b/.travis.yml index b932ae8463..33e495f86a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ compiler: branches: only: - master + - ci before_install: ./travis-deps libass-stable $LIBAV script: ./configure && make diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index f626f861f6..8239375079 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -80,6 +80,9 @@ configuration files specifying a list of fallbacks may make sense. See `audio_outputs` for details and descriptions of available drivers. +--ar, --no-ar + Enable/disable AppleIR remote support. Enabled by default. + --aspect=<ratio> Override movie aspect ratio, in case aspect information is incorrect or missing in the file being played. See also ``--no-aspect``. @@ -46,9 +46,10 @@ SOURCES-$(LIBPOSTPROC) += video/filter/vf_pp.c SOURCES-$(LIBSMBCLIENT) += stream/stream_smb.c SOURCES-$(MACOSX_BUNDLE) += osdep/macosx_bundle.m -SOURCES-$(COCOA) += video/out/osx_common.m \ - video/out/cocoa_common.m \ - osdep/macosx_application.m +SOURCES-$(COCOA) += video/out/cocoa_common.m \ + osdep/macosx_application.m \ + osdep/macosx_events.m \ + osdep/ar/HIDRemote.m SOURCES-$(MNG) += demux/demux_mng.c SOURCES-$(MPG123) += audio/decode/ad_mpg123.c diff --git a/core/defaultopts.c b/core/defaultopts.c index 93dad1e624..a8a6b26930 100644 --- a/core/defaultopts.c +++ b/core/defaultopts.c @@ -108,6 +108,9 @@ void set_default_mplayer_options(struct MPOpts *opts) .use_joystick = 1, .use_lirc = 1, .use_lircc = 1, +#ifdef CONFIG_COCOA + .use_ar = 1, +#endif .default_bindings = 1, } }; diff --git a/core/input/input.c b/core/input/input.c index c9958753cd..4bfc22a08c 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -61,6 +61,10 @@ #include <lirc/lircc.h> #endif +#ifdef CONFIG_COCOA +#include "osdep/macosx_events.h" +#endif + #define MP_MAX_KEY_DOWN 4 struct cmd_bind { @@ -390,6 +394,21 @@ static const struct key_name key_names[] = { { MP_JOY_BTN8, "JOY_BTN8" }, { MP_JOY_BTN9, "JOY_BTN9" }, + { 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_POWER, "POWER" }, { MP_KEY_MENU, "MENU" }, { MP_KEY_PLAY, "PLAY" }, @@ -532,6 +551,9 @@ static const m_option_t mp_input_opts[] = { OPT_FLAG("joystick", input.use_joystick, CONF_GLOBAL), OPT_FLAG("lirc", input.use_lirc, CONF_GLOBAL), OPT_FLAG("lircc", input.use_lircc, CONF_GLOBAL), +#ifdef CONFIG_COCOA + OPT_FLAG("ar", input.use_ar, CONF_GLOBAL), +#endif { NULL, NULL, 0, 0, 0, 0, NULL} }; @@ -1474,6 +1496,9 @@ static void read_all_fd_events(struct input_ctx *ictx, int time) static void read_all_events(struct input_ctx *ictx, int time) { getch2_poll(); +#ifdef CONFIG_COCOA + cocoa_check_events(); +#endif read_all_fd_events(ictx, time); } @@ -1803,6 +1828,12 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf, } #endif +#ifdef CONFIG_COCOA + if (input_conf->use_ar) { + cocoa_start_apple_remote(); + } +#endif + if (input_conf->in_file) { int mode = O_RDONLY; #ifndef __MINGW32__ @@ -1834,11 +1865,17 @@ static void clear_queue(struct cmd_queue *queue) } } -void mp_input_uninit(struct input_ctx *ictx) +void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf) { if (!ictx) return; +#ifdef CONFIG_COCOA + if (input_conf->use_ar) { + cocoa_stop_apple_remote(); + } +#endif + for (int i = 0; i < ictx->num_key_fd; i++) { if (ictx->key_fds[i].close_func) ictx->key_fds[i].close_func(ictx->key_fds[i].fd); diff --git a/core/input/input.h b/core/input/input.h index 6c33e47fdc..944debd847 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -216,7 +216,7 @@ struct input_conf; struct input_ctx *mp_input_init(struct input_conf *input_conf, bool load_default_conf); -void mp_input_uninit(struct input_ctx *ictx); +void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf); struct m_config; void mp_input_register_options(struct m_config *cfg); diff --git a/core/input/keycodes.h b/core/input/keycodes.h index 2e0e5fd33f..b9d2da23b7 100644 --- a/core/input/keycodes.h +++ b/core/input/keycodes.h @@ -172,6 +172,23 @@ #define MP_MOUSE_BTN19_DBL (MP_MOUSE_BASE_DBL+19) #define MP_MOUSE_BTN_DBL_END (MP_MOUSE_BASE_DBL+20) +// 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) + /* Special keys */ #define MP_KEY_INTERN (MP_KEY_BASE+0x1000) #define MP_KEY_CLOSE_WIN (MP_KEY_INTERN+0) diff --git a/core/m_option.c b/core/m_option.c index 931b498213..406e4ede0b 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -762,6 +762,13 @@ static int parse_str(const m_option_t *opt, struct bstr name, goto exit; } + m_opt_string_validate_fn validate = opt->priv; + if (validate) { + r = validate(opt, name, param); + if (r < 0) + goto exit; + } + if (opt->flags & M_OPT_PARSE_ESCAPES) { char *res = unescape_string(tmp, param); if (!res) { diff --git a/core/mplayer.c b/core/mplayer.c index 4d71b5f55f..baae55b581 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -588,7 +588,7 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx, timeEndPeriod(1); #endif - mp_input_uninit(mpctx->input); + mp_input_uninit(mpctx->input, &mpctx->opts.input); osd_free(mpctx->osd); @@ -3885,6 +3885,7 @@ static void init_input(struct MPContext *mpctx) #ifdef CONFIG_COCOA cocoa_set_input_context(mpctx->input); + cocoa_set_key_fifo(mpctx->key_fifo); #endif } diff --git a/core/options.h b/core/options.h index 31b4bc9136..0504ea0591 100644 --- a/core/options.h +++ b/core/options.h @@ -239,6 +239,9 @@ typedef struct MPOpts { int use_joystick; int use_lirc; int use_lircc; +#ifdef CONFIG_COCOA + int use_ar; +#endif int default_bindings; int test; } input; diff --git a/demux/demux.c b/demux/demux.c index 25f31a3f60..5de6b84745 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -1002,7 +1002,7 @@ struct demuxer *demux_open_withparams(struct MPOpts *opts, // format, instead of reyling on libav to auto-detect the stream's format // correctly. switch (file_format) { - case DEMUXER_TYPE_MPEG_PS: + //case DEMUXER_TYPE_MPEG_PS: //case DEMUXER_TYPE_MPEG_TS: case DEMUXER_TYPE_Y4M: case DEMUXER_TYPE_NSV: diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 828479e50f..914ace3a41 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -2075,6 +2075,7 @@ static void handle_realaudio(demuxer_t *demuxer, mkv_track_t *track, } } +#if NEED_WAVPACK_PARSE // Copied from libavformat/matroskadec.c (FFmpeg 310f9dd / 2013-05-30) // Originally added with Libav commit 9b6f47c // License: LGPL v2.1 or later @@ -2153,6 +2154,7 @@ fail: talloc_free(dst); return -1; } +#endif static void mkv_parse_packet(mkv_track_t *track, bstr *buffer) { diff --git a/etc/input.conf b/etc/input.conf index 5dbb7c8a06..1cbd2446ba 100644 --- a/etc/input.conf +++ b/etc/input.conf @@ -9,8 +9,8 @@ # mpv --input-test --pause dummy.mkv can be used to test which commands keys are # bound to. # -# If you wish to unbind a key, use key ignore. -# e.g. ENTER ignore +# If you wish to unbind a key, bind it to the 'ignore' command: +# KEY ignore # # Note that merely removing default key bindings from this file won't remove # the default bindings mpv was compiled with, unless @@ -20,7 +20,7 @@ # Lines starting with # are comments. Use SHARP to assign the # key. # # Strings need to be quoted and escaped: -# KEY show_text "This is a single backslash: \\ and a quote: \" !" +# KEY show_text "This is a single backslash: \\ and a quote: \" !" # # You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with # modifiers Shift, Ctrl, Alt and Meta, but note that currently reading @@ -136,7 +136,22 @@ k tv_step_channel -1 n tv_step_norm u tv_step_chanlist -# +# 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 1 +AR_VUP_HOLD add chapter 1 +AR_VDOWN add volume -1 +AR_VDOWN_HOLD add chapter -1 + # Joystick section # WARNING: joystick support has to be explicitly enabled at # compiletime with --enable-joystick diff --git a/osdep/ar/HIDRemote.h b/osdep/ar/HIDRemote.h new file mode 100644 index 0000000000..9dd16faa5a --- /dev/null +++ b/osdep/ar/HIDRemote.h @@ -0,0 +1,378 @@ +// +// 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 noone 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 persued 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 new file mode 100644 index 0000000000..f05628c040 --- /dev/null +++ b/osdep/ar/HIDRemote.m @@ -0,0 +1,2068 @@ +// +// 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/gui |