summaryrefslogtreecommitdiffstats
path: root/osdep/macosx_application.m
diff options
context:
space:
mode:
Diffstat (limited to 'osdep/macosx_application.m')
-rw-r--r--osdep/macosx_application.m200
1 files changed, 142 insertions, 58 deletions
diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m
index e57b6545b0..1329091e12 100644
--- a/osdep/macosx_application.m
+++ b/osdep/macosx_application.m
@@ -20,15 +20,11 @@
#include "talloc.h"
#include "core/mp_msg.h"
-#include "core/mp_fifo.h"
#include "core/input/input.h"
#include "core/input/keycodes.h"
#include "osdep/macosx_application_objc.h"
-#include "video/out/osx_common.h"
-static Application *app;
-static NSAutoreleasePool *pool;
static pthread_t playback_thread_id;
@interface Application (PrivateMethods)
@@ -50,6 +46,67 @@ static pthread_t playback_thread_id;
- (void)setAppleMenu:(NSMenu *)aMenu;
@end
+@implementation InputQueue {
+ NSMutableArray *_fifo;
+}
+
+- (id)init
+{
+ if (self = [super init]) {
+ self->_fifo = [[NSMutableArray alloc] init];
+ }
+
+ return self;
+}
+
+- (void)push:(int)keycode
+{
+ @synchronized (_fifo) {
+ [_fifo addObject:[NSNumber numberWithInt:keycode]];
+ }
+}
+
+- (int)pop
+{
+ int r = -1;
+
+ @synchronized (_fifo) {
+ if ([_fifo count] > 0) {
+ r = [[_fifo objectAtIndex:0] intValue];
+ [_fifo removeObjectAtIndex:0];
+ }
+ }
+
+ return r;
+}
+
+- (void)dealloc
+{
+ [self->_fifo release];
+ [super dealloc];
+}
+@end
+
+Application *mpv_shared_app(void)
+{
+ return (Application *)[Application sharedApplication];
+}
+
+static NSString *escape_loadfile_name(NSString *input)
+{
+ NSArray *mappings = @[
+ @{ @"in": @"\\", @"out": @"\\\\" },
+ @{ @"in": @"\"", @"out": @"\\\"" },
+ ];
+
+ for (NSDictionary *mapping in mappings) {
+ input = [input stringByReplacingOccurrencesOfString:mapping[@"in"]
+ withString:mapping[@"out"]];
+ }
+
+ return input;
+}
+
@implementation Application
@synthesize files = _files;
@synthesize argumentsList = _arguments_list;
@@ -57,15 +114,45 @@ static pthread_t playback_thread_id;
@synthesize inputContext = _input_context;
@synthesize keyFIFO = _key_fifo;
+@synthesize iqueue = _iqueue;
+@synthesize eventsResponder = _events_responder;
@synthesize menuItems = _menu_items;
+- (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];
+ }
+
+ if (self.inputContext)
+ mp_input_wakeup(self.inputContext);
+}
+
- (id)init
{
if (self = [super init]) {
self.menuItems = [[[NSMutableDictionary alloc] init] autorelease];
self.files = nil;
self.argumentsList = [[[NSMutableArray alloc] init] autorelease];
+ self.iqueue = [[[InputQueue alloc] init] autorelease];
+ self.eventsResponder = [[[EventsResponder alloc] init] autorelease];
self.willStopOnOpenEvent = NO;
+
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask
+ handler:^(NSEvent *event) {
+ return [self.eventsResponder handleKeyDown:event];
+ }];
+
}
return self;
@@ -115,23 +202,23 @@ static pthread_t playback_thread_id;
[NSApp setMainMenu:main_menu];
[NSApp setAppleMenu:[self appleMenuWithMainMenu:main_menu]];
- [app mainMenuItemWithParent:main_menu child:[self movieMenu]];
- [app mainMenuItemWithParent:main_menu child:[self windowMenu]];
+ [NSApp mainMenuItemWithParent:main_menu child:[self movieMenu]];
+ [NSApp mainMenuItemWithParent:main_menu child:[self windowMenu]];
}
#undef _R
- (void)stopPlayback
{
- [self stop:"quit"];
+ [self stopMPV:"quit"];
}
- (void)stopPlaybackAndRememberPosition
{
- [self stop:"quit_watch_later"];
+ [self stopMPV:"quit_watch_later"];
}
-- (void)stop:(char *)cmd
+- (void)stopMPV:(char *)cmd
{
if (self.inputContext) {
mp_cmd_t *cmdt = mp_input_parse_cmd(bstr0(cmd), "");
@@ -192,6 +279,7 @@ static pthread_t playback_thread_id;
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
{
+ Application *app = mpv_shared_app();
NSMutableArray *filesToOpen = [[[NSMutableArray alloc] init] autorelease];
[filenames enumerateObjectsUsingBlock:^(id obj, NSUInteger i, BOOL *_) {
@@ -237,44 +325,47 @@ struct playback_thread_ctx {
static void *playback_thread(void *ctx_obj)
{
- struct playback_thread_ctx *ctx = (struct playback_thread_ctx*) ctx_obj;
- ctx->mpv_main(*ctx->argc, *ctx->argv);
- cocoa_stop_runloop();
- pthread_exit(NULL);
+ @autoreleasepool {
+ struct playback_thread_ctx *ctx = (struct playback_thread_ctx*) ctx_obj;
+ ctx->mpv_main(*ctx->argc, *ctx->argv);
+ cocoa_stop_runloop();
+ pthread_exit(NULL);
+ }
}
int cocoa_main(mpv_main_fn mpv_main, int argc, char *argv[])
{
- struct playback_thread_ctx ctx = {0};
- ctx.mpv_main = mpv_main;
- ctx.argc = &argc;
- ctx.argv = &argv;
-
- init_cocoa_application();
- macosx_finder_args_preinit(&argc, &argv);
- pthread_create(&playback_thread_id, NULL, playback_thread, &ctx);
- cocoa_run_runloop();
-
- // This should never be reached: cocoa_run_runloop blocks until the process
- // is quit
- mp_msg(MSGT_CPLAYER, MSGL_ERR, "There was either a problem initializing "
- "Cocoa or the Runloop was stopped unexpectedly. Please report this "
- "issues to a developer.\n");
- pthread_join(playback_thread_id, NULL);
- return 1;
+ @autoreleasepool {
+ struct playback_thread_ctx ctx = {0};
+ ctx.mpv_main = mpv_main;
+ ctx.argc = &argc;
+ ctx.argv = &argv;
+
+ init_cocoa_application();
+ macosx_finder_args_preinit(&argc, &argv);
+ pthread_create(&playback_thread_id, NULL, playback_thread, &ctx);
+ cocoa_run_runloop();
+
+ // This should never be reached: cocoa_run_runloop blocks until the
+ // process is quit
+ mp_msg(MSGT_CPLAYER, MSGL_ERR, "There was either a problem "
+ "initializing Cocoa or the Runloop was stopped unexpectedly. "
+ "Please report this issues to a developer.\n");
+ pthread_join(playback_thread_id, NULL);
+ return 1;
+ }
}
void cocoa_register_menu_item_action(MPMenuKey key, void* action)
{
- [app registerSelector:(SEL)action forKey:key];
+ [NSApp registerSelector:(SEL)action forKey:key];
}
void init_cocoa_application(void)
{
- NSApp = [NSApplication sharedApplication];
- app = [[Application alloc] init];
- [NSApp setDelegate:app];
- [app initialize_menu];
+ NSApp = mpv_shared_app();
+ [NSApp setDelegate:NSApp];
+ [NSApp initialize_menu];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
atexit_b(^{
@@ -287,21 +378,10 @@ void init_cocoa_application(void)
void terminate_cocoa_application(void)
{
- [NSApp hide:app];
- [NSApp terminate:app];
-}
-
-void cocoa_autorelease_pool_alloc(void)
-{
- pool = [[NSAutoreleasePool alloc] init];
-}
-
-void cocoa_autorelease_pool_drain(void)
-{
- [pool drain];
+ [NSApp hide:NSApp];
+ [NSApp terminate:NSApp];
}
-
void cocoa_run_runloop()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@@ -319,8 +399,12 @@ void cocoa_stop_runloop(void)
void cocoa_set_input_context(struct input_ctx *input_context)
{
- [NSApp setDelegate:app];
- app.inputContext = input_context;
+ mpv_shared_app().inputContext = input_context;
+}
+
+void cocoa_set_key_fifo(struct mp_fifo *key_fifo)
+{
+ mpv_shared_app().keyFIFO = key_fifo;
}
void cocoa_post_fake_event(void)
@@ -339,7 +423,7 @@ void cocoa_post_fake_event(void)
static void macosx_wait_fileopen_events()
{
- app.willStopOnOpenEvent = YES;
+ mpv_shared_app().willStopOnOpenEvent = YES;
cocoa_run_runloop(); // block until done
}
@@ -356,19 +440,19 @@ static void macosx_redirect_output_to_logfile(const char *filename)
static bool psn_matches_current_process(char *psn_arg_to_check)
{
ProcessSerialNumber psn;
- size_t psn_length = 5+10+1+10;
- char psn_arg[psn_length+1];
-
GetCurrentProcess(&psn);
- snprintf(psn_arg, 5+10+1+10+1, "-psn_%u_%u",
- psn.highLongOfPSN, psn.lowLongOfPSN);
- psn_arg[psn_length]=0;
- return strcmp(psn_arg, psn_arg_to_check) == 0;
+ NSString *in_psn = [NSString stringWithUTF8String:psn_arg_to_check];
+ NSString *real_psn = [NSString stringWithFormat:@"-psn_%u_%u",
+ psn.highLongOfPSN, psn.lowLongOfPSN];
+
+ return [real_psn isEqualToString:in_psn];
}
void macosx_finder_args_preinit(int *argc, char ***argv)
{
+ Application *app = mpv_shared_app();
+
if (*argc==2 && psn_matches_current_process((*argv)[1])) {
macosx_redirect_output_to_logfile("mpv");
macosx_wait_fileopen_events();