11package io.github.zyrouge.symphony.services.radio
22
33import io.github.zyrouge.symphony.Symphony
4+ import io.github.zyrouge.symphony.services.database.store.SongQueueSongMappingStore
45import io.github.zyrouge.symphony.services.groove.entities.Song
56import io.github.zyrouge.symphony.services.groove.entities.SongQueue
67import io.github.zyrouge.symphony.services.groove.entities.SongQueueSongMapping
8+ import io.github.zyrouge.symphony.utils.complex_linked_list.ComplexLinkedListOperator
79
810class RadioQueue (private val symphony : Symphony ) {
11+ private class SongQueueSongMappingOperatorEntityFunctions :
12+ ComplexLinkedListOperator .EntityFunctions <String , SongQueueSongMapping > {
13+ override fun getEntityId (entity : SongQueueSongMapping ) = entity.id
14+ override fun getEntityNextId (entity : SongQueueSongMapping ) = entity.nextId
15+ override fun getEntityIsHead (entity : SongQueueSongMapping ) = entity.isHead
16+
17+ override fun updateEntityNextId (entity : SongQueueSongMapping , nNextId : String? ) =
18+ entity.copy(nextId = nNextId)
19+
20+ override fun updateEntityIsHead (entity : SongQueueSongMapping , nIsHead : Boolean ) =
21+ entity.copy(isHead = nIsHead)
22+ }
23+
24+ private class SongQueueSongMappingOperatorPersistenceFunctions (
25+ private val store : SongQueueSongMappingStore ,
26+ private val queueId : String ,
27+ ) :
28+ ComplexLinkedListOperator .PersistenceFunctions <String , SongQueueSongMapping > {
29+ override fun getEntitiesByIds (ids : List <String >) = store.entriesByIds(queueId, ids)
30+ .mapValues { it.value.mapping }
31+
32+ override fun getEntitiesByNextIds (nextIds : List <String >) =
33+ store.entriesByNextIds(queueId, nextIds)
34+ .mapValues { it.value.mapping }
35+
36+ override fun getHeadEntity () = store.findHead(queueId)?.mapping
37+ override fun getTailEntity () = store.findByNextId(queueId, null )?.mapping
38+
39+ override suspend fun insertEntities (entities : List <SongQueueSongMapping >) {
40+ store.insert(* entities.toTypedArray())
41+ }
42+
43+ override suspend fun updateEntities (entities : List <SongQueueSongMapping >) {
44+ store.update(* entities.toTypedArray())
45+ }
46+
47+ override suspend fun deleteEntities (ids : List <String >) {
48+ store.delete(queueId, ids)
49+ }
50+ }
51+
952// val queueFlow = symphony.database.songQueue.findFirstAsFlow()
1053// val queue = AtomicReference<SongQueue.AlongAttributes?>(null)
1154
@@ -54,50 +97,37 @@ class RadioQueue(private val symphony: Symphony) {
5497 )
5598 symphony.database.songQueue.insert(queue)
5699 }
57- var previousSong = previousSongMappingId?.let {
58- symphony.database.songQueueSongMapping.findById(queueId, it)
59- }
60- var nextMappingId = previousSong?.mapping?.nextId
61- var ogNextMappingId = previousSong?.mapping?.ogNextId
62- val added = mutableListOf<SongQueueSongMapping >()
63- var i = 0
64- val songIdsCount = songIds.size
65- for (x in songIds.reversed()) {
66- val isHead = origQueue == null && i == songIdsCount - 1
67- val mapping = SongQueueSongMapping (
100+ val operator = createSongQueueSongMappingOperator(queueId)
101+ operator .add(previousSongMappingId, songIds) { x, isHead, nextId ->
102+ SongQueueSongMapping (
68103 id = symphony.database.songQueueSongMappingIdGenerator.next(),
69104 queueId = queueId,
70105 songId = x,
71106 isHead = isHead,
72- nextId = nextMappingId ,
73- ogNextId = ogNextMappingId ,
107+ nextId = nextId ,
108+ ogNextId = nextId ,
74109 )
75- added.add(mapping)
76- nextMappingId = mapping.id
77- ogNextMappingId = mapping.id
78- i++
79110 }
80- symphony.database.songQueueSongMapping.insert(* added.toTypedArray())
81111 afterAdd(options)
82112 }
83113
84114 suspend fun add (
85115 songId : String ,
86- previousSongId : String? = null,
116+ previousSongMappingId : String? = null,
87117 options : Radio .PlayOptions = Radio .PlayOptions (),
88- ) = add(listOf (songId), previousSongId , options)
118+ ) = add(listOf (songId), previousSongMappingId , options)
89119
90120 suspend fun add (
91121 songs : List <Song >,
92- previousSongId : String? = null,
122+ previousSongMappingId : String? = null,
93123 options : Radio .PlayOptions = Radio .PlayOptions (),
94- ) = add(songs.map { it.id }, previousSongId , options)
124+ ) = add(songs.map { it.id }, previousSongMappingId , options)
95125
96126 suspend fun add (
97127 song : Song ,
98- previousSongId : String? = null,
128+ previousSongMappingId : String? = null,
99129 options : Radio .PlayOptions = Radio .PlayOptions (),
100- ) = add(listOf (song.id), previousSongId , options)
130+ ) = add(listOf (song.id), previousSongMappingId , options)
101131
102132 private fun afterAdd (options : Radio .PlayOptions ) {
103133 if (! symphony.radio.hasPlayer) {
@@ -106,36 +136,18 @@ class RadioQueue(private val symphony: Symphony) {
106136 symphony.radio.onUpdate.dispatch(Radio .Events .Queue .Modified )
107137 }
108138
109- fun remove (id : String ) {
110- originalQueue.removeAt(index)
111- currentQueue.removeAt(index)
112- symphony.radio.onUpdate.dispatch(Radio .Events .Queue .Modified )
113- if (currentSongIndex == index) {
114- symphony.radio.play(Radio .PlayOptions (index = currentSongIndex))
115- } else if (index < currentSongIndex) {
116- currentSongIndex--
139+ suspend fun remove (songMappingIds : List <String >): Boolean {
140+ val queue = symphony.database.songQueue.findByInternalId(SONG_QUEUE_INTERNAL_ID_DEFAULT )
141+ if (queue == null ) {
142+ return false
117143 }
144+ val queueId = queue.entity.id
145+ val operator = createSongQueueSongMappingOperator(queueId)
146+ val result = operator .remove(songMappingIds)
147+ return result.deletedKeys.isNotEmpty()
118148 }
119149
120- fun remove (indices : List <Int >) {
121- var deflection = 0
122- var currentSongRemoved = false
123- val sortedIndices = indices.sortedDescending()
124- for (i in sortedIndices) {
125- val index = i - deflection
126- originalQueue.removeAt(index)
127- currentQueue.removeAt(index)
128- when {
129- i < currentSongIndex -> deflection++
130- i == currentSongIndex -> currentSongRemoved = true
131- }
132- }
133- currentSongIndex - = deflection
134- symphony.radio.onUpdate.dispatch(Radio .Events .Queue .Modified )
135- if (currentSongRemoved) {
136- symphony.radio.play(Radio .PlayOptions (index = currentSongIndex))
137- }
138- }
150+ suspend fun remove (songMappingId : String ) = remove(listOf (songMappingId))
139151
140152 fun setLoopMode (loopMode : LoopMode ) {
141153 currentLoopMode = loopMode
@@ -169,6 +181,14 @@ class RadioQueue(private val symphony: Symphony) {
169181 symphony.radio.onUpdate.dispatch(Radio .Events .Queue .Modified )
170182 }
171183
184+ private fun createSongQueueSongMappingOperator (queueId : String ) = ComplexLinkedListOperator (
185+ SongQueueSongMappingOperatorEntityFunctions (),
186+ SongQueueSongMappingOperatorPersistenceFunctions (
187+ symphony.database.songQueueSongMapping,
188+ queueId
189+ )
190+ )
191+
172192 companion object {
173193 const val SONG_QUEUE_INTERNAL_ID_DEFAULT = 1
174194 }
0 commit comments