Skip to content

Commit

Permalink
Implemented playlists
Browse files Browse the repository at this point in the history
  • Loading branch information
reactormonk committed Jun 15, 2023
1 parent a8d2924 commit 40e6ea0
Show file tree
Hide file tree
Showing 23 changed files with 405 additions and 20 deletions.
4 changes: 4 additions & 0 deletions chromecast-receiver/js/io/SenderMessagesDispatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ function SenderMessagesDispatcher(communicationConstants, callbacks) {
callbacks.loadVideo(message.data.videoId, Number(message.data.startSeconds))
else if(message.data.command === communicationConstants.CUE)
callbacks.cueVideo(message.data.videoId, Number(message.data.startSeconds))
else if(message.data.command === communicationConstants.LOAD_PLAYLIST)
callbacks.loadPlaylist(message.data.playlistId, message.data.playlistIndex, Number(message.data.startSeconds))
else if(message.data.command === communicationConstants.CUE_PLAYLIST)
callbacks.cuePlaylist(message.data.playlistId, message.data.playlistIndex, Number(message.data.startSeconds))
else if(message.data.command === communicationConstants.PLAY)
callbacks.playVideo()
else if(message.data.command === communicationConstants.PAUSE)
Expand Down
27 changes: 27 additions & 0 deletions chromecast-receiver/js/io/YouTubePlayerRemoteBridge.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,28 @@ function YouTubePlayerRemoteBridge(communicationConstants, communicationChannel)
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.VIDEO_ID, data))
}

function sendPlaylistId(playlist) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.PLAYLIST_ID, playlist))
}
function sendPlaylistIndex(playlist) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.PLAYLIST_INDEX, index))
}
function sendPlaylistType(playlistType) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.PLAYLIST_TYPE, playlistType))
}
function sendPlaylistLength(length) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.PLAYLIST_LENGTH, length))
}
function sendVideoList(videos) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.VIDEO_LIST, videos))
}
function sendLoopStatus(loop) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.LOOP_STATUS, loop))
}
function sendShuffleStatus(shuffle) {
communicationChannel.sendMessage(new YouTubeMessage(communicationConstants.SHUFFLE_STATUS, shuffle))
}

return {
sendYouTubeIframeAPIReady: sendYouTubeIframeAPIReady,
sendReady: sendReady,
Expand All @@ -58,6 +80,11 @@ function YouTubePlayerRemoteBridge(communicationConstants, communicationChannel)
sendVideoCurrentTime: sendVideoCurrentTime,
sendVideoDuration: sendVideoDuration,
sendVideoId: sendVideoId,
sendPlaylistIndex: sendPlaylistIndex,
sendPlaylistId: sendPlaylistId,
sendPlaylistType: sendPlaylistType,
sendPlaylistLength: sendPlaylistLength,
sendVideoList: sendVideoList,
}
}

Expand Down
4 changes: 4 additions & 0 deletions chromecast-sender-sample-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ android {
}

namespace 'com.pierfrancescosoffritti.cyplayersample'
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}

dependencies {
Expand Down
4 changes: 4 additions & 0 deletions chromecast-sender/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ android {
]
}
namespace 'com.pierfrancescosoffritti.androidyoutubeplayer.chromecast.chromecastsender'
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,42 @@ class ChromecastYouTubePlayer internal constructor(private val chromecastCommuni
chromecastCommunicationChannel.sendMessage(message)
}

override fun loadPlaylist(videos: List<String>, index: Int, startSeconds: Float) {
TODO("Not yet implemented")
}

override fun loadPlaylist(list: String, listType: String, index: Int, startSeconds: Float) {
TODO("Not yet implemented")
}

override fun cuePlaylist(videos: List<String>, index: Int, startSeconds: Float) {
TODO("Not yet implemented")
}

override fun cuePlaylist(list: String, listType: String, index: Int, startSeconds: Float) {
TODO("Not yet implemented")
}

override fun setLoop(loop: Boolean) {
TODO("Not yet implemented")
}

override fun setShuffle(shuffle: Boolean) {
TODO("Not yet implemented")
}

override fun nextVideo() {
TODO("Not yet implemented")
}

override fun previousVideo() {
TODO("Not yet implemented")
}

override fun playVideoAt(index: Int) {
TODO("Not yet implemented")
}

override fun play() {
val message = JSONUtils.buildFlatJson(
"command" to ChromecastCommunicationConstants.PLAY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.pierfrancescosoffritti.androidyoutubeplayer.chromecast.chromecastsend
* Set of constants used for sender-receiver communication. The sender will send the constants to the receiver when a connection is initiated.
*/
internal object ChromecastCommunicationConstants {

// receiver to sender
const val INIT_COMMUNICATION_CONSTANTS = "INIT_COMMUNICATION_CONSTANTS"

Expand All @@ -19,10 +20,21 @@ internal object ChromecastCommunicationConstants {
const val VIDEO_CURRENT_TIME = "VIDEO_CURRENT_TIME"
const val VIDEO_DURATION = "VIDEO_DURATION"
const val VIDEO_ID = "VIDEO_ID"
const val PLAYLIST_ID = "PLAYLIST_ID"
const val PLAYLIST_INDEX = "PLAYLIST_INDEX"
const val PLAYLIST_TYPE = "PLAYLIST_TYPE"
const val PLAYLIST_LENGTH = "PLAYLIST_LENGTH"
const val VIDEO_LIST = "VIDEO_LIST"
const val LOOP_STATUS = "LOOP_STATUS"
const val SHUFFLE_STATUS = "SHUFFLE_STATUS"

// sender to receiver
const val LOAD = "LOAD"
const val LOAD_PLAYLIST = "LOAD_PLAYLIST"
const val LOAD_PLAYLIST_OBJ = "LOAD_PLAYLIST_OBJ"
const val CUE = "CUE"
const val CUE_PLAYLIST = "CUE_PLAYLIST"
const val CUE_PLAYLIST_OBJ = "CUE_PLAYLIST_OBJ"
const val PLAY = "PLAY"
const val PAUSE = "PAUSE"
const val SET_VOLUME = "SET_VOLUME"
Expand All @@ -42,9 +54,20 @@ internal object ChromecastCommunicationConstants {
VIDEO_CURRENT_TIME to VIDEO_CURRENT_TIME,
VIDEO_DURATION to VIDEO_DURATION,
VIDEO_ID to VIDEO_ID,
PLAYLIST_ID to PLAYLIST_ID,
PLAYLIST_INDEX to PLAYLIST_INDEX,
PLAYLIST_TYPE to PLAYLIST_TYPE,
PLAYLIST_LENGTH to PLAYLIST_LENGTH,
VIDEO_LIST to VIDEO_LIST,
SHUFFLE_STATUS to SHUFFLE_STATUS,
LOOP_STATUS to LOOP_STATUS,

LOAD to LOAD,
LOAD_PLAYLIST to LOAD_PLAYLIST,
LOAD_PLAYLIST_OBJ to LOAD_PLAYLIST_OBJ,
CUE to CUE,
CUE_PLAYLIST to CUE_PLAYLIST,
CUE_PLAYLIST_OBJ to CUE_PLAYLIST_OBJ,
PLAY to PLAY,
PAUSE to PAUSE,
SET_VOLUME to SET_VOLUME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ internal class ChromecastYouTubeMessageDispatcher(
ChromecastCommunicationConstants.VIDEO_CURRENT_TIME -> bridge.sendVideoCurrentTime(messageFromReceiver.data)
ChromecastCommunicationConstants.VIDEO_DURATION -> bridge.sendVideoDuration(messageFromReceiver.data)
ChromecastCommunicationConstants.VIDEO_ID -> bridge.sendVideoId(messageFromReceiver.data)
ChromecastCommunicationConstants.PLAYLIST_ID -> bridge.sendPlaylistId(messageFromReceiver.data)
ChromecastCommunicationConstants.PLAYLIST_TYPE -> bridge.sendPlaylistType(messageFromReceiver.data)
ChromecastCommunicationConstants.PLAYLIST_LENGTH -> bridge.sendPlaylistLength(messageFromReceiver.data)
ChromecastCommunicationConstants.VIDEO_LIST -> bridge.sendVideoList(messageFromReceiver.data)
ChromecastCommunicationConstants.PLAYLIST_INDEX -> bridge.sendPlaylistIndex(messageFromReceiver.data)
}
}
}
8 changes: 4 additions & 4 deletions core-sample-app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ android {
}
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
packagingOptions {
resources {
// this is needed because I'm importing 2 modules called "core" (core and com.psoffritti.librarysampleapptemplate:core) (https://discuss.kotlinlang.org/t/disable-meta-inf-generation-in-gradle-android-project/3830)
Expand All @@ -32,6 +28,10 @@ android {
}

namespace 'com.pierfrancescosoffritti.aytplayersample'
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}

dependencies {
Expand Down
18 changes: 18 additions & 0 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,26 @@ android {
]
}
namespace 'com.pierfrancescosoffritti.androidyoutubeplayer'

compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
}

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}

kotlin {
jvmToolchain {
targetCompatibility = JavaVersion.VERSION_17
}
}


dependencies {
testImplementation "junit:junit:$versions.junit"
androidTestImplementation "androidx.test:runner:$versions.runner"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,23 @@ interface YouTubePlayer {
*/
fun cueVideo(videoId: String, startSeconds: Float)

fun loadPlaylist(videos: List<String>, index: Int, startSeconds: Float)
/**
* @param index Start index. if the index is out of range, youtube will only play the first video on the playlist, then stop.
*/
fun loadPlaylist(list: String, listType: String, index: Int, startSeconds: Float)

fun cuePlaylist(videos: List<String>, index: Int, startSeconds: Float)
/**
* @param index Start index. if the index is out of range, youtube will only play the first video on the playlist, then stop.
*/
fun cuePlaylist(list: String, listType: String, index: Int, startSeconds: Float)
fun setLoop(loop: Boolean)
fun setShuffle(shuffle: Boolean)
fun nextVideo()
fun previousVideo()
fun playVideoAt(index: Int)

fun play()
fun pause()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,62 @@ class YouTubePlayerBridge(private val youTubePlayerOwner: YouTubePlayerBridgeCal
youTubePlayerOwner.listeners.forEach { it.onVideoId(youTubePlayerOwner.getInstance(), videoId) }
}

@JavascriptInterface
fun sendPlaylistId(playlistId: String) = mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onPlaylistId(youTubePlayerOwner.getInstance(), playlistId) }
}
@JavascriptInterface
fun sendPlaylistType(playlistType: String) = mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onPlaylistType(youTubePlayerOwner.getInstance(), playlistType) }
}

@JavascriptInterface
fun sendPlaylistLength(data: String) {
val length = try {
data.toInt()
} catch (e: NumberFormatException) {
e.printStackTrace()
return
}
mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onPlaylistLength(youTubePlayerOwner.getInstance(), length) }
}
}

@JavascriptInterface
fun sendPlaylistIndex(playlistIndex: String) {
val index = try {
playlistIndex.toInt()
} catch (e: NumberFormatException) {
e.printStackTrace()
return
}
mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onPlaylistIndex(youTubePlayerOwner.getInstance(), index) }
}
}
@JavascriptInterface
fun sendVideoList(data: String) {
val list = data.split(",")
mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onVideoList(youTubePlayerOwner.getInstance(), list) }
}
}
@JavascriptInterface
fun sendLoopStatus(data: String) {
val loop = (data == "true")
mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onLoopStatus(youTubePlayerOwner.getInstance(), loop) }
}
}
@JavascriptInterface
fun sendShuffleStatus(data: String) {
val shuffle = (data == "true")
mainThreadHandler.post {
youTubePlayerOwner.listeners.forEach { it.onShuffleStatus(youTubePlayerOwner.getInstance(), shuffle) }
}
}

private fun parsePlayerState(state: String): PlayerConstants.PlayerState {
return when {
state.equals(STATE_UNSTARTED, ignoreCase = true) -> PlayerConstants.PlayerState.UNSTARTED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ abstract class AbstractYouTubePlayerListener : YouTubePlayerListener {
override fun onVideoDuration(youTubePlayer: YouTubePlayer, duration: Float) {}
override fun onVideoLoadedFraction(youTubePlayer: YouTubePlayer, loadedFraction: Float) {}
override fun onVideoId(youTubePlayer: YouTubePlayer, videoId: String) {}
override fun onPlaylistId(youTubePlayer: YouTubePlayer, playlistId: String) {}
override fun onPlaylistType(instance: YouTubePlayer, playlistType: String) {}
override fun onPlaylistIndex(youTubePlayer: YouTubePlayer, index: Int) {}
override fun onPlaylistLength(instance: YouTubePlayer, length: Int) {}
override fun onVideoList(instance: YouTubePlayer, list: List<String>) {}
override fun onLoopStatus(instance: YouTubePlayer, loop: Boolean) {}
override fun onShuffleStatus(instance: YouTubePlayer, loop: Boolean) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,11 @@ interface YouTubePlayerListener {
fun onVideoId(youTubePlayer: YouTubePlayer, videoId: String)

fun onApiChange(youTubePlayer: YouTubePlayer)
fun onPlaylistIndex(youTubePlayer: YouTubePlayer, index: Int)
fun onPlaylistId(youTubePlayer: YouTubePlayer, playlistId: String)
fun onVideoList(instance: YouTubePlayer, list: List<String>)
fun onPlaylistType(instance: YouTubePlayer, playlistType: String)
fun onPlaylistLength(instance: YouTubePlayer, length: Int)
fun onLoopStatus(instance: YouTubePlayer, loop: Boolean)
fun onShuffleStatus(instance: YouTubePlayer, loop: Boolean)
}
Loading

0 comments on commit 40e6ea0

Please sign in to comment.