mirror of
https://github.com/mpv-player/mpv
synced 2025-04-07 10:02:50 +00:00
osx: add Apple Remote support
After killing the non functional AR support in c8fd9e5
I got much complaints so
this adds AR support back in (and it works). I am using the HIDRemote class by
Felix Schwarz and that part of the code is under the BSD license. I slightly
modified it replacing [NSApplication sharedApplication] with NSApp. The code
of the class is quite complex (probably because it had to deal with all the
edge cases with IOKit) but it works nicely as a black box.
In a later commit I'll remove the deprecation warnings caused by HIDRemote's
usage of Gestalt.
Check out `etc/input.conf` for the default bindings.
Apple Remote functionality is automatically compiled in when cocoa is enabled.
It can be disabled at runtime with the `--no-ar` option.
This commit is contained in:
parent
c39efb96d1
commit
72f2942dfa
@ -80,6 +80,9 @@
|
|||||||
configuration files specifying a list of fallbacks may make sense. See
|
configuration files specifying a list of fallbacks may make sense. See
|
||||||
`audio_outputs` for details and descriptions of available drivers.
|
`audio_outputs` for details and descriptions of available drivers.
|
||||||
|
|
||||||
|
--ar, --no-ar
|
||||||
|
Enable/disable AppleIR remote support. Enabled by default.
|
||||||
|
|
||||||
--aspect=<ratio>
|
--aspect=<ratio>
|
||||||
Override movie aspect ratio, in case aspect information is incorrect or
|
Override movie aspect ratio, in case aspect information is incorrect or
|
||||||
missing in the file being played. See also ``--no-aspect``.
|
missing in the file being played. See also ``--no-aspect``.
|
||||||
|
3
Makefile
3
Makefile
@ -48,7 +48,8 @@ SOURCES-$(LIBSMBCLIENT) += stream/stream_smb.c
|
|||||||
SOURCES-$(MACOSX_BUNDLE) += osdep/macosx_bundle.m
|
SOURCES-$(MACOSX_BUNDLE) += osdep/macosx_bundle.m
|
||||||
SOURCES-$(COCOA) += video/out/cocoa_common.m \
|
SOURCES-$(COCOA) += video/out/cocoa_common.m \
|
||||||
osdep/macosx_application.m \
|
osdep/macosx_application.m \
|
||||||
osdep/macosx_events.m
|
osdep/macosx_events.m \
|
||||||
|
osdep/ar/HIDRemote.m
|
||||||
SOURCES-$(MNG) += demux/demux_mng.c
|
SOURCES-$(MNG) += demux/demux_mng.c
|
||||||
SOURCES-$(MPG123) += audio/decode/ad_mpg123.c
|
SOURCES-$(MPG123) += audio/decode/ad_mpg123.c
|
||||||
|
|
||||||
|
@ -106,6 +106,9 @@ void set_default_mplayer_options(struct MPOpts *opts)
|
|||||||
.use_joystick = 1,
|
.use_joystick = 1,
|
||||||
.use_lirc = 1,
|
.use_lirc = 1,
|
||||||
.use_lircc = 1,
|
.use_lircc = 1,
|
||||||
|
#ifdef CONFIG_COCOA
|
||||||
|
.use_ar = 1,
|
||||||
|
#endif
|
||||||
.default_bindings = 1,
|
.default_bindings = 1,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -394,6 +394,21 @@ static const struct key_name key_names[] = {
|
|||||||
{ MP_JOY_BTN8, "JOY_BTN8" },
|
{ MP_JOY_BTN8, "JOY_BTN8" },
|
||||||
{ MP_JOY_BTN9, "JOY_BTN9" },
|
{ 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_POWER, "POWER" },
|
||||||
{ MP_KEY_MENU, "MENU" },
|
{ MP_KEY_MENU, "MENU" },
|
||||||
{ MP_KEY_PLAY, "PLAY" },
|
{ MP_KEY_PLAY, "PLAY" },
|
||||||
@ -536,6 +551,7 @@ static const m_option_t mp_input_opts[] = {
|
|||||||
OPT_FLAG("joystick", input.use_joystick, CONF_GLOBAL),
|
OPT_FLAG("joystick", input.use_joystick, CONF_GLOBAL),
|
||||||
OPT_FLAG("lirc", input.use_lirc, CONF_GLOBAL),
|
OPT_FLAG("lirc", input.use_lirc, CONF_GLOBAL),
|
||||||
OPT_FLAG("lircc", input.use_lircc, CONF_GLOBAL),
|
OPT_FLAG("lircc", input.use_lircc, CONF_GLOBAL),
|
||||||
|
OPT_FLAG("ar", input.use_ar, CONF_GLOBAL),
|
||||||
{ NULL, NULL, 0, 0, 0, 0, NULL}
|
{ NULL, NULL, 0, 0, 0, 0, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1810,6 +1826,12 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_COCOA
|
||||||
|
if (input_conf->use_ar) {
|
||||||
|
cocoa_start_apple_remote();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (input_conf->in_file) {
|
if (input_conf->in_file) {
|
||||||
int mode = O_RDONLY;
|
int mode = O_RDONLY;
|
||||||
#ifndef __MINGW32__
|
#ifndef __MINGW32__
|
||||||
@ -1841,11 +1863,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)
|
if (!ictx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef CONFIG_COCOA
|
||||||
|
if (input_conf->use_ar) {
|
||||||
|
cocoa_stop_apple_remote();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int i = 0; i < ictx->num_key_fd; i++) {
|
for (int i = 0; i < ictx->num_key_fd; i++) {
|
||||||
if (ictx->key_fds[i].close_func)
|
if (ictx->key_fds[i].close_func)
|
||||||
ictx->key_fds[i].close_func(ictx->key_fds[i].fd);
|
ictx->key_fds[i].close_func(ictx->key_fds[i].fd);
|
||||||
|
@ -216,7 +216,7 @@ struct input_conf;
|
|||||||
struct input_ctx *mp_input_init(struct input_conf *input_conf,
|
struct input_ctx *mp_input_init(struct input_conf *input_conf,
|
||||||
bool load_default_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;
|
struct m_config;
|
||||||
void mp_input_register_options(struct m_config *cfg);
|
void mp_input_register_options(struct m_config *cfg);
|
||||||
|
@ -172,6 +172,23 @@
|
|||||||
#define MP_MOUSE_BTN19_DBL (MP_MOUSE_BASE_DBL+19)
|
#define MP_MOUSE_BTN19_DBL (MP_MOUSE_BASE_DBL+19)
|
||||||
#define MP_MOUSE_BTN_DBL_END (MP_MOUSE_BASE_DBL+20)
|
#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 */
|
/* Special keys */
|
||||||
#define MP_KEY_INTERN (MP_KEY_BASE+0x1000)
|
#define MP_KEY_INTERN (MP_KEY_BASE+0x1000)
|
||||||
#define MP_KEY_CLOSE_WIN (MP_KEY_INTERN+0)
|
#define MP_KEY_CLOSE_WIN (MP_KEY_INTERN+0)
|
||||||
|
@ -601,7 +601,7 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx,
|
|||||||
timeEndPeriod(1);
|
timeEndPeriod(1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mp_input_uninit(mpctx->input);
|
mp_input_uninit(mpctx->input, &mpctx->opts.input);
|
||||||
|
|
||||||
osd_free(mpctx->osd);
|
osd_free(mpctx->osd);
|
||||||
|
|
||||||
|
@ -231,6 +231,9 @@ typedef struct MPOpts {
|
|||||||
int use_joystick;
|
int use_joystick;
|
||||||
int use_lirc;
|
int use_lirc;
|
||||||
int use_lircc;
|
int use_lircc;
|
||||||
|
#ifdef CONFIG_COCOA
|
||||||
|
int use_ar;
|
||||||
|
#endif
|
||||||
int default_bindings;
|
int default_bindings;
|
||||||
int test;
|
int test;
|
||||||
} input;
|
} input;
|
||||||
|
@ -136,7 +136,22 @@ k tv_step_channel -1
|
|||||||
n tv_step_norm
|
n tv_step_norm
|
||||||
u tv_step_chanlist
|
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
|
# Joystick section
|
||||||
# WARNING: joystick support has to be explicitly enabled at
|
# WARNING: joystick support has to be explicitly enabled at
|
||||||
# compiletime with --enable-joystick
|
# compiletime with --enable-joystick
|
||||||
|
378
osdep/ar/HIDRemote.h
Normal file
378
osdep/ar/HIDRemote.h
Normal file
@ -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;
|
2068
osdep/ar/HIDRemote.m
Normal file
2068
osdep/ar/HIDRemote.m
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import "ar/HIDRemote.h"
|
||||||
#include "osdep/macosx_application.h"
|
#include "osdep/macosx_application.h"
|
||||||
|
|
||||||
struct cocoa_input_queue;
|
struct cocoa_input_queue;
|
||||||
@ -26,9 +27,12 @@ struct cocoa_input_queue;
|
|||||||
- (int) pop;
|
- (int) pop;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface EventsResponder : NSResponder
|
@interface EventsResponder : NSObject <HIDRemoteDelegate>
|
||||||
- (void)handleMediaKey:(int)key;
|
- (void)handleMediaKey:(int)key;
|
||||||
- (NSEvent *)handleKeyDown:(NSEvent *)event;
|
- (NSEvent *)handleKeyDown:(NSEvent *)event;
|
||||||
|
- (void)startAppleRemote;
|
||||||
|
- (void)stopAppleRemote;
|
||||||
|
@property(nonatomic, retain) HIDRemote *remote;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface Application : NSApplication
|
@interface Application : NSApplication
|
||||||
|
@ -23,5 +23,7 @@
|
|||||||
|
|
||||||
void cocoa_put_key(int keycode);
|
void cocoa_put_key(int keycode);
|
||||||
void cocoa_check_events(void);
|
void cocoa_check_events(void);
|
||||||
|
void cocoa_start_apple_remote(void);
|
||||||
|
void cocoa_stop_apple_remote(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
*
|
*
|
||||||
* This file is part of mpv.
|
* This file is part of mpv.
|
||||||
*
|
*
|
||||||
* mplayer2 is free software; you can redistribute it and/or modify
|
* mpv is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* mplayer2 is distributed in the hope that it will be useful,
|
* mpv is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
@ -92,6 +92,18 @@ static int convert_key(unsigned key, unsigned charcode)
|
|||||||
return charcode;
|
return charcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cocoa_start_apple_remote(void)
|
||||||
|
{
|
||||||
|
Application *app = mpv_shared_app();
|
||||||
|
[app.eventsResponder startAppleRemote];
|
||||||
|
}
|
||||||
|
|
||||||
|
void cocoa_stop_apple_remote(void)
|
||||||
|
{
|
||||||
|
Application *app = mpv_shared_app();
|
||||||
|
[app.eventsResponder stopAppleRemote];
|
||||||
|
}
|
||||||
|
|
||||||
void cocoa_check_events(void)
|
void cocoa_check_events(void)
|
||||||
{
|
{
|
||||||
Application *app = mpv_shared_app();
|
Application *app = mpv_shared_app();
|
||||||
@ -106,6 +118,23 @@ void cocoa_put_key(int keycode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
@implementation EventsResponder
|
@implementation EventsResponder
|
||||||
|
- (void)startAppleRemote
|
||||||
|
{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
self.remote = [[[HIDRemote alloc] init] autorelease];
|
||||||
|
if (self.remote) {
|
||||||
|
[self.remote setDelegate:self];
|
||||||
|
[self.remote startRemoteControl:kHIDRemoteModeExclusiveAuto];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
- (void)stopAppleRemote
|
||||||
|
{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[self.remote stopRemoteControl];
|
||||||
|
});
|
||||||
|
}
|
||||||
- (NSArray *) keyEquivalents
|
- (NSArray *) keyEquivalents
|
||||||
{
|
{
|
||||||
return @[@"h", @"q", @"Q", @"0", @"1", @"2"];
|
return @[@"h", @"q", @"Q", @"0", @"1", @"2"];
|
||||||
@ -158,4 +187,32 @@ void cocoa_put_key(int keycode)
|
|||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
- (void)hidRemote:(HIDRemote *)remote
|
||||||
|
eventWithButton:(HIDRemoteButtonCode)buttonCode
|
||||||
|
isPressed:(BOOL)isPressed
|
||||||
|
fromHardwareWithAttributes:(NSMutableDictionary *)attributes
|
||||||
|
{
|
||||||
|
if (!isPressed) return;
|
||||||
|
|
||||||
|
NSDictionary *keymap = @{
|
||||||
|
@(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),
|
||||||
|
};
|
||||||
|
|
||||||
|
int key = [keymap[@(buttonCode)] intValue];
|
||||||
|
if (key > 0)
|
||||||
|
cocoa_put_key(key);
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
Loading…
Reference in New Issue
Block a user