2019-09-29 16:35:12 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
typealias swift_wakeup_cb_fn = (@convention(c) (UnsafeMutableRawPointer?) -> Void)?
|
|
|
|
|
2020-06-27 09:12:46 +00:00
|
|
|
class MPVHelper {
|
|
|
|
var log: LogHelper
|
2019-09-29 16:35:12 +00:00
|
|
|
var vo: UnsafeMutablePointer<vo>
|
2019-11-30 22:47:52 +00:00
|
|
|
var optsCachePtr: UnsafeMutablePointer<m_config_cache>
|
|
|
|
var optsPtr: UnsafeMutablePointer<mp_vo_opts>
|
2020-07-31 08:37:02 +00:00
|
|
|
var macOptsCachePtr: UnsafeMutablePointer<m_config_cache>
|
|
|
|
var macOptsPtr: UnsafeMutablePointer<macos_opts>
|
2019-11-30 22:47:52 +00:00
|
|
|
|
|
|
|
// these computed properties return a local copy of the struct accessed:
|
|
|
|
// - don't use if you rely on the pointers
|
|
|
|
// - only for reading
|
2019-09-29 16:35:12 +00:00
|
|
|
var vout: vo { get { return vo.pointee } }
|
2019-11-30 22:47:52 +00:00
|
|
|
var optsCache: m_config_cache { get { return optsCachePtr.pointee } }
|
|
|
|
var opts: mp_vo_opts { get { return optsPtr.pointee } }
|
2020-07-31 08:37:02 +00:00
|
|
|
var macOptsCache: m_config_cache { get { return macOptsCachePtr.pointee } }
|
|
|
|
var macOpts: macos_opts { get { return macOptsPtr.pointee } }
|
2019-11-30 22:47:52 +00:00
|
|
|
|
2019-09-29 16:35:12 +00:00
|
|
|
var input: OpaquePointer { get { return vout.input_ctx } }
|
|
|
|
|
2020-06-27 09:12:46 +00:00
|
|
|
init(_ vo: UnsafeMutablePointer<vo>, _ log: LogHelper) {
|
2019-09-29 16:35:12 +00:00
|
|
|
self.vo = vo
|
2020-06-27 09:12:46 +00:00
|
|
|
self.log = log
|
2019-11-30 22:47:52 +00:00
|
|
|
|
|
|
|
guard let app = NSApp as? Application,
|
|
|
|
let cache = m_config_cache_alloc(vo, vo.pointee.global, app.getVoSubConf()) else
|
|
|
|
{
|
2020-06-27 09:12:46 +00:00
|
|
|
log.sendError("NSApp couldn't be retrieved")
|
2019-11-30 22:47:52 +00:00
|
|
|
exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
optsCachePtr = cache
|
|
|
|
optsPtr = UnsafeMutablePointer<mp_vo_opts>(OpaquePointer(cache.pointee.opts))
|
2019-09-29 16:35:12 +00:00
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
guard let macCache = m_config_cache_alloc(vo,
|
|
|
|
vo.pointee.global,
|
|
|
|
app.getMacOSConf()) else
|
2019-09-29 16:35:12 +00:00
|
|
|
{
|
2019-11-30 22:47:52 +00:00
|
|
|
// will never be hit, mp_get_config_group asserts for invalid groups
|
2020-07-31 08:37:02 +00:00
|
|
|
exit(1)
|
2019-09-29 16:35:12 +00:00
|
|
|
}
|
2020-07-31 08:37:02 +00:00
|
|
|
macOptsCachePtr = macCache
|
|
|
|
macOptsPtr = UnsafeMutablePointer<macos_opts>(OpaquePointer(macCache.pointee.opts))
|
2019-09-29 16:35:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
func nextChangedOption(property: inout UnsafeMutableRawPointer?) -> Bool {
|
2019-11-30 22:47:52 +00:00
|
|
|
return m_config_cache_get_next_changed(optsCachePtr, &property)
|
|
|
|
}
|
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
func setOption(fullscreen: Bool) {
|
options: introduce bool option type, use it for --fullscreen
The option code is very old and was added to MPlayer in the early 2000s,
when C99 was still new. MPlayer did not use the "bool" type anywhere,l
and the logical option equivalent to bool, the "flag" option type, used
int, with the convention that only the values 0 and 1 are allowed.
mpv may have hammered many, many additional tentacles to the option
code, but some of the basics never changed, and m_option_type_flag still
uses int. This seems a bit weird, since mpv uses bool for booleans. So
finally introduce an m_option_type_bool. To avoid duplicating too much
code, change the flag code to bool, and "reimplement" m_option_type_flag
on top of m_option_type_bool.
As a "demonstration", change the --fullscreen option to this new type.
Ideally, all options would be changed too bool, and m_option_type_flag
would be removed. But that is a lot of monotonous thankless work, so I'm
not doing it, and making it a painful years long transition.
At the same time, I'm introducing a new concept for option declarations.
Instead of OPT_BOOL(), which define the full m_option struct contents,
there's OPTF_BOOL(), which only takes the option field name itself. The
name is provided via a normal struct field initializer. Other fields
(such as flags) can be provided via designated initializers.
The advantage of this is that we don't need tons of nested vararg
macros. We also don't need to deal with 0-sized varargs being a pain
(and in fact they are not a thing in standard C99 and probably C11).
There is no need to provide a mandatory flags argument either, which is
the reason why so many OPT_ macros are used with a "0" argument. (The
flag argument seems to confuse other developers; they either don't
immediately recognize what it is, and sometimes it's supposed to be the
option's default value.)
Not having to mess with the flag argument in such option macros is also
a reason for the removal of M_OPT_RANGE etc., for the better or worse.
The only place that special-cased the _flag option type was in
command.c; change it to use something effectively very similar that
automatically includes the new _bool option type. Everything else should
be transparent to the change. The fullscreen option change should be
transparent too, as C99 bool is basically an integer type that is
clamped to 0/1 (except in Swift, Swift sucks).
2020-03-14 01:07:35 +00:00
|
|
|
optsPtr.pointee.fullscreen = fullscreen
|
2020-12-20 19:05:18 +00:00
|
|
|
_ = withUnsafeMutableBytes(of: &optsPtr.pointee.fullscreen) { (ptr: UnsafeMutableRawBufferPointer) in
|
|
|
|
m_config_cache_write_opt(optsCachePtr, ptr.baseAddress)
|
|
|
|
}
|
2019-11-30 22:47:52 +00:00
|
|
|
}
|
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
func setOption(minimized: Bool) {
|
2019-11-30 22:47:52 +00:00
|
|
|
optsPtr.pointee.window_minimized = Int32(minimized)
|
2020-12-20 19:05:18 +00:00
|
|
|
_ = withUnsafeMutableBytes(of: &optsPtr.pointee.window_minimized) { (ptr: UnsafeMutableRawBufferPointer) in
|
|
|
|
m_config_cache_write_opt(optsCachePtr, ptr.baseAddress)
|
|
|
|
}
|
2019-11-30 22:47:52 +00:00
|
|
|
}
|
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
func setOption(maximized: Bool) {
|
2019-12-01 20:08:54 +00:00
|
|
|
optsPtr.pointee.window_maximized = Int32(maximized)
|
2020-12-20 19:05:18 +00:00
|
|
|
_ = withUnsafeMutableBytes(of: &optsPtr.pointee.window_maximized) { (ptr: UnsafeMutableRawBufferPointer) in
|
|
|
|
m_config_cache_write_opt(optsCachePtr, ptr.baseAddress)
|
|
|
|
}
|
2019-12-01 20:08:54 +00:00
|
|
|
}
|
|
|
|
|
2020-07-31 08:37:02 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2019-09-29 16:35:12 +00:00
|
|
|
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()
|
|
|
|
}
|
2020-12-20 19:03:12 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
2020-12-20 19:05:18 +00:00
|
|
|
|
|
|
|
class func getPointer<T>(_ value: inout T) -> UnsafeMutableRawPointer? {
|
|
|
|
return withUnsafeMutableBytes(of: &value) { (ptr: UnsafeMutableRawBufferPointer) in
|
|
|
|
ptr.baseAddress
|
|
|
|
}
|
|
|
|
}
|
2019-09-29 16:35:12 +00:00
|
|
|
}
|