diff options
Diffstat (limited to '')
-rw-r--r-- | misc/io_utils.h (renamed from osdep/macosx_menubar_objc.h) | 12 | ||||
-rw-r--r-- | osdep/mac/app_bridge.h (renamed from osdep/macosx_application.h) | 22 | ||||
-rw-r--r-- | osdep/mac/libmpv_helper.swift (renamed from osdep/macos/libmpv_helper.swift) | 119 | ||||
-rw-r--r-- | osdep/mac/precise_timer.swift (renamed from osdep/macos/precise_timer.swift) | 9 | ||||
-rw-r--r-- | osdep/mac/swift_compat.swift (renamed from osdep/macos/swift_compat.swift) | 0 | ||||
-rw-r--r-- | osdep/macos/log_helper.swift | 47 | ||||
-rw-r--r-- | osdep/macos/mpv_helper.swift | 156 | ||||
-rw-r--r-- | osdep/macos/remote_command_center.swift | 191 | ||||
-rw-r--r-- | osdep/macos/swift_extensions.swift | 58 | ||||
-rw-r--r-- | osdep/macosx_application.m | 375 | ||||
-rw-r--r-- | osdep/macosx_application_objc.h | 40 | ||||
-rw-r--r-- | osdep/macosx_events.h | 36 | ||||
-rw-r--r-- | osdep/macosx_events.m | 408 | ||||
-rw-r--r-- | osdep/macosx_events_objc.h | 45 | ||||
-rw-r--r-- | osdep/macosx_menubar.m | 853 | ||||
-rw-r--r-- | osdep/macosx_touchbar.h | 46 | ||||
-rw-r--r-- | osdep/macosx_touchbar.m | 334 | ||||
-rw-r--r-- | video/out/win32/menu.h (renamed from osdep/macosx_menubar.h) | 24 |
18 files changed, 61 insertions, 2714 deletions
diff --git a/osdep/macosx_menubar_objc.h b/misc/io_utils.h index 072fef8..012f242 100644 --- a/osdep/macosx_menubar_objc.h +++ b/misc/io_utils.h @@ -1,4 +1,6 @@ /* + * I/O utility functions + * * This file is part of mpv. * * mpv is free software; you can redistribute it and/or @@ -15,11 +17,9 @@ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ -#import <Cocoa/Cocoa.h> -#include "osdep/macosx_menubar.h" - -@interface MenuBar : NSObject +#pragma once -- (void)registerSelector:(SEL)action forKey:(MPMenuKey)key; +#include <stddef.h> -@end +int mp_mkostemps(char *template, int suffixlen, int flags); +bool mp_save_to_file(const char *filepath, const void *data, size_t size); diff --git a/osdep/macosx_application.h b/osdep/mac/app_bridge.h index 753b9f0..db03c8e 100644 --- a/osdep/macosx_application.h +++ b/osdep/mac/app_bridge.h @@ -15,25 +15,27 @@ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef MPV_MACOSX_APPLICATION -#define MPV_MACOSX_APPLICATION +#pragma once -#include "osdep/macosx_menubar.h" +#include <stdbool.h> #include "options/m_option.h" +struct input_ctx; +struct mpv_handle; + enum { FRAME_VISIBLE = 0, FRAME_WHOLE, }; enum { - RENDER_TIMER_CALLBACK = 0, - RENDER_TIMER_PRECISE, + RENDER_TIMER_PRESENTATION_FEEDBACK = -1, RENDER_TIMER_SYSTEM, + RENDER_TIMER_CALLBACK, + RENDER_TIMER_PRECISE, }; struct macos_opts { - int macos_title_bar_style; int macos_title_bar_appearance; int macos_title_bar_material; struct m_color macos_title_bar_color; @@ -46,10 +48,12 @@ struct macos_opts { bool cocoa_cb_10bit_context; }; +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); +void cocoa_init_cocoa_cb(void); // multithreaded wrapper for mpv_main int cocoa_main(int argc, char *argv[]); -void cocoa_register_menu_item_action(MPMenuKey key, void* action); extern const struct m_sub_options macos_conf; - -#endif /* MPV_MACOSX_APPLICATION */ diff --git a/osdep/macos/libmpv_helper.swift b/osdep/mac/libmpv_helper.swift index 8b1c697..23953eb 100644 --- a/osdep/macos/libmpv_helper.swift +++ b/osdep/mac/libmpv_helper.swift @@ -23,27 +23,14 @@ let glDummy: @convention(c) () -> Void = {} class LibmpvHelper { var log: LogHelper - var mpvHandle: OpaquePointer? + var mpv: OpaquePointer? var mpvRenderContext: OpaquePointer? - var macOptsPtr: UnsafeMutableRawPointer? - var macOpts: macos_opts = macos_opts() var fbo: GLint = 1 - let deinitLock = NSLock() - - init(_ mpv: OpaquePointer, _ mpLog: OpaquePointer?) { - mpvHandle = mpv - log = LogHelper(mpLog) - - guard let app = NSApp as? Application, - let ptr = mp_get_config_group(nil, - mp_client_get_global(mpvHandle), - app.getMacOSConf()) else - { - log.sendError("macOS config group couldn't be retrieved'") - exit(1) - } - macOptsPtr = ptr - macOpts = UnsafeMutablePointer<macos_opts>(OpaquePointer(ptr)).pointee + let uninitLock = NSLock() + + init(_ mpv: OpaquePointer, _ log: LogHelper) { + self.mpv = mpv + self.log = log } func initRender() { @@ -52,7 +39,7 @@ class LibmpvHelper { let pAddress = mpv_opengl_init_params(get_proc_address: getProcAddress, get_proc_address_ctx: nil) - MPVHelper.withUnsafeMutableRawPointers([pAddress, advanced]) { (pointers: [UnsafeMutableRawPointer?]) in + TypeHelper.withUnsafeMutableRawPointers([pAddress, advanced]) { (pointers: [UnsafeMutableRawPointer?]) in var params: [mpv_render_param] = [ mpv_render_param(type: MPV_RENDER_PARAM_API_TYPE, data: api), mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, data: pointers[0]), @@ -60,12 +47,11 @@ class LibmpvHelper { mpv_render_param() ] - if (mpv_render_context_create(&mpvRenderContext, mpvHandle, ¶ms) < 0) { - log.sendError("Render context init has failed.") + if (mpv_render_context_create(&mpvRenderContext, mpv, ¶ms) < 0) { + log.error("Render context init has failed.") exit(1) } } - } let getProcAddress: (@convention(c) (UnsafeMutableRawPointer?, UnsafePointer<Int8>?) @@ -87,17 +73,17 @@ class LibmpvHelper { func setRenderUpdateCallback(_ callback: @escaping mpv_render_update_fn, context object: AnyObject) { if mpvRenderContext == nil { - log.sendWarning("Init mpv render context first.") + log.warning("Init mpv render context first.") } else { - mpv_render_context_set_update_callback(mpvRenderContext, callback, MPVHelper.bridge(obj: object)) + mpv_render_context_set_update_callback(mpvRenderContext, callback, TypeHelper.bridge(obj: object)) } } func setRenderControlCallback(_ callback: @escaping mp_render_cb_control_fn, context object: AnyObject) { if mpvRenderContext == nil { - log.sendWarning("Init mpv render context first.") + log.warning("Init mpv render context first.") } else { - mp_render_context_set_control_callback(mpvRenderContext, callback, MPVHelper.bridge(obj: object)) + mp_render_context_set_control_callback(mpvRenderContext, callback, TypeHelper.bridge(obj: object)) } } @@ -107,18 +93,18 @@ class LibmpvHelper { } func isRenderUpdateFrame() -> Bool { - deinitLock.lock() + uninitLock.lock() if mpvRenderContext == nil { - deinitLock.unlock() + uninitLock.unlock() return false } let flags: UInt64 = mpv_render_context_update(mpvRenderContext) - deinitLock.unlock() + uninitLock.unlock() return flags & UInt64(MPV_RENDER_UPDATE_FRAME.rawValue) > 0 } func drawRender(_ surface: NSSize, _ depth: GLint, _ ctx: CGLContextObj, skip: Bool = false) { - deinitLock.lock() + uninitLock.lock() if mpvRenderContext != nil { var i: GLint = 0 let flip: CInt = 1 @@ -134,7 +120,7 @@ class LibmpvHelper { h: Int32(surface.height), internal_format: 0) - MPVHelper.withUnsafeMutableRawPointers([data, flip, ditherDepth, skip]) { (pointers: [UnsafeMutableRawPointer?]) in + TypeHelper.withUnsafeMutableRawPointers([data, flip, ditherDepth, skip]) { (pointers: [UnsafeMutableRawPointer?]) in var params: [mpv_render_param] = [ mpv_render_param(type: MPV_RENDER_PARAM_OPENGL_FBO, data: pointers[0]), mpv_render_param(type: MPV_RENDER_PARAM_FLIP_Y, data: pointers[1]), @@ -151,13 +137,13 @@ class LibmpvHelper { if !skip { CGLFlushDrawable(ctx) } - deinitLock.unlock() + uninitLock.unlock() } func setRenderICCProfile(_ profile: NSColorSpace) { if mpvRenderContext == nil { return } guard var iccData = profile.iccProfileData else { - log.sendWarning("Invalid ICC profile data.") + log.warning("Invalid ICC profile data.") return } iccData.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) in @@ -182,69 +168,14 @@ class LibmpvHelper { } } - func commandAsync(_ cmd: [String?], id: UInt64 = 1) { - if mpvHandle == nil { return } - var mCmd = cmd - mCmd.append(nil) - var cargs = mCmd.map { $0.flatMap { UnsafePointer<Int8>(strdup($0)) } } - mpv_command_async(mpvHandle, id, &cargs) - for ptr in cargs { free(UnsafeMutablePointer(mutating: ptr)) } - } - - // Unsafe function when called while using the render API - func command(_ cmd: String) { - if mpvHandle == nil { return } - mpv_command_string(mpvHandle, cmd) - } - - func getBoolProperty(_ name: String) -> Bool { - if mpvHandle == nil { return false } - var value = Int32() - mpv_get_property(mpvHandle, name, MPV_FORMAT_FLAG, &value) - return value > 0 - } - - func getIntProperty(_ name: String) -> Int { - if mpvHandle == nil { return 0 } - var value = Int64() - mpv_get_property(mpvHandle, name, MPV_FORMAT_INT64, &value) - return Int(value) - } - - func getStringProperty(_ name: String) -> String? { - guard let mpv = mpvHandle else { return nil } - guard let value = mpv_get_property_string(mpv, name) else { return nil } - let str = String(cString: value) - mpv_free(value) - return str - } - - func deinitRender() { + func uninit() { mpv_render_context_set_update_callback(mpvRenderContext, nil, nil) mp_render_context_set_control_callback(mpvRenderContext, nil, nil) - deinitLock.lock() + uninitLock.lock() mpv_render_context_free(mpvRenderContext) mpvRenderContext = nil - deinitLock.unlock() - } - - func deinitMPV(_ destroy: Bool = false) { - if destroy { - mpv_destroy(mpvHandle) - } - ta_free(macOptsPtr) - macOptsPtr = nil - mpvHandle = nil - } - - // *(char **) MPV_FORMAT_STRING on mpv_event_property - class func mpvStringArrayToString(_ obj: UnsafeMutableRawPointer) -> String? { - let cstr = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>(OpaquePointer(obj)) - return String(cString: cstr[0]) - } - - // MPV_FORMAT_FLAG - class func mpvFlagToBool(_ obj: UnsafeMutableRawPointer) -> Bool? { - return UnsafePointer<Bool>(OpaquePointer(obj))?.pointee + mpv_destroy(mpv) + mpv = nil + uninitLock.unlock() } } diff --git a/osdep/macos/precise_timer.swift b/osdep/mac/precise_timer.swift index f4ad3bb..d4837f9 100644 --- a/osdep/macos/precise_timer.swift +++ b/osdep/mac/precise_timer.swift @@ -24,7 +24,6 @@ struct Timing { class PreciseTimer { unowned var common: Common - var mpv: MPVHelper? { get { return common.mpv } } let nanoPerSecond: Double = 1e+9 let machToNano: Double = { @@ -59,9 +58,9 @@ class PreciseTimer { init?(common com: Common) { common = com - pthread_create(&thread, &threadAttr, entryC, MPVHelper.bridge(obj: self)) + pthread_create(&thread, &threadAttr, entryC, TypeHelper.bridge(obj: self)) if thread == nil { - common.log.sendWarning("Couldn't create pthread for high precision timer") + common.log.warning("Couldn't create pthread for high precision timer") return nil } @@ -85,7 +84,7 @@ class PreciseTimer { isHighPrecision = success == KERN_SUCCESS if !isHighPrecision { - common.log.sendWarning("Couldn't create a high precision timer") + common.log.warning("Couldn't create a high precision timer") } } @@ -119,7 +118,7 @@ class PreciseTimer { let threadSignal: @convention(c) (Int32) -> () = { (sig: Int32) in } let entryC: @convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? = { (ptr: UnsafeMutableRawPointer) in - let ptimer: PreciseTimer = MPVHelper.bridge(ptr: ptr) + let ptimer: PreciseTimer = TypeHelper.bridge(ptr: ptr) ptimer.entry() return nil } diff --git a/osdep/macos/swift_compat.swift b/osdep/mac/swift_compat.swift index 83059da..83059da 100644 --- a/osdep/macos/swift_compat.swift +++ b/osdep/mac/swift_compat.swift diff --git a/osdep/macos/log_helper.swift b/osdep/macos/log_helper.swift deleted file mode 100644 index 9464075..0000000 --- a/osdep/macos/log_helper.swift +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -import Cocoa - -class LogHelper: NSObject { - var log: OpaquePointer? - - init(_ log: OpaquePointer?) { - self.log = log - } - - func sendVerbose(_ msg: String) { - send(message: msg, type: MSGL_V) - } - - func sendInfo(_ msg: String) { - send(message: msg, type: MSGL_INFO) - } - - func sendWarning(_ msg: String) { - send(message: msg, type: MSGL_WARN) - } - - func sendError(_ msg: String) { - send(message: msg, type: MSGL_ERR) - } - - func send(message msg: String, type t: Int) { - let args: [CVarArg] = [ (msg as NSString).utf8String ?? "NO MESSAGE"] - mp_msg_va(log, Int32(t), "%s\n", getVaList(args)) - } -} diff --git a/osdep/macos/mpv_helper.swift b/osdep/macos/mpv_helper.swift deleted file mode 100644 index 3b2a716..0000000 --- a/osdep/macos/mpv_helper.swift +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -import Cocoa - -typealias swift_wakeup_cb_fn = (@convention(c) (UnsafeMutableRawPointer?) -> Void)? - -class MPVHelper { - var log: LogHelper - var vo: UnsafeMutablePointer<vo> - var optsCachePtr: UnsafeMutablePointer<m_config_cache> - var optsPtr: UnsafeMutablePointer<mp_vo_opts> - var macOptsCachePtr: UnsafeMutablePointer<m_config_cache> - var macOptsPtr: UnsafeMutablePointer<macos_opts> - - // these computed properties return a local copy of the struct accessed: - // - don't use if you rely on the pointers - // - only for reading - var vout: vo { get { return vo.pointee } } - var optsCache: m_config_cache { get { return optsCachePtr.pointee } } - var opts: mp_vo_opts { get { return optsPtr.pointee } } - var macOptsCache: m_config_cache { get { return macOptsCachePtr.pointee } } - var macOpts: macos_opts { get { return macOptsPtr.pointee } } - - var input: OpaquePointer { get { return vout.input_ctx } } - - init(_ vo: UnsafeMutablePointer<vo>, _ log: LogHelper) { - self.vo = vo - self.log = log - - guard let app = NSApp as? Application, - let cache = m_config_cache_alloc(vo, vo.pointee.global, app.getVoSubConf()) else - { - log.sendError("NSApp couldn't be retrieved") - exit(1) - } - - optsCachePtr = cache - optsPtr = UnsafeMutablePointer<mp_vo_opts>(OpaquePointer(cache.pointee.opts)) - - guard let macCache = m_config_cache_alloc(vo, - vo.pointee.global, - app.getMacOSConf()) else - { - // will never be hit, mp_get_config_group asserts for invalid groups - exit(1) - } - macOptsCachePtr = macCache - macOptsPtr = UnsafeMutablePointer<macos_opts>(OpaquePointer(macCache.pointee.opts)) - } - - func canBeDraggedAt(_ pos: NSPoint) -> Bool { - let canDrag = !mp_input_test_dragging(input, Int32(pos.x), Int32(pos.y)) - return canDrag - } - - func mouseEnabled() -> Bool { - return mp_input_mouse_enabled(input) - } - - func setMousePosition(_ pos: NSPoint) { - mp_input_set_mouse_pos(input, Int32(pos.x), Int32(pos.y)) - } - - func putAxis(_ mpkey: Int32, delta: Double) { - mp_input_put_wheel(input, mpkey, delta) - } - - func nextChangedOption(property: inout UnsafeMutableRawPointer?) -> Bool { - return m_config_cache_get_next_changed(optsCachePtr, &property) - } - - func setOption(fullscreen: Bool) { - optsPtr.pointee.fullscreen = fullscreen - _ = withUnsafeMutableBytes(of: &optsPtr.pointee.fullscreen) { (ptr: UnsafeMutableRawBufferPointer) in - m_config_cache_write_opt(optsCachePtr, ptr.baseAddress) - } - } - - func setOption(minimized: Bool) { - optsPtr.pointee.window_minimized = minimized - _ = withUnsafeMutableBytes(of: &optsPtr.pointee.window_minimized) { (ptr: UnsafeMutableRawBufferPointer) in - m_config_cache_write_opt(optsCachePtr, ptr.baseAddress) - } - } - - func setOption(maximized: Bool) { - optsPtr.pointee.window_maximized = maximized - _ = withUnsafeMutableBytes(of: &optsPtr.pointee.window_maximized) { (ptr: UnsafeMutableRawBufferPointer) in - m_config_cache_write_opt(optsCachePtr, ptr.baseAddress) - } - } - - func setMacOptionCallback(_ callback: swift_wakeup_cb_fn, context object: AnyObject) { - m_config_cache_set_wakeup_cb(macOptsCachePtr, callback, MPVHelper.bridge(obj: object)) - } - - func nextChangedMacOption(property: inout UnsafeMutableRawPointer?) -> Bool { - return m_config_cache_get_next_changed(macOptsCachePtr, &property) - } - - func command(_ cmd: String) { - let cCmd = UnsafePointer<Int8>(strdup(cmd)) - let mpvCmd = mp_input_parse_cmd(input, bstr0(cCmd), "") - mp_input_queue_cmd(input, mpvCmd) - free(UnsafeMutablePointer(mutating: cCmd)) - } - - // (__bridge void*) - class func bridge<T: AnyObject>(obj: T) -> UnsafeMutableRawPointer { - return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque()) - } - - // (__bridge T*) - class func bridge<T: AnyObject>(ptr: UnsafeRawPointer) -> T { - return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue() - } - - class func withUnsafeMutableRawPointers(_ arguments: [Any], - pointers: [UnsafeMutableRawPointer?] = [], - closure: (_ pointers: [UnsafeMutableRawPointer?]) -> Void) { - if arguments.count > 0 { - let args = Array(arguments.dropFirst(1)) - var newPtrs = pointers - var firstArg = arguments.first - withUnsafeMutableBytes(of: &firstArg) { (ptr: UnsafeMutableRawBufferPointer) in - newPtrs.append(ptr.baseAddress) - withUnsafeMutableRawPointers(args, pointers: newPtrs, closure: closure) - } - - return - } - - closure(pointers) - } - - class func getPointer<T>(_ value: inout T) -> UnsafeMutableRawPointer? { - return withUnsafeMutableBytes(of: &value) { (ptr: UnsafeMutableRawBufferPointer) in - ptr.baseAddress - } - } -} diff --git a/osdep/macos/remote_command_center.swift b/osdep/macos/remote_command_center.swift deleted file mode 100644 index 6fb2229..0000000 --- a/osdep/macos/remote_command_center.swift +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -import MediaPlayer - -class RemoteCommandCenter: NSObject { - enum KeyType { - case normal - case repeatable - } - - var config: [MPRemoteCommand:[String:Any]] = [ - MPRemoteCommandCenter.shared().pauseCommand: [ - "mpKey": MP_KEY_PAUSEONLY, - "keyType": KeyType.normal - ], - MPRemoteCommandCenter.shared().playCommand: [ - "mpKey": MP_KEY_PLAYONLY, - "keyType": KeyType.normal - ], - MPRemoteCommandCenter.shared().stopCommand: [ - "mpKey": MP_KEY_STOP, - "keyType": KeyType.normal - ], - MPRemoteCommandCenter.shared().nextTrackCommand: [ - "mpKey": MP_KEY_NEXT, - "keyType": KeyType.normal - ], - MPRemoteCommandCenter.shared().previousTrackCommand: [ - "mpKey": MP_KEY_PREV, - "keyType": KeyType.normal - ], - MPRemoteCommandCenter.shared().togglePlayPauseCommand: [ - "mpKey": MP_KEY_PLAY, - "keyType": KeyType.normal - ], - MPRemoteCommandCenter.shared().seekForwardCommand: [ - "mpKey": MP_KEY_FORWARD, - "keyType": KeyType.repeatable, - "state": MP_KEY_STATE_UP - ], - MPRemoteCommandCenter.shared().seekBackwardCommand: [ - "mpKey": MP_KEY_REWIND, - "keyType": KeyType.repeatable, - "state": MP_KEY_STATE_UP - ], - ] - - var nowPlayingInfo: [String: Any] = [ - MPNowPlayingInfoPropertyMediaType: NSNumber(value: MPNowPlayingInfoMediaType.video.rawValue), - MPNowPlayingInfoPropertyDefaultPlaybackRate: NSNumber(value: 1), - MPNowPlayingInfoPropertyPlaybackProgress: NSNumber(value: 0.0), - MPMediaItemPropertyPlaybackDuration: NSNumber(value: 0), - MPMediaItemPropertyTitle: "mpv", - MPMediaItemPropertyAlbumTitle: "mpv", - MPMediaItemPropertyArtist: "mpv", - ] - - let disabledCommands: [MPRemoteCommand] = [ - MPRemoteCommandCenter.shared().changePlaybackRateCommand, - MPRemoteCommandCenter.shared().changeRepeatModeCommand, - MPRemoteCommandCenter.shared().changeShuffleModeCommand, - MPRemoteCommandCenter.shared().skipForwardCommand, - MPRemoteCommandCenter.shared().skipBackwardCommand, - MPRemoteCommandCenter.shared().changePlaybackPositionCommand, - MPRemoteCommandCenter.shared().enableLanguageOptionCommand, - MPRemoteCommandCenter.shared().disableLanguageOptionCommand, - MPRemoteCommandCenter.shared().ratingCommand, - MPRemoteCommandCenter.shared().likeCommand, - MPRemoteCommandCenter.shared().dislikeCommand, - MPRemoteCommandCenter.shared().bookmarkCommand, - ] - - var mpInfoCenter: MPNowPlayingInfoCenter { get { return MPNowPlayingInfoCenter.default() } } - var isPaused: Bool = false { didSet { updatePlaybackState() } } - - @objc override init() { - super.init() - - for cmd in disabledCommands { - cmd.isEnabled = false - } - } - - @objc func start() { - for (cmd, _) in config { - cmd.isEnabled = true - cmd.addTarget { [unowned self] event in - return self.cmdHandler(event) - } - } - - if let app = NSApp as? Application, let icon = app.getMPVIcon() { - let albumArt = MPMediaItemArtwork(boundsSize: icon.size) { _ in - return icon - } - nowPlayingInfo[MPMediaItemPropertyArtwork] = albumArt - } - - mpInfoCenter.nowPlayingInfo = nowPlayingInfo - mpInfoCenter.playbackState = .playing - - NotificationCenter.default.addObserver( - self, - selector: #selector(self.makeCurrent), - name: NSApplication.willBecomeActiveNotification, - object: nil - ) - } - - @objc func stop() { - for (cmd, _) in config { - cmd.isEnabled = false - cmd.removeTarget(nil) - } - - mpInfoCenter.nowPlayingInfo = nil - mpInfoCenter.playbackState = .unknown - } - - @objc func makeCurrent(notification: NSNotification) { - mpInfoCenter.playbackState = .paused - mpInfoCenter.playbackState = .playing - updatePlaybackState() - } - - func updatePlaybackState() { - mpInfoCenter.playbackState = isPaused ? .paused : .playing - } - - func cmdHandler(_ event: MPRemoteCommandEvent) -> MPRemoteCommandHandlerStatus { - guard let cmdConfig = config[event.command], - let mpKey = cmdConfig["mpKey"] as? Int32, - let keyType = cmdConfig["keyType"] as? KeyType else - { - return .commandFailed - } - - var state = cmdConfig["state"] as? UInt32 ?? 0 - - if let currentState = cmdConfig["state"] as? UInt32, keyType == .repeatable { - state = MP_KEY_STATE_DOWN - config[event.command]?["state"] = MP_KEY_STATE_DOWN - if currentState == MP_KEY_STATE_DOWN { - state = MP_KEY_STATE_UP - config[event.command]?["state"] = MP_KEY_STATE_UP - } - } - - EventsResponder.sharedInstance().handleMPKey(mpKey, withMask: Int32(state)) - - return .success - } - - @objc func processEvent(_ event: UnsafeMutablePointer<mpv_event>) { - switch event.pointee.event_id { - case MPV_EVENT_PROPERTY_CHANGE: - handlePropertyChange(event) - default: - break - } - } - - func handlePropertyChange(_ event: UnsafeMutablePointer<mpv_event>) { - let pData = OpaquePointer(event.pointee.data) - guard let property = UnsafePointer<mpv_event_property>(pData)?.pointee else { - return - } - - switch String(cString: property.name) { - case "pause" where property.format == MPV_FORMAT_FLAG: - isPaused = LibmpvHelper.mpvFlagToBool(property.data) ?? false - default: - break - } - } -} diff --git a/osdep/macos/swift_extensions.swift b/osdep/macos/swift_extensions.swift deleted file mode 100644 index 127c568..0000000 --- a/osdep/macos/swift_extensions.swift +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -import Cocoa - -extension NSDeviceDescriptionKey { - static let screenNumber = NSDeviceDescriptionKey("NSScreenNumber") -} - -extension NSScreen { - - public var displayID: CGDirectDisplayID { - get { - return deviceDescription[.screenNumber] as? CGDirectDisplayID ?? 0 - } - } -} - -extension NSColor { - - convenience init(hex: String) { - let int = Int(hex.dropFirst(), radix: 16) ?? 0 - let alpha = CGFloat((int >> 24) & 0x000000FF)/255 - let red = CGFloat((int >> 16) & 0x000000FF)/255 - let green = CGFloat((int >> 8) & 0x000000FF)/255 - let blue = CGFloat((int) & 0x000000FF)/255 - - self.init(calibratedRed: red, green: green, blue: blue, alpha: alpha) - } -} - -extension Bool { - - init(_ int32: Int32) { - self.init(int32 != 0) - } -} - -extension Int32 { - - init(_ bool: Bool) { - self.init(bool ? 1 : 0) - } -} diff --git a/osdep/macosx_application.m b/osdep/macosx_application.m deleted file mode 100644 index 73503ad..0000000 --- a/osdep/macosx_application.m +++ /dev/null @@ -1,375 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include "config.h" -#include "mpv_talloc.h" - -#include "common/msg.h" -#include "input/input.h" -#include "player/client.h" -#include "options/m_config.h" -#include "options/options.h" - -#import "osdep/macosx_application_objc.h" -#import "osdep/macosx_events_objc.h" -#include "osdep/threads.h" -#include "osdep/main-fn.h" - -#if HAVE_MACOS_TOUCHBAR -#import "osdep/macosx_touchbar.h" -#endif -#if HAVE_MACOS_COCOA_CB -#include "osdep/macOS_swift.h" -#endif - -#define MPV_PROTOCOL @"mpv://" - -#define OPT_BASE_STRUCT struct macos_opts -const struct m_sub_options macos_conf = { - .opts = (const struct m_option[]) { - {"macos-title-bar-appearance", OPT_CHOICE(macos_title_bar_appearance, - {"auto", 0}, {"aqua", 1}, {"darkAqua", 2}, - {"vibrantLight", 3}, {"vibrantDark", 4}, - {"aquaHighContrast", 5}, {"darkAquaHighContrast", 6}, - {"vibrantLightHighContrast", 7}, - {"vibrantDarkHighContrast", 8})}, - {"macos-title-bar-material", OPT_CHOICE(macos_title_bar_material, - {"titlebar", 0}, {"selection", 1}, {"menu", 2}, - {"popover", 3}, {"sidebar", 4}, {"headerView", 5}, - {"sheet", 6}, {"windowBackground", 7}, {"hudWindow", 8}, - {"fullScreen", 9}, {"toolTip", 10}, {"contentBackground", 11}, - {"underWindowBackground", 12}, {"underPageBackground", 13}, - {"dark", 14}, {"light", 15}, {"mediumLight", 16}, - {"ultraDark", 17})}, - {"macos-title-bar-color", OPT_COLOR(macos_title_bar_color)}, - {"macos-fs-animation-duration", - OPT_CHOICE(macos_fs_animation_duration, {"default", -1}), - M_RANGE(0, 1000)}, - {"macos-force-dedicated-gpu", OPT_BOOL(macos_force_dedicated_gpu)}, - {"macos-app-activation-policy", OPT_CHOICE(macos_app_activation_policy, - {"regular", 0}, {"accessory", 1}, {"prohibited", 2})}, - {"macos-geometry-calculation", OPT_CHOICE(macos_geometry_calculation, - {"visible", FRAME_VISIBLE}, {"whole", FRAME_WHOLE})}, - {"macos-render-timer", OPT_CHOICE(macos_render_timer, - {"callback", RENDER_TIMER_CALLBACK}, {"precise", RENDER_TIMER_PRECISE}, - {"system", RENDER_TIMER_SYSTEM})}, - {"cocoa-cb-sw-renderer", OPT_CHOICE(cocoa_cb_sw_renderer, - {"auto", -1}, {"no", 0}, {"yes", 1})}, - {"cocoa-cb-10bit-context", OPT_BOOL(cocoa_cb_10bit_context)}, - {0} - }, - .size = sizeof(struct macos_opts), - .defaults = &(const struct macos_opts){ - .macos_title_bar_color = {0, 0, 0, 0}, - .macos_fs_animation_duration = -1, - .cocoa_cb_sw_renderer = -1, - .cocoa_cb_10bit_context = true - }, -}; - -// Whether the NSApplication singleton was created. If this is false, we are -// running in libmpv mode, and cocoa_main() was never called. -static bool application_instantiated; - -static mp_thread playback_thread_id; - -@interface Application () -{ - EventsResponder *_eventsResponder; -} - -@end - -static Application *mpv_shared_app(void) -{ - return (Application *)[Application sharedApplication]; -} - -static void terminate_cocoa_application(void) -{ - dispatch_async(dispatch_get_main_queue(), ^{ - [NSApp hide:NSApp]; - [NSApp terminate:NSApp]; - }); -} - -@implementation Application -@synthesize menuBar = _menu_bar; -@synthesize openCount = _open_count; -@synthesize cocoaCB = _cocoa_cb; - -- (void)sendEvent:(NSEvent *)event -{ - if ([self modalWindow] || ![_eventsResponder processKeyEvent:event]) - [super sendEvent:event]; - [_eventsResponder wakeup]; -} - -- (id)init -{ - if (self = [super init]) { - _eventsResponder = [EventsResponder sharedInstance]; - - NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager]; - [em setEventHandler:self - andSelector:@selector(getUrl:withReplyEvent:) - forEventClass:kInternetEventClass - andEventID:kAEGetURL]; - } - - return self; -} - -- (void)dealloc -{ - NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager]; - [em removeEventHandlerForEventClass:kInternetEventClass - andEventID:kAEGetURL]; - [em removeEventHandlerForEventClass:kCoreEventClass - andEventID:kAEQuitApplication]; - [super dealloc]; -} - -static const char macosx_icon[] = -#include "TOOLS/osxbundle/icon.icns.inc" -; - -- (NSImage *)getMPVIcon -{ - // The C string contains a trailing null, so we strip it away - NSData *icon_data = [NSData dataWithBytesNoCopy:(void *)macosx_icon - length:sizeof(macosx_icon) - 1 - freeWhenDone:NO]; - return [[NSImage alloc] initWithData:icon_data]; -} - -#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; -} -#endif - -- (void)processEvent:(struct mpv_event *)event -{ -#if HAVE_MACOS_TOUCHBAR - [(TouchBar *)self.touchBar processEvent:event]; -#endif - if (_cocoa_cb) { - [_cocoa_cb processEvent:event]; - } -} - -- (void)setMpvHandle:(struct mpv_handle *)ctx -{ -#if HAVE_MACOS_COCOA_CB - [NSApp setCocoaCB:[[CocoaCB alloc] init:ctx]]; -#endif -} - -- (const struct m_sub_options *)getMacOSConf -{ - return &macos_conf; -} - -- (const struct m_sub_options *)getVoSubConf -{ - return &vo_sub_opts; -} - -- (void)queueCommand:(char *)cmd -{ - [_eventsResponder queueCommand:cmd]; -} - -- (void)stopMPV:(char *)cmd -{ - if (![_eventsResponder queueCommand:cmd]) - terminate_cocoa_application(); -} - -- (void)applicationWillFinishLaunching:(NSNotification *)notification -{ - NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager]; - [em setEventHandler:self - andSelector:@selector(handleQuitEvent:withReplyEvent:) - forEventClass:kCoreEventClass - andEventID:kAEQuitApplication]; -} - -- (void)handleQuitEvent:(NSAppleEventDescriptor *)event - withReplyEvent:(NSAppleEventDescriptor *)replyEvent -{ - [self stopMPV:"quit"]; -} - -- (void)getUrl:(NSAppleEventDescriptor *)event - withReplyEvent:(NSAppleEventDescriptor *)replyEvent -{ - NSString *url = - [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; - - url = [url stringByReplacingOccurrencesOfString:MPV_PROTOCOL - withString:@"" - options:NSAnchoredSearch - range:NSMakeRange(0, [MPV_PROTOCOL length])]; - - url = [url stringByRemovingPercentEncoding]; - [_eventsResponder handleFilesArray:@[url]]; -} - -- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames -{ - if (mpv_shared_app().openCount > 0) { - mpv_shared_app().openCount--; - return; - } - [self openFiles:filenames]; -} - -- (void)openFiles:(NSArray *)filenames -{ - SEL cmpsel = @selector(localizedStandardCompare:); - NSArray *files = [filenames sortedArrayUsingSelector:cmpsel]; - [_eventsResponder handleFilesArray:files]; -} -@end - -struct playback_thread_ctx { - int *argc; - char ***argv; -}; - -static void cocoa_run_runloop(void) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [NSApp run]; - [pool drain]; -} - -static MP_THREAD_VOID playback_thread(void *ctx_obj) -{ - mp_thread_set_name("core/playback"); - @autoreleasepool { - struct playback_thread_ctx *ctx = (struct playback_thread_ctx*) ctx_obj; - int r = mpv_main(*ctx->argc, *ctx->argv); - terminate_cocoa_application(); - // normally never reached - unless the cocoa mainloop hasn't started yet - exit(r); - } -} - -void cocoa_register_menu_item_action(MPMenuKey key, void* action) -{ - if (application_instantiated) - [[NSApp menuBar] registerSelector:(SEL)action forKey:key]; -} - -static void init_cocoa_application(bool regular) -{ - NSApp = mpv_shared_app(); - [NSApp setDelegate:NSApp]; - [NSApp setMenuBar:[[MenuBar alloc] init]]; - - // Will be set to Regular from cocoa_common during UI creation so that we - // don't create an icon when playing audio only files. - [NSApp setActivationPolicy: regular ? - NSApplicationActivationPolicyRegular : - NSApplicationActivationPolicyAccessory]; - - atexit_b(^{ - // Because activation policy has just been set to behave like a real - // application, that policy must be reset on exit to prevent, among - // other things, the menubar created here from remaining on screen. - dispatch_async(dispatch_get_main_queue(), ^{ - [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited]; - }); - }); -} - -static bool bundle_started_from_finder() -{ - NSString* bundle = [[[NSProcessInfo processInfo] environment] objectForKey:@"MPVBUNDLE"]; - return [bundle isEqual:@"true"]; -} - -static bool is_psn_argument(char *arg_to_check) -{ - NSString *arg = [NSString stringWithUTF8String:arg_to_check]; - return [arg hasPrefix:@"-psn_"]; -} - -static void setup_bundle(int *argc, char *argv[]) -{ - if (*argc > 1 && is_psn_argument(argv[1])) { - *argc = 1; - argv[1] = NULL; - } - - NSDictionary *env = [[NSProcessInfo processInfo] environment]; - NSString *path_bundle = [env objectForKey:@"PATH"]; - NSString *path_new = [NSString stringWithFormat:@"%@:%@:%@:%@:%@", - path_bundle, - @"/usr/local/bin", - @"/usr/local/sbin", - @"/opt/local/bin", - @"/opt/local/sbin"]; - setenv("PATH", [path_new UTF8String], 1); -} - -int cocoa_main(int argc, char *argv[]) -{ - @autoreleasepool { - application_instantiated = true; - [[EventsResponder sharedInstance] setIsApplication:YES]; - - struct playback_thread_ctx ctx = {0}; - ctx.argc = &argc; - ctx.argv = &argv; - - if (bundle_started_from_finder()) { - setup_bundle(&argc, argv); - init_cocoa_application(true); - } else { - for (int i = 1; i < argc; i++) - if (argv[i][0] != '-') - mpv_shared_app().openCount++; - init_cocoa_application(false); - } - - mp_thread_create(&playback_thread_id, playback_thread, &ctx); - [[EventsResponder sharedInstance] waitForInputContext]; - cocoa_run_runloop(); - - // This should never be reached: cocoa_run_runloop blocks until the - // process is quit - fprintf(stderr, "There was either a problem " - "initializing Cocoa or the Runloop was stopped unexpectedly. " - "Please report this issues to a developer.\n"); - mp_thread_join(playback_thread_id); - return 1; - } -} diff --git a/osdep/macosx_application_objc.h b/osdep/macosx_application_objc.h deleted file mode 100644 index 11959a8..0000000 --- a/osdep/macosx_application_objc.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#import <Cocoa/Cocoa.h> -#include "osdep/macosx_application.h" -#import "osdep/macosx_menubar_objc.h" - -@class CocoaCB; -struct mpv_event; -struct mpv_handle; - -@interface Application : NSApplication - -- (NSImage *)getMPVIcon; -- (void)processEvent:(struct mpv_event *)event; -- (void)queueCommand:(char *)cmd; -- (void)stopMPV:(char *)cmd; -- (void)openFiles:(NSArray *)filenames; -- (void)setMpvHandle:(struct mpv_handle *)ctx; -- (const struct m_sub_options *)getMacOSConf; -- (const struct m_sub_options *)getVoSubConf; - -@property(nonatomic, retain) MenuBar *menuBar; -@property(nonatomic, assign) size_t openCount; -@property(nonatomic, retain) CocoaCB *cocoaCB; -@end diff --git a/osdep/macosx_events.h b/osdep/macosx_events.h deleted file mode 100644 index 9188c8b..0000000 --- a/osdep/macosx_events.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Cocoa Application Event Handling - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef MACOSX_EVENTS_H -#define MACOSX_EVENTS_H -#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); - -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 diff --git a/osdep/macosx_events.m b/osdep/macosx_events.m deleted file mode 100644 index 627077a..0000000 --- a/osdep/macosx_events.m +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Cocoa Application Event Handling - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -// Carbon header is included but Carbon is NOT linked to mpv's binary. This -// file only needs this include to use the keycode definitions in keymap. -#import <Carbon/Carbon.h> - -// Media keys definitions -#import <IOKit/hidsystem/ev_keymap.h> -#import <Cocoa/Cocoa.h> - -#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" - -#import "osdep/macosx_events_objc.h" -#import "osdep/macosx_application_objc.h" - -#include "config.h" - -#if HAVE_MACOS_COCOA_CB -#include "osdep/macOS_swift.h" -#endif - -@interface EventsResponder () -{ - struct input_ctx *_inputContext; - struct mpv_handle *_ctx; - BOOL _is_application; - NSCondition *_input_lock; -} - -- (NSEvent *)handleKey:(NSEvent *)event; -- (BOOL)setMpvHandle:(struct mpv_handle *)ctx; -- (void)readEvents; -- (void)startMediaKeys; -- (void)stopMediaKeys; -- (int)mapKeyModifiers:(int)cocoaModifiers; -- (int)keyModifierMask:(NSEvent *)event; -@end - - -#define NSLeftAlternateKeyMask (0x000020 | NSEventModifierFlagOption) -#define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption) - -static bool LeftAltPressed(int mask) -{ - return (mask & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask; -} - -static bool RightAltPressed(int mask) -{ - return (mask & NSRightAlternateKeyMask) == NSRightAlternateKeyMask; -} - -static const struct mp_keymap keymap[] = { - // special keys - {kVK_Return, MP_KEY_ENTER}, {kVK_Escape, MP_KEY_ESC}, - {kVK_Delete, MP_KEY_BACKSPACE}, {kVK_Option, MP_KEY_BACKSPACE}, - {kVK_Control, MP_KEY_BACKSPACE}, {kVK_Shift, MP_KEY_BACKSPACE}, - {kVK_Tab, MP_KEY_TAB}, - - // cursor keys - {kVK_UpArrow, MP_KEY_UP}, {kVK_DownArrow, MP_KEY_DOWN}, - {kVK_LeftArrow, MP_KEY_LEFT}, {kVK_RightArrow, MP_KEY_RIGHT}, - - // navigation block - {kVK_Help, MP_KEY_INSERT}, {kVK_ForwardDelete, MP_KEY_DELETE}, - {kVK_Home, MP_KEY_HOME}, {kVK_End, MP_KEY_END}, - {kVK_PageUp, MP_KEY_PAGE_UP}, {kVK_PageDown, MP_KEY_PAGE_DOWN}, - - // F-keys - {kVK_F1, MP_KEY_F + 1}, {kVK_F2, MP_KEY_F + 2}, {kVK_F3, MP_KEY_F + 3}, - {kVK_F4, MP_KEY_F + 4}, {kVK_F5, MP_KEY_F + 5}, {kVK_F6, MP_KEY_F + 6}, - {kVK_F7, MP_KEY_F + 7}, {kVK_F8, MP_KEY_F + 8}, {kVK_F9, MP_KEY_F + 9}, - {kVK_F10, MP_KEY_F + 10}, {kVK_F11, MP_KEY_F + 11}, {kVK_F12, MP_KEY_F + 12}, - {kVK_F13, MP_KEY_F + 13}, {kVK_F14, MP_KEY_F + 14}, {kVK_F15, MP_KEY_F + 15}, - {kVK_F16, MP_KEY_F + 16}, {kVK_F17, MP_KEY_F + 17}, {kVK_F18, MP_KEY_F + 18}, - {kVK_F19, MP_KEY_F + 19}, {kVK_F20, MP_KEY_F + 20}, - - // numpad - {kVK_ANSI_KeypadPlus, '+'}, {kVK_ANSI_KeypadMinus, '-'}, - {kVK_ANSI_KeypadMultiply, '*'}, {kVK_ANSI_KeypadDivide, '/'}, - {kVK_ANSI_KeypadEnter, MP_KEY_KPENTER}, - {kVK_ANSI_KeypadDecimal, MP_KEY_KPDEC}, - {kVK_ANSI_Keypad0, MP_KEY_KP0}, {kVK_ANSI_Keypad1, MP_KEY_KP1}, - {kVK_ANSI_Keypad2, MP_KEY_KP2}, {kVK_ANSI_Keypad3, MP_KEY_KP3}, - {kVK_ANSI_Keypad4, MP_KEY_KP4}, {kVK_ANSI_Keypad5, MP_KEY_KP5}, - {kVK_ANSI_Keypad6, MP_KEY_KP6}, {kVK_ANSI_Keypad7, MP_KEY_KP7}, - {kVK_ANSI_Keypad8, MP_KEY_KP8}, {kVK_ANSI_Keypad9, MP_KEY_KP9}, - - {0, 0} -}; - -static int convert_key(unsigned key, unsigned charcode) -{ - int mpkey = lookup_keymap_table(keymap, key); - if (mpkey) - return mpkey; - return charcode; -} - -void cocoa_init_media_keys(void) -{ - [[EventsResponder sharedInstance] startMediaKeys]; -} - -void cocoa_uninit_media_keys(void) -{ - [[EventsResponder sharedInstance] stopMediaKeys]; -} - -void cocoa_put_key(int keycode) -{ - [[EventsResponder sharedInstance] putKey:keycode]; -} - -void cocoa_put_key_with_modifiers(int keycode, int modifiers) -{ - keycode |= [[EventsResponder sharedInstance] mapKeyModifiers:modifiers]; - cocoa_put_key(keycode); -} - -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) -{ - if ([[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 - -@synthesize remoteCommandCenter = _remoteCommandCenter; - -+ (EventsResponder *)sharedInstance -{ - static EventsResponder *responder = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - responder = [EventsResponder new]; - }); - return responder; -} - -- (id)init -{ - self = [super init]; - if (self) { - _input_lock = [NSCondition new]; - } - return self; -} - -- (void)waitForInputContext -{ - [_input_lock lock]; - while (!_inputContext) - [_input_lock wait]; - [_input_lock unlock]; -} - -- (void)setInputContext:(struct input_ctx *)ctx -{ - [_input_lock lock]; - _inputContext = ctx; - [_input_lock signal]; - [_input_lock unlock]; -} - -- (void)wakeup -{ - [_input_lock lock]; - if (_inputContext) - mp_input_wakeup(_inputContext); - [_input_lock unlock]; -} - -- (bool)queueCommand:(char *)cmd -{ - bool r = false; - [_input_lock lock]; - if (_inputContext) { - mp_cmd_t *cmdt = mp_input_parse_cmd(_inputContext, bstr0(cmd), ""); - mp_input_queue_cmd(_inputContext, cmdt); - r = true; - } - [_input_lock unlock]; - return r; -} - -- (void)putKey:(int)keycode -{ - [_input_lock lock]; - if (_inputContext) - mp_input_put_key(_inputContext, keycode); - [_input_lock unlock]; -} - -- (BOOL)useAltGr -{ - BOOL r = YES; - [_input_lock lock]; - if (_inputContext) - r = mp_input_use_alt_gr(_inputContext); - [_input_lock unlock]; - return r; -} - -- (void)setIsApplication:(BOOL)isApplication -{ - _is_application = isApplication; -} - -- (BOOL)setMpvHandle:(struct mpv_handle *)ctx -{ - if (_is_application) { - dispatch_sync(dispatch_get_main_queue(), ^{ - _ctx = ctx; - [NSApp setMpvHandle:ctx]; - }); - return YES; - } else { - mpv_destroy(ctx); - return NO; - } -} - -- (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 -{ - if(_is_application) { - [NSApp processEvent:event]; - } - - if (_remoteCommandCenter) { - [_remoteCommandCenter processEvent:event]; - } - - switch (event->event_id) { - case MPV_EVENT_SHUTDOWN: { -#if HAVE_MACOS_COCOA_CB - if ([(Application *)NSApp cocoaCB].isShuttingDown) { - _ctx = nil; - return; - } -#endif - mpv_destroy(_ctx); - _ctx = nil; - break; - } - } -} - -- (void)startMediaKeys -{ -#if HAVE_MACOS_MEDIA_PLAYER - if (_remoteCommandCenter == nil) { - _remoteCommandCenter = [[RemoteCommandCenter alloc] init]; - } -#endif - - [_remoteCommandCenter start]; -} - -- (void)stopMediaKeys -{ - [_remoteCommandCenter stop]; -} - -- (int)mapKeyModifiers:(int)cocoaModifiers -{ - int mask = 0; - if (cocoaModifiers & NSEventModifierFlagShift) - mask |= MP_KEY_MODIFIER_SHIFT; - if (cocoaModifiers & NSEventModifierFlagControl) - mask |= MP_KEY_MODIFIER_CTRL; - if (LeftAltPressed(cocoaModifiers) || - (RightAltPressed(cocoaModifiers) && ![self useAltGr])) - mask |= MP_KEY_MODIFIER_ALT; - if (cocoaModifiers & NSEventModifierFlagCommand) - mask |= MP_KEY_MODIFIER_META; - return mask; -} - -- (int)mapTypeModifiers:(NSEventType)type -{ - NSDictionary *map = @{ - @(NSEventTypeKeyDown) : @(MP_KEY_STATE_DOWN), - @(NSEventTypeKeyUp) : @(MP_KEY_STATE_UP), - }; - return [map[@(type)] intValue]; -} - -- (int)keyModifierMask:(NSEvent *)event -{ - return [self mapKeyModifiers:[event modifierFlags]] | - [self mapTypeModifiers:[event type]]; -} - --(BOOL)handleMPKey:(int)key withMask:(int)mask -{ - if (key > 0) { - cocoa_put_key(key | mask); - if (mask & MP_KEY_STATE_UP) - cocoa_put_key(MP_INPUT_RELEASE_ALL); - return YES; - } else { - return NO; - } -} - -- (NSEvent*)handleKey:(NSEvent *)event -{ - if ([event isARepeat]) return nil; - - NSString *chars; - - if ([self useAltGr] && RightAltPressed([event modifierFlags])) { - chars = [event characters]; - } else { - chars = [event charactersIgnoringModifiers]; - } - - struct bstr t = bstr0([chars UTF8String]); - int key = convert_key([event keyCode], bstr_decode_utf8(t, &t)); - - if (key > -1) - [self handleMPKey:key withMask:[self keyModifierMask:event]]; - - return nil; -} - -- (bool)processKeyEvent:(NSEvent *)event -{ - if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp){ - if (![[NSApp mainMenu] performKeyEquivalent:event]) - [self handleKey:event]; - return true; - } - return false; -} - -- (void)handleFilesArray:(NSArray *)files -{ - enum mp_dnd_action action = [NSEvent modifierFlags] & - NSEventModifierFlagShift ? DND_APPEND : DND_REPLACE; - - size_t num_files = [files count]; - char **files_utf8 = talloc_array(NULL, char*, num_files); - [files enumerateObjectsUsingBlock:^(NSString *p, NSUInteger i, BOOL *_){ - if ([p hasPrefix:@"file:///.file/id="]) - p = [[NSURL URLWithString:p] path]; - char *filename = (char *)[p UTF8String]; - size_t bytes = [p lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - files_utf8[i] = talloc_memdup(files_utf8, filename, bytes + 1); - }]; - [_input_lock lock]; - if (_inputContext) - mp_event_drop_files(_inputContext, num_files, files_utf8, action); - [_input_lock unlock]; - talloc_free(files_utf8); -} - -@end diff --git a/osdep/macosx_events_objc.h b/osdep/macosx_events_objc.h deleted file mode 100644 index 9394fe7..0000000 --- a/osdep/macosx_events_objc.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Cocoa Application Event Handling - * - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#import <Cocoa/Cocoa.h> -#include "osdep/macosx_events.h" - -@class RemoteCommandCenter; -struct input_ctx; - -@interface EventsResponder : NSObject - -+ (EventsResponder *)sharedInstance; -- (void)setInputContext:(struct input_ctx *)ctx; -- (void)setIsApplication:(BOOL)isApplication; - -/// Blocks until inputContext is present. -- (void)waitForInputContext; -- (void)wakeup; -- (void)putKey:(int)keycode; -- (void)handleFilesArray:(NSArray *)files; - -- (bool)queueCommand:(char *)cmd; -- (bool)processKeyEvent:(NSEvent *)event; - -- (BOOL)handleMPKey:(int)key withMask:(int)mask; - -@property(nonatomic, retain) RemoteCommandCenter *remoteCommandCenter; - -@end diff --git a/osdep/macosx_menubar.m b/osdep/macosx_menubar.m deleted file mode 100644 index 5c6cd47..0000000 --- a/osdep/macosx_menubar.m +++ /dev/null @@ -1,853 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with mpv. If not, see <http://www.gnu.org/licenses/>. - */ - -#include "config.h" -#include "common/common.h" - -#import "macosx_menubar_objc.h" -#import "osdep/macosx_application_objc.h" - -@implementation MenuBar -{ - NSArray *menuTree; -} - -- (id)init -{ - if (self = [super init]) { - NSUserDefaults *userDefaults =[NSUserDefaults standardUserDefaults]; - [userDefaults setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"]; - [userDefaults setBool:YES forKey:@"NSDisabledDictationMenuItem"]; - [userDefaults setBool:YES forKey:@"NSDisabledCharacterPaletteMenuItem"]; - [NSWindow setAllowsAutomaticWindowTabbing: NO]; - - menuTree = @[ - @{ - @"name": @"Apple", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"About mpv", - @"action" : @"about", - @"key" : @"", - @"target" : self - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Preferences…", - @"action" : @"preferences:", - @"key" : @",", - @"target" : self, - @"file" : @"mpv.conf", - @"alertTitle1": @"No Application found to open your config file.", - @"alertText1" : @"Please open the mpv.conf file with " - "your preferred text editor in the now " - "open folder to edit your config.", - @"alertTitle2": @"No config file found.", - @"alertText2" : @"Please create a mpv.conf file with your " - "preferred text editor in the now open folder.", - @"alertTitle3": @"No config path or file found.", - @"alertText3" : @"Please create the following path ~/.config/mpv/ " - "and a mpv.conf file within with your preferred " - "text editor." - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Keyboard Shortcuts Config…", - @"action" : @"preferences:", - @"key" : @"", - @"target" : self, - @"file" : @"input.conf", - @"alertTitle1": @"No Application found to open your config file.", - @"alertText1" : @"Please open the input.conf file with " - "your preferred text editor in the now " - "open folder to edit your config.", - @"alertTitle2": @"No config file found.", - @"alertText2" : @"Please create a input.conf file with your " - "preferred text editor in the now open folder.", - @"alertTitle3": @"No config path or file found.", - @"alertText3" : @"Please create the following path ~/.config/mpv/ " - "and a input.conf file within with your preferred " - "text editor." - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Services", - @"key" : @"", - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Hide mpv", - @"action" : @"hide:", - @"key" : @"h", - @"target" : NSApp - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Hide Others", - @"action" : @"hideOtherApplications:", - @"key" : @"h", - @"modifiers" : [NSNumber numberWithUnsignedInteger: - NSEventModifierFlagCommand | - NSEventModifierFlagOption], - @"target" : NSApp - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Show All", - @"action" : @"unhideAllApplications:", - @"key" : @"", - @"target" : NSApp - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Quit and Remember Position", - @"action" : @"quit:", - @"key" : @"", - @"target" : self, - @"cmd" : @"quit-watch-later" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Quit mpv", - @"action" : @"quit:", - @"key" : @"q", - @"target" : self, - @"cmd" : @"quit" - }] - ] - }, - @{ - @"name": @"File", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Open File…", - @"action" : @"openFile", - @"key" : @"o", - @"target" : self - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Open URL…", - @"action" : @"openURL", - @"key" : @"O", - @"target" : self - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Open Playlist…", - @"action" : @"openPlaylist", - @"key" : @"", - @"target" : self - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Close", - @"action" : @"performClose:", - @"key" : @"w" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Save Screenshot", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"async screenshot" - }] - ] - }, - @{ - @"name": @"Edit", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Undo", - @"action" : @"undo:", - @"key" : @"z" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Redo", - @"action" : @"redo:", - @"key" : @"Z" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Cut", - @"action" : @"cut:", - @"key" : @"x" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Copy", - @"action" : @"copy:", - @"key" : @"c" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Paste", - @"action" : @"paste:", - @"key" : @"v" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Select All", - @"action" : @"selectAll:", - @"key" : @"a" - }] - ] - }, - @{ - @"name": @"View", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Fullscreen", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle fullscreen" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Float on Top", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle ontop" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Visibility on All Workspaces", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle on-all-workspaces" - }], -#if HAVE_MACOS_TOUCHBAR - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Customize Touch Bar…", - @"action" : @"toggleTouchBarCustomizationPalette:", - @"key" : @"", - @"target" : NSApp - }] -#endif - ] - }, - @{ - @"name": @"Video", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Zoom Out", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add panscan -0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Zoom In", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add panscan 0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Reset Zoom", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set panscan 0" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Aspect Ratio 4:3", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set video-aspect-override \"4:3\"" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Aspect Ratio 16:9", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set video-aspect-override \"16:9\"" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Aspect Ratio 1.85:1", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set video-aspect-override \"1.85:1\"" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Aspect Ratio 2.35:1", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set video-aspect-override \"2.35:1\"" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Reset Aspect Ratio", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set video-aspect-override \"-1\"" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Rotate Left", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle-values video-rotate 0 270 180 90" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Rotate Right", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle-values video-rotate 90 180 270 0" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Reset Rotation", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set video-rotate 0" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Half Size", - @"key" : @"0", - @"cmdSpecial" : [NSNumber numberWithInt:MPM_H_SIZE] - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Normal Size", - @"key" : @"1", - @"cmdSpecial" : [NSNumber numberWithInt:MPM_N_SIZE] - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Double Size", - @"key" : @"2", - @"cmdSpecial" : [NSNumber numberWithInt:MPM_D_SIZE] - }] - ] - }, - @{ - @"name": @"Audio", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Next Audio Track", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle audio" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Previous Audio Track", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle audio down" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Mute", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle mute" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Play Audio Later", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add audio-delay 0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Play Audio Earlier", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add audio-delay -0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Reset Audio Delay", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set audio-delay 0.0 " - }] - ] - }, - @{ - @"name": @"Subtitle", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Next Subtitle Track", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle sub" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Previous Subtitle Track", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle sub down" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Force Style", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle-values sub-ass-override \"force\" \"no\"" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Display Subtitles Later", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add sub-delay 0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Display Subtitles Earlier", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add sub-delay -0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Reset Subtitle Delay", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set sub-delay 0.0" - }] - ] - }, - @{ - @"name": @"Playback", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Pause", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle pause" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Increase Speed", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add speed 0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Decrease Speed", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add speed -0.1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Reset Speed", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"set speed 1.0" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Show Playlist", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"script-message osc-playlist" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Show Chapters", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"script-message osc-chapterlist" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Show Tracks", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"script-message osc-tracklist" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Next File", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"playlist-next" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Previous File", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"playlist-prev" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Loop File", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle-values loop-file \"inf\" \"no\"" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Toggle Loop Playlist", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"cycle-values loop-playlist \"inf\" \"no\"" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Shuffle", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"playlist-shuffle" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Next Chapter", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add chapter 1" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Previous Chapter", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"add chapter -1" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Step Forward", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"frame-step" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Step Backward", - @"action" : @"cmd:", - @"key" : @"", - @"target" : self, - @"cmd" : @"frame-back-step" - }] - ] - }, - @{ - @"name": @"Window", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Minimize", - @"key" : @"m", - @"cmdSpecial" : [NSNumber numberWithInt:MPM_MINIMIZE] - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Zoom", - @"key" : @"z", - @"cmdSpecial" : [NSNumber numberWithInt:MPM_ZOOM] - }] - ] - }, - @{ - @"name": @"Help", - @"menu": @[ - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"mpv Website…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://mpv.io" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"mpv on github…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://github.com/mpv-player/mpv" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Online Manual…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://mpv.io/manual/master/" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Online Wiki…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://github.com/mpv-player/mpv/wiki" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Release Notes…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://github.com/mpv-player/mpv/blob/master/RELEASE_NOTES" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Keyboard Shortcuts…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://github.com/mpv-player/mpv/blob/master/etc/input.conf" - }], - @{ @"name": @"separator" }, - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Report Issue…", - @"action" : @"url:", - @"key" : @"", - @"target" : self, - @"url" : @"https://github.com/mpv-player/mpv/issues/new/choose" - }], - [NSMutableDictionary dictionaryWithDictionary:@{ - @"name" : @"Show log File…", - @"action" : @"showFile:", - @"key" : @"", - @"target" : self, - @"file" : @"~/Library/Logs/mpv.log", - @"alertTitle" : @"No log File found.", - @"alertText" : @"You deactivated logging for the Bundle." - }] - ] - } - ]; - - [NSApp setMainMenu:[self mainMenu]]; - } - - return self; -} - -- (NSMenu *)mainMenu -{ - NSMenu *mainMenu = [[NSMenu alloc] initWithTitle:@"MainMenu"]; - [NSApp setServicesMenu:[[NSMenu alloc] init]]; - NSString* bundle = [[[NSProcessInfo processInfo] environment] objectForKey:@"MPVBUNDLE"]; - - for(id mMenu in menuTree) { - NSMenu *menu = [[NSMenu alloc] initWithTitle:mMenu[@"name"]]; - NSMenuItem *mItem = [mainMenu addItemWithTitle:mMenu[@"name"] - action:nil - keyEquivalent:@""]; - [mainMenu setSubmenu:menu forItem:mItem]; - - for(id subMenu in mMenu[@"menu"]) { - NSString *name = subMenu[@"name"]; - NSString *action = subMenu[@"action"]; - -#if HAVE_MACOS_TOUCHBAR - if ([action isEqual:@"toggleTouchBarCustomizationPalette:"]) { - continue; - } -#endif - - if ([name isEqual:@"Show log File…"] && ![bundle isEqual:@"true"]) { - continue; - } - - if ([name isEqual:@"separator"]) { - [menu addItem:[NSMenuItem separatorItem]]; - } else { - NSMenuItem *iItem = [menu addItemWithTitle:name - action:NSSelectorFromString(action) - keyEquivalent:subMenu[@"key"]]; - [iItem setTarget:subMenu[@"target"]]; - [subMenu setObject:iItem forKey:@"menuItem"]; - - NSNumber *m = subMenu[@"modifiers"]; - if (m) { - [iItem setKeyEquivalentModifierMask:m.unsignedIntegerValue]; - } - - if ([subMenu[@"name"] isEqual:@"Services"]) { - iItem.submenu = [NSApp servicesMenu]; - } - } - } - } - - return mainMenu; -} - -- (void)about -{ - NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: - @"mpv", @"ApplicationName", - [(Application *)NSApp getMPVIcon], @"ApplicationIcon", - [NSString stringWithUTF8String:mpv_copyright], @"Copyright", - [NSString stringWithUTF8String:mpv_version], @"ApplicationVersion", - nil]; - [NSApp orderFrontStandardAboutPanelWithOptions:options]; -} - -- (void)preferences:(NSMenuItem *)menuItem -{ - NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSMutableDictionary *mItemDict = [self getDictFromMenuItem:menuItem]; - NSArray *configPaths = @[ - [NSString stringWithFormat:@"%@/.mpv/", NSHomeDirectory()], - [NSString stringWithFormat:@"%@/.config/mpv/", NSHomeDirectory()]]; - - for (id path in configPaths) { - NSString *fileP = [path stringByAppendingString:mItemDict[@"file"]]; - if ([fileManager fileExistsAtPath:fileP]){ - if ([workspace openFile:fileP]) - return; - [workspace openFile:path]; - [self alertWithTitle:mItemDict[@"alertTitle1"] - andText:mItemDict[@"alertText1"]]; - return; - } - if ([workspace openFile:path]) { - [self alertWithTitle:mItemDict[@"alertTitle2"] - andText:mItemDict[@"alertText2"]]; - return; - } - } - - [self alertWithTitle:mItemDict[@"alertTitle3"] - andText:mItemDict[@"alertText3"]]; -} - -- (void)quit:(NSMenuItem *)menuItem -{ - NSString *cmd = [self getDictFromMenuItem:menuItem][@"cmd"]; - [(Application *)NSApp stopMPV:(char *)[cmd UTF8String]]; -} - -- (void)openFile -{ - NSOpenPanel *panel = [[NSOpenPanel alloc] init]; - [panel setCanChooseDirectories:YES]; - [panel setAllowsMultipleSelection:YES]; - - if ([panel runModal] == NSModalResponseOK){ - NSMutableArray *fileArray = [[NSMutableArray alloc] init]; - for (id url in [panel URLs]) - [fileArray addObject:[url path]]; - [(Application *)NSApp openFiles:fileArray]; - } -} - -- (void)openPlaylist -{ - NSOpenPanel *panel = [[NSOpenPanel alloc] init]; - - if ([panel runModal] == NSModalResponseOK){ - NSString *pl = [NSString stringWithFormat:@"loadlist \"%@\"", - [panel URLs][0].path]; - [(Application *)NSApp queueCommand:(char *)[pl UTF8String]]; - } -} - -- (void)openURL -{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"Open URL"]; - [alert addButtonWithTitle:@"Ok"]; - [alert addButtonWithTitle:@"Cancel"]; - [alert setIcon:[(Application *)NSApp getMPVIcon]]; - - NSTextField *input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 24)]; - [input setPlaceholderString:@"URL"]; - [alert setAccessoryView:input]; - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [input becomeFirstResponder]; - }); - - if ([alert runModal] == NSAlertFirstButtonReturn && [input stringValue].length > 0) { - NSArray *url = [NSArray arrayWithObjects:[input stringValue], nil]; - [(Application *)NSApp openFiles:url]; - } -} - -- (void)cmd:(NSMenuItem *)menuItem -{ - NSString *cmd = [self getDictFromMenuItem:menuItem][@"cmd"]; - [(Application *)NSApp queueCommand:(char *)[cmd UTF8String]]; -} - -- (void)url:(NSMenuItem *)menuItem -{ - NSString *url = [self getDictFromMenuItem:menuItem][@"url"]; - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]]; -} - -- (void)showFile:(NSMenuItem *)menuItem -{ - NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSMutableDictionary *mItemDict = [self getDictFromMenuItem:menuItem]; - NSString *file = [mItemDict[@"file"] stringByExpandingTildeInPath]; - - if ([fileManager fileExistsAtPath:file]){ - NSURL *url = [NSURL fileURLWithPath:file]; - NSArray *urlArray = [NSArray arrayWithObjects:url, nil]; - - [workspace activateFileViewerSelectingURLs:urlArray]; - return; - } - - [self alertWithTitle:mItemDict[@"alertTitle"] - andText:mItemDict[@"alertText"]]; -} - -- (void)alertWithTitle:(NSString *)title andText:(NSString *)text -{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:title]; - [alert setInformativeText:text]; - [alert addButtonWithTitle:@"Ok"]; - [alert setIcon:[(Application *)NSApp getMPVIcon]]; - [alert runModal]; -} - -- (NSMutableDictionary *)getDictFromMenuItem:(NSMenuItem *)menuItem -{ - for(id mMenu in menuTree) { - for(id subMenu in mMenu[@"menu"]) { - if([subMenu[@"menuItem"] isEqual:menuItem]) - return subMenu; - } - } - - return nil; -} - -- (void)registerSelector:(SEL)action forKey:(MPMenuKey)key -{ - for(id mMenu in menuTree) { - for(id subMenu in mMenu[@"menu"]) { - if([subMenu[@"cmdSpecial"] isEqual:[NSNumber numberWithInt:key]]) { - [subMenu[@"menuItem"] setAction:action]; - return; - } - } - } -} - -@end diff --git a/osdep/macosx_touchbar.h b/osdep/macosx_touchbar.h deleted file mode 100644 index a03b68c..0000000 --- a/osdep/macosx_touchbar.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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; -@property(nonatomic, assign) int pause; - -@end diff --git a/osdep/macosx_touchbar.m b/osdep/macosx_touchbar.m deleted file mode 100644 index ccce8f7..0000000 --- a/osdep/macosx_touchbar.m +++ /dev/null @@ -1,334 +0,0 @@ -/* - * This file is part of mpv. - * - * mpv is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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; -@synthesize pause = _pause; - -- (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" - }] - }; - - [self addObserver:self forKeyPath:@"visible" options:0 context:nil]; - } - return self; -} - -- (nullable NSTouchBarItem *)touchBar:(NSTouchBar *)touchBar - makeItemForIdentifier:(NSTouchBarItemIdentifier)identifier -{ - if ([self.touchbarItems[identifier][@"type"] isEqualToString:@"slider"]) { - NSCustomTouchBarItem *tbItem = [[NSCustomTouchBarItem alloc] initWithIdentifier:identifier]; - NSSlider *slider = [NSSlider sliderWithTarget:self action:@selector(seekbarChanged:)]; - slider.minValue = 0.0f; - slider.maxValue = 100.0f; - tbItem.view = slider; - tbItem.customizationLabel = self.touchbarItems[identifier][@"name"]; - [self.touchbarItems[identifier] setObject:slider forKey:@"view"]; - [self.touchbarItems[identifier] setObject:tbItem forKey:@"tbItem"]; - [tbItem addObserver:self forKeyPath:@"visible" options:0 context:nil]; - 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"]; - [self.touchbarItems[identifier] setObject:tbItem forKey:@"tbItem"]; - [tbItem addObserver:self forKeyPath:@"visible" options:0 context:nil]; - 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"]; - [self.touchbarItems[identifier] setObject:tbItem forKey:@"tbItem"]; - [tbItem addObserver:self forKeyPath:@"visible" options:0 context:nil]; - return tbItem; - } - - return nil; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary<NSKeyValueChangeKey,id> *)change - context:(void *)context { - if ([keyPath isEqualToString:@"visible"]) { - NSNumber *visible = [object valueForKey:@"visible"]; - if (visible.boolValue) { - [self updateTouchBarTimeItems]; - [self updatePlayButton]; - } - } -} - -- (void)updateTouchBarTimeItems -{ - if (!self.isVisible) - return; - - [self updateSlider]; - [self updateTimeLeft]; - [self updateCurrentPosition]; -} - -- (void)updateSlider -{ - NSCustomTouchBarItem *tbItem = self.touchbarItems[seekBar][@"tbItem"]; - if (!tbItem.visible) - return; - - NSSlider *seekSlider = self.touchbarItems[seekBar][@"view"]; - - if (self.duration <= 0) { - seekSlider.enabled = NO; - seekSlider.doubleValue = 0; - } else { - seekSlider.enabled = YES; - if (!seekSlider.highlighted) - seekSlider.doubleValue = (self.position/self.duration)*100; - } -} - -- (void)updateTimeLeft -{ - NSCustomTouchBarItem *tbItem = self.touchbarItems[timeLeft][@"tbItem"]; - if (!tbItem.visible) - return; - - NSTextField *timeLeftItem = self.touchbarItems[timeLeft][@"view"]; - - [self removeConstraintForIdentifier:timeLeft]; - if (self.duration <= 0) { - timeLeftItem.stringValue = @""; - } else { - int left = (int)(floor(self.duration)-floor(self.position)); - NSString *leftFormat = [self formatTime:left]; - NSString *durFormat = [self formatTime:self.duration]; - timeLeftItem.stringValue = [NSString stringWithFormat:@"-%@", leftFormat]; - [self applyConstraintFromString:[NSString stringWithFormat:@"-%@", durFormat] - forIdentifier:timeLeft]; - } -} - -- (void)updateCurrentPosition -{ - NSCustomTouchBarItem *tbItem = self.touchbarItems[currentPosition][@"tbItem"]; - if (!tbItem.visible) - return; - - NSTextField *curPosItem = self.touchbarItems[currentPosition][@"view"]; - NSString *posFormat = [self formatTime:(int)floor(self.position)]; - curPosItem.stringValue = posFormat; - - [self removeConstraintForIdentifier:currentPosition]; - if (self.duration <= 0) { - [self applyConstraintFromString:[self formatTime:self.position] - forIdentifier:currentPosition]; - } else { - NSString *durFormat = [self formatTime:self.duration]; - [self applyConstraintFromString:durFormat forIdentifier:currentPosition]; - } -} - -- (void)updatePlayButton -{ - NSCustomTouchBarItem *tbItem = self.touchbarItems[play][@"tbItem"]; - if (!self.isVisible || !tbItem.visible) - return; - - NSButton *playButton = self.touchbarItems[play][@"view"]; - if (self.pause) { - playButton.image = self.touchbarItems[play][@"imageAlt"]; - } else { - playButton.image = self.touchbarItems[play][@"image"]; - } -} - -- (void)buttonAction:(NSButton *)sender -{ - NSString *identifier = [self getIdentifierFromView:sender]; - [self.app queueCommand:(char *)[self.touchbarItems[identifier][@"cmd"] UTF8String]]; -} - -- (void)seekbarChanged:(NSSlider *)slider -{ - NSString *identifier = [self getIdentifierFromView:slider]; - NSString *seek = [NSString stringWithFormat: - self.touchbarItems[identifier][@"cmd"], slider.doubleValue]; - [self.app queueCommand:(char *)[seek UTF8String]]; -} - -- (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"]; - } -} - -- (NSString *)getIdentifierFromView:(id)view -{ - NSString *identifier; - for (identifier in self.touchbarItems) - if([self.touchbarItems[identifier][@"view"] isEqual:view]) - break; - return identifier; -} - -- (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) { - double newPosition = *(double *)property->data; - newPosition = newPosition < 0 ? 0 : newPosition; - if ((int)(floor(newPosition) - floor(self.position)) != 0) { - self.position = newPosition; - [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) { - self.pause = *(int *)property->data; - [self updatePlayButton]; - } -} - -@end diff --git a/osdep/macosx_menubar.h b/video/out/win32/menu.h index 509083d..8b1fe72 100644 --- a/osdep/macosx_menubar.h +++ b/video/out/win32/menu.h @@ -15,16 +15,18 @@ * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef MPV_MACOSX_MENU -#define MPV_MACOSX_MENU +#ifndef MP_WIN32_MENU_H +#define MP_WIN32_MENU_H -// Menu Keys identifying menu items -typedef enum { - MPM_H_SIZE, - MPM_N_SIZE, - MPM_D_SIZE, - MPM_MINIMIZE, - MPM_ZOOM, -} MPMenuKey; +#include <windows.h> -#endif /* MPV_MACOSX_MENU */ +struct mpv_node; +struct menu_ctx; + +struct menu_ctx *mp_win32_menu_init(void); +void mp_win32_menu_uninit(struct menu_ctx *ctx); +void mp_win32_menu_show(struct menu_ctx *ctx, HWND hwnd); +void mp_win32_menu_update(struct menu_ctx *ctx, struct mpv_node *data); +const char* mp_win32_menu_get_cmd(struct menu_ctx *ctx, UINT id); + +#endif |