Skip to content
This repository was archived by the owner on Jun 21, 2025. It is now read-only.

Commit 8a613ae

Browse files
PO - Looping, trackAtIndex
1 parent 5faa069 commit 8a613ae

15 files changed

Lines changed: 115 additions & 144 deletions

Aural.xcodeproj/project.pbxproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@
117117
3E0218602C23490E00865AC2 /* PlaylistCommandNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E02165B2C23490E00865AC2 /* PlaylistCommandNotification.swift */; };
118118
3E0218612C23490E00865AC2 /* RepeatAndShuffleModesCommandNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E02165C2C23490E00865AC2 /* RepeatAndShuffleModesCommandNotification.swift */; };
119119
3E0218622C23490E00865AC2 /* SelectSearchResultCommandNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E02165D2C23490E00865AC2 /* SelectSearchResultCommandNotification.swift */; };
120-
3E0218632C23490E00865AC2 /* TrackPlaybackCommandNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E02165E2C23490E00865AC2 /* TrackPlaybackCommandNotification.swift */; };
121120
3E0218642C23490E00865AC2 /* AppReopenedNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E0216602C23490E00865AC2 /* AppReopenedNotification.swift */; };
122121
3E0218652C23490E00865AC2 /* AudioGraphChangeNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E0216612C23490E00865AC2 /* AudioGraphChangeNotifications.swift */; };
123122
3E0218662C23490E00865AC2 /* ChapterChangedNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E0216622C23490E00865AC2 /* ChapterChangedNotification.swift */; };
@@ -1205,7 +1204,6 @@
12051204
3E02165B2C23490E00865AC2 /* PlaylistCommandNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlaylistCommandNotification.swift; sourceTree = "<group>"; };
12061205
3E02165C2C23490E00865AC2 /* RepeatAndShuffleModesCommandNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RepeatAndShuffleModesCommandNotification.swift; sourceTree = "<group>"; };
12071206
3E02165D2C23490E00865AC2 /* SelectSearchResultCommandNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectSearchResultCommandNotification.swift; sourceTree = "<group>"; };
1208-
3E02165E2C23490E00865AC2 /* TrackPlaybackCommandNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrackPlaybackCommandNotification.swift; sourceTree = "<group>"; };
12091207
3E0216602C23490E00865AC2 /* AppReopenedNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppReopenedNotification.swift; sourceTree = "<group>"; };
12101208
3E0216612C23490E00865AC2 /* AudioGraphChangeNotifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioGraphChangeNotifications.swift; sourceTree = "<group>"; };
12111209
3E0216622C23490E00865AC2 /* ChapterChangedNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChapterChangedNotification.swift; sourceTree = "<group>"; };
@@ -2628,7 +2626,6 @@
26282626
3E02165B2C23490E00865AC2 /* PlaylistCommandNotification.swift */,
26292627
3E02165C2C23490E00865AC2 /* RepeatAndShuffleModesCommandNotification.swift */,
26302628
3E02165D2C23490E00865AC2 /* SelectSearchResultCommandNotification.swift */,
2631-
3E02165E2C23490E00865AC2 /* TrackPlaybackCommandNotification.swift */,
26322629
);
26332630
path = Commands;
26342631
sourceTree = "<group>";
@@ -6699,7 +6696,6 @@
66996696
3E3D7C8F2BDAEC8000A82646 /* MenuBarFontSchemesTableViewDelegate.swift in Sources */,
67006697
3ECF71BC2B75B48E00FDB69B /* CompactPlayQueueSearchViewController.swift in Sources */,
67016698
3E02197D2C23490E00865AC2 /* AVFExtensions.swift in Sources */,
6702-
3E0218632C23490E00865AC2 /* TrackPlaybackCommandNotification.swift in Sources */,
67036699
3E24147A2DA6EE9A0098C1EF /* ReplayGainUnit+Analysis.swift in Sources */,
67046700
3E6C126225CEBE0600BF0D07 /* UIPresetsManagerWindowController.swift in Sources */,
67056701
3E8B8C362BEF59960025D60B /* LastFMPreferencesViewController.swift in Sources */,

Source/Core/Messaging/NotificationDefinitions/Commands/TrackPlaybackCommandNotification.swift

Lines changed: 0 additions & 61 deletions
This file was deleted.

Source/Core/Messaging/NotificationNames/PlayerNotifications.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,11 @@ extension Notification.Name {
6060

6161
// MARK: Playback commands (sent to the player)
6262

63-
// Commands the player to play a specific track
64-
static let playTrack = Notification.Name("player_playTrack")
65-
6663
// Commands the player to perform "autoplay"
6764
static let autoplay = Notification.Name("player_autoplay")
6865

6966
static let beginGaplessPlayback = Notification.Name("player_beginGaplessPlayback")
7067

71-
// Commands the player to toggle A ⇋ B segment playback loop
72-
static let toggleLoop = Notification.Name("player_toggleLoop")
73-
7468
// ----------------------------------------------------------------------------------------
7569

7670
// MARK: Chapter playback commands (sent to the player)

Source/Core/Orchestration/PlaybackOrchestrator+Play.swift

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ extension PlaybackOrchestrator {
4242
ui?.playbackPositionChanged(newPosition: self.playbackPosition)
4343
}
4444

45+
func playTrack(atIndex index: Int, params: PlaybackParams) {
46+
47+
if doPlay(withParams: params, trackProducer: {playQueue.select(trackAt: index)}) {
48+
49+
ui?.playingTrackChanged(newTrack: self.playingTrack)
50+
ui?.playbackStateChanged(newState: self.state)
51+
ui?.playbackPositionChanged(newPosition: self.playbackPosition)
52+
}
53+
}
54+
4555
private func pause() {
4656

4757
player.pause()
@@ -55,10 +65,12 @@ extension PlaybackOrchestrator {
5565
ui?.playbackPositionChanged(newPosition: self.playbackPosition)
5666
}
5767

58-
func resumeIfPaused() {
68+
func resumeAfterSeekIfPaused() {
5969

6070
if state == .paused {
6171
resume()
72+
} else {
73+
ui?.playbackPositionChanged(newPosition: self.playbackPosition)
6274
}
6375
}
6476

@@ -67,7 +79,7 @@ extension PlaybackOrchestrator {
6779
if state.isPlayingOrPaused {
6880

6981
player.seek(to: 0, canSeekOutsideLoop: true)
70-
resumeIfPaused()
82+
resumeAfterSeekIfPaused()
7183
}
7284

7385
return currentStateAsCommandResult
@@ -97,6 +109,12 @@ extension PlaybackOrchestrator {
97109
return currentStateAsCommandResult
98110
}
99111

112+
func toggleLoop() {
113+
114+
player.toggleLoop()
115+
ui?.playbackLoopChanged(newLoop: self.playbackLoop, newLoopState: self.playbackLoopState)
116+
}
117+
100118
// Captures the current player state and proceeds with playback according to the playback sequence
101119
private func doPlay(withParams params: PlaybackParams = .defaultParams, trackProducer: TrackProducer) -> Bool {
102120

Source/Core/Orchestration/PlaybackOrchestrator.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,12 @@ class PlaybackOrchestrator: PlaybackOrchestratorProtocol {
5656
var playingTrack: Track? {
5757
player.playingTrack
5858
}
59+
60+
var playbackLoop: PlaybackLoop? {
61+
player.playbackLoop
62+
}
63+
64+
var playbackLoopState: PlaybackLoopState {
65+
player.playbackLoopState
66+
}
5967
}

Source/Core/Orchestration/PlaybackOrchestratorProtocol.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ protocol PlaybackOrchestratorProtocol {
1414

1515
@discardableResult func togglePlayPause() -> PlaybackCommandResult
1616

17+
func playTrack(atIndex index: Int, params: PlaybackParams)
18+
1719
@discardableResult func previousTrack() -> PlaybackCommandResult
1820

1921
@discardableResult func nextTrack() -> PlaybackCommandResult
2022

23+
@discardableResult func replayTrack() -> PlaybackCommandResult
24+
2125
@discardableResult func seekTo(percentage: Double) -> PlaybackCommandResult
2226

2327
@discardableResult func seekTo(position: TimeInterval) -> PlaybackCommandResult
@@ -30,7 +34,7 @@ protocol PlaybackOrchestratorProtocol {
3034

3135
@discardableResult func seekForwardSecondary() -> PlaybackCommandResult
3236

33-
@discardableResult func replayTrack() -> PlaybackCommandResult
37+
func toggleLoop()
3438

3539
@discardableResult func stop() -> PlaybackCommandResult
3640

@@ -45,10 +49,16 @@ protocol PlaybackOrchestratorProtocol {
4549
var playbackPosition: PlaybackPosition? {get}
4650

4751
var playingTrack: Track? {get}
52+
53+
var playbackLoop: PlaybackLoop? {get}
4854
}
4955

5056
extension PlaybackOrchestratorProtocol {
5157

58+
func playTrack(atIndex index: Int) {
59+
playTrack(atIndex: index, params: .defaultParams)
60+
}
61+
5262
@discardableResult func seekBackward() -> PlaybackCommandResult {
5363
seekBackward(userInputMode: .discrete)
5464
}
@@ -67,6 +77,8 @@ protocol PlaybackUI {
6777
func playingTrackChanged(newTrack: Track?)
6878

6979
func playbackPositionChanged(newPosition: PlaybackPosition?)
80+
81+
func playbackLoopChanged(newLoop: PlaybackLoop?, newLoopState: PlaybackLoopState)
7082
}
7183

7284
struct PlaybackCommandResult {

Source/Core/Playback/PlaybackChain/StartPlaybackChain/PredictiveTrackPreparationAction.swift

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,40 +36,42 @@ class PredictiveTrackPreparationAction: PlaybackChainAction {
3636

3737
func execute(_ context: PlaybackRequestContext, _ chain: PlaybackChain) {
3838

39+
// TODO: Temporarily disabling this ... SIGBRT
40+
3941
// Perform this task async, since it is not required to complete immediately.
40-
// Since this task is not time-critical, it is okay to use the "utility" quality of service.
41-
DispatchQueue.global(qos: .utility).async {
42-
43-
// The candidates for which track might play next consist of:
44-
//
45-
// 1 - The "subsequent" track in the playback sequence, i.e. the track that would play next automatically.
46-
// 2 - The "next" track which would play if the user triggered the "Next track" function.
47-
let nillableTracksArray: [Track?] = [self.playQueue.peekSubsequent(), self.playQueue.peekNext()]
48-
49-
// Since some of the candidate tracks might be the same track (subsequent track might be the same as the next track), we need
50-
// to put them in a Set, and also eliminate nil values.
51-
let predictedNextTracks: Set<Track> = Set(nillableTracksArray.compactMap{$0}.filter {$0 != context.requestedTrack})
52-
53-
// Prepare each of the candidate tracks for playback.
54-
predictedNextTracks.forEach {
55-
try? self.trackReader.prepareForPlayback(track: $0, immediate: false)
56-
}
57-
58-
// Update the preppedTracks set and close files that no longer need to be open (i.e. not
59-
// currently playing and not predicted to play next).
60-
61-
let playingTrack: Track? = context.requestedTrack
62-
let tracksToClose: [Track] = self.preppedTracks.set.filter {$0 != playingTrack && !predictedNextTracks.contains($0)}
63-
64-
for track in tracksToClose {
65-
66-
track.playbackContext?.close()
67-
self.preppedTracks.remove(track)
68-
}
69-
70-
// Add the candidate tracks to the preppedTracks set.
71-
self.preppedTracks.performUnion(with: predictedNextTracks)
72-
}
42+
// // Since this task is not time-critical, it is okay to use the "utility" quality of service.
43+
// DispatchQueue.global(qos: .utility).async {
44+
//
45+
// // The candidates for which track might play next consist of:
46+
// //
47+
// // 1 - The "subsequent" track in the playback sequence, i.e. the track that would play next automatically.
48+
// // 2 - The "next" track which would play if the user triggered the "Next track" function.
49+
// let nillableTracksArray: [Track?] = [self.playQueue.peekSubsequent(), self.playQueue.peekNext()]
50+
//
51+
// // Since some of the candidate tracks might be the same track (subsequent track might be the same as the next track), we need
52+
// // to put them in a Set, and also eliminate nil values.
53+
// let predictedNextTracks: Set<Track> = Set(nillableTracksArray.compactMap{$0}.filter {$0 != context.requestedTrack})
54+
//
55+
// // Prepare each of the candidate tracks for playback.
56+
// predictedNextTracks.forEach {
57+
// try? self.trackReader.prepareForPlayback(track: $0, immediate: false)
58+
// }
59+
//
60+
// // Update the preppedTracks set and close files that no longer need to be open (i.e. not
61+
// // currently playing and not predicted to play next).
62+
//
63+
// let playingTrack: Track? = context.requestedTrack
64+
// let tracksToClose: [Track] = self.preppedTracks.set.filter {$0 != playingTrack && !predictedNextTracks.contains($0)}
65+
//
66+
// for track in tracksToClose {
67+
//
68+
// track.playbackContext?.close()
69+
// self.preppedTracks.remove(track)
70+
// }
71+
//
72+
// // Add the candidate tracks to the preppedTracks set.
73+
// self.preppedTracks.performUnion(with: predictedNextTracks)
74+
// }
7375

7476
chain.proceed(context)
7577
}

Source/UI/CompactPlayer/PlayQueue/Search/CompactPlayQueueSearchViewController+TableView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class CompactPlayQueueSearchResultIndexCell: AuralTableCellView {
9292

9393
func playSearchResult() {
9494

95-
Messenger.publish(TrackPlaybackCommandNotification(index: playQueueTrackIndex))
95+
playbackOrch.playTrack(atIndex: playQueueTrackIndex)
9696
Messenger.publish(.View.CompactPlayer.showPlayer)
9797
}
9898
}

Source/UI/CompactPlayer/PlayQueue/Search/CompactPlayQueueSearchViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class CompactPlayQueueSearchViewController: NSViewController {
9999
let result = searchResults?.results[resultIndex],
100100
let pqLocation = result.location as? PlayQueueSearchResultLocation {
101101

102-
messenger.publish(TrackPlaybackCommandNotification(index: pqLocation.index))
102+
playbackOrch.playTrack(atIndex: pqLocation.index)
103103
}
104104
}
105105

Source/UI/Menus/PlaybackMenuController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class PlaybackMenuController: NSObject, NSMenuDelegate {
158158

159159
// Toggles A ⇋ B playback loop
160160
@IBAction func toggleLoopAction(_ sender: AnyObject) {
161-
Messenger.publish(.Player.toggleLoop)
161+
playbackOrch.toggleLoop()
162162
}
163163

164164
// MARK: Basic playback functions (chapters)

0 commit comments

Comments
 (0)