소스 검색

Merge branch 'tsumugi/devel' into tsumugi/master

yattoz 4 년 전
부모
커밋
9dff2f63d4

+ 2 - 2
app/build.gradle 파일 보기

29
         applicationId "fr.forum_thalie.tsumugi"
29
         applicationId "fr.forum_thalie.tsumugi"
30
         minSdkVersion 16
30
         minSdkVersion 16
31
         targetSdkVersion 29
31
         targetSdkVersion 29
32
-        versionCode 112
33
-        versionName "1.1.2"
32
+        versionCode 113
33
+        versionName "1.1.3"
34
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
34
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
35
         vectorDrawables.useSupportLibrary = true
35
         vectorDrawables.useSupportLibrary = true
36
     }
36
     }

+ 2 - 0
app/src/main/java/fr/forum_thalie/tsumugi/BootBroadcastReceiver.kt 파일 보기

7
 import android.util.Log
7
 import android.util.Log
8
 import androidx.preference.PreferenceManager
8
 import androidx.preference.PreferenceManager
9
 import fr.forum_thalie.tsumugi.alarm.RadioAlarm
9
 import fr.forum_thalie.tsumugi.alarm.RadioAlarm
10
+import fr.forum_thalie.tsumugi.planning.Planning
10
 import fr.forum_thalie.tsumugi.playerstore.PlayerStore
11
 import fr.forum_thalie.tsumugi.playerstore.PlayerStore
11
 
12
 
12
 class BootBroadcastReceiver : BroadcastReceiver(){
13
 class BootBroadcastReceiver : BroadcastReceiver(){
24
         {
25
         {
25
 
26
 
26
             RadioAlarm.instance.setNextAlarm(context) // schedule next alarm
27
             RadioAlarm.instance.setNextAlarm(context) // schedule next alarm
28
+            Planning.instance.parseUrl(context = context)
27
             if (!PlayerStore.instance.isInitialized)
29
             if (!PlayerStore.instance.isInitialized)
28
                 PlayerStore.instance.initApi()
30
                 PlayerStore.instance.initApi()
29
             if (PlayerStore.instance.streamerName.value.isNullOrBlank())
31
             if (PlayerStore.instance.streamerName.value.isNullOrBlank())

+ 1 - 1
app/src/main/java/fr/forum_thalie/tsumugi/RadioService.kt 파일 보기

140
                     PlayerStore.instance.isStreamDown = true
140
                     PlayerStore.instance.isStreamDown = true
141
                 }
141
                 }
142
                 else -> {
142
                 else -> {
143
-                    PlayerStore.instance.fetchApi(numberOfSongs >= 2)
143
+                    PlayerStore.instance.fetchApi(/* numberOfSongs >= 2 */)
144
                 }
144
                 }
145
             }
145
             }
146
         }
146
         }

+ 17 - 19
app/src/main/java/fr/forum_thalie/tsumugi/playerstore/PlayerStore.kt 파일 보기

7
 import android.util.Log
7
 import android.util.Log
8
 import androidx.lifecycle.MutableLiveData
8
 import androidx.lifecycle.MutableLiveData
9
 import fr.forum_thalie.tsumugi.*
9
 import fr.forum_thalie.tsumugi.*
10
+import fr.forum_thalie.tsumugi.planning.Planning
10
 import org.json.JSONObject
11
 import org.json.JSONObject
11
 import java.net.URL
12
 import java.net.URL
12
 import java.text.ParseException
13
 import java.text.ParseException
58
 
59
 
59
     private fun getTimestamp(s: String) : Long
60
     private fun getTimestamp(s: String) : Long
60
     {
61
     {
61
-        val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault())
62
+        val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss z", Locale.getDefault())
62
         try {
63
         try {
63
-            val t: Date? = dateFormat.parse(s)
64
+            val t: Date? = dateFormat.parse("$s ${Planning.instance.timeZone.id}")
65
+            //[REMOVE LOG CALLS]Log.d(tag, "date: $s -> $t")
64
             return t!!.time
66
             return t!!.time
65
         } catch (e: ParseException) {
67
         } catch (e: ParseException) {
66
             e.printStackTrace()
68
             e.printStackTrace()
90
 
92
 
91
         currentSong.stopTime.value = ends
93
         currentSong.stopTime.value = ends
92
 
94
 
95
+        val apiTime = getTimestamp(res.getJSONObject("station").getString("schedulerTime"))
93
         // I noticed that the server has a big (3 to 9 seconds !!) offset for current time.
96
         // I noticed that the server has a big (3 to 9 seconds !!) offset for current time.
94
         // we can measure it when the player is playing, to compensate it and have our progress bar perfectly timed
97
         // we can measure it when the player is playing, to compensate it and have our progress bar perfectly timed
95
         // latencyCompensator is set to null when beginPlaying() (we can't measure it at the moment we start playing, since we're in the middle of a song),
98
         // latencyCompensator is set to null when beginPlaying() (we can't measure it at the moment we start playing, since we're in the middle of a song),
96
         // at this moment, we set it to 0. Then, next time the updateApi is called when we're playing, we measure the latency and we set out latencyComparator.
99
         // at this moment, we set it to 0. Then, next time the updateApi is called when we're playing, we measure the latency and we set out latencyComparator.
97
         if(isCompensatingLatency)
100
         if(isCompensatingLatency)
98
         {
101
         {
99
-            latencyCompensator = getTimestamp(res.getJSONObject("station").getString("schedulerTime")) - (currentSong.startTime.value ?: getTimestamp(res.getJSONObject("station").getString("schedulerTime")))
100
-            //[REMOVE LOG CALLS]Log.d((tag, "latency compensator set to ${(latencyCompensator).toFloat()/1000} s")
102
+            latencyCompensator = apiTime - (currentSong.startTime.value!!)
103
+            //[REMOVE LOG CALLS]Log.d(tag, "latency compensator set to ${(latencyCompensator).toFloat() / 1000} s")
101
         }
104
         }
102
-        currentTime.value = getTimestamp(res.getJSONObject("station").getString("schedulerTime")) - (latencyCompensator)
105
+        currentTime.value = apiTime - (latencyCompensator)
103
 
106
 
104
         /*
107
         /*
105
         val listeners = resMain.getInt("listeners")
108
         val listeners = resMain.getInt("listeners")
163
     // ##################################################
166
     // ##################################################
164
 
167
 
165
     fun updateQueue() {
168
     fun updateQueue() {
166
-        if (queue.isNotEmpty()) {
167
-            queue.remove(queue.first())
168
-            //[REMOVE LOG CALLS]Log.d((tag, queue.toString())
169
-            fetchLastRequest()
170
-            isQueueUpdated.value = true
171
-        } else if (isInitialized) {
172
-            fetchLastRequest()
173
-        } else {
174
-            //[REMOVE LOG CALLS]Log.d((tag,  "queue is empty! fetching anyway !!")
175
-            fetchLastRequest()
176
-        }
169
+        //[REMOVE LOG CALLS]Log.d(tag, queue.toString())
170
+        fetchLastRequest()
177
     }
171
     }
178
 
172
 
179
     fun updateLp() {
173
     fun updateLp() {
192
 
186
 
193
     private fun fetchLastRequest()
187
     private fun fetchLastRequest()
194
     {
188
     {
189
+        isQueueUpdated.value = false
195
         val sleepScrape: (Any?) -> String = {
190
         val sleepScrape: (Any?) -> String = {
196
             /* we can maximize our chances to retrieve the last queued song by specifically waiting for the number of seconds we measure between ICY metadata and API change.
191
             /* we can maximize our chances to retrieve the last queued song by specifically waiting for the number of seconds we measure between ICY metadata and API change.
197
              we add 2 seconds just to get a higher probability that the API has correctly updated. (the latency compensator can have a jitter of 1 second usually)
192
              we add 2 seconds just to get a higher probability that the API has correctly updated. (the latency compensator can have a jitter of 1 second usually)
225
                     initApi()
220
                     initApi()
226
                 } else
221
                 } else
227
                 */
222
                 */
228
-                if (resMain.has("next") /*&& queue.isNotEmpty()*/) {
223
+                if (resMain.has("next")) {
229
                     val queueJSON =
224
                     val queueJSON =
230
                         resMain.getJSONObject("next")
225
                         resMain.getJSONObject("next")
231
                     val t = extractSong(queueJSON)
226
                     val t = extractSong(queueJSON)
232
-                    if (queue.isNotEmpty() && (t == queue.last() || t == currentSong))
227
+                    if (queue.isNotEmpty() && (t == queue.last() || t == currentSong) && isQueueUpdated.value == false)
233
                     {
228
                     {
234
-                        //[REMOVE LOG CALLS]Log.d((tag, playerStoreTag +  "Song already in there: $t")
229
+                        //[REMOVE LOG CALLS]Log.d(tag, playerStoreTag +  "Song already in there: $t\nQueue:$queue")
235
                         Async(sleepScrape, post)
230
                         Async(sleepScrape, post)
236
                     } else {
231
                     } else {
232
+                        if (queue.isNotEmpty())
233
+                            queue.remove(queue.first())
237
                         queue.add(queue.size, t)
234
                         queue.add(queue.size, t)
238
                         //[REMOVE LOG CALLS]Log.d(tag, playerStoreTag +  "added last queue song: $t")
235
                         //[REMOVE LOG CALLS]Log.d(tag, playerStoreTag +  "added last queue song: $t")
239
                         isQueueUpdated.value = true
236
                         isQueueUpdated.value = true
237
+                        return // FUUUCK IT WAS CALLING THE ASYNC ONE MORE TIME AFTERWARDS !?
240
                     }
238
                     }
241
                 }
239
                 }
242
             }
240
             }

+ 1 - 1
app/src/main/java/fr/forum_thalie/tsumugi/playerstore/Song.kt 파일 보기

48
     override fun equals(other: Any?) : Boolean
48
     override fun equals(other: Any?) : Boolean
49
     {
49
     {
50
         val song: Song = other as Song
50
         val song: Song = other as Song
51
-        return this.title.value == song.title.value && this.artist.value == song.artist.value
51
+        return this.title.value === song.title.value && this.artist.value === song.artist.value
52
     }
52
     }
53
 
53
 
54
     fun copy(song: Song) {
54
     fun copy(song: Song) {