Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Releases/v1.2.0 #67

Merged
merged 1 commit into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@ package com.mux.player.media3.examples

import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata
import androidx.media3.common.PlaybackException
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.ViewHolder
import com.mux.stats.sdk.core.model.CustomData
import com.mux.stats.sdk.core.model.CustomerData
import com.mux.stats.sdk.core.model.CustomerVideoData
Expand All @@ -21,6 +29,8 @@ import com.mux.stats.sdk.core.util.UUID
import com.mux.player.MuxPlayer
import com.mux.player.media3.R
import com.mux.player.media3.databinding.ActivityConfigurablePlayerBinding
import com.mux.player.media3.databinding.NumericParamEntryBinding
import com.mux.player.media3.databinding.TextParamEntryBinding

/**
* A configurable example that uses the normal media3 player UI to play a video in the foreground from
Expand All @@ -46,40 +56,31 @@ class ConfigurablePlayerActivity : AppCompatActivity() {
playbackParamsHelper.restoreInstanceState(savedInstanceState)
}

binding.configurablePlayerPlaybackIdIn.hint = playbackParamsHelper.playbackIdOrDefault()
binding.configurablePlayerPlaybackId.hint = playbackParamsHelper.playbackIdOrDefault()
binding.configurablePlayerPlaybackId.onClear = { playbackParamsHelper.playbackId = null }
binding.configurablePlayerCustomDomain.onClear = { playbackParamsHelper.customDomain = null }
binding.configurablePlayerInstantclipStart.onClear =
{ playbackParamsHelper.assetStartTime = null }
binding.configurablePlayerInstantclipEnd.onClear = { playbackParamsHelper.assetEndTime = null }
binding.configurablePlayerPlaybackToken.onClear = { playbackParamsHelper.playbackToken = null }
binding.configurablePlayerDrmToken.onClear = { playbackParamsHelper.drmToken = null }

binding.configurablePlayerUpdateMediaItem.setOnClickListener {
playbackParamsHelper.playbackId = binding.configurablePlayerPlaybackIdIn.text?.trim()?.toString()
playbackParamsHelper.playbackToken =
binding.configurablePlayerPlaybackTokenIn.text?.trim()?.toString()
playbackParamsHelper.drmToken = binding.configurablePlayerDrmTokenIn.text?.trim()?.toString()
playbackParamsHelper.customDomain = binding.configurablePlayerDomainIn.text?.trim()?.toString()
playbackParamsHelper.playbackId = binding.configurablePlayerPlaybackId.entry
playbackParamsHelper.playbackToken = binding.configurablePlayerPlaybackToken.entry
playbackParamsHelper.drmToken = binding.configurablePlayerDrmToken.entry
playbackParamsHelper.customDomain = binding.configurablePlayerCustomDomain.entry
playbackParamsHelper.assetStartTime = binding.configurablePlayerInstantclipStart.entry
playbackParamsHelper.assetEndTime = binding.configurablePlayerInstantclipEnd.entry

maybePlayMediaItem(playbackParamsHelper.createMediaItem())
}
binding.configurablePlaybackIdClear.setOnClickListener {
binding.configurablePlayerPlaybackIdIn.text = null
playbackParamsHelper.playbackId = null
}
binding.configurablePlayerDrmTokenClear.setOnClickListener {
binding.configurablePlayerDrmTokenIn.text = null
playbackParamsHelper.drmToken = null
}
binding.configurablePlayerPlaybackTokenClear.setOnClickListener {
binding.configurablePlayerPlaybackTokenIn.text = null
playbackParamsHelper.playbackToken = null
}
binding.configurablePlayerDomainClear.setOnClickListener {
binding.configurablePlayerDomainIn.text = null
playbackParamsHelper.customDomain = null
}
}

override fun onStart() {
super.onStart()

val mediaItem = playbackParamsHelper.createMediaItem()

maybePlayMediaItem(mediaItem)
}

Expand Down Expand Up @@ -168,7 +169,6 @@ class ConfigurablePlayerActivity : AppCompatActivity() {

out.addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
// todo - better error info than this, inline in ui
Log.e(TAG, "player error!", error)
Toast.makeText(
this@ConfigurablePlayerActivity,
Expand All @@ -185,3 +185,109 @@ class ConfigurablePlayerActivity : AppCompatActivity() {
val TAG = ConfigurablePlayerActivity::class.simpleName
}
}

class TextParamEntryView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

private val binding: TextParamEntryBinding = TextParamEntryBinding.inflate(
LayoutInflater.from(context),
this,
true
)

init {
context.theme.obtainStyledAttributes(attrs, R.styleable.TextParamEntryView, 0, R.style.Theme_MuxVideoMedia3).apply {
try {
hint = getString(R.styleable.TextParamEntryView_hint)
} finally {
recycle()
}
}
context.theme.obtainStyledAttributes(attrs, R.styleable.ParamEntry, 0, 0).apply {
try {
title = getString(R.styleable.ParamEntry_title)
} finally {
recycle()
}
}
binding.textParamEntryClear.setOnClickListener {
binding.textParamEntryIn.text = null
onClear?.invoke()
}
}

var title: CharSequence? = null
set(value) {
binding.textParamEntryLbl.text = value
field = value
}
var hint: CharSequence? = null
set(value) {
binding.textParamEntryIn.hint = value
field = value
}

var onClear: (() -> Unit)? = null
val entry: String? get() {
val text = binding.textParamEntryIn.text?.trim()?.ifEmpty { null }?.toString()
return text
}
}

class NumericParamEntryView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {

private val binding: NumericParamEntryBinding = NumericParamEntryBinding.inflate(
LayoutInflater.from(context),
this,
true
)

init {
context.theme.obtainStyledAttributes(attrs, R.styleable.NumericParamEntryView, 0, 0).apply {
try {
hint = getFloat(R.styleable.NumericParamEntryView_hint_num, Float.NaN)
.toDouble()
.takeIf { !it.isNaN() }
} finally {
recycle()
}
}
context.theme.obtainStyledAttributes(attrs, R.styleable.ParamEntry, 0, 0).apply {
try {
title = getString(R.styleable.ParamEntry_title)
} finally {
recycle()
}
}

binding.numericParamEntryClear.setOnClickListener {
binding.numericParamEntryIn.text = null
onClear?.invoke()
}
}

var title: CharSequence? = null
set(value) {
binding.numericParamEntryLbl.text = value
field = value
}
var hint: Double? = null
set(value) {
binding.numericParamEntryIn.hint = value?.toString()
field = value
}

var onClear: (() -> Unit)? = null
val entry: Double? get() {
val text =
binding.numericParamEntryIn.text?.trim()?.ifEmpty { null }?.toString()?.toDoubleOrNull()
return text
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ class PlaybackParamsHelper {
var drmToken: String? = null
var playbackId: String? = null
var customDomain: String? = null
var assetStartTime: Double? = null
var assetEndTime: Double? = null

fun createMediaItemBuilder(): MediaItem.Builder {
return MediaItems.builderFromMuxPlaybackId(
playbackId = playbackIdOrDefault(),
minResolution = minRes,
maxResolution = maxRes,
renditionOrder = renditionOrder,
assetStartTime = assetStartTime,
assetEndTime = assetEndTime,
playbackToken = playbackToken?.ifEmpty { null },
drmToken = drmToken?.ifEmpty { null },
domain = customDomain?.ifEmpty { null },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,33 +38,25 @@ class SmartCacheActivity : AppCompatActivity() {
playbackParamsHelper.restoreInstanceState(savedInstanceState)
}

binding.configurablePlayerPlaybackIdIn.hint = playbackParamsHelper.playbackIdOrDefault()
binding.configurablePlayerPlaybackId.hint = playbackParamsHelper.playbackIdOrDefault()
binding.configurablePlayerPlaybackId.onClear = { playbackParamsHelper.playbackId = null }
binding.configurablePlayerCustomDomain.onClear = { playbackParamsHelper.customDomain = null }
binding.configurablePlayerInstantclipStart.onClear =
{ playbackParamsHelper.assetStartTime = null }
binding.configurablePlayerInstantclipEnd.onClear = { playbackParamsHelper.assetEndTime = null }
binding.configurablePlayerPlaybackToken.onClear = { playbackParamsHelper.playbackToken = null }
binding.configurablePlayerDrmToken.onClear = { playbackParamsHelper.drmToken = null }

binding.configurablePlayerUpdateMediaItem.setOnClickListener {
playbackParamsHelper.playbackId = binding.configurablePlayerPlaybackIdIn.text?.trim()?.toString()
playbackParamsHelper.playbackToken =
binding.configurablePlayerPlaybackTokenIn.text?.trim()?.toString()
playbackParamsHelper.drmToken = binding.configurablePlayerDrmTokenIn.text?.trim()?.toString()
playbackParamsHelper.customDomain = binding.configurablePlayerDomainIn.text?.trim()?.toString()
playbackParamsHelper.playbackId = binding.configurablePlayerPlaybackId.entry
playbackParamsHelper.playbackToken = binding.configurablePlayerPlaybackToken.entry
playbackParamsHelper.drmToken = binding.configurablePlayerDrmToken.entry
playbackParamsHelper.customDomain = binding.configurablePlayerCustomDomain.entry
playbackParamsHelper.assetStartTime = binding.configurablePlayerInstantclipStart.entry
playbackParamsHelper.assetEndTime = binding.configurablePlayerInstantclipEnd.entry

maybePlayMediaItem(playbackParamsHelper.createMediaItem())
}
binding.configurablePlaybackIdClear.setOnClickListener {
binding.configurablePlayerPlaybackIdIn.text = null
playbackParamsHelper.playbackId = null
}
binding.configurablePlayerDrmTokenClear.setOnClickListener {
binding.configurablePlayerDrmTokenIn.text = null
playbackParamsHelper.drmToken = null
}
binding.configurablePlayerPlaybackTokenClear.setOnClickListener {
binding.configurablePlayerPlaybackTokenIn.text = null
playbackParamsHelper.playbackToken = null
}
binding.configurablePlayerDomainClear.setOnClickListener {
binding.configurablePlayerDomainIn.text = null
playbackParamsHelper.customDomain = null
}
}

override fun onStart() {
Expand Down Expand Up @@ -139,7 +131,6 @@ class SmartCacheActivity : AppCompatActivity() {

out.addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
// todo - better error info than this, inline in ui
Log.e(TAG, "player error!", error)
Toast.makeText(
this@SmartCacheActivity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,13 @@ class PlayerCarouselActivity : AppCompatActivity() {
adapter = { adapter }
)

carousel.addOnChildAttachStateChangeListener(object : RecyclerView.OnChildAttachStateChangeListener {
carousel.addOnChildAttachStateChangeListener(object :
RecyclerView.OnChildAttachStateChangeListener {
override fun onChildViewAttachedToWindow(view: View) {
// If the player is idle when we bind, the UI is initializing and we should autoplay
if (viewModel.player.playbackState == Player.STATE_IDLE
|| viewModel.player.currentMediaItem == null) {
|| viewModel.player.currentMediaItem == null
) {
val item = adapter.items[0]
viewModel.changeMediaItem(item.mediaItem)
viewModel.playIntoView(view.findViewById(R.id.item_fullscreen_player_playerview))
Expand All @@ -66,6 +68,7 @@ class PlayerCarouselActivity : AppCompatActivity() {
Log.d("PlayerCarouselActivity", "Player was idle. Autoplaying")
}
}

override fun onChildViewDetachedFromWindow(view: View) {
}
})
Expand All @@ -88,13 +91,21 @@ class PlayerCarouselActivity : AppCompatActivity() {
title = "Tears of Steel",
description = "A time travel story with really cool high-quality CGI and some truly" +
" powerful dialogue writing",
mediaItem = MediaItems.fromMuxPlaybackId(PlaybackIds.TEARS_OF_STEEL),
mediaItem = MediaItems.fromMuxPlaybackId(
PlaybackIds.TEARS_OF_STEEL,
assetStartTime = 25.0,
assetEndTime = 35.0,
),
),
CarouselItem(
title = "Sintel",
description = "A knight meets a baby dragon and together they do some adventure stuff." +
" The dragon is super adorable, I forget what actually happens though",
mediaItem = MediaItems.fromMuxPlaybackId(PlaybackIds.SINTEL),
" PS, adorable monster alert",
mediaItem = MediaItems.fromMuxPlaybackId(
PlaybackIds.SINTEL,
assetStartTime = 240.0,
assetEndTime = 285.0,
),
),
CarouselItem(
title = "Robot shooting a bird",
Expand All @@ -104,12 +115,20 @@ class PlayerCarouselActivity : AppCompatActivity() {
CarouselItem(
title = "Making of Sintel",
description = "A documentary about the making of Sintel",
mediaItem = MediaItems.fromMuxPlaybackId(PlaybackIds.MAKING_OF_SINTEL),
mediaItem = MediaItems.fromMuxPlaybackId(
PlaybackIds.MAKING_OF_SINTEL,
assetStartTime = 140.0,
assetEndTime = 300.0,
),
),
CarouselItem(
title = "Big Buck Bunny",
description = "A rabbit gets harassed by a bunch of punk squirrels.",
mediaItem = MediaItems.fromMuxPlaybackId(PlaybackIds.BIG_BUCK_BUNNY),
mediaItem = MediaItems.fromMuxPlaybackId(
PlaybackIds.BIG_BUCK_BUNNY,
assetStartTime = 200.0,
assetEndTime = 260.0,
),
),
CarouselItem(
title = "Mux Marketing Video",
Expand All @@ -124,13 +143,21 @@ class PlayerCarouselActivity : AppCompatActivity() {
title = "Making of Big Buck Bunny",
description = "A group of nerds talk about making big buck bunny, presumably because they " +
"were the ones that did that",
mediaItem = MediaItems.fromMuxPlaybackId(PlaybackIds.MAKING_OF_BUCK_BUNNY),
mediaItem = MediaItems.fromMuxPlaybackId(
PlaybackIds.MAKING_OF_BUCK_BUNNY,
assetStartTime = 0.0,
assetEndTime = 30.0,
),
),
CarouselItem(
title = "Elephant's Dream",
description = "A surreal fantasy action movie. The first Open Movie Project movie. It's " +
"old but kinda trippy",
mediaItem = MediaItems.fromMuxPlaybackId(PlaybackIds.ELEPHANTS_DREAM),
mediaItem = MediaItems.fromMuxPlaybackId(
PlaybackIds.ELEPHANTS_DREAM,
assetStartTime = 300.0,
assetEndTime = 450.0,
),
),
CarouselItem(
title = "View From a Blue Moon",
Expand Down
Loading
Loading