Skip to content

Commit af4f298

Browse files
authored
Merge pull request #574 from namehillsoftware/bugfix/restarting-playback-at-same-playlist-position
[Bugfix] Restarting Playback at Original Playlist Position
2 parents 8b083fa + 64a5055 commit af4f298

File tree

2 files changed

+139
-24
lines changed

2 files changed

+139
-24
lines changed

projectBlueWater/src/main/java/com/lasthopesoftware/bluewater/client/playback/engine/bootstrap/ManagedPlaylistPlayer.kt

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import com.lasthopesoftware.bluewater.client.playback.volume.PlaylistVolumeManag
1313
import com.lasthopesoftware.promises.extensions.ProgressingPromise
1414
import com.lasthopesoftware.promises.extensions.ProgressingPromiseProxy
1515
import com.lasthopesoftware.promises.extensions.keepPromise
16-
import com.lasthopesoftware.promises.extensions.toPromise
1716
import com.lasthopesoftware.resources.closables.PromisingCloseable
1817
import com.namehillsoftware.handoff.promises.Promise
1918
import org.joda.time.Duration
@@ -36,34 +35,30 @@ class ManagedPlaylistPlayer(
3635
override fun updateFromState(libraryId: LibraryId): Promise<NowPlaying?> = promisedPlayer
3736
.updateAndGet { originallyPromised ->
3837
originallyPromised
39-
.eventually { (op, player) ->
38+
.eventually { (_, player) ->
4039
nowPlayingState
4140
.promiseNowPlaying(libraryId)
4241
.eventually { np ->
43-
when {
44-
op == np -> Pair(np, player).toPromise()
45-
np == null -> {
46-
playbackQueues.reset()
42+
if (np == null) {
43+
playbackQueues.reset()
44+
player
45+
?.haltPlayback()
46+
.keepPromise()
47+
.then { _ -> Pair(null, null) }
48+
} else {
49+
with (np) {
50+
val positionedFileQueueProvider = positionedFileQueueProviders.getValue(isRepeating)
51+
val queue = positionedFileQueueProvider.provideQueue(libraryId, playlist, playlistPosition)
52+
val preparedPlaybackQueue = playbackQueues.initializePreparedPlaybackQueue(queue)
53+
4754
player
48-
?.haltPlayback()
55+
?.promiseClose()
4956
.keepPromise()
50-
.then { _ -> Pair(null, null) }
51-
}
52-
else -> {
53-
with (np) {
54-
val positionedFileQueueProvider = positionedFileQueueProviders.getValue(isRepeating)
55-
val queue = positionedFileQueueProvider.provideQueue(libraryId, playlist, playlistPosition)
56-
val preparedPlaybackQueue = playbackQueues.initializePreparedPlaybackQueue(queue)
57-
58-
player
59-
?.promiseClose()
60-
.keepPromise()
61-
.then { _ ->
62-
val newPlayer = PlaylistPlayer(preparedPlaybackQueue, Duration.millis(filePosition))
63-
volumeManagement.managePlayer(newPlayer)
64-
Pair(np, newPlayer)
65-
}
66-
}
57+
.then { _ ->
58+
val newPlayer = PlaylistPlayer(preparedPlaybackQueue, Duration.millis(filePosition))
59+
volumeManagement.managePlayer(newPlayer)
60+
Pair(np, newPlayer)
61+
}
6762
}
6863
}
6964
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package com.lasthopesoftware.bluewater.client.playback.engine.GivenAPlayingPlaybackEngine.AndTheTrackIsSkipped
2+
3+
import com.lasthopesoftware.bluewater.client.browsing.files.ServiceFile
4+
import com.lasthopesoftware.bluewater.client.browsing.library.access.FakeLibraryRepository
5+
import com.lasthopesoftware.bluewater.client.browsing.library.access.FakePlaybackQueueConfiguration
6+
import com.lasthopesoftware.bluewater.client.browsing.library.repository.Library
7+
import com.lasthopesoftware.bluewater.client.browsing.library.repository.LibraryId
8+
import com.lasthopesoftware.bluewater.client.connection.selected.GivenANullConnection.AndTheSelectedLibraryChanges.FakeSelectedLibraryProvider
9+
import com.lasthopesoftware.bluewater.client.playback.engine.PlaybackEngine
10+
import com.lasthopesoftware.bluewater.client.playback.engine.bootstrap.ManagedPlaylistPlayer
11+
import com.lasthopesoftware.bluewater.client.playback.engine.preparation.PreparedPlaybackQueueResourceManagement
12+
import com.lasthopesoftware.bluewater.client.playback.file.PositionedFile
13+
import com.lasthopesoftware.bluewater.client.playback.file.preparation.FakeMappedPlayableFilePreparationSourceProvider
14+
import com.lasthopesoftware.bluewater.client.playback.file.preparation.queues.CompletingFileQueueProvider
15+
import com.lasthopesoftware.bluewater.client.playback.nowplaying.storage.NowPlayingRepository
16+
import com.lasthopesoftware.bluewater.client.playback.volume.PlaylistVolumeManager
17+
import com.lasthopesoftware.bluewater.shared.promises.extensions.toExpiringFuture
18+
import com.namehillsoftware.handoff.promises.Promise
19+
import org.assertj.core.api.Assertions.assertThat
20+
import org.junit.jupiter.api.BeforeAll
21+
import org.junit.jupiter.api.Test
22+
23+
class `When changing the track back to the skipped track` {
24+
companion object {
25+
private const val libraryId = 434
26+
}
27+
28+
private val mut by lazy {
29+
val fakePlaybackPreparerProvider = FakeMappedPlayableFilePreparationSourceProvider(
30+
listOf(
31+
ServiceFile("1"),
32+
ServiceFile("2"),
33+
ServiceFile("3"),
34+
ServiceFile("4"),
35+
ServiceFile("5")
36+
)
37+
)
38+
val library = Library(id = libraryId)
39+
val libraryProvider = FakeLibraryRepository(library)
40+
val preparedPlaybackQueueResourceManagement =
41+
PreparedPlaybackQueueResourceManagement(fakePlaybackPreparerProvider, FakePlaybackQueueConfiguration())
42+
val repository = NowPlayingRepository(
43+
FakeSelectedLibraryProvider(),
44+
libraryProvider,
45+
)
46+
val playbackBootstrapper = ManagedPlaylistPlayer(
47+
PlaylistVolumeManager(1.0f),
48+
preparedPlaybackQueueResourceManagement,
49+
repository,
50+
listOf(CompletingFileQueueProvider()),
51+
)
52+
val playbackEngine =
53+
PlaybackEngine(
54+
preparedPlaybackQueueResourceManagement,
55+
listOf(CompletingFileQueueProvider()),
56+
repository,
57+
playbackBootstrapper,
58+
playbackBootstrapper,
59+
)
60+
Pair(fakePlaybackPreparerProvider, playbackEngine)
61+
}
62+
63+
private var nextSwitchedFile: PositionedFile? = null
64+
65+
@BeforeAll
66+
fun act() {
67+
val (fakePlaybackPreparerProvider, playbackEngine) = mut
68+
69+
val promisedPlaybackStarted = Promise {
70+
playbackEngine
71+
.setOnPlayingFileChanged { _, p ->
72+
it.sendResolution(p)
73+
}
74+
}
75+
76+
val promisedStart = playbackEngine
77+
.startPlaylist(
78+
LibraryId(libraryId),
79+
listOf(
80+
ServiceFile("1"),
81+
ServiceFile("2"),
82+
ServiceFile("3"),
83+
ServiceFile("4"),
84+
ServiceFile("5")
85+
),
86+
1
87+
)
88+
89+
val playingPlaybackHandler = fakePlaybackPreparerProvider.deferredResolutions[ServiceFile("2")]?.resolve()
90+
promisedStart.toExpiringFuture().get()
91+
promisedPlaybackStarted.toExpiringFuture().get()
92+
93+
val promisedNextTrackStarted = Promise {
94+
playbackEngine
95+
.setOnPlayingFileChanged { _, p ->
96+
it.sendResolution(p)
97+
}
98+
}
99+
100+
playingPlaybackHandler?.resolve()
101+
102+
fakePlaybackPreparerProvider.deferredResolutions[ServiceFile("3")]?.resolve()
103+
promisedNextTrackStarted.toExpiringFuture().get()
104+
105+
val promisedSkipBack = playbackEngine.skipToPrevious()
106+
fakePlaybackPreparerProvider.deferredResolutions[ServiceFile("2")]?.resolve()
107+
108+
nextSwitchedFile = promisedSkipBack.toExpiringFuture().get()?.second
109+
}
110+
111+
@Test
112+
fun `then the engine is playing`() {
113+
assertThat(mut.second.isPlaying).isTrue
114+
}
115+
116+
@Test
117+
fun `then the next file change is the switched to the correct track position`() {
118+
assertThat(nextSwitchedFile?.playlistPosition).isEqualTo(1)
119+
}
120+
}

0 commit comments

Comments
 (0)