summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/options.rst3
-rw-r--r--core/defaultopts.c1
-rw-r--r--core/input/input.c17
-rw-r--r--core/input/keycodes.h6
-rw-r--r--core/options.h1
-rw-r--r--etc/input.conf5
-rw-r--r--osdep/macosx_application.m14
-rw-r--r--osdep/macosx_application_objc.h5
-rw-r--r--osdep/macosx_events.h8
-rw-r--r--osdep/macosx_events.m113
10 files changed, 140 insertions, 33 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index 8239375079..e0d0dc9f1f 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -1125,6 +1125,9 @@
--mc=<seconds/frame>
Maximum A-V sync correction per frame (in seconds)
+--media-keys, --no-media-keys
+ OSX only: Enabled by default. Enables/disable media keys support.
+
--mf=<option1:option2:...>
Used when decoding from multiple PNG or JPEG files with ``mf://``.
diff --git a/core/defaultopts.c b/core/defaultopts.c
index a8a6b26930..a03370bed6 100644
--- a/core/defaultopts.c
+++ b/core/defaultopts.c
@@ -110,6 +110,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
.use_lircc = 1,
#ifdef CONFIG_COCOA
.use_ar = 1,
+ .use_media_keys = 1,
#endif
.default_bindings = 1,
}
diff --git a/core/input/input.c b/core/input/input.c
index 4bfc22a08c..8bc877ce79 100644
--- a/core/input/input.c
+++ b/core/input/input.c
@@ -409,6 +409,10 @@ static const struct key_name key_names[] = {
{ MP_AR_VDOWN, "AR_VDOWN" },
{ MP_AR_VDOWN_HOLD, "AR_VDOWN_HOLD" },
+ { MP_MK_PLAY, "MK_PLAY" },
+ { MP_MK_PREV, "MK_PREV" },
+ { MP_MK_NEXT, "MK_NEXT" },
+
{ MP_KEY_POWER, "POWER" },
{ MP_KEY_MENU, "MENU" },
{ MP_KEY_PLAY, "PLAY" },
@@ -553,6 +557,7 @@ static const m_option_t mp_input_opts[] = {
OPT_FLAG("lircc", input.use_lircc, CONF_GLOBAL),
#ifdef CONFIG_COCOA
OPT_FLAG("ar", input.use_ar, CONF_GLOBAL),
+ OPT_FLAG("media-keys", input.use_media_keys, CONF_GLOBAL),
#endif
{ NULL, NULL, 0, 0, 0, 0, NULL}
};
@@ -1830,7 +1835,11 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf,
#ifdef CONFIG_COCOA
if (input_conf->use_ar) {
- cocoa_start_apple_remote();
+ cocoa_init_apple_remote();
+ }
+
+ if (input_conf->use_media_keys) {
+ cocoa_init_media_keys();
}
#endif
@@ -1872,7 +1881,11 @@ void mp_input_uninit(struct input_ctx *ictx, struct input_conf *input_conf)
#ifdef CONFIG_COCOA
if (input_conf->use_ar) {
- cocoa_stop_apple_remote();
+ cocoa_uninit_apple_remote();
+ }
+
+ if (input_conf->use_media_keys) {
+ cocoa_uninit_media_keys();
}
#endif
diff --git a/core/input/keycodes.h b/core/input/keycodes.h
index b9d2da23b7..8770f8abfa 100644
--- a/core/input/keycodes.h
+++ b/core/input/keycodes.h
@@ -189,6 +189,12 @@
#define MP_AR_VDOWN (MP_AR_BASE + 12)
#define MP_AR_VDOWN_HOLD (MP_AR_BASE + 13)
+// Apple Media Keys input module
+#define MP_MK_BASE (MP_KEY_BASE+0xF0)
+#define MP_MK_PLAY (MP_AR_BASE + 0)
+#define MP_MK_PREV (MP_AR_BASE + 1)
+#define MP_MK_NEXT (MP_AR_BASE + 2)
+
/* Special keys */
#define MP_KEY_INTERN (MP_KEY_BASE+0x1000)
#define MP_KEY_CLOSE_WIN (MP_KEY_INTERN+0)
diff --git a/core/options.h b/core/options.h
index 0504ea0591..eaa908d7bd 100644
--- a/core/options.h
+++ b/core/options.h
@@ -241,6 +241,7 @@ typedef struct MPOpts {
int use_lircc;
#ifdef CONFIG_COCOA
int use_ar;
+ int use_media_keys;
#endif
int default_bindings;
int test;
diff --git a/etc/input.conf b/etc/input.conf
index 1cbd2446ba..3f9cea3c44 100644
--- a/etc/input.conf
+++ b/etc/input.conf
@@ -152,6 +152,11 @@ AR_VUP_HOLD add chapter 1
AR_VDOWN add volume -1
AR_VDOWN_HOLD add chapter -1
+# Media Keys section
+MK_PLAY cycle pause
+MK_PREV playlist_prev
+MK_NEXT playlist_next
+
# Joystick section
# WARNING: joystick support has to be explicitly enabled at
# compiletime with --enable-joystick
diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m
index 1329091e12..665a04b222 100644
--- a/osdep/macosx_application.m
+++ b/osdep/macosx_application.m
@@ -120,19 +120,7 @@ static NSString *escape_loadfile_name(NSString *input)
- (void)sendEvent:(NSEvent *)event
{
- if ([event type] == NSSystemDefined && [event subtype] == 8) {
- // It's a media key! Handle it specially. The magic numbers are reverse
- // engineered and found on several blog posts. Unfortunately there is
- // no public API for this. F-bomb.
- int code = (([event data1] & 0xFFFF0000) >> 16);
- int flags = ([event data1] & 0x0000FFFF);
- int down = (((flags & 0xFF00) >> 8)) == 0xA;
-
- if (down)
- [self.eventsResponder handleMediaKey:code];
- } else {
- [super sendEvent:event];
- }
+ [super sendEvent:event];
if (self.inputContext)
mp_input_wakeup(self.inputContext);
diff --git a/osdep/macosx_application_objc.h b/osdep/macosx_application_objc.h
index 3ab74698c3..c8026cfc14 100644
--- a/osdep/macosx_application_objc.h
+++ b/osdep/macosx_application_objc.h
@@ -28,10 +28,13 @@ struct cocoa_input_queue;
@end
@interface EventsResponder : NSObject <HIDRemoteDelegate>
-- (void)handleMediaKey:(int)key;
+- (BOOL)handleMediaKey:(int)key;
- (NSEvent *)handleKeyDown:(NSEvent *)event;
- (void)startAppleRemote;
- (void)stopAppleRemote;
+- (void)startMediaKeys;
+- (void)restartMediaKeys;
+- (void)stopMediaKeys;
@property(nonatomic, retain) HIDRemote *remote;
@end
diff --git a/osdep/macosx_events.h b/osdep/macosx_events.h
index 9557aeab5c..b8162dc125 100644
--- a/osdep/macosx_events.h
+++ b/osdep/macosx_events.h
@@ -23,7 +23,11 @@
void cocoa_put_key(int keycode);
void cocoa_check_events(void);
-void cocoa_start_apple_remote(void);
-void cocoa_stop_apple_remote(void);
+
+void cocoa_init_apple_remote(void);
+void cocoa_uninit_apple_remote(void);
+
+void cocoa_init_media_keys(void);
+void cocoa_uninit_media_keys(void);
#endif
diff --git a/osdep/macosx_events.m b/osdep/macosx_events.m
index 86d0ebaa3e..7970f0b5d5 100644
--- a/osdep/macosx_events.m
+++ b/osdep/macosx_events.m
@@ -92,18 +92,67 @@ static int convert_key(unsigned key, unsigned charcode)
return charcode;
}
-void cocoa_start_apple_remote(void)
+void cocoa_init_apple_remote(void)
{
Application *app = mpv_shared_app();
[app.eventsResponder startAppleRemote];
}
-void cocoa_stop_apple_remote(void)
+void cocoa_uninit_apple_remote(void)
{
Application *app = mpv_shared_app();
[app.eventsResponder stopAppleRemote];
}
+static CGEventRef tap_event_callback(CGEventTapProxy proxy, CGEventType type,
+ CGEventRef event, void *ctx)
+{
+ EventsResponder *responder = ctx;
+
+ if (type == kCGEventTapDisabledByTimeout) {
+ // The Mach Port receiving the taps became unresponsive for some
+ // reason, restart listening on it.
+ [responder restartMediaKeys];
+ return event;
+ }
+
+ if (type == kCGEventTapDisabledByUserInput)
+ return event;
+
+ NSEvent *nse = [NSEvent eventWithCGEvent:event];
+
+ if ([nse type] != NSSystemDefined || [nse subtype] != 8)
+ // This is not a media key
+ return event;
+
+ // It's a media key! Handle it specially. The magic numbers are reverse
+ // engineered and found on several blog posts. Unfortunately there is
+ // no public API for this. F-bomb.
+ int code = (([nse data1] & 0xFFFF0000) >> 16);
+ int flags = ([nse data1] & 0x0000FFFF);
+ int down = (((flags & 0xFF00) >> 8)) == 0xA;
+
+ if (down && [responder handleMediaKey:code]) {
+ // Handled this event, return nil so that it is removed from the
+ // global queue.
+ return nil;
+ } else {
+ // Was a media key but we were not interested in it. Leave it in the
+ // global queue by returning the original event.
+ return event;
+ }
+}
+
+void cocoa_init_media_keys(void) {
+ Application *app = mpv_shared_app();
+ [app.eventsResponder startMediaKeys];
+}
+
+void cocoa_uninit_media_keys(void) {
+ Application *app = mpv_shared_app();
+ [app.eventsResponder stopMediaKeys];
+}
+
void cocoa_check_events(void)
{
Application *app = mpv_shared_app();
@@ -117,7 +166,9 @@ void cocoa_put_key(int keycode)
[mpv_shared_app().iqueue push:keycode];
}
-@implementation EventsResponder
+@implementation EventsResponder {
+ CFMachPortRef _mk_tap_port;
+}
- (void)startAppleRemote
{
dispatch_async(dispatch_get_main_queue(), ^{
@@ -135,24 +186,56 @@ void cocoa_put_key(int keycode)
[self.remote stopRemoteControl];
});
}
+- (void)restartMediaKeys
+{
+ CGEventTapEnable(self->_mk_tap_port, true);
+}
+- (void)startMediaKeys
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ // Install a Quartz Event Tap. This will notify mpv through the
+ // returned Mach Port and cause mpv to execute the `tap_event_callback`
+ // function.
+ self->_mk_tap_port = CGEventTapCreate(kCGSessionEventTap,
+ kCGHeadInsertEventTap,
+ kCGEventTapOptionDefault,
+ CGEventMaskBit(NX_SYSDEFINED),
+ tap_event_callback,
+ self);
+
+ assert(self->_mk_tap_port != nil);
+
+ NSMachPort *port = (NSMachPort *)self->_mk_tap_port;
+ [[NSRunLoop mainRunLoop] addPort:port forMode:NSRunLoopCommonModes];
+ });
+}
+- (void)stopMediaKeys
+{
+ dispatch_async(dispatch_get_main_queue(), ^{
+ NSMachPort *port = (NSMachPort *)self->_mk_tap_port;
+ [[NSRunLoop mainRunLoop] removePort:port forMode:NSRunLoopCommonModes];
+ CFRelease(self->_mk_tap_port);
+ self->_mk_tap_port = nil;
+ });
+}
- (NSArray *) keyEquivalents
{
return @[@"h", @"q", @"Q", @"0", @"1", @"2"];
}
-- (void)handleMediaKey:(int)key
+- (BOOL)handleMediaKey:(int)key
{
- switch (key) {
- case NX_KEYTYPE_PLAY:
- cocoa_put_key(MP_KEY_PLAY);
- break;
-
- case NX_KEYTYPE_FAST:
- cocoa_put_key(MP_KEY_NEXT);
- break;
+ NSDictionary *keymap = @{
+ @(NX_KEYTYPE_PLAY): @(MP_MK_PLAY),
+ @(NX_KEYTYPE_REWIND): @(MP_MK_PREV),
+ @(NX_KEYTYPE_FAST): @(MP_MK_NEXT),
+ };
- case NX_KEYTYPE_REWIND:
- cocoa_put_key(MP_KEY_PREV);
- break;
+ int mpkey = [keymap[@(key)] intValue];
+ if (mpkey > 0) {
+ cocoa_put_key(mpkey);
+ return YES;
+ } else {
+ return NO;
}
}
- (NSEvent*)handleKeyDown:(NSEvent *)event