Skip to content

Commit

Permalink
Merge pull request #14 from StreamAMG/release/1.2.0
Browse files Browse the repository at this point in the history
SMD-2016 Release Android SDK
  • Loading branch information
StefanoStream authored Apr 12, 2023
2 parents 06b76ca + f537b28 commit 9b01554
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 24 deletions.
2 changes: 1 addition & 1 deletion AuthenticationReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ Change Log:

All notable changes to this project will be documented in this section.

### 1.1.9-SNAPSHOT - Remove getKS call after successful login
### 1.1.9 - Remove getKS call after successful login

### 1.0.1 - Release

Expand Down
2 changes: 2 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Change Log:

All notable changes to this project will be documented in this section.

### 1.2.0 - Subtitle improvements: Default subtitle track auto-selected and get Label caption on subtitle selector

### 1.1.9 - Remove getKS call after successful login and updated validatePurchase to return error when valid token not available

### 1.1.8 - Integrated Subtitles UI and added support to pass custom JWT Token when validating purchase
Expand Down
12 changes: 10 additions & 2 deletions PlayKitReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,7 @@ playKit.player?.setVolume(0.5F)
To instruct PlayKit to use a certain track when streaming (if available), you can use the following function:

``` Kotlin
playKit.changeTrack(id: String?)
playKit.changeTrack(id: String)
```

PlayKit will atttempt to change the track to the chosen one for the rest of the stream. The id of the track should be the uniqueId of the available MediaTrack
Expand All @@ -638,13 +638,21 @@ override fun tracksAvailable(tracks: List<MediaTrack>) {

Once the tracks are available and ready, is possible to filter and select the chosen track in this way:
``` Kotlin
playKit.changeTrack(tracks.firstOrNull { it.language?.contains("english") == true && it.type == TrackType.TEXT }?.uniqueId)
tracks.firstOrNull { it.language?.contains("english") == true && it.type == TrackType.TEXT }?.let { track ->
playKit.changeTrack(track.uniqueId)
}
```

Hovewer, PlayKit will take care to select the default caption track once the video will be loaded.

# Change Log

All notable changes to this project will be documented in this section.

### 1.2.0
- Default subtitle track auto-selected
- Get Label caption on subtitle selector

### 1.1.8
- Subtitles UI selector

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,8 @@ alternatively, to install all SDK elements, use the following line:
```

Sync your Gradle files, and the AMG SDK should import and be available for use.


## Change Log

All notable changes to this project will be documented [here](Changelod.md)
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ plugins {
id 'maven-publish'
}
// Versions of the library modules are matched (eg 1.0 core goes with 1.0 cloudmatrix) to prevent dependency issues
ext.SDK_VERSION_CODE = 20
ext.SDK_VERSION_NAME = "1.1.9"
ext.SDK_VERSION_CODE = 21
ext.SDK_VERSION_NAME = "1.2.0"

publishing {
publications {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,12 @@ class AMGPlayKit : LinearLayout, AMGPlayerInterface {
tracks?.addAll(event.tracksInfo.textTracks.map { MediaTrack(it.uniqueId, TrackType.TEXT, it.language, it.label, it.mimeType) })
tracks?.addAll(event.tracksInfo.audioTracks.map { MediaTrack(it.uniqueId, TrackType.AUDIO, it.language, it.label, codecName = it.codecName, bitrate = it.bitrate, channelCount = it.channelCount) })
tracks?.addAll(event.tracksInfo.imageTracks.map { MediaTrack(it.uniqueId, TrackType.IMAGE, url = it.url, bitrate = it.bitrate, duration = it.duration, label = it.label, cols = it.cols, rows = it.rows, width = it.width.toInt(), height = it.height.toInt()) })
tracks?.let {
listener?.tracksAvailable(it)
controlsView.createSubtitleSelector(it.filter { it.type == TrackType.TEXT })
tracks?.let { tracks ->
tracks.filter { it.type == TrackType.TEXT }.let { textTracks ->
checkDefaultCaptionTrack(textTracks)
controlsView.createSubtitlesSelector(textTracks)
}
listener?.tracksAvailable(tracks)
}
}

Expand All @@ -267,12 +270,49 @@ class AMGPlayKit : LinearLayout, AMGPlayerInterface {

}

override fun setTrack(track: MediaTrack?) {
changeTrack(track?.uniqueId ?: "")
private fun checkDefaultCaptionTrack(textTracks: List<MediaTrack>) {
controlsView.selectedCaption = 0
currentMediaItem?.captionAsset?.objects?.let {
for (caption in it) { // Find the Label first
if (caption.isDefault == true) {
textTracks.indexOfFirst { mediaTrack ->
mediaTrack.label == caption.label
}.let { defaultIndexCaptionTrack ->
if (defaultIndexCaptionTrack >= 0) {
player?.changeTrack(textTracks[defaultIndexCaptionTrack].uniqueId)
controlsView.setCaptionOnSelector(defaultIndexCaptionTrack)
return
}
}
}
}
for (caption in it) { // As fallback, find the Language if Label not set
if (caption.isDefault == true) {
textTracks.indexOfFirst { mediaTrack ->
mediaTrack.label == caption.language
}.let { defaultIndexCaptionTrack ->
if (defaultIndexCaptionTrack >= 0) {
player?.changeTrack(textTracks[defaultIndexCaptionTrack].uniqueId)
controlsView.setCaptionOnSelector(defaultIndexCaptionTrack)
return
}
}
}
}
}
}

override fun setTrack(track: MediaTrack) {
changeTrack(track.uniqueId)
}

fun changeTrack(id: String?) {
fun changeTrack(id: String) {
player?.changeTrack(id)
tracks?.filter { it.type == TrackType.TEXT }?.indexOfFirst { mediaTrack ->
mediaTrack.uniqueId == id
}?.let { trackIndex ->
controlsView.setCaptionOnSelector(trackIndex)
}
}

fun getTracks() : List<MediaTrack>? {
Expand Down Expand Up @@ -559,8 +599,6 @@ class AMGPlayKit : LinearLayout, AMGPlayerInterface {
listBitrate = bitrates
}

player?.changeTrack(mediaConfig.captionAsset?.objects?.lastOrNull()?.id)

controlsView.setMediaType(mediaType)
if (mediaType == AMGMediaType.VOD){
isLive(mediaConfig.serverURL, mediaConfig.entryID, mediaConfig.ks){isLiveBool ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class AMGPlayKitStandardControl : LinearLayout, AMGControlInterface {
var fadeTime: Long = 5000

var selectedBitrate = 0
var selectedSubtitle = 0
var selectedCaption: Int = 0

var shouldHideOnOrientation = -1
lateinit var mainView: ConstraintLayout
Expand Down Expand Up @@ -501,40 +501,40 @@ class AMGPlayKitStandardControl : LinearLayout, AMGControlInterface {
append(spannable)
}

fun createSubtitleSelector(subtitles: List<MediaTrack>) {
fun createSubtitlesSelector(subtitles: List<MediaTrack>) {
subtitleSelectorView.removeAllViews()
subtitles.forEachIndexed { index, mediaTrack ->
subtitleSelectorView.addView(listDivider())
subtitleSelectorView.addView(subtitleButton(mediaTrack, index))
}
}

private fun subtitleButton(track: MediaTrack?, index: Int): Button {
private fun subtitleButton(track: MediaTrack, index: Int): Button {
val btnSubtitle = standardButton()
btnSubtitle.tag = index
track?.label?.let {
if (it == "none") {
btnSubtitle.setText(R.string.subtitle_off)
} else {
btnSubtitle.text = Locale(it).displayLanguage.replaceFirstChar { char -> char.uppercase() }
btnSubtitle.text = it
}
}

toggleSubtitleButton(index, btnSubtitle, selectedSubtitle == index)
toggleSubtitleButton(index, btnSubtitle, selectedCaption == index)

btnSubtitle.setOnClickListener {
Log.d("SUBTITLE","Selected subtitle: ${track?.label}")

// Previous subtitle back to normal status
val btnPrevSubtitle = subtitleSelectorView.findViewWithTag<Button>(selectedSubtitle)
toggleSubtitleButton(selectedSubtitle, btnPrevSubtitle, false)
val btnPrevSubtitle = subtitleSelectorView.findViewWithTag<Button>(selectedCaption)
toggleSubtitleButton(selectedCaption, btnPrevSubtitle, false)
// Select new subtitle
toggleSubtitleButton(index, btnSubtitle, true)

player?.setTrack(track)
subtitleSelectorView.visibility = View.GONE
subtitleButton.setBackgroundResource(R.color.transparent)
selectedSubtitle = index
selectedCaption = index
}

return btnSubtitle
Expand Down Expand Up @@ -653,6 +653,15 @@ class AMGPlayKitStandardControl : LinearLayout, AMGControlInterface {

return divider
}

fun setCaptionOnSelector(index: Int) {
val btnPrevSubtitle = subtitleSelectorView.findViewWithTag<Button>(selectedCaption)
val btnNewSubtitle = subtitleSelectorView.findViewWithTag<Button>(index)
toggleSubtitleButton(selectedCaption, btnPrevSubtitle, false)
// Select new subtitle
toggleSubtitleButton(index, btnNewSubtitle, true)
selectedCaption = index
}
}

fun View.margin(end: Float? = null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ interface AMGPlayerInterface {
fun swapOrientation()
fun goLive()
fun setMaximumBitrate(bitrate: FlavorAsset?)
fun setTrack(track: MediaTrack?)
fun setTrack(track: MediaTrack)
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,18 @@ class MediaItem(
var externalSubtitles = mutableListOf<PKExternalSubtitle>()

for (value in list.objects) {
if (serverURL.isNotEmpty() && value.id != null && value.language != null && value.languageCode != null) {
if (serverURL.isNotEmpty() && value.id != null && value.language != null && value.languageCode != null && value.status != -1) {
val url = "$serverURL/api_v3/index.php/service/caption_captionasset/action/serveWebVTT/captionAssetId/${value.id}/segmentIndex/-1/version/2/captions.vtt"
val eSub = PKExternalSubtitle()
eSub.language = value.language
eSub.label = value.languageCode
eSub.label = if (!value.label.isNullOrEmpty()) value.label else value.language
eSub.url = url
externalSubtitles.add(eSub)
}
}

externalSubtitles = externalSubtitles.distinctBy { Pair(it.language, it.label) }.toMutableList()

return externalSubtitles
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class AMGPurchases : PurchasesCall(), IAPInterface {

override fun response(response: StreamAMGError) {
Log.d("AMGCall", "FAILED! ${response.messages}")
successCallback?.invoke(null, response)
}

override fun updateIAPUI() {
Expand Down

0 comments on commit 9b01554

Please sign in to comment.