added current programme calculation. Added dummy fragment.
parent
ef83c693d0
commit
0218dfab75
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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> {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue