mirror of
https://github.com/mpv-player/mpv
synced 2025-03-19 01:47:38 +00:00
osx: initial Touch Bar support
This commit is contained in:
parent
afbd657bb8
commit
f8a223b7ac
@ -17,10 +17,12 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include "config.h"
|
||||
#include "mpv_talloc.h"
|
||||
|
||||
#include "common/msg.h"
|
||||
#include "input/input.h"
|
||||
#include "player/client.h"
|
||||
|
||||
#import "osdep/macosx_application_objc.h"
|
||||
#include "osdep/macosx_compat.h"
|
||||
@ -28,6 +30,10 @@
|
||||
#include "osdep/threads.h"
|
||||
#include "osdep/main-fn.h"
|
||||
|
||||
#if HAVE_MACOS_TOUCHBAR
|
||||
#import "osdep/macosx_touchbar.h"
|
||||
#endif
|
||||
|
||||
#define MPV_PROTOCOL @"mpv://"
|
||||
|
||||
// Whether the NSApplication singleton was created. If this is false, we are
|
||||
@ -106,6 +112,38 @@ static void terminate_cocoa_application(void)
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
#if HAVE_MACOS_TOUCHBAR
|
||||
- (NSTouchBar *)makeTouchBar
|
||||
{
|
||||
TouchBar *tBar = [[TouchBar alloc] init];
|
||||
[tBar setApp:self];
|
||||
tBar.delegate = tBar;
|
||||
tBar.customizationIdentifier = customID;
|
||||
tBar.defaultItemIdentifiers = @[play, previousItem, nextItem, seekBar];
|
||||
tBar.customizationAllowedItemIdentifiers = @[play, seekBar, previousItem,
|
||||
nextItem, previousChapter, nextChapter, cycleAudio, cycleSubtitle,
|
||||
currentPosition, timeLeft];
|
||||
return tBar;
|
||||
}
|
||||
|
||||
- (void)toggleTouchBarMenu
|
||||
{
|
||||
[NSApp toggleTouchBarCustomizationPalette:self];
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)processEvent:(struct mpv_event *)event
|
||||
{
|
||||
#if HAVE_MACOS_TOUCHBAR
|
||||
[(TouchBar *)self.touchBar processEvent:event];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)queueCommand:(char *)cmd
|
||||
{
|
||||
[_eventsResponder queueCommand:cmd];
|
||||
}
|
||||
|
||||
#define _R(P, T, E, K) \
|
||||
{ \
|
||||
NSMenuItem *tmp = [self menuItemWithParent:(P) title:(T) \
|
||||
@ -139,6 +177,13 @@ static void terminate_cocoa_application(void)
|
||||
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Window"];
|
||||
_R(menu, @"Minimize", @"m", MPM_MINIMIZE)
|
||||
_R(menu, @"Zoom", @"z", MPM_ZOOM)
|
||||
|
||||
#if HAVE_MACOS_TOUCHBAR
|
||||
[menu addItem:[NSMenuItem separatorItem]];
|
||||
[self menuItemWithParent:menu title:@"Customize Touch Bar…"
|
||||
action:@selector(toggleTouchBarMenu) keyEquivalent: @""];
|
||||
#endif
|
||||
|
||||
return [menu autorelease];
|
||||
}
|
||||
|
||||
@ -322,6 +367,7 @@ int cocoa_main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
application_instantiated = true;
|
||||
[[EventsResponder sharedInstance] setIsApplication:YES];
|
||||
|
||||
struct playback_thread_ctx ctx = {0};
|
||||
ctx.argc = &argc;
|
||||
|
@ -18,10 +18,15 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include "osdep/macosx_application.h"
|
||||
|
||||
struct mpv_event;
|
||||
|
||||
@interface Application : NSApplication
|
||||
|
||||
- (void)initialize_menu;
|
||||
- (void)registerSelector:(SEL)selector forKey:(MPMenuKey)key;
|
||||
- (void)stopPlayback;
|
||||
- (void)processEvent:(struct mpv_event *)event;
|
||||
- (void)queueCommand:(char *)cmd;
|
||||
|
||||
@property(nonatomic, retain) NSMutableDictionary *menuItems;
|
||||
@property(nonatomic, retain) NSArray *files;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "input/keycodes.h"
|
||||
|
||||
struct input_ctx;
|
||||
struct mpv_handle;
|
||||
|
||||
void cocoa_put_key(int keycode);
|
||||
void cocoa_put_key_with_modifiers(int keycode, int modifiers);
|
||||
@ -36,5 +37,6 @@ void cocoa_init_media_keys(void);
|
||||
void cocoa_uninit_media_keys(void);
|
||||
|
||||
void cocoa_set_input_context(struct input_ctx *input_context);
|
||||
void cocoa_set_mpv_handle(struct mpv_handle *ctx);
|
||||
|
||||
#endif
|
||||
|
@ -28,18 +28,22 @@
|
||||
#include "mpv_talloc.h"
|
||||
#include "input/event.h"
|
||||
#include "input/input.h"
|
||||
#include "player/client.h"
|
||||
#include "input/keycodes.h"
|
||||
// doesn't make much sense, but needed to access keymap functionality
|
||||
#include "video/out/vo.h"
|
||||
|
||||
#include "osdep/macosx_compat.h"
|
||||
#import "osdep/macosx_events_objc.h"
|
||||
#import "osdep/macosx_application_objc.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@interface EventsResponder ()
|
||||
{
|
||||
struct input_ctx *_inputContext;
|
||||
struct mpv_handle *_ctx;
|
||||
BOOL _is_application;
|
||||
NSCondition *_input_lock;
|
||||
CFMachPortRef _mk_tap_port;
|
||||
#if HAVE_APPLE_REMOTE
|
||||
@ -49,6 +53,8 @@
|
||||
|
||||
- (BOOL)handleMediaKey:(NSEvent *)event;
|
||||
- (NSEvent *)handleKey:(NSEvent *)event;
|
||||
- (void)setMpvHandle:(struct mpv_handle *)ctx;
|
||||
- (void)readEvents;
|
||||
- (void)startEventMonitor;
|
||||
- (void)startAppleRemote;
|
||||
- (void)stopAppleRemote;
|
||||
@ -210,6 +216,20 @@ void cocoa_set_input_context(struct input_ctx *input_context)
|
||||
[[EventsResponder sharedInstance] setInputContext:input_context];
|
||||
}
|
||||
|
||||
static void wakeup(void *context)
|
||||
{
|
||||
[[EventsResponder sharedInstance] readEvents];
|
||||
}
|
||||
|
||||
void cocoa_set_mpv_handle(struct mpv_handle *ctx)
|
||||
{
|
||||
[[EventsResponder sharedInstance] setMpvHandle:ctx];
|
||||
mpv_observe_property(ctx, 0, "duration", MPV_FORMAT_DOUBLE);
|
||||
mpv_observe_property(ctx, 0, "time-pos", MPV_FORMAT_DOUBLE);
|
||||
mpv_observe_property(ctx, 0, "pause", MPV_FORMAT_FLAG);
|
||||
mpv_set_wakeup_callback(ctx, wakeup, NULL);
|
||||
}
|
||||
|
||||
@implementation EventsResponder
|
||||
|
||||
+ (EventsResponder *)sharedInstance
|
||||
@ -286,6 +306,47 @@ void cocoa_set_input_context(struct input_ctx *input_context)
|
||||
return r;
|
||||
}
|
||||
|
||||
- (void)setIsApplication:(BOOL)isApplication
|
||||
{
|
||||
_is_application = isApplication;
|
||||
}
|
||||
|
||||
- (void)setMpvHandle:(struct mpv_handle *)ctx
|
||||
{
|
||||
if (_is_application) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{ _ctx = ctx; });
|
||||
} else {
|
||||
_ctx = ctx;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)readEvents
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
while (_ctx) {
|
||||
mpv_event *event = mpv_wait_event(_ctx, 0);
|
||||
if (event->event_id == MPV_EVENT_NONE)
|
||||
break;
|
||||
[self processEvent:event];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
-(void)processEvent:(struct mpv_event *)event
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_SHUTDOWN: {
|
||||
mpv_detach_destroy(_ctx);
|
||||
_ctx = nil;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(_is_application) {
|
||||
[NSApp processEvent:event];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startEventMonitor
|
||||
{
|
||||
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown|NSEventMaskKeyUp
|
||||
|
@ -29,6 +29,8 @@ struct input_ctx;
|
||||
|
||||
- (void)setInputContext:(struct input_ctx *)ctx;
|
||||
|
||||
- (void)setIsApplication:(BOOL)isApplication;
|
||||
|
||||
/// Blocks until inputContext is present.
|
||||
- (void)waitForInputContext;
|
||||
|
||||
|
45
osdep/macosx_touchbar.h
Normal file
45
osdep/macosx_touchbar.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "osdep/macosx_application_objc.h"
|
||||
|
||||
#define BASE_ID @"io.mpv.touchbar"
|
||||
static NSTouchBarCustomizationIdentifier customID = BASE_ID;
|
||||
static NSTouchBarItemIdentifier seekBar = BASE_ID ".seekbar";
|
||||
static NSTouchBarItemIdentifier play = BASE_ID ".play";
|
||||
static NSTouchBarItemIdentifier nextItem = BASE_ID ".nextItem";
|
||||
static NSTouchBarItemIdentifier previousItem = BASE_ID ".previousItem";
|
||||
static NSTouchBarItemIdentifier nextChapter = BASE_ID ".nextChapter";
|
||||
static NSTouchBarItemIdentifier previousChapter = BASE_ID ".previousChapter";
|
||||
static NSTouchBarItemIdentifier cycleAudio = BASE_ID ".cycleAudio";
|
||||
static NSTouchBarItemIdentifier cycleSubtitle = BASE_ID ".cycleSubtitle";
|
||||
static NSTouchBarItemIdentifier currentPosition = BASE_ID ".currentPosition";
|
||||
static NSTouchBarItemIdentifier timeLeft = BASE_ID ".timeLeft";
|
||||
|
||||
struct mpv_event;
|
||||
|
||||
@interface TouchBar : NSTouchBar <NSTouchBarDelegate>
|
||||
|
||||
-(void)processEvent:(struct mpv_event *)event;
|
||||
|
||||
@property(nonatomic, retain) Application *app;
|
||||
@property(nonatomic, retain) NSDictionary *touchbarItems;
|
||||
@property(nonatomic, assign) double duration;
|
||||
@property(nonatomic, assign) double position;
|
||||
|
||||
@end
|
272
osdep/macosx_touchbar.m
Normal file
272
osdep/macosx_touchbar.m
Normal file
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "player/client.h"
|
||||
#import "macosx_touchbar.h"
|
||||
|
||||
@implementation TouchBar
|
||||
|
||||
@synthesize app = _app;
|
||||
@synthesize touchbarItems = _touchbar_items;
|
||||
@synthesize duration = _duration;
|
||||
@synthesize position = _position;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if (self = [super init]) {
|
||||
self.touchbarItems = @{
|
||||
seekBar: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"slider",
|
||||
@"name": @"Seek Bar",
|
||||
@"cmd": @"seek %f absolute-percent"
|
||||
}],
|
||||
play: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Play Button",
|
||||
@"cmd": @"cycle pause",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarPauseTemplate],
|
||||
@"imageAlt": [NSImage imageNamed:NSImageNameTouchBarPlayTemplate]
|
||||
}],
|
||||
previousItem: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Previous Playlist Item",
|
||||
@"cmd": @"playlist-prev",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarGoBackTemplate]
|
||||
}],
|
||||
nextItem: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Next Playlist Item",
|
||||
@"cmd": @"playlist-next",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarGoForwardTemplate]
|
||||
}],
|
||||
previousChapter: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Previous Chapter",
|
||||
@"cmd": @"add chapter -1",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarSkipBackTemplate]
|
||||
}],
|
||||
nextChapter: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Next Chapter",
|
||||
@"cmd": @"add chapter 1",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarSkipAheadTemplate]
|
||||
}],
|
||||
cycleAudio: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Cycle Audio",
|
||||
@"cmd": @"cycle audio",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarAudioInputTemplate]
|
||||
}],
|
||||
cycleSubtitle: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"button",
|
||||
@"name": @"Cycle Subtitle",
|
||||
@"cmd": @"cycle sub",
|
||||
@"image": [NSImage imageNamed:NSImageNameTouchBarComposeTemplate]
|
||||
}],
|
||||
currentPosition: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"text",
|
||||
@"name": @"Current Position"
|
||||
}],
|
||||
timeLeft: [NSMutableDictionary dictionaryWithDictionary:@{
|
||||
@"type": @"text",
|
||||
@"name": @"Time Left"
|
||||
}]
|
||||
};
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)processEvent:(struct mpv_event *)event
|
||||
{
|
||||
switch (event->event_id) {
|
||||
case MPV_EVENT_END_FILE: {
|
||||
self.position = 0;
|
||||
self.duration = 0;
|
||||
break;
|
||||
}
|
||||
case MPV_EVENT_PROPERTY_CHANGE: {
|
||||
[self handlePropertyChange:(mpv_event_property *)event->data];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(void)handlePropertyChange:(struct mpv_event_property *)property
|
||||
{
|
||||
NSString *name = [NSString stringWithUTF8String:property->name];
|
||||
mpv_format format = property->format;
|
||||
|
||||
if ([name isEqualToString:@"time-pos"] && format == MPV_FORMAT_DOUBLE) {
|
||||
self.position = *(double *)property->data;
|
||||
self.position = self.position < 0 ? 0 : self.position;
|
||||
[self updateTouchBarTimeItems];
|
||||
} else if ([name isEqualToString:@"duration"] && format == MPV_FORMAT_DOUBLE) {
|
||||
self.duration = *(double *)property->data;
|
||||
[self updateTouchBarTimeItems];
|
||||
} else if ([name isEqualToString:@"pause"] && format == MPV_FORMAT_FLAG) {
|
||||
NSButton *playButton = self.touchbarItems[play][@"view"];
|
||||
if (*(int *)property->data) {
|
||||
playButton.image = self.touchbarItems[play][@"imageAlt"];
|
||||
} else {
|
||||
playButton.image = self.touchbarItems[play][@"image"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar
|
||||
makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier
|
||||
{
|
||||
if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"slider"]) {
|
||||
NSSliderTouchBarItem *tbItem = [[NSSliderTouchBarItem alloc] initWithIdentifier:identifier];
|
||||
tbItem.slider.minValue = 0.0f;
|
||||
tbItem.slider.maxValue = 100.0f;
|
||||
tbItem.target = self;
|
||||
tbItem.action = @selector(seekbarChanged:);
|
||||
tbItem.customizationLabel = self.touchbarItems[identifier][@"name"];
|
||||
[self.touchbarItems[identifier] setObject:tbItem.slider forKey:@"view"];
|
||||
return tbItem;
|
||||
} else if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"button"]) {
|
||||
NSCustomTouchBarItem *tbItem = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
||||
NSImage *tbImage = self.touchbarItems[identifier][@"image"];
|
||||
NSButton *tbButton = [NSButton buttonWithImage:tbImage target:self action:@selector(buttonAction:)];
|
||||
tbItem.view = tbButton;
|
||||
tbItem.customizationLabel = self.touchbarItems[identifier][@"name"];
|
||||
[self.touchbarItems[identifier] setObject:tbButton forKey:@"view"];
|
||||
return tbItem;
|
||||
} else if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"text"]) {
|
||||
NSCustomTouchBarItem *tbItem = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier];
|
||||
NSTextField *tbText = [NSTextField labelWithString:@"0:00"];
|
||||
tbText.alignment = NSTextAlignmentCenter;
|
||||
tbItem.view = tbText;
|
||||
tbItem.customizationLabel = self.touchbarItems[identifier][@"name"];
|
||||
[self.touchbarItems[identifier] setObject:tbText forKey:@"view"];
|
||||
return tbItem;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSString *)formatTime:(int)time
|
||||
{
|
||||
int seconds = time % 60;
|
||||
int minutes = (time / 60) % 60;
|
||||
int hours = time / (60 * 60);
|
||||
|
||||
NSString *stime = hours > 0 ? [NSString stringWithFormat:@"%d:", hours] : @"";
|
||||
stime = (stime.length > 0 || minutes > 9) ?
|
||||
[NSString stringWithFormat:@"%@%02d:", stime, minutes] :
|
||||
[NSString stringWithFormat:@"%d:", minutes];
|
||||
stime = [NSString stringWithFormat:@"%@%02d", stime, seconds];
|
||||
|
||||
return stime;
|
||||
}
|
||||
|
||||
- (void)removeConstraintForIdentifier:(NSTouchBarItemIdentifier)identifier
|
||||
{
|
||||
NSTextField *field = self.touchbarItems[identifier][@"view"];
|
||||
[field removeConstraint:self.touchbarItems[identifier][@"constrain"]];
|
||||
}
|
||||
|
||||
- (void)applyConstraintFromString:(NSString *)string
|
||||
forIdentifier:(NSTouchBarItemIdentifier)identifier
|
||||
{
|
||||
NSTextField *field = self.touchbarItems[identifier][@"view"];
|
||||
if (field) {
|
||||
NSString *fString = [[string componentsSeparatedByCharactersInSet:
|
||||
[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@"0"];
|
||||
NSTextField *textField = [NSTextField labelWithString:fString];
|
||||
NSSize size = [textField frame].size;
|
||||
|
||||
NSLayoutConstraint *con =
|
||||
[NSLayoutConstraint constraintWithItem:field
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1.0
|
||||
constant:(int)ceil(size.width*1.1)];
|
||||
[field addConstraint:con];
|
||||
[self.touchbarItems[identifier] setObject:con forKey:@"constrain"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateTouchBarTimeItemConstrains
|
||||
{
|
||||
[self removeConstraintForIdentifier:currentPosition];
|
||||
[self removeConstraintForIdentifier:timeLeft];
|
||||
|
||||
if (self.duration <= 0) {
|
||||
[self applyConstraintFromString:[self formatTime:self.position]
|
||||
forIdentifier:currentPosition];
|
||||
} else {
|
||||
NSString *durFormat = [self formatTime:self.duration];
|
||||
|
||||
[self applyConstraintFromString:durFormat forIdentifier:currentPosition];
|
||||
[self applyConstraintFromString:[NSString stringWithFormat:@"-%@", durFormat]
|
||||
forIdentifier:timeLeft];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateTouchBarTimeItems
|
||||
{
|
||||
NSSlider *seekSlider = self.touchbarItems[seekBar][@"view"];
|
||||
NSTextField *curPosItem = self.touchbarItems[currentPosition][@"view"];
|
||||
NSTextField *timeLeftItem = self.touchbarItems[timeLeft][@"view"];
|
||||
|
||||
if (self.duration <= 0) {
|
||||
seekSlider.enabled = NO;
|
||||
seekSlider.doubleValue = 0;
|
||||
timeLeftItem.stringValue = @"";
|
||||
}
|
||||
else {
|
||||
seekSlider.enabled = YES;
|
||||
if (!seekSlider.highlighted)
|
||||
seekSlider.doubleValue = (self.position/self.duration)*100;
|
||||
int left = (int)(floor(self.duration)-floor(self.position));
|
||||
NSString *leftFormat = [self formatTime:left];
|
||||
timeLeftItem.stringValue = [NSString stringWithFormat:@"-%@", leftFormat];
|
||||
}
|
||||
NSString *posFormat = [self formatTime:(int)floor(self.position)];
|
||||
curPosItem.stringValue = posFormat;
|
||||
|
||||
[self updateTouchBarTimeItemConstrains];
|
||||
}
|
||||
|
||||
- (NSString *)getIdentifierFromView:(id)view
|
||||
{
|
||||
NSString *identifier;
|
||||
for (identifier in self.touchbarItems)
|
||||
if([self.touchbarItems[identifier][@"view"] isEqual:view])
|
||||
break;
|
||||
return identifier;
|
||||
}
|
||||
|
||||
- (void)buttonAction:(NSButton *)sender
|
||||
{
|
||||
NSString *identifier = [self getIdentifierFromView:sender];
|
||||
[self.app queueCommand:(char *)[self.touchbarItems[identifier][@"cmd"] UTF8String]];
|
||||
}
|
||||
|
||||
- (void)seekbarChanged:(NSSliderTouchBarItem *)sender
|
||||
{
|
||||
NSString *identifier = [self getIdentifierFromView:sender.slider];
|
||||
NSString *seek = [NSString stringWithFormat:
|
||||
self.touchbarItems[identifier][@"cmd"], sender.slider.doubleValue];
|
||||
[self.app queueCommand:(char *)[seek UTF8String]];
|
||||
}
|
||||
|
||||
@end
|
@ -455,6 +455,11 @@ int mp_initialize(struct MPContext *mpctx, char **options)
|
||||
|
||||
MP_STATS(mpctx, "start init");
|
||||
|
||||
#if HAVE_COCOA
|
||||
mpv_handle *ctx = mp_new_client(mpctx->clients, "osx");
|
||||
cocoa_set_mpv_handle(ctx);
|
||||
#endif
|
||||
|
||||
#if HAVE_ENCODING
|
||||
if (opts->encode_opts->file && opts->encode_opts->file[0]) {
|
||||
mpctx->encode_lavc_ctx = encode_lavc_init(opts->encode_opts,
|
||||
|
7
waftools/fragments/touchbar.m
Normal file
7
waftools/fragments/touchbar.m
Normal file
@ -0,0 +1,7 @@
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
[[NSTouchBar alloc] init];
|
||||
return 0;
|
||||
}
|
11
wscript
11
wscript
@ -923,7 +923,16 @@ standalone_features = [
|
||||
'desc': 'Apple Remote support',
|
||||
'deps': [ 'cocoa' ],
|
||||
'func': check_true
|
||||
}
|
||||
}, {
|
||||
'name': '--macos-touchbar',
|
||||
'desc': 'macOS Touch Bar support',
|
||||
'deps': [ 'cocoa' ],
|
||||
'func': check_cc(
|
||||
fragment=load_fragment('touchbar.m'),
|
||||
framework_name=['AppKit'],
|
||||
compile_filename='test-touchbar.m',
|
||||
linkflags='-fobjc-arc')
|
||||
}
|
||||
]
|
||||
|
||||
_INSTALL_DIRS_LIST = [
|
||||
|
@ -418,6 +418,7 @@ def build(ctx):
|
||||
( "osdep/ar/HIDRemote.m", "apple-remote" ),
|
||||
( "osdep/macosx_application.m", "cocoa" ),
|
||||
( "osdep/macosx_events.m", "cocoa" ),
|
||||
( "osdep/macosx_touchbar.m", "macos-touchbar" ),
|
||||
( "osdep/semaphore_osx.c" ),
|
||||
( "osdep/subprocess.c" ),
|
||||
( "osdep/subprocess-posix.c", "posix-spawn" ),
|
||||
|
Loading…
Reference in New Issue
Block a user