Last active
June 14, 2018 06:49
-
-
Save clackbib/1cb6a617e9d051ad7315dd6ad75750cd to your computer and use it in GitHub Desktop.
Ideas for MediaPlayer/Exoplayer Kotlin extensions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.util.Log | |
import com.google.android.exoplayer2.ExoPlaybackException | |
import com.google.android.exoplayer2.PlaybackParameters | |
import com.google.android.exoplayer2.Player | |
import com.google.android.exoplayer2.Timeline | |
import com.google.android.exoplayer2.source.TrackGroupArray | |
import com.google.android.exoplayer2.trackselection.TrackSelectionArray | |
private fun sample(player: Player) { | |
player.setup { | |
onLoadingChange { | |
Log.d("SAMPLE", "Loading = $it") | |
} | |
onError { exception -> | |
exception?.let { | |
Log.e("SAMPLE", it.message, it) | |
} | |
} | |
onTracksChanged { tracks, selections -> | |
Log.d("SAMPLE", "TrackGroupArray size=${tracks?.length}") | |
Log.d("SAMPLE", "TrackSelectionArray size=${selections?.length}") | |
} | |
} | |
} | |
private fun sampleDesugared(player: Player) { | |
player.addListener(object : Player.EventListener { | |
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) { | |
Log.d("SAMPLE", "TrackGroupArray size=${trackGroups?.length}") | |
Log.d("SAMPLE", "TrackSelectionArray size=${trackSelections?.length}") | |
} | |
override fun onPlayerError(error: ExoPlaybackException?) { | |
error?.let { | |
Log.e("SAMPLE", it.message, it) | |
} | |
} | |
override fun onLoadingChanged(isLoading: Boolean) { | |
Log.d("SAMPLE", "Loading = $isLoading") | |
} | |
override fun onPositionDiscontinuity(reason: Int) { | |
// noop | |
} | |
override fun onRepeatModeChanged(repeatMode: Int) { | |
// noop | |
} | |
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) { | |
// noop | |
} | |
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?) { | |
// noop | |
} | |
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { | |
// noop | |
} | |
override fun onSeekProcessed() { | |
// noop | |
} | |
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) { | |
// noop | |
} | |
}) | |
} | |
class PlayerListenerBuilder { | |
private var onPlaybackParameters: ((PlaybackParameters?) -> Unit)? = null | |
private var onSeek: (() -> Unit)? = null | |
private var onTracksChanged: ((TrackGroupArray?, TrackSelectionArray?) -> Unit)? = null | |
private var onError: ((ExoPlaybackException?) -> Unit)? = null | |
private var onLoadingChange: ((Boolean?) -> Unit)? = null | |
private var onShuffleChange: ((Boolean?) -> Unit)? = null | |
private var onPositionDiscontinuity: ((Int?) -> Unit)? = null | |
private var onRepeatModeChange: ((Int?) -> Unit)? = null | |
private var onTimelineChange: ((Timeline?, Any?) -> Unit)? = null | |
private var onPlayerState: ((Boolean, Int) -> Unit)? = null | |
fun onPlaybackParameters(callback: ((PlaybackParameters?) -> Unit)) { | |
onPlaybackParameters = callback | |
} | |
fun onSeek(callback: (() -> Unit)) { | |
onSeek = callback | |
} | |
fun onTracksChanged(callback: (TrackGroupArray?, TrackSelectionArray?) -> Unit) { | |
onTracksChanged = callback | |
} | |
fun onError(callback: (ExoPlaybackException?) -> Unit) { | |
onError = callback | |
} | |
fun onLoadingChange(callback: (Boolean?) -> Unit) { | |
onLoadingChange = callback | |
} | |
fun onShuffleChange(callback: (Boolean?) -> Unit) { | |
onShuffleChange = callback | |
} | |
fun onPositionDiscontinuity(callback: (Int?) -> Unit) { | |
this.onPositionDiscontinuity = callback | |
} | |
fun onRepeatModeChange(callback: (Int?) -> Unit) { | |
onRepeatModeChange = callback | |
} | |
fun onTimelineChange(callback: (Timeline?, Any?) -> Unit) { | |
onTimelineChange = callback | |
} | |
fun onPlayerState(callback: (Boolean, Int) -> Unit) { | |
onPlayerState = callback | |
} | |
fun build(): Player.EventListener { | |
return object : Player.EventListener { | |
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters?) { | |
onPlaybackParameters?.invoke(playbackParameters) | |
} | |
override fun onSeekProcessed() { | |
onSeek?.invoke() | |
} | |
override fun onTracksChanged(trackGroups: TrackGroupArray?, trackSelections: TrackSelectionArray?) { | |
onTracksChanged?.invoke(trackGroups, trackSelections) | |
} | |
override fun onPlayerError(error: ExoPlaybackException?) { | |
onError?.invoke(error) | |
} | |
override fun onLoadingChanged(isLoading: Boolean) { | |
onLoadingChange?.invoke(isLoading) | |
} | |
override fun onPositionDiscontinuity(reason: Int) { | |
onPositionDiscontinuity?.invoke(reason) | |
} | |
override fun onRepeatModeChanged(repeatMode: Int) { | |
onRepeatModeChange?.invoke(repeatMode) | |
} | |
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) { | |
onShuffleChange?.invoke(shuffleModeEnabled) | |
} | |
override fun onTimelineChanged(timeline: Timeline?, manifest: Any?) { | |
onTimelineChange?.invoke(timeline, manifest) | |
} | |
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) { | |
onPlayerState?.invoke(playWhenReady, playbackState) | |
} | |
} | |
} | |
} | |
fun Player.setup(configure: PlayerListenerBuilder.() -> Unit) { | |
val builder = PlayerListenerBuilder() | |
builder.configure() | |
this.addListener(builder.build()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import android.net.Uri | |
import com.google.android.exoplayer2.ExoPlayer | |
import com.google.android.exoplayer2.PlaybackParameters | |
import com.google.android.exoplayer2.Player | |
import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource | |
import com.google.android.exoplayer2.source.ExtractorMediaSource | |
import com.google.android.exoplayer2.source.MediaSource | |
private fun sampleUsage(mediaSourceFactory: ExtractorMediaSource.Factory, | |
player: ExoPlayer, | |
uris: List<Uri>) { | |
val playlist = listOf(Uri.parse("http://sampleaudio.com/random.mp3"), | |
Uri.parse("file://downloads/random2.mp3"), | |
Uri.parse("file://downloads/random3.mp3")) | |
.toMediaSource(mediaSourceFactory) | |
val playlist2 = uris.toMediaSource(mediaSourceFactory) | |
player.prepare(playlist - 1 + playlist2) { | |
playWhenReady = true | |
shuffleModeEnabled = false | |
repeatMode = Player.REPEAT_MODE_ALL | |
playbackParameters = PlaybackParameters(1.2f, 0.8f) | |
} | |
} | |
private fun sampleUsageDesugared(mediaSourceFactory: ExtractorMediaSource.Factory, | |
player: ExoPlayer, | |
uris: List<Uri>) { | |
val trackOne = mediaSourceFactory.createMediaSource(Uri.parse("http://sampleaudio.com/random.mp3")) | |
val trackTwo = mediaSourceFactory.createMediaSource(Uri.parse("file://downloads/random2.mp3")) | |
val trackThree = mediaSourceFactory.createMediaSource(Uri.parse("file://downloads/random3.mp3")) | |
val playlist = DynamicConcatenatingMediaSource() | |
playlist.addMediaSource(trackOne) | |
playlist.addMediaSource(trackTwo) | |
playlist.addMediaSource(trackThree) | |
val playlist2 = DynamicConcatenatingMediaSource() | |
for (uri: Uri in uris) { | |
playlist2.addMediaSource(mediaSourceFactory.createMediaSource(uri)) | |
} | |
val playlist3 = DynamicConcatenatingMediaSource() | |
playlist3.addMediaSource(playlist) | |
playlist.removeMediaSource(1) | |
playlist3.addMediaSource(playlist2) | |
player.playWhenReady = true | |
player.shuffleModeEnabled = false | |
player.repeatMode = Player.REPEAT_MODE_ALL | |
player.playbackParameters = PlaybackParameters(1.2f, 0.8f) | |
player.prepare(playlist3) | |
} | |
operator fun MediaSource.plus(other: MediaSource): DynamicConcatenatingMediaSource { | |
val source = DynamicConcatenatingMediaSource() | |
source.addMediaSource(this) | |
source.addMediaSource(other) | |
return source | |
} | |
operator fun DynamicConcatenatingMediaSource.minus(atIndex: Int): DynamicConcatenatingMediaSource { | |
this.removeMediaSource(atIndex) | |
return this | |
} | |
operator fun DynamicConcatenatingMediaSource.plus(other: MediaSource): DynamicConcatenatingMediaSource { | |
this.addMediaSource(other) | |
return this | |
} | |
operator fun DynamicConcatenatingMediaSource.plusAssign(other: MediaSource) { | |
this + other | |
} | |
operator fun DynamicConcatenatingMediaSource.minusAssign(atIndex: Int) { | |
this - atIndex | |
} | |
operator fun DynamicConcatenatingMediaSource.get(index: Int): MediaSource? { | |
return this.getMediaSource(index) | |
} | |
inline fun ExoPlayer.prepare(mediaSource: MediaSource, config: ExoPlayer.() -> Unit) { | |
config() | |
this.prepare(mediaSource) | |
} | |
operator fun Uri.plus(otherUri: Uri): MutableList<Uri> { | |
return mutableListOf(this, otherUri) | |
} | |
operator fun MutableList<Uri>.plus(otherUri: Uri): MutableList<Uri> { | |
this.add(otherUri) | |
return this | |
} | |
fun List<Uri>.toMediaSource(factory: ExtractorMediaSource.Factory): DynamicConcatenatingMediaSource { | |
val source = DynamicConcatenatingMediaSource() | |
this.forEach { | |
source += it.toMediaSource(factory) | |
} | |
return source | |
} | |
fun Uri.toMediaSource(factory: ExtractorMediaSource.Factory): MediaSource { | |
return factory.createMediaSource(this) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment