Skip to content

Commit 52546bd

Browse files
authored
Add a PillarboxCastPlayer and update the demo (#875)
1 parent eee45c9 commit 52546bd

File tree

6 files changed

+123
-11
lines changed

6 files changed

+123
-11
lines changed

pillarbox-cast/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/*
2+
* Copyright (c) SRG SSR. All rights reserved.
3+
* License information is available from the LICENSE file.
4+
*/
15
plugins {
26
alias(libs.plugins.pillarbox.android.library)
37
alias(libs.plugins.pillarbox.android.library.compose)
@@ -6,6 +10,7 @@ plugins {
610
}
711

812
dependencies {
13+
implementation(project(":pillarbox-player"))
914
implementation(platform(libs.androidx.compose.bom))
1015
api(libs.androidx.compose.runtime)
1116
api(libs.androidx.compose.ui)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright (c) SRG SSR. All rights reserved.
3+
* License information is available from the LICENSE file.
4+
*/
5+
package ch.srgssr.pillarbox.cast
6+
7+
import androidx.media3.cast.CastPlayer
8+
import androidx.media3.cast.SessionAvailabilityListener
9+
import androidx.media3.common.ForwardingPlayer
10+
import ch.srgssr.pillarbox.player.PillarboxPlayer
11+
import com.google.android.gms.cast.MediaQueueItem
12+
import com.google.android.gms.cast.framework.CastContext
13+
14+
/**
15+
* A [PillarboxPlayer] implementation that forwards calls to a [CastPlayer].
16+
*
17+
* It disables smooth seeking and tracking capabilities as these are not supported or relevant in the context of Cast playback.
18+
*
19+
* @param castPlayer The underlying [CastPlayer] instance to which method calls will be forwarded.
20+
*/
21+
class PillarboxCastPlayer(private val castPlayer: CastPlayer) : PillarboxPlayer, ForwardingPlayer(castPlayer) {
22+
override var smoothSeekingEnabled: Boolean = false
23+
set(value) {
24+
field = false
25+
}
26+
27+
override var trackingEnabled: Boolean = false
28+
set(value) {
29+
field = false
30+
}
31+
32+
constructor(context: CastContext) : this(CastPlayer(context))
33+
34+
/**
35+
* Returns the item that corresponds to the period with the given id, or `null` if no media queue or period with id [periodId] exist.
36+
*
37+
* @param periodId The id of the period ([getCurrentTimeline]) that corresponds to the item to get.
38+
* @return The item that corresponds to the period with the given id, or `null` if no media queue or period with id [periodId] exist.
39+
*/
40+
fun getItem(periodId: Int): MediaQueueItem? {
41+
return castPlayer.getItem(periodId)
42+
}
43+
44+
/**
45+
* Returns whether a cast session is available.
46+
*/
47+
fun isCastSessionAvailable(): Boolean {
48+
return castPlayer.isCastSessionAvailable
49+
}
50+
51+
/**
52+
* Sets a listener for updates on the cast session availability.
53+
*
54+
* @param listener The [SessionAvailabilityListener], or `null` to clear the listener.
55+
*/
56+
fun setSessionAvailabilityListener(listener: SessionAvailabilityListener?) {
57+
castPlayer.setSessionAvailabilityListener(listener)
58+
}
59+
}

pillarbox-demo-cast/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ plugins {
99
dependencies {
1010
implementation(project(":pillarbox-demo-shared"))
1111
implementation(project(":pillarbox-cast"))
12+
implementation(project(":pillarbox-ui"))
1213
implementation(libs.androidx.activity)
1314
implementation(libs.androidx.activity.compose)
1415
implementation(platform(libs.androidx.compose.bom))
@@ -17,7 +18,6 @@ dependencies {
1718
implementation(libs.androidx.compose.material3)
1819
implementation(libs.androidx.compose.runtime)
1920
implementation(libs.androidx.compose.ui)
20-
implementation(libs.androidx.compose.ui.text)
2121
debugImplementation(libs.androidx.compose.ui.tooling)
2222
implementation(libs.androidx.compose.ui.tooling.preview)
2323
implementation(libs.androidx.compose.ui.unit)

pillarbox-demo-cast/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright (c) SRG SSR. All rights reserved.
4+
~ License information is available from the LICENSE file.
5+
-->
26
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
37

48
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
59

610
<application
11+
android:name=".CastApplication"
712
android:allowBackup="true"
813
android:icon="@mipmap/ic_launcher_pillarbox"
914
android:label="@string/app_name"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) SRG SSR. All rights reserved.
3+
* License information is available from the LICENSE file.
4+
*/
5+
package ch.srgssr.pillarbox.demo.cast
6+
7+
import android.app.Application
8+
import ch.srgssr.pillarbox.cast.getCastContext
9+
import com.google.android.gms.cast.framework.CastContext
10+
11+
/**
12+
* [CastApplication] initializes Google Cast functionality by setting up the [CastContext].
13+
*/
14+
class CastApplication : Application() {
15+
override fun onCreate() {
16+
super.onCreate()
17+
18+
getCastContext()
19+
}
20+
}

pillarbox-demo-cast/src/main/java/ch/srgssr/pillarbox/demo/cast/MainActivity.kt

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,65 @@ package ch.srgssr.pillarbox.demo.cast
77
import android.os.Bundle
88
import androidx.activity.compose.setContent
99
import androidx.activity.enableEdgeToEdge
10-
import androidx.compose.foundation.layout.Box
1110
import androidx.compose.foundation.layout.fillMaxSize
1211
import androidx.compose.foundation.layout.padding
1312
import androidx.compose.material3.Scaffold
14-
import androidx.compose.material3.Text
1513
import androidx.compose.runtime.Composable
14+
import androidx.compose.runtime.remember
1615
import androidx.compose.ui.Modifier
1716
import androidx.compose.ui.tooling.preview.Preview
1817
import androidx.fragment.app.FragmentActivity
18+
import androidx.media3.cast.SessionAvailabilityListener
19+
import androidx.media3.common.MediaItem
20+
import androidx.media3.common.MimeTypes
21+
import ch.srgssr.pillarbox.cast.PillarboxCastPlayer
1922
import ch.srgssr.pillarbox.cast.getCastContext
2023
import ch.srgssr.pillarbox.cast.widget.CastButton
2124
import ch.srgssr.pillarbox.demo.cast.ui.theme.PillarboxTheme
25+
import ch.srgssr.pillarbox.ui.exoplayer.ExoPlayerView
2226

2327
/**
2428
* Activity showing how to use Cast with Pillarbox.
2529
*/
2630
class MainActivity : FragmentActivity() {
2731
override fun onCreate(savedInstanceState: Bundle?) {
2832
super.onCreate(savedInstanceState)
29-
// Force creation CastContext
30-
getCastContext()
3133

3234
enableEdgeToEdge()
35+
3336
setContent {
37+
val player = remember {
38+
PillarboxCastPlayer(getCastContext()).apply {
39+
val mediaItem = MediaItem.Builder()
40+
.setMimeType(MimeTypes.VIDEO_MP4)
41+
.setUri("https://storage.googleapis.com/wvmedia/clear/h264/tears/tears.mpd")
42+
.build()
43+
44+
setSessionAvailabilityListener(object : SessionAvailabilityListener {
45+
override fun onCastSessionAvailable() {
46+
setMediaItem(mediaItem)
47+
}
48+
49+
override fun onCastSessionUnavailable() {
50+
release()
51+
}
52+
})
53+
}
54+
}
55+
3456
PillarboxTheme {
3557
Scaffold(
3658
modifier = Modifier.fillMaxSize(),
3759
floatingActionButton = {
3860
CastButton()
39-
}
61+
},
4062
) { innerPadding ->
41-
Box(
42-
modifier = Modifier.padding(innerPadding)
43-
) {
44-
Text(text = "Demo showing the cast button!")
45-
}
63+
ExoPlayerView(
64+
player = player,
65+
modifier = Modifier
66+
.padding(innerPadding)
67+
.fillMaxSize(),
68+
)
4669
}
4770
}
4871
}

0 commit comments

Comments
 (0)