added current programme calculation. Added dummy fragment.

remotes/origin/devel
yattoz 2019-12-16 23:38:50 +01:00
parent ef83c693d0
commit 0218dfab75
10 changed files with 189 additions and 56 deletions

View File

@ -1,10 +1,10 @@
{ {
"planning": [ "planning": [
{ {
"title": "Anime Matin", "title": "Musique Classique",
"periodicity": "1111100", "periodicity": "1111111",
"hour_begin": "9:00", "hour_begin": "6:00",
"hour_end": "10:30" "hour_end": "7:00"
}, },
{ {
"title": "Jeux Vidéos Matin", "title": "Jeux Vidéos Matin",
@ -12,11 +12,54 @@
"hour_begin": "09:00", "hour_begin": "09:00",
"hour_end": "10:30" "hour_end": "10:30"
}, },
{
"title": "Anime Matin",
"periodicity": "1111100",
"hour_begin": "10:30",
"hour_end": "12:00"
},
{
"title": "Jeux Vidéos Aprem'",
"periodicity": "1111111",
"hour_begin": "14:00",
"hour_end": "15:30"
},
{
"title": "Anime Aprem'",
"periodicity": "1111111",
"hour_begin": "15:30",
"hour_end": "17:00"
},
{
"title": "Jeux Vidéos Soirée",
"periodicity": "1111100",
"hour_begin": "19:00",
"hour_end": "20:00"
},
{
"title": "Anime Soirée",
"periodicity": "1111100",
"hour_begin": "20:00",
"hour_end": "21:00"
},
{
"title": "Jeux Vidéos Nuit",
"periodicity": "1111111",
"hour_begin": "00:00",
"hour_end": "01:00"
},
{
"title": "Anime Nuit",
"periodicity": "1111111",
"hour_begin": "01:00",
"hour_end": "02:00"
},
{ {
"title": "Programmation nocturne", "title": "Programmation nocturne",
"periodicity": "1111111", "periodicity": "1111111",
"hour_begin": "23:00", "hour_begin": "02:00",
"hour_end": "5:30" "hour_end": "06:00"
} }
] ],
"regular_programme" : "Programmation habituelle"
} }

View File

@ -16,7 +16,7 @@ import fr.forum_thalie.tsumugi.playerstore.PlayerStore
import java.util.Timer import java.util.Timer
import android.view.MenuItem import android.view.MenuItem
import fr.forum_thalie.tsumugi.alarm.RadioAlarm import fr.forum_thalie.tsumugi.alarm.RadioAlarm
import fr.forum_thalie.tsumugi.planning.PlanningParser import fr.forum_thalie.tsumugi.planning.Planning
/* Log to file import /* Log to file import
@ -157,7 +157,7 @@ class MainActivity : BaseActivity() {
} }
// fetch program // fetch program
PlanningParser.instance.parseUrl(/* getString(R.string.planning_url) */ context = this) Planning.instance.parseUrl(/* getString(R.string.planning_url) */ context = this)
// initialize the UI // initialize the UI
setTheme(R.style.AppTheme) setTheme(R.style.AppTheme)

View File

@ -34,6 +34,7 @@ import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.metadata.icy.* import com.google.android.exoplayer2.metadata.icy.*
import fr.forum_thalie.tsumugi.alarm.RadioAlarm import fr.forum_thalie.tsumugi.alarm.RadioAlarm
import fr.forum_thalie.tsumugi.alarm.RadioSleeper import fr.forum_thalie.tsumugi.alarm.RadioSleeper
import fr.forum_thalie.tsumugi.planning.Planning
import fr.forum_thalie.tsumugi.playerstore.PlayerStore import fr.forum_thalie.tsumugi.playerstore.PlayerStore
import java.util.* import java.util.*
import kotlin.math.exp import kotlin.math.exp
@ -129,6 +130,7 @@ class RadioService : MediaBrowserServiceCompat() {
PlayerStore.instance.updateLp() PlayerStore.instance.updateLp()
} }
nowPlayingNotification.update(this) nowPlayingNotification.update(this)
Log.d(tag, Planning.instance.currentProgramme())
} }
private val streamerPictureObserver = Observer<Bitmap> { private val streamerPictureObserver = Observer<Bitmap> {

View File

@ -6,9 +6,19 @@ import org.json.JSONObject
import java.io.IOException import java.io.IOException
import java.net.URL import java.net.URL
class PlanningParser { class Planning {
val programs: ArrayList<Program> = ArrayList() private val programmes: ArrayList<Programme> = ArrayList()
private var regularProgramme: String? = null
fun currentProgramme(): String
{
programmes.forEach {
if (it.isCurrent())
return it.title
}
return regularProgramme ?: "none"
}
fun parseUrl(url: String? = null, context: Context? = null) fun parseUrl(url: String? = null, context: Context? = null)
{ {
@ -46,16 +56,18 @@ class PlanningParser {
val hourEndS = item.getString("hour_end").split(":") val hourEndS = item.getString("hour_end").split(":")
val hourEnd = hourEndS.first().toInt()* 60 + hourEndS.last().toInt() val hourEnd = hourEndS.first().toInt()* 60 + hourEndS.last().toInt()
val title = item.getString("title") val title = item.getString("title")
programs.add(Program(title, periodicity, hourBegin, hourEnd)) programmes.add(Programme(title, periodicity, hourBegin, hourEnd))
} }
} }
if (result.has("regular_programme"))
regularProgramme = result.getString("regular_programme")
} }
Async(scrape, post) Async(scrape, post)
} }
companion object { companion object {
val instance by lazy { val instance by lazy {
PlanningParser() Planning()
} }
} }
} }

View File

@ -1,41 +0,0 @@
package fr.forum_thalie.tsumugi.planning
import android.util.Log
import fr.forum_thalie.tsumugi.tag
import org.json.JSONObject
import java.util.*
class Program (val title: String, private val periodicity: Int, private val hourBegin: Int, private val hourEnd: Int) {
fun isCurrent(): Boolean
{
val now = Calendar.getInstance()
val currentDay = if (now.get(Calendar.DAY_OF_WEEK) - 1 == 0) 6 else now.get(Calendar.DAY_OF_WEEK) - 2
// 0 (Monday) to 5 (Saturday) + 6 (Sunday)
// this translates to "true" when:
// - the currentDay is flagged in the "periodicity" bit array
// OR
// - Yesterday is flagged in the "periodicity" bit array AND the program does span over 2 days (night programs typically).
// We'll check a after this whether the current hour is within the span.
val isNow: Boolean = ((((1000000 shr currentDay) and (periodicity)) == 1)) || (((1000000 shr ((currentDay-1)%7) and (periodicity)) == 1) && hourEnd < hourBegin)
// shr = shift-right. It's a binary mask.
if (isNow)
{
val hasBegun = (now.get(Calendar.HOUR_OF_DAY)*60 + now.get(Calendar.MINUTE) >= hourBegin )
val hasNotEnded = (now.get(Calendar.HOUR_OF_DAY)*60 + now.get(Calendar.MINUTE) <= hourEnd )
if (hasBegun && hasNotEnded)
return true
}
return false
}
override fun toString(): String {
return "Title: $title, time info (periodicity, begin, end): $periodicity, $hourBegin, $hourEnd"
}
init {
Log.d(tag, this.toString())
}
}

View File

@ -0,0 +1,50 @@
package fr.forum_thalie.tsumugi.planning
import android.util.Log
import fr.forum_thalie.tsumugi.tag
import java.util.*
class Programme (val title: String, private val periodicity: Int, private val hourBegin: Int, private val hourEnd: Int) {
fun isCurrent(): Boolean {
val now = Calendar.getInstance()
val currentDay =
if (now.get(Calendar.DAY_OF_WEEK) - 1 == 0) 6 else now.get(Calendar.DAY_OF_WEEK) - 2
// 0 (Monday) to 5 (Saturday) + 6 (Sunday)
// this translates to "true" when:
// - the currentDay is flagged in the "periodicity" bit array
// OR
// - Yesterday is flagged in the "periodicity" bit array AND the program does span over 2 days (night programs).
// We'll check a after this whether the current hour is within the span.
val isToday: Boolean = ((((1000000 shr currentDay) and (periodicity)) != 0))
val isSpanningOverNight =
(((1000000 shr ((currentDay - 1) % 7) and (periodicity)) != 0) && hourEnd < hourBegin)
Log.d(tag, "$title is today: $isToday or spanning $isSpanningOverNight")
// shr = shift-right. It's a binary mask.
// if the program started yesterday, and spanned over night, it means that there could be a chance that it's still active.
// we only need to check if the end time has been reached.
if (isSpanningOverNight) {
return (now.get(Calendar.HOUR_OF_DAY) * 60 + now.get(Calendar.MINUTE) < hourEnd)
}
// if the program is today, we need to check if we're in the hour span.
if (isToday) {
val hasBegun =
(now.get(Calendar.HOUR_OF_DAY) * 60 + now.get(Calendar.MINUTE) >= hourBegin)
val hasNotEnded =
(now.get(Calendar.HOUR_OF_DAY) * 60 + now.get(Calendar.MINUTE) < hourEnd) || hourEnd < hourBegin
return (hasBegun && hasNotEnded)
}
return false
}
override fun toString(): String {
return "Title: $title, time info (periodicity, begin, end): $periodicity, $hourBegin, $hourEnd"
}
init {
Log.d(tag, this.toString())
}
}

View File

@ -0,0 +1,57 @@
package fr.forum_thalie.tsumugi.ui.songs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import fr.forum_thalie.tsumugi.R
import fr.forum_thalie.tsumugi.playerstore.PlayerStore
import fr.forum_thalie.tsumugi.ui.songs.queuelp.LastPlayedFragment
import fr.forum_thalie.tsumugi.ui.songs.queuelp.SongAdaptater
class ProgrammeFragment : Fragment() {
private lateinit var recyclerView: RecyclerView
private lateinit var viewAdapter: RecyclerView.Adapter<*>
private lateinit var viewManager: RecyclerView.LayoutManager
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
val root = inflater.inflate(R.layout.fragment_programme, container, false)
/*
viewManager = LinearLayoutManager(context)
viewAdapter = SongAdaptater(PlayerStore.instance.lp)
recyclerView = root.findViewById<RecyclerView>(R.id.queue_lp_recycler).apply {
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
setHasFixedSize(true)
// use a linear layout manager
layoutManager = viewManager
// specify an viewAdapter (see also next example)
adapter = viewAdapter
}
*/
return root
}
override fun onDestroyView() {
super.onDestroyView()
}
companion object {
@JvmStatic
fun newInstance() = LastPlayedFragment()
}
}

View File

@ -27,9 +27,11 @@ class SongsFragment : Fragment() {
root = inflater.inflate(R.layout.fragment_songs, container, false) root = inflater.inflate(R.layout.fragment_songs, container, false)
viewPager = root.findViewById(R.id.tabPager) viewPager = root.findViewById(R.id.tabPager)
adapter = SongsPagerAdapter(childFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) adapter = SongsPagerAdapter(childFragmentManager, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT)
adapter.addFragment(LastPlayedFragment.newInstance(), "last played") adapter.addFragment(LastPlayedFragment.newInstance(), getString(R.string.lp))
// You can add more fragments to the adapter, to display more information (for example with R/a/dio, queue, request, faves...) // You can add more fragments to the adapter, to display more information (for example with R/a/dio, queue, request, faves...)
adapter.addFragment(ProgrammeFragment.newInstance(), getString(R.string.programme))
viewPager.adapter = adapter viewPager.adapter = adapter

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -13,7 +13,6 @@
<string name="STREAM_URL_RSTLSS">http://stream.radiosolution.fr/rstlss.mp3</string> <string name="STREAM_URL_RSTLSS">http://stream.radiosolution.fr/rstlss.mp3</string>
<string name="volume">Volume: </string> <string name="volume">Volume: </string>
<string name="MAIN_API">https://r-a-d.io/api</string>
<string name="up_next">Up next:</string> <string name="up_next">Up next:</string>
<string name="now_streaming">Now streaming</string> <string name="now_streaming">Now streaming</string>
@ -47,5 +46,7 @@
<string name="select_one_day">Select at least one day</string> <string name="select_one_day">Select at least one day</string>
<string name="no_alarm_set">No alarm set</string> <string name="no_alarm_set">No alarm set</string>
<string name="next_alarm">Next alarm:</string> <string name="next_alarm">Next alarm:</string>
<string name="lp">Last played</string>
<string name="programme">Programme</string>
</resources> </resources>