Merge branch 'tsumugi/devel' into tsumugi/master

remotes/origin/devel
yattoz 2020-01-17 19:56:11 +01:00
commit 9dff2f63d4
5 changed files with 23 additions and 23 deletions

View File

@ -29,8 +29,8 @@ android {
applicationId "fr.forum_thalie.tsumugi" applicationId "fr.forum_thalie.tsumugi"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 112 versionCode 113
versionName "1.1.2" versionName "1.1.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }

View File

@ -7,6 +7,7 @@ import android.os.Build
import android.util.Log import android.util.Log
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import fr.forum_thalie.tsumugi.alarm.RadioAlarm import fr.forum_thalie.tsumugi.alarm.RadioAlarm
import fr.forum_thalie.tsumugi.planning.Planning
import fr.forum_thalie.tsumugi.playerstore.PlayerStore import fr.forum_thalie.tsumugi.playerstore.PlayerStore
class BootBroadcastReceiver : BroadcastReceiver(){ class BootBroadcastReceiver : BroadcastReceiver(){
@ -24,6 +25,7 @@ class BootBroadcastReceiver : BroadcastReceiver(){
{ {
RadioAlarm.instance.setNextAlarm(context) // schedule next alarm RadioAlarm.instance.setNextAlarm(context) // schedule next alarm
Planning.instance.parseUrl(context = context)
if (!PlayerStore.instance.isInitialized) if (!PlayerStore.instance.isInitialized)
PlayerStore.instance.initApi() PlayerStore.instance.initApi()
if (PlayerStore.instance.streamerName.value.isNullOrBlank()) if (PlayerStore.instance.streamerName.value.isNullOrBlank())

View File

@ -140,7 +140,7 @@ class RadioService : MediaBrowserServiceCompat() {
PlayerStore.instance.isStreamDown = true PlayerStore.instance.isStreamDown = true
} }
else -> { else -> {
PlayerStore.instance.fetchApi(numberOfSongs >= 2) PlayerStore.instance.fetchApi(/* numberOfSongs >= 2 */)
} }
} }
} }

View File

@ -7,6 +7,7 @@ import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import fr.forum_thalie.tsumugi.* import fr.forum_thalie.tsumugi.*
import fr.forum_thalie.tsumugi.planning.Planning
import org.json.JSONObject import org.json.JSONObject
import java.net.URL import java.net.URL
import java.text.ParseException import java.text.ParseException
@ -58,9 +59,10 @@ class PlayerStore {
private fun getTimestamp(s: String) : Long private fun getTimestamp(s: String) : Long
{ {
val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss", Locale.getDefault()) val dateFormat = SimpleDateFormat("yyyy-MM-dd hh:mm:ss z", Locale.getDefault())
try { try {
val t: Date? = dateFormat.parse(s) val t: Date? = dateFormat.parse("$s ${Planning.instance.timeZone.id}")
//[REMOVE LOG CALLS]Log.d(tag, "date: $s -> $t")
return t!!.time return t!!.time
} catch (e: ParseException) { } catch (e: ParseException) {
e.printStackTrace() e.printStackTrace()
@ -90,16 +92,17 @@ class PlayerStore {
currentSong.stopTime.value = ends currentSong.stopTime.value = ends
val apiTime = getTimestamp(res.getJSONObject("station").getString("schedulerTime"))
// I noticed that the server has a big (3 to 9 seconds !!) offset for current time. // I noticed that the server has a big (3 to 9 seconds !!) offset for current time.
// we can measure it when the player is playing, to compensate it and have our progress bar perfectly timed // we can measure it when the player is playing, to compensate it and have our progress bar perfectly timed
// 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), // 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),
// 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. // 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.
if(isCompensatingLatency) if(isCompensatingLatency)
{ {
latencyCompensator = getTimestamp(res.getJSONObject("station").getString("schedulerTime")) - (currentSong.startTime.value ?: getTimestamp(res.getJSONObject("station").getString("schedulerTime"))) latencyCompensator = apiTime - (currentSong.startTime.value!!)
//[REMOVE LOG CALLS]Log.d((tag, "latency compensator set to ${(latencyCompensator).toFloat()/1000} s") //[REMOVE LOG CALLS]Log.d(tag, "latency compensator set to ${(latencyCompensator).toFloat() / 1000} s")
} }
currentTime.value = getTimestamp(res.getJSONObject("station").getString("schedulerTime")) - (latencyCompensator) currentTime.value = apiTime - (latencyCompensator)
/* /*
val listeners = resMain.getInt("listeners") val listeners = resMain.getInt("listeners")
@ -163,17 +166,8 @@ class PlayerStore {
// ################################################## // ##################################################
fun updateQueue() { fun updateQueue() {
if (queue.isNotEmpty()) { //[REMOVE LOG CALLS]Log.d(tag, queue.toString())
queue.remove(queue.first()) fetchLastRequest()
//[REMOVE LOG CALLS]Log.d((tag, queue.toString())
fetchLastRequest()
isQueueUpdated.value = true
} else if (isInitialized) {
fetchLastRequest()
} else {
//[REMOVE LOG CALLS]Log.d((tag, "queue is empty! fetching anyway !!")
fetchLastRequest()
}
} }
fun updateLp() { fun updateLp() {
@ -192,6 +186,7 @@ class PlayerStore {
private fun fetchLastRequest() private fun fetchLastRequest()
{ {
isQueueUpdated.value = false
val sleepScrape: (Any?) -> String = { val sleepScrape: (Any?) -> String = {
/* 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. /* 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.
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) 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,18 +220,21 @@ class PlayerStore {
initApi() initApi()
} else } else
*/ */
if (resMain.has("next") /*&& queue.isNotEmpty()*/) { if (resMain.has("next")) {
val queueJSON = val queueJSON =
resMain.getJSONObject("next") resMain.getJSONObject("next")
val t = extractSong(queueJSON) val t = extractSong(queueJSON)
if (queue.isNotEmpty() && (t == queue.last() || t == currentSong)) if (queue.isNotEmpty() && (t == queue.last() || t == currentSong) && isQueueUpdated.value == false)
{ {
//[REMOVE LOG CALLS]Log.d((tag, playerStoreTag + "Song already in there: $t") //[REMOVE LOG CALLS]Log.d(tag, playerStoreTag + "Song already in there: $t\nQueue:$queue")
Async(sleepScrape, post) Async(sleepScrape, post)
} else { } else {
if (queue.isNotEmpty())
queue.remove(queue.first())
queue.add(queue.size, t) queue.add(queue.size, t)
//[REMOVE LOG CALLS]Log.d(tag, playerStoreTag + "added last queue song: $t") //[REMOVE LOG CALLS]Log.d(tag, playerStoreTag + "added last queue song: $t")
isQueueUpdated.value = true isQueueUpdated.value = true
return // FUUUCK IT WAS CALLING THE ASYNC ONE MORE TIME AFTERWARDS !?
} }
} }
} }

View File

@ -48,7 +48,7 @@ class Song(artistTitle: String = "", _id : Int = 0) {
override fun equals(other: Any?) : Boolean override fun equals(other: Any?) : Boolean
{ {
val song: Song = other as Song val song: Song = other as Song
return this.title.value == song.title.value && this.artist.value == song.artist.value return this.title.value === song.title.value && this.artist.value === song.artist.value
} }
fun copy(song: Song) { fun copy(song: Song) {