Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Front Row.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
};
name = Debug;
};
Expand Down Expand Up @@ -434,7 +434,7 @@
SDKROOT = macosx;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_VERSION = 5.0;
SWIFT_VERSION = 6.0;
};
name = Release;
};
Expand Down
28 changes: 10 additions & 18 deletions Front Row/FrontRowApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,13 @@ import SwiftUI
@main
struct FrontRowApp: App {
@NSApplicationDelegateAdaptor private var appDelegate: AppDelegate
@State private var playEngine: PlayEngine
@State private var presentedViewManager: PresentedViewManager
@State private var windowController: WindowController
@State private var playEngine = PlayEngine.shared
@State private var presentedViewManager = PresentedViewManager.shared
@State private var windowController = WindowController.shared
private let updaterController: SPUStandardUpdaterController
private let keyDownListener = KeyDownListener()

init() {
self._playEngine = .init(wrappedValue: .shared)
self._presentedViewManager = .init(wrappedValue: .shared)
self._windowController = .init(wrappedValue: .shared)

updaterController = SPUStandardUpdaterController(
startingUpdater: true,
updaterDelegate: nil,
Expand All @@ -39,7 +35,6 @@ struct FrontRowApp: App {
ContentView()
.preferredColorScheme(.dark)
.ignoresSafeArea()
.environment(playEngine)
.navigationTitle(playEngine.fileURL?.lastPathComponent ?? "Front Row")
.if(playEngine.isLocalFile) { view in
view.navigationDocument(playEngine.fileURL!)
Expand Down Expand Up @@ -75,18 +70,15 @@ struct FrontRowApp: App {
}
}
.restorationBehavior(.disabled)
.environment(playEngine)
.environment(presentedViewManager)
.environment(windowController)
.commands {
AppCommands(updater: updaterController.updater)
FileCommands(playEngine: $playEngine)
ViewCommands(
playEngine: $playEngine,
windowController: $windowController)
PlaybackCommands(
playEngine: $playEngine,
presentedViewManager: $presentedViewManager)
WindowCommands(
playEngine: $playEngine,
windowController: $windowController)
FileCommands()
ViewCommands()
PlaybackCommands()
WindowCommands()
HelpCommands()
}
}
Expand Down
10 changes: 5 additions & 5 deletions Front Row/Main Menu/FileCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import AVKit
import SwiftUI

struct FileCommands: Commands {
@Binding var playEngine: PlayEngine

var body: some Commands {
CommandGroup(replacing: .newItem) {
Button {
Expand Down Expand Up @@ -38,19 +36,21 @@ struct FileCommands: Commands {
Divider()

Button {
guard let item = PlayEngine.shared.player.currentItem else { return }
guard let asset = item.asset as? AVURLAsset else { return }
guard let item = PlayEngine.shared.player.currentItem,
let asset = item.asset as? AVURLAsset
else { return }
NSWorkspace.shared.activateFileViewerSelecting([asset.url])
} label: {
Text(
"Show in Finder",
comment: "Show the currently playing file in Finder"
)
}
.disabled(!playEngine.isLocalFile)
.disabled(!PlayEngine.shared.isLocalFile)
}
}

@MainActor
private func showOpenFileDialog() async {
let panel = NSOpenPanel()
panel.allowedContentTypes = PlayEngine.supportedFileTypes
Expand Down
6 changes: 3 additions & 3 deletions Front Row/Main Menu/PlaybackCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import AVKit
import SwiftUI

struct PlaybackCommands: Commands {
@Binding var playEngine: PlayEngine
@Binding var presentedViewManager: PresentedViewManager
@Bindable private var playEngine = PlayEngine.shared
@Bindable private var presentedViewManager = PresentedViewManager.shared

var body: some Commands {
CommandMenu("Playback") {
Expand Down Expand Up @@ -151,7 +151,7 @@ struct PlaybackCommands: Commands {
if let group = playEngine.audioGroup {
Picker("Audio Track", selection: $playEngine.audioTrack) {
Text("Off").tag(nil as AVMediaSelectionOption?)
ForEach(group.options) { option in
ForEach(group.options, id: \.stableID) { option in
Text(verbatim: option.displayName).tag(Optional(option))
}
}
Expand Down
15 changes: 7 additions & 8 deletions Front Row/Main Menu/ViewCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,18 @@ import AVKit
import SwiftUI

struct ViewCommands: Commands {
@Binding var playEngine: PlayEngine
@Binding var windowController: WindowController

var body: some Commands {
CommandGroup(replacing: .toolbar) {
Button {
NSApplication.shared.mainWindow?.toggleFullScreen(nil)
} label: {
Text(windowController.isFullscreen ? "Exit Full Screen" : "Enter Full Screen")
Text(
WindowController.shared.isFullscreen
? "Exit Full Screen" : "Enter Full Screen")
}
.keyboardShortcut(.return, modifiers: [])

Toggle(isOn: $windowController.isOnTop) {
Toggle(isOn: Bindable(WindowController.shared).isOnTop) {
Text("Float on Top")
}

Expand All @@ -32,14 +31,14 @@ struct ViewCommands: Commands {
}

@ViewBuilder private var subtitlePicker: some View {
if let group = playEngine.subtitleGroup {
Picker("Subtitle", selection: $playEngine.subtitle) {
if let group = PlayEngine.shared.subtitleGroup {
Picker("Subtitle", selection: Bindable(PlayEngine.shared).subtitle) {
Text("Off").tag(nil as AVMediaSelectionOption?)

let optionsWithoutForcedSubs = group.options.filter {
!$0.displayName.contains("Forced")
}
ForEach(optionsWithoutForcedSubs) {
ForEach(optionsWithoutForcedSubs, id: \.stableID) {
option in
Text(verbatim: option.displayName).tag(Optional(option))
}
Expand Down
5 changes: 1 addition & 4 deletions Front Row/Main Menu/WindowCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
import SwiftUI

struct WindowCommands: Commands {
@Binding var playEngine: PlayEngine
@Binding var windowController: WindowController

var body: some Commands {
CommandGroup(after: .windowSize) {
Section {
Expand All @@ -23,7 +20,7 @@ struct WindowCommands: Commands {
)
}
.keyboardShortcut("0", modifiers: [.command])
.disabled(!playEngine.isLoaded || windowController.isFullscreen)
.disabled(!PlayEngine.shared.isLoaded || WindowController.shared.isFullscreen)
}
}
}
Expand Down
54 changes: 12 additions & 42 deletions Front Row/Support/Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,50 +51,19 @@ struct AnyDropDelegate: DropDelegate {
}
}

extension NSItemProvider: @unchecked Sendable {}

extension NSItemProvider {
func loadObject<T>(ofClass: T.Type) async throws -> T? where T: NSItemProviderReading {
try await withCheckedThrowingContinuation { continuation in
_ = loadObject(ofClass: ofClass) { data, error in
if let error {
continuation.resume(throwing: error)
return
}

guard let object = data as? T else {
continuation.resume(returning: nil)
return
}

continuation.resume(returning: object)
/// Load a file URL from the item provider.
func loadFileURL(completion: @escaping @Sendable (URL?) -> Void) {
loadItem(forTypeIdentifier: "public.file-url", options: nil) { data, _ in
guard let data = data as? Data,
let url = URL(dataRepresentation: data, relativeTo: nil)
else {
completion(nil)
return
}
completion(url)
}
}

func loadObject<T>(ofClass: T.Type) async throws -> T?
where T: _ObjectiveCBridgeable, T._ObjectiveCType: NSItemProviderReading {
try await withCheckedThrowingContinuation { continuation in
_ = loadObject(ofClass: ofClass) { data, error in
if let error {
continuation.resume(throwing: error)
return
}

guard let data else {
continuation.resume(returning: nil)
return
}

continuation.resume(returning: data)
}
}
}

/// Get a URL from the item provider, if any.
func getURL() async -> URL? {
try? await loadObject(ofClass: URL.self)
}
}

extension NSSize {
Expand Down Expand Up @@ -131,8 +100,9 @@ extension NSSize {
}
}

extension AVMediaSelectionOption: Identifiable {
public var id: String {
extension AVMediaSelectionOption {
/// Provides a stable identifier for the option.
var stableID: String {
let dict = propertyList() as? NSDictionary
guard let dict, let id = dict.value(forKey: "MediaSelectionOptionsPersistentID") as? Int
else {
Expand Down
25 changes: 15 additions & 10 deletions Front Row/Support/KeyDownListener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,25 @@ final class KeyDownListener {
return event
}

let allWindows = NSApp.windows
let firstResponders = allWindows.compactMap { $0.firstResponder }
let fieldEditors = firstResponders.filter { ($0 as? NSText)?.isEditable == true }
guard fieldEditors.isEmpty else { return event }

switch command {
case .escape:
if !WindowController.shared.isFullscreen {
NSApp.hide(nil)
PlayEngine.shared.pause()
return nil
let shouldHandle = MainActor.assumeIsolated {
let allWindows = NSApp.windows
let firstResponders = allWindows.compactMap { $0.firstResponder }
let fieldEditors = firstResponders.filter {
($0 as? NSText)?.isEditable == true
}
guard fieldEditors.isEmpty else { return false }

if !WindowController.shared.isFullscreen {
NSApp.hide(nil)
PlayEngine.shared.pause()
return true
}
return false
}
return shouldHandle ? nil : event
}
return event
}
}

Expand Down
2 changes: 1 addition & 1 deletion Front Row/Support/NowPlayable+RemoteCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import MediaPlayer

extension NowPlayable {
func setupRemoteCommandHandlers(playEngine: PlayEngine) {
@MainActor func setupRemoteCommandHandlers(playEngine: PlayEngine) {
let commandCenter = MPRemoteCommandCenter.shared()

commandCenter.playCommand.isEnabled = true
Expand Down
1 change: 1 addition & 0 deletions Front Row/Support/NowPlayable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct NowPlayableDynamicMetadata {
let duration: Float
}

@MainActor
final class NowPlayable {

static let shared = NowPlayable()
Expand Down
Loading