From 81b8cbd5f170461b710b78ee365c67e33136af0a Mon Sep 17 00:00:00 2001
From: Arkadiusz Fal <arek@arekf.net>
Date: Thu, 16 Jun 2022 19:44:39 +0200
Subject: [PATCH] Add dropped frames counter

---
 Model/Player/Backends/MPVBackend.swift      | 16 +++++++++++-----
 Model/Player/Backends/MPVClient.swift       | 12 ++++++++----
 Model/Player/PlayerControlsModel.swift      |  7 ++-----
 Model/Player/PlayerModel.swift              |  8 ++++++++
 Shared/Player/Controls/PlayerControls.swift |  5 +++--
 5 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/Model/Player/Backends/MPVBackend.swift b/Model/Player/Backends/MPVBackend.swift
index ee6131d9..410f0145 100644
--- a/Model/Player/Backends/MPVBackend.swift
+++ b/Model/Player/Backends/MPVBackend.swift
@@ -6,6 +6,8 @@ import Logging
 import SwiftUI
 
 final class MPVBackend: PlayerBackend {
+    static var clientUpdatesInterval = 1.0
+
     private var logger = Logger(label: "mpv-backend")
 
     var model: PlayerModel!
@@ -66,11 +68,15 @@ final class MPVBackend: PlayerBackend {
         client?.tracksCount ?? -1
     }
 
+    var frameDropCount: Int {
+        client?.frameDropCount ?? 0
+    }
+
     init(model: PlayerModel, controls: PlayerControlsModel? = nil) {
         self.model = model
         self.controls = controls
 
-        clientTimer = .init(timeInterval: 1)
+        clientTimer = .init(timeInterval: Self.clientUpdatesInterval)
         clientTimer.eventHandler = getClientUpdates
     }
 
@@ -272,15 +278,15 @@ final class MPVBackend: PlayerBackend {
     func closePiP(wasPlaying _: Bool) {}
 
     func updateControls() {
+        guard model.presentingPlayer else {
+            return
+        }
+
         DispatchQueue.main.async { [weak self] in
             guard let self = self else {
                 return
             }
 
-            guard self.controls.player.presentingPlayer else {
-                return
-            }
-
             self.logger.info("updating controls")
             self.controls.currentTime = self.currentTime ?? .zero
             self.controls.duration = self.playerItemDuration ?? .zero
diff --git a/Model/Player/Backends/MPVClient.swift b/Model/Player/Backends/MPVClient.swift
index c350907f..52ae8609 100644
--- a/Model/Player/Backends/MPVClient.swift
+++ b/Model/Player/Backends/MPVClient.swift
@@ -141,6 +141,10 @@ final class MPVClient: ObservableObject {
         CMTime.secondsInDefaultTimescale(mpv.isNil ? -1 : getDouble("time-pos"))
     }
 
+    var frameDropCount: Int {
+        mpv.isNil ? 0 : getInt("frame-drop-count")
+    }
+
     var duration: CMTime {
         CMTime.secondsInDefaultTimescale(mpv.isNil ? -1 : getDouble("duration"))
     }
@@ -320,11 +324,11 @@ final class MPVClient: ObservableObject {
     private func glUpdate(_ ctx: UnsafeMutableRawPointer?) {
         let glView = unsafeBitCast(ctx, to: MPVOGLView.self)
 
-        guard glView.needsDrawing else {
-            return
-        }
-
         glView.queue.async {
+            guard glView.needsDrawing else {
+                return
+            }
+
             glView.display()
         }
     }
diff --git a/Model/Player/PlayerControlsModel.swift b/Model/Player/PlayerControlsModel.swift
index cd4dde07..6d2acd76 100644
--- a/Model/Player/PlayerControlsModel.swift
+++ b/Model/Player/PlayerControlsModel.swift
@@ -11,8 +11,6 @@ final class PlayerControlsModel: ObservableObject {
     @Published var timer: Timer?
     @Published var playingFullscreen = false
 
-    private var throttle = Throttle(interval: 1)
-
     var player: PlayerModel!
 
     var playbackTime: String {
@@ -62,6 +60,7 @@ final class PlayerControlsModel: ObservableObject {
             return
         }
 
+        player.backend.updateControls()
         withAnimation(PlayerControls.animation) {
             presentingControls = true
         }
@@ -147,8 +146,6 @@ final class PlayerControlsModel: ObservableObject {
     }
 
     func update() {
-        throttle.execute { [weak self] in
-            self?.player?.backend.updateControls()
-        }
+        player?.backend.updateControls()
     }
 }
diff --git a/Model/Player/PlayerModel.swift b/Model/Player/PlayerModel.swift
index 26cedcac..df9f67f5 100644
--- a/Model/Player/PlayerModel.swift
+++ b/Model/Player/PlayerModel.swift
@@ -554,6 +554,10 @@ final class PlayerModel: ObservableObject {
             Windows.player.toggleFullScreen()
         #endif
 
+        #if os(iOS)
+            setNeedsDrawing(false)
+        #endif
+
         controls.playingFullscreen = !isFullScreen
 
         #if os(iOS)
@@ -565,6 +569,10 @@ final class PlayerModel: ObservableObject {
             } else {
                 Orientation.lockOrientation(.allButUpsideDown, andRotateTo: .portrait)
             }
+
+            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
+                self?.setNeedsDrawing(true)
+            }
         #endif
     }
 
diff --git a/Shared/Player/Controls/PlayerControls.swift b/Shared/Player/Controls/PlayerControls.swift
index 207cc081..8fe10190 100644
--- a/Shared/Player/Controls/PlayerControls.swift
+++ b/Shared/Player/Controls/PlayerControls.swift
@@ -256,8 +256,9 @@ struct PlayerControls: View {
         #endif
     }
 
-    @ViewBuilder private var backendButton: some View {
-        button(player.activeBackend.label, width: 100) {
+    private var backendButton: some View {
+        let label = "\(player.activeBackend.label)\(player.activeBackend == .mpv ? " - \(player.mpvBackend.frameDropCount)" : "")"
+        return button(label, width: 120) {
             player.saveTime {
                 player.changeActiveBackend(from: player.activeBackend, to: player.activeBackend.next())
                 model.resetTimer()