Skip to content

Commit

Permalink
Support displaying more precise time and duration in the OSC
Browse files Browse the repository at this point in the history
  • Loading branch information
lhc70000 committed Aug 25, 2020
1 parent 5db5e49 commit 4e3226d
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 37 deletions.
3 changes: 2 additions & 1 deletion iina/AppData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import Cocoa
struct AppData {

/** time interval to sync play pos */
static let getTimeInterval: Double = 0.1
static let syncTimeInterval: Double = 0.1
static let syncTimePreciseInterval: Double = 0.04

/** speed values when clicking left / right arrow button */

Expand Down
5 changes: 5 additions & 0 deletions iina/Base.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
// MainWindowController.swift
"main.buffering_indicator" = "Buffering… %d%%";
"main.opening_stream" = "Opening stream…";
"osc.precision" = "Precision";
"osc.1s" = "1 second";
"osc.100ms" = "100 milliseconds";
"osc.10ms" = "10 milliseconds";
"osc.1ms" = "1 millisecond";

// QuickSettingViewController.swift
"quicksetting.item_default" = "Default";
Expand Down
25 changes: 13 additions & 12 deletions iina/Base.lproj/MiniPlayerWindowController.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.2"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
Expand Down Expand Up @@ -48,7 +48,7 @@
<windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="300" height="72"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="900"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<value key="minSize" type="size" width="300" height="72"/>
<view key="contentView" id="se5-gp-TjO">
<rect key="frame" x="0.0" y="0.0" width="300" height="72"/>
Expand All @@ -74,10 +74,10 @@
<visualEffectView wantsLayer="YES" blendingMode="behindWindow" material="underWindowBackground" state="active" translatesAutoresizingMaskIntoConstraints="NO" id="HdA-I9-dRJ">
<rect key="frame" x="0.0" y="0.0" width="300" height="72"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xAK-xc-Njn" customClass="DurationDisplayTextField" customModule="IINA" customModuleProvider="target">
<textField horizontalHuggingPriority="249" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="xAK-xc-Njn" customClass="DurationDisplayTextField" customModule="IINA" customModuleProvider="target">
<rect key="frame" x="260" y="9" width="36" height="11"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="Dnz-rF-ikZ"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="32" id="Dnz-rF-ikZ"/>
</constraints>
<textFieldCell key="cell" controlSize="mini" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="-:--:--" id="V74-PQ-Yfr">
<font key="font" metaFont="label" size="9"/>
Expand All @@ -88,10 +88,10 @@
<binding destination="-2" name="font" keyPath="monospacedFont" id="TM3-Ri-L7h"/>
</connections>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9EY-2T-Ebf" customClass="DurationDisplayTextField" customModule="IINA" customModuleProvider="target">
<textField horizontalHuggingPriority="249" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9EY-2T-Ebf" customClass="DurationDisplayTextField" customModule="IINA" customModuleProvider="target">
<rect key="frame" x="4" y="9" width="36" height="11"/>
<constraints>
<constraint firstAttribute="width" constant="32" id="1iE-QR-s8H"/>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="32" id="1iE-QR-s8H"/>
</constraints>
<textFieldCell key="cell" controlSize="mini" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="right" title="-:--:--" id="WnA-NE-3bG">
<font key="font" metaFont="label" size="9"/>
Expand Down Expand Up @@ -123,7 +123,7 @@
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="kcj-EY-i9R" customClass="ScrollingTextField" customModule="IINA" customModuleProvider="target">
<rect key="frame" x="109" y="8" width="82" height="14"/>
<textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Artist - Album" id="Nle-gv-CWY">
<font key="font" metaFont="menu" size="11"/>
<font key="font" metaFont="message" size="11"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
Expand Down Expand Up @@ -250,16 +250,17 @@
<constraint firstItem="Zv7-H8-iOq" firstAttribute="leading" secondItem="HdA-I9-dRJ" secondAttribute="leading" id="0RG-9U-PfH"/>
<constraint firstItem="e3M-Ma-JJM" firstAttribute="top" secondItem="HdA-I9-dRJ" secondAttribute="top" constant="50" id="9qE-pN-912"/>
<constraint firstItem="9EY-2T-Ebf" firstAttribute="leading" secondItem="HdA-I9-dRJ" secondAttribute="leading" constant="6" id="CDO-gT-VfY"/>
<constraint firstItem="e3M-Ma-JJM" firstAttribute="leading" secondItem="HdA-I9-dRJ" secondAttribute="leading" constant="44" id="FqJ-tE-vz0"/>
<constraint firstItem="9EY-2T-Ebf" firstAttribute="centerY" secondItem="e3M-Ma-JJM" secondAttribute="centerY" id="HEK-U3-nXU"/>
<constraint firstItem="xAK-xc-Njn" firstAttribute="centerY" secondItem="e3M-Ma-JJM" secondAttribute="centerY" id="IxN-QB-clc"/>
<constraint firstItem="e3M-Ma-JJM" firstAttribute="leading" secondItem="9EY-2T-Ebf" secondAttribute="trailing" constant="6" id="Kq9-D1-FXY"/>
<constraint firstAttribute="trailing" secondItem="xAK-xc-Njn" secondAttribute="trailing" constant="6" id="KxC-bd-MIe"/>
<constraint firstAttribute="height" constant="72" id="Nfm-Ob-h4c"/>
<constraint firstItem="9EY-2T-Ebf" firstAttribute="width" secondItem="xAK-xc-Njn" secondAttribute="width" id="UYG-wX-fNd"/>
<constraint firstItem="cDR-8J-QI7" firstAttribute="leading" secondItem="HdA-I9-dRJ" secondAttribute="leading" id="VVS-g3-XqO"/>
<constraint firstItem="cDR-8J-QI7" firstAttribute="top" secondItem="HdA-I9-dRJ" secondAttribute="top" id="Ypa-JG-tiE"/>
<constraint firstAttribute="trailing" secondItem="e3M-Ma-JJM" secondAttribute="trailing" constant="44" id="ZEF-WM-2mj"/>
<constraint firstItem="Zv7-H8-iOq" firstAttribute="top" secondItem="HdA-I9-dRJ" secondAttribute="top" id="fw5-6p-eNb"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="cDR-8J-QI7" secondAttribute="bottom" constant="24" id="n2O-up-sBQ"/>
<constraint firstItem="xAK-xc-Njn" firstAttribute="leading" secondItem="e3M-Ma-JJM" secondAttribute="trailing" constant="6" id="oEQ-mY-BqT"/>
<constraint firstAttribute="trailing" secondItem="cDR-8J-QI7" secondAttribute="trailing" id="uCr-Bo-TON"/>
<constraint firstAttribute="trailing" secondItem="Zv7-H8-iOq" secondAttribute="trailing" id="vmF-Ea-a1k"/>
</constraints>
Expand Down Expand Up @@ -466,13 +467,13 @@
<resources>
<image name="NSStopProgressFreestandingTemplate" width="14" height="14"/>
<image name="back" width="11" height="11"/>
<image name="mute" width="17" height="14"/>
<image name="mute" width="16" height="14"/>
<image name="nextl" width="24" height="24"/>
<image name="nextr" width="24" height="24"/>
<image name="pause" width="24" height="24"/>
<image name="play" width="24" height="24"/>
<image name="playlist" width="14" height="14"/>
<image name="toggle-album-art" width="14" height="14"/>
<image name="volume" width="17" height="14"/>
<image name="volume" width="16" height="14"/>
</resources>
</document>
33 changes: 28 additions & 5 deletions iina/DurationDisplayTextField.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
import Foundation

class DurationDisplayTextField: NSTextField {

enum DisplayMode {
case current
case duration // displays the duration of the movie
case remaining // displays the remaining time in the movie
}

static var precision : UInt = UInt(Preference.integer(for: .timeDisplayPrecision))
var mode: DisplayMode = .duration

/** Switches the display mode between duration and remaining time */
Expand All @@ -29,20 +29,20 @@ class DurationDisplayTextField: NSTextField {
}
}


func updateText(with duration: VideoTime, given current: VideoTime) {
let precision = DurationDisplayTextField.precision
let stringValue: String
switch mode {
case .current:
stringValue = current.stringRepresentation
stringValue = current.stringRepresentationWithPrecision(precision)
case .duration:
stringValue = duration.stringRepresentation
stringValue = duration.stringRepresentationWithPrecision(precision)
case .remaining:
var remaining = (duration - current)
if remaining.second < 0 {
remaining = VideoTime.zero
}
stringValue = "-\(remaining.stringRepresentation)"
stringValue = "-\(remaining.stringRepresentationWithPrecision(precision))"
}
self.stringValue = stringValue
}
Expand All @@ -54,6 +54,19 @@ class DurationDisplayTextField: NSTextField {
Preference.set(mode == .remaining, for: .showRemainingTime)
}

override func rightMouseDown(with event: NSEvent) {
let precision = DurationDisplayTextField.precision
let menu = NSMenu(title: "Time label settings")
menu.addItem(withTitle: NSLocalizedString("osc.precision", comment: "Precision"))
["1s", "100ms", "10ms", "1ms"].enumerated().forEach { (index, key) in
menu.addItem(withTitle: NSLocalizedString("osc.\(key)", comment: ""),
action: #selector(self.setPrecision(_:)),
target: self, tag: index,
stateOn: precision == index)
}
NSMenu.popUpContextMenu(menu, with: event, for: self)
}

override func touchesBegan(with event: NSEvent) {
// handles the remaining time text field in the touch bar
super.touchesBegan(with: event)
Expand All @@ -62,4 +75,14 @@ class DurationDisplayTextField: NSTextField {
Preference.set(mode == .remaining, for: .touchbarShowRemainingTime)
}

@objc func setPrecision(_ sender: NSMenuItem) {
let precision = UInt(sender.tag)
DurationDisplayTextField.precision = precision
Preference.set(Int(precision), for: .timeDisplayPrecision)
PlayerCore.playerCores.forEach { core in
if core.syncPlayTimeTimer != nil {
core.createSyncUITimer()
}
}
}
}
14 changes: 12 additions & 2 deletions iina/PlayerCore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,7 @@ class PlayerCore: NSObject {
getPlaylist()
getChapters()
clearAbLoop()
syncPlayTimeTimer = Timer.scheduledTimer(timeInterval: TimeInterval(AppData.getTimeInterval),
target: self, selector: #selector(self.syncUITime), userInfo: nil, repeats: true)
createSyncUITimer()
if #available(macOS 10.12.2, *) {
touchBarSupport.setupTouchBarUI()
}
Expand Down Expand Up @@ -1210,6 +1209,17 @@ class PlayerCore: NSObject {

// MARK: - Sync with UI in MainWindow

func createSyncUITimer() {
invalidateTimer()
syncPlayTimeTimer = Timer.scheduledTimer(
timeInterval: TimeInterval(DurationDisplayTextField.precision >= 2 ? AppData.syncTimePreciseInterval : AppData.syncTimeInterval),
target: self,
selector: #selector(self.syncUITime),
userInfo: nil,
repeats: true
)
}

func notifyMainWindowVideoSizeChanged() {
mainWindow.adjustFrameByVideoSize()
if isInMiniPlayer {
Expand Down
2 changes: 2 additions & 0 deletions iina/Preference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ struct Preference {
static let forceTouchAction = Key("forceTouchAction")

static let showRemainingTime = Key("showRemainingTime")
static let timeDisplayPrecision = Key("timeDisplayPrecision")
static let touchbarShowRemainingTime = Key("touchbarShowRemainingTime")

static let followGlobalSeekTypeWhenAdjustSlider = Key("followGlobalSeekTypeWhenAdjustSlider")
Expand Down Expand Up @@ -701,6 +702,7 @@ struct Preference {
.resizeWindowTiming: ResizeWindowTiming.onlyWhenOpen.rawValue,
.resizeWindowOption: ResizeWindowOption.videoSize10.rawValue,
.showRemainingTime: false,
.timeDisplayPrecision: 0,
.touchbarShowRemainingTime: true,
.enableThumbnailPreview: true,
.maxThumbnailPreviewCacheSize: 500,
Expand Down
37 changes: 20 additions & 17 deletions iina/VideoTime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,36 @@ class VideoTime {
var second: Double

var h: Int {
get {
return (Int(second) / 3600)
}
Int(second) / 3600
}

var m: Int {
get {
return (Int(second) % 3600) / 60
}
(Int(second) % 3600) / 60
}

var s: Int {
get {
return (Int(second) % 3600) % 60
}
(Int(second) % 3600) % 60
}

var stringRepresentation: String {
get {
if self == Constants.Time.infinite {
return "End"
}
let ms = (m < 10 ? "0\(m)" : "\(m)")
let ss = (s < 10 ? "0\(s)" : "\(s)")
let hs = (h > 0 ? "\(h):" : "")
return "\(hs)\(ms):\(ss)"
stringRepresentationWithPrecision(0)
}

func stringRepresentationWithPrecision(_ precision: UInt) -> String {
if self == Constants.Time.infinite {
return "End"
}
let h_ = h > 0 ? "\(h):" : ""
let m_ = m < 10 ? "0\(m)" : "\(m)"
let s_: String

if precision >= 1 && precision <= 3 {
s_ = String(format: "%0\(precision + 3).\(precision)f", fmod(second, 60))
} else {
s_ = s < 10 ? "0\(s)" : "\(s)"
}

return h_ + m_ + ":" + s_
}

convenience init?(_ format: String) {
Expand Down
5 changes: 5 additions & 0 deletions iina/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
// MainWindowController.swift
"main.buffering_indicator" = "Buffering… %d%%";
"main.opening_stream" = "Opening stream…";
"osc.precision" = "Precision";
"osc.1s" = "1 second";
"osc.100ms" = "100 milliseconds";
"osc.10ms" = "10 milliseconds";
"osc.1ms" = "1 millisecond";

// QuickSettingViewController.swift
"quicksetting.item_default" = "Default";
Expand Down

0 comments on commit 4e3226d

Please sign in to comment.