Skip to content

Commit

Permalink
MediaItemTrackerData is immutable like MediaItem.
Browse files Browse the repository at this point in the history
  • Loading branch information
StaehliJ committed Feb 9, 2024
1 parent eaa43ab commit f29591e
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,17 @@ class MediaCompositionMediaItemSource(
if (resource.tokenType == Resource.TokenType.AKAMAI) {
uri = appendTokenQueryToUri(uri)
}
val trackerData = mediaItem.getMediaItemTrackerData()
trackerDataProvider?.update(trackerData, resource, chapter, result)
trackerData.putData(SRGEventLoggerTracker::class.java, null)
getComScoreData(result, chapter, resource)?.let {
trackerData.putData(ComScoreTracker::class.java, it)
}
getCommandersActData(result, chapter, resource)?.let {
trackerData.putData(CommandersActTracker::class.java, it)
}
val trackerData = mediaItem.getMediaItemTrackerData().buildUpon().apply {
trackerDataProvider?.update(this, resource, chapter, result)
putData(SRGEventLoggerTracker::class.java, null)
getComScoreData(result, chapter, resource)?.let {
putData(ComScoreTracker::class.java, it)
}
getCommandersActData(result, chapter, resource)?.let {
putData(CommandersActTracker::class.java, it)
}
}.build()

return mediaItem.buildUpon()
.setMediaMetadata(fillMetaData(mediaItem.mediaMetadata, chapter))
.setDrmConfiguration(fillDrmConfiguration(resource))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ interface TrackerDataProvider {
/**
* Update tracker data with given integration layer data.
*
* @param trackerData The [MediaItemTrackerData] to update.
* @param trackerData The [MediaItemTrackerData.Builder] to update.
* @param resource The selected [Resource].
* @param chapter The selected [Chapter].
* @param mediaComposition The loaded [MediaComposition].
*/
fun update(
trackerData: MediaItemTrackerData,
trackerData: MediaItemTrackerData.Builder,
resource: Resource,
chapter: Chapter,
mediaComposition: MediaComposition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fun MediaItem.getMediaItemTrackerDataOrNull(): MediaItemTrackerData? {
* @return current [MediaItemTrackerData] or create.
*/
fun MediaItem.getMediaItemTrackerData(): MediaItemTrackerData {
return getMediaItemTrackerDataOrNull() ?: MediaItemTrackerData()
return getMediaItemTrackerDataOrNull() ?: MediaItemTrackerData.EMPTY
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@
package ch.srgssr.pillarbox.player.tracker

/**
* MediaItem tracker data.
*
* @constructor Create empty Tracker data
* Immutable MediaItem tracker data.
*/
class MediaItemTrackerData {
private val map = HashMap<Class<*>, Any?>()
class MediaItemTrackerData private constructor(private val map: Map<Class<*>, Any?>) {

/**
* List of tracker class that have data.
Expand Down Expand Up @@ -43,13 +40,61 @@ class MediaItemTrackerData {
}

/**
* Put data for trackerClass
* Build upon
*
* @param T extends [MediaItemTracker].
* @param trackerClass The class of the [MediaItemTracker].
* @param data The data to associated with any instance of trackerClass.
* @return A builder filled with current data.
*/
fun <T : MediaItemTracker> putData(trackerClass: Class<T>, data: Any? = null) {
map[trackerClass] = data
fun buildUpon(): Builder = Builder(this)

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as MediaItemTrackerData

return map == other.map
}

override fun hashCode(): Int {
return map.hashCode()
}

override fun toString(): String {
return "MediaItemTrackerData(map=$map)"
}

companion object {
/**
* Empty [MediaItemTrackerData].
*/
val EMPTY = MediaItemTrackerData(emptyMap())
}

/**
* Builder
*y
* @param source set this builder with source value.
*/
class Builder(source: MediaItemTrackerData = EMPTY) {
private val map = HashMap<Class<*>, Any?>(source.map)

/**
* Put data for trackerClass
*
* @param T extends [MediaItemTracker].
* @param trackerClass The class of the [MediaItemTracker].
* @param data The data to associated with any instance of trackerClass.
*/
fun <T : MediaItemTracker> putData(trackerClass: Class<T>, data: Any? = null): Builder {
map[trackerClass] = data
return this
}

/**
* Build
*
* @return a new instance of [MediaItemTrackerData]
*/
fun build(): MediaItemTrackerData = MediaItemTrackerData(map.toMap())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ class MediaItemTest {

@Test
fun `getMediaItemTrackerData with tag set`() {
val mediaItemTrackerData = MediaItemTrackerData()
mediaItemTrackerData.putData(MediaItemTracker::class.java)
val mediaItemTrackerData = MediaItemTrackerData.Builder().apply {
putData(MediaItemTracker::class.java)
}.build()

val mediaItem = MediaItem.Builder()
.setUri(mockk<Uri>())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
/*
* Copyright (c) SRG SSR. All rights reserved.
* License information is available from the LICENSE file.
*/
package ch.srgssr.pillarbox.player.tracker

import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata
import androidx.media3.exoplayer.ExoPlayer
import androidx.test.ext.junit.runners.AndroidJUnit4
import ch.srgssr.pillarbox.player.extension.getMediaItemTrackerData
import ch.srgssr.pillarbox.player.extension.setTrackerData
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertFalse
import kotlin.test.assertTrue

@RunWith(AndroidJUnit4::class)
class CurrentMediaItemTrackerAreEqualTest {

@Test
fun `areEqual both mediaItem are null`() {
assertTrue(CurrentMediaItemTracker.areEqual(null, null))
}

@Test
fun `areEqual first mediaItem is null`() {
assertFalse(CurrentMediaItemTracker.areEqual(null, MediaItem.EMPTY))
}

@Test
fun `areEqual second mediaItem is null`() {
assertFalse(CurrentMediaItemTracker.areEqual(MediaItem.EMPTY, null))
}

@Test
fun `areEqual with different media id without tag and url`() {
val mediaItem = createMediaItemWithMediaId("M1")
val mediaItem2 = createMediaItemWithMediaId("M2")
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with same media id without tag and url`() {
val mediaItem = createMediaItemWithMediaId("M1")
val mediaItem2 = createMediaItemWithMediaId("M1")
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with one default media id`() {
val mediaItem = createMediaItemWithMediaId(MediaItem.DEFAULT_MEDIA_ID)
val mediaItem2 = createMediaItemWithMediaId("M1")
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with both default media id`() {
val mediaItem = createMediaItemWithMediaId(MediaItem.DEFAULT_MEDIA_ID)
val mediaItem2 = createMediaItemWithMediaId(MediaItem.DEFAULT_MEDIA_ID)
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with same media id same url same tag`() {
val mediaId = "M1"
val url = "https://streaming.com/video.mp4"
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag1")
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag1")
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with same media id same url without tag`() {
val mediaId = "M1"
val url = "https://streaming.com/video.mp4"
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url)
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = url)
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with same media id same url and different tag`() {
val mediaId = "M1"
val url = "https://streaming.com/video.mp4"
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = null)
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag2")
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual with same media id different url and same tag`() {
val mediaId = "M1"
val url = "https://streaming.com/video.mp4"
val mediaItem = createMediaItemWithMediaId(mediaId = mediaId, url = url, tag = "Tag1")
val mediaItem2 = createMediaItemWithMediaId(mediaId = mediaId, url = "https://streaming.com/video2.mp4", tag = "Tag1")
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual no media id same url different tag`() {
val mediaItem = MediaItem.Builder()
.setUri("https://streaming.com/video.mp4")
.setTag("Tag1")
.build()

val mediaItem2 = mediaItem.buildUpon()
.setTag("Tag2")
.build()
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual same MediaItemTrackerData content`() {
val mediaItem = MediaItem.Builder()
.setUri("https://streaming.com/video.mp4")
.setTrackerData(MediaItemTrackerData.Builder().apply { putData(Tracker::class.java, "data1") }.build())
.build()

val mediaItem2 = MediaItem.Builder()
.setUri("https://streaming.com/video.mp4")
.setTrackerData(MediaItemTrackerData.Builder().apply { putData(Tracker::class.java, "data1") }.build())
.build()
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual same MediaItemTrackerData`() {
val mediaItem = MediaItem.Builder()
.setUri("https://streaming.com/video.mp4")
.setTrackerData(MediaItemTrackerData.Builder().apply { putData(Tracker::class.java, "data1") }.build())
.build()

val mediaItem2 = mediaItem.buildUpon()
.setTrackerData(mediaItem.getMediaItemTrackerData().buildUpon().apply { putData(Tracker::class.java, "data1") }.build())
.build()
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areEqual same MediaItemTrackerData but different MediaMetadata`() {
val mediaItem = MediaItem.Builder()
.setUri("https://streaming.com/video.mp4")
.setTrackerData(MediaItemTrackerData.Builder().apply { putData(Tracker::class.java, "data1") }.build())
.build()

val mediaItem2 = mediaItem.buildUpon()
.setTrackerData(mediaItem.getMediaItemTrackerData().buildUpon().apply { putData(Tracker::class.java, "data1") }.build())
.setMediaMetadata(MediaMetadata.Builder().setTitle("New title").build())
.build()
assertTrue(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

@Test
fun `areNotEqual different data`() {
val mediaItem = MediaItem.Builder()
.setUri("https://streaming.com/video.mp4")
.setTrackerData(MediaItemTrackerData.Builder().apply { putData(Tracker::class.java, "data1") }.build())
.build()

val mediaItem2 = mediaItem.buildUpon()
.setTrackerData(mediaItem.getMediaItemTrackerData().buildUpon().apply { putData(Tracker::class.java, "data2") }.build())
.build()
assertFalse(CurrentMediaItemTracker.areEqual(mediaItem, mediaItem2))
}

private class Tracker : MediaItemTracker {
override fun start(player: ExoPlayer, initialData: Any?) {
// Nothing
}

override fun stop(player: ExoPlayer, reason: MediaItemTracker.StopReason, positionMs: Long) {
// Nothing
}
}

companion object {
private fun createMediaItemWithMediaId(
mediaId: String,
url: String? = null,
tag: Any? = null,
): MediaItem {
return MediaItem.Builder()
.setUri(url)
.setMediaId(mediaId)
.setTag(tag)
.build()
}
}
}
Loading

0 comments on commit f29591e

Please sign in to comment.