From 9e010f50b2a30d293fc6f56240fa3dc0e3e7db25 Mon Sep 17 00:00:00 2001
From: 1hitsong <3330318+1hitsong@users.noreply.github.com>
Date: Mon, 20 Nov 2023 15:55:15 -0500
Subject: [PATCH] Add audio track selection to video player
---
components/ItemGrid/LoadVideoContentTask.bs | 18 +++++++
components/RadioDialog.bs | 3 +-
components/manager/ViewCreator.bs | 50 ++++++++++++++++++++
components/video/OSD.xml | 1 +
components/video/VideoPlayerView.bs | 31 ++++++++++++
components/video/VideoPlayerView.xml | 2 +
images/icons/musicNote.png | Bin 0 -> 2178 bytes
7 files changed, 104 insertions(+), 1 deletion(-)
create mode 100644 images/icons/musicNote.png
diff --git a/components/ItemGrid/LoadVideoContentTask.bs b/components/ItemGrid/LoadVideoContentTask.bs
index 4e65bdbd..21611249 100644
--- a/components/ItemGrid/LoadVideoContentTask.bs
+++ b/components/ItemGrid/LoadVideoContentTask.bs
@@ -131,6 +131,7 @@ sub LoadItems_AddVideoContent(video as object, mediaSourceId as dynamic, audio_s
end if
addSubtitlesToVideo(video, meta)
+ addAudioStreamsToVideo(video)
if meta.live
video.transcodeParams = {
@@ -219,6 +220,23 @@ sub addVideoContentURL(video, mediaSourceId, audio_stream_idx, fully_external)
end if
end sub
+
+' addAudioStreamsToVideo: Add audio stream data to video
+'
+' @param {dynamic} video component to add fullAudioData to
+sub addAudioStreamsToVideo(video)
+ audioStreams = []
+ mediaStreams = m.playbackInfo.MediaSources[0].MediaStreams
+
+ for i = 0 to mediaStreams.Count() - 1
+ if LCase(mediaStreams[i].Type) = "audio"
+ audioStreams.push(mediaStreams[i])
+ end if
+ end for
+
+ video.fullAudioData = audioStreams
+end sub
+
sub addSubtitlesToVideo(video, meta)
subtitles = sortSubtitles(meta.id, m.playbackInfo.MediaSources[0].MediaStreams)
safesubs = subtitles["all"]
diff --git a/components/RadioDialog.bs b/components/RadioDialog.bs
index 9d79a0ee..05c55280 100644
--- a/components/RadioDialog.bs
+++ b/components/RadioDialog.bs
@@ -109,7 +109,8 @@ sub onContentDataChanged()
m.radioOptions.selectedIndex = i
end if
- textLine = cardItem.CreateChild("SimpleLabel")
+ textLine = cardItem.CreateChild("ScrollingLabel")
+ textLine.maxWidth = "750"
textLine.text = item.track.description
cardItem.observeField("selected", "onItemSelected")
i++
diff --git a/components/manager/ViewCreator.bs b/components/manager/ViewCreator.bs
index 76383443..165cd020 100644
--- a/components/manager/ViewCreator.bs
+++ b/components/manager/ViewCreator.bs
@@ -14,6 +14,7 @@ sub CreateVideoPlayerView()
m.view.observeField("state", "onStateChange")
m.view.observeField("selectPlaybackInfoPressed", "onSelectPlaybackInfoPressed")
m.view.observeField("selectSubtitlePressed", "onSelectSubtitlePressed")
+ m.view.observeField("selectAudioPressed", "onSelectAudioPressed")
mediaSourceId = m.global.queueManager.callFunc("getCurrentItem").mediaSourceId
@@ -32,6 +33,36 @@ end sub
' Event Handlers
' -----------------
+
+' onSelectAudioPressed: Display audio selection dialog
+'
+sub onSelectAudioPressed()
+ audioData = {
+ data: []
+ }
+
+ for each item in m.view.fullAudioData
+
+ audioStreamItem = {
+ "Index": item.Index,
+ "IsExternal": item.IsExternal,
+ "Track": {
+ "description": item.DisplayTitle
+ },
+ "Type": "audioselection"
+ }
+
+ if m.view.audioIndex = item.Index
+ audioStreamItem.selected = true
+ end if
+
+ audioData.data.push(audioStreamItem)
+ end for
+
+ m.global.sceneManager.callFunc("radioDialog", tr("Select Audio"), audioData)
+ m.global.sceneManager.observeField("returnData", "onSelectionMade")
+end sub
+
' User requested subtitle selection popup
sub onSelectSubtitlePressed()
' None is always first in the subtitle list
@@ -85,6 +116,25 @@ sub onSelectionMade()
if LCase(m.global.sceneManager.returnData.type) = "subtitleselection"
processSubtitleSelection()
+ return
+ end if
+
+ if LCase(m.global.sceneManager.returnData.type) = "audioselection"
+ processAudioSelection()
+ return
+ end if
+end sub
+
+
+' processAudioSelection: Audio track selection handler
+'
+sub processAudioSelection()
+ selectedAudioTrack = m.global.sceneManager.returnData
+
+ if isValid(selectedAudioTrack)
+ if isValid(selectedAudioTrack.index)
+ m.view.audioIndex = selectedAudioTrack.index
+ end if
end if
end sub
diff --git a/components/video/OSD.xml b/components/video/OSD.xml
index b8ff7ff0..2e1328cf 100644
--- a/components/video/OSD.xml
+++ b/components/video/OSD.xml
@@ -8,6 +8,7 @@
+
diff --git a/components/video/VideoPlayerView.bs b/components/video/VideoPlayerView.bs
index d86a7e61..26cafe6f 100644
--- a/components/video/VideoPlayerView.bs
+++ b/components/video/VideoPlayerView.bs
@@ -32,6 +32,7 @@ sub init()
m.top.observeField("state", "onState")
m.top.observeField("content", "onContentChange")
m.top.observeField("selectedSubtitle", "onSubtitleChange")
+ m.top.observeField("audioIndex", "onAudioIndexChange")
' Custom Caption Function
m.top.observeField("allowCaptions", "onAllowCaptionsChange")
@@ -163,6 +164,12 @@ sub handleShowSubtitleMenuAction()
m.top.selectSubtitlePressed = true
end sub
+' handleShowAudioMenuAction: Handles action to show audio selection menu
+'
+sub handleShowAudioMenuAction()
+ m.top.selectAudioPressed = true
+end sub
+
' handleShowVideoInfoPopupAction: Handles action to show video info popup
'
sub handleShowVideoInfoPopupAction()
@@ -204,6 +211,11 @@ sub onOSDAction()
return
end if
+ if action = "showaudiomenu"
+ handleShowAudioMenuAction()
+ return
+ end if
+
if action = "showvideoinfopopup"
handleShowVideoInfoPopupAction()
return
@@ -262,6 +274,24 @@ sub onSubtitleChange()
m.top.control = "stop"
m.LoadMetaDataTask.selectedSubtitleIndex = m.top.SelectedSubtitle
+ m.LoadMetaDataTask.selectedAudioStreamIndex = m.top.audioIndex
+ m.LoadMetaDataTask.itemId = m.currentItem.id
+ m.LoadMetaDataTask.observeField("content", "onVideoContentLoaded")
+ m.LoadMetaDataTask.control = "RUN"
+end sub
+
+' Event handler for when audioIndex changes
+sub onAudioIndexChange()
+ ' Skip initial audio index setting
+ if m.top.position = 0 then return
+
+ ' Save the current video position
+ m.global.queueManager.callFunc("setTopStartingPoint", int(m.top.position) * 10000000&)
+
+ m.top.control = "stop"
+
+ m.LoadMetaDataTask.selectedSubtitleIndex = m.top.SelectedSubtitle
+ m.LoadMetaDataTask.selectedAudioStreamIndex = m.top.audioIndex
m.LoadMetaDataTask.itemId = m.currentItem.id
m.LoadMetaDataTask.observeField("content", "onVideoContentLoaded")
m.LoadMetaDataTask.control = "RUN"
@@ -314,6 +344,7 @@ sub onVideoContentLoaded()
m.top.container = videoContent[0].container
m.top.mediaSourceId = videoContent[0].mediaSourceId
m.top.fullSubtitleData = videoContent[0].fullSubtitleData
+ m.top.fullAudioData = videoContent[0].fullAudioData
m.top.audioIndex = videoContent[0].audioIndex
m.top.transcodeParams = videoContent[0].transcodeparams
m.chapters = videoContent[0].chapters
diff --git a/components/video/VideoPlayerView.xml b/components/video/VideoPlayerView.xml
index 3469b17d..c72dac56 100644
--- a/components/video/VideoPlayerView.xml
+++ b/components/video/VideoPlayerView.xml
@@ -3,6 +3,7 @@
+
@@ -22,6 +23,7 @@
+
diff --git a/images/icons/musicNote.png b/images/icons/musicNote.png
new file mode 100644
index 0000000000000000000000000000000000000000..2592230e63847194dee39ad7ce10ca5f276aa328
GIT binary patch
literal 2178
zcmXw32{_bi7eD{`k1=K}V+)OCRHzh6rMk)A7A=^hNXaODMr3rgsGIS(q?N11Qi-X#
zmP#Tfqb#G{ax>zl?5-Ay?8A*QcYNRTz0Y}`^ZT9mob!91_j%4a&vbWDq0FZMfXZf9
zCr3Ed9#zfS7htpEd!rWKivd1WuiT8&J<%A%hmt1+U&|(2hfcM0
zm2zGbi=V9L$D0B+Cr09Oxm6R^Et2na-LVun@nXLojh?IpTw9bKp4hB^@{S8X;jf
z>~%P>Ml7dWkIqpiJr3k4-ay57^gpTKUiNejgsqBS{}xpv1>Q9z0sN
zj?f7>ZVL>Sn#h1Kme;2&@>}oY;1UFRRKU(1)@C-zAK=69>sJ
zv$nn!bf*Ls)<{-RVc%ww&4>uaW0U;zlpbw)gW%$K&D1DNU1u4P4FKexOB{K
zMe_pnRS2WxagAg<2NK3}sgO3sB4BJzc8HPavgaDmdXl-$^Oce&I9znzrR0m!S_d8<
z%?LJL2)l&8KBMEeEheDWej~*1y59i8YN{FJ=uzg<4u{i=Y@khlNxzDyeQeAz{J9by
z6ZD;UQy4(R*eA30C)G=2P;y5EVb*4`_rF7$s4g)_tJk9l751-Dh>c
zqe(>KMj}?PF%%PBfJ9EgwmVe@F#mvxT<~CLwESa)hOcxXv8&Yjq9h5fty8U~;*RJYbg7@9UTsM#d?FiHxo6A4;NzPyM-ze^5jLS7zP#
zLK7IIF#5BWL(0?7{-KDC0`~k+f>{Iau{oSL9Lg6gf%#&$zFEb_R&D&RVI?V!pkZVRl4
zH>1CsD?`!8jq0HtjYS0$ok9wB4W&2&ZLDphW@le3zxdcj!{r8tMuOc8;Zc}0-0DH<
zw%i;|H!1h@8aoL5_|wEdkmi|d5EMQ61+X>0%y>5BN1uy(y3_yyhbkGPDd}T^m$QQGLThsx-oapww}G~B_5{_smNLsg8unq
zzl`^mUy^ly?+ya*-rBh04LgdWcNe`{^do!wL{(z*tabZV6t7@+MgJIeub%B^4|0OF
zWE<5mTVD{?*(gj0E#%6|>gs+E&aYWZ62hlw^p6y^dmI?jPR>j)}S-LS};Cf^qk9qO?Mv2(rdHE
z%(|1avnqh6eqK7=EIox{`qnYp14G&nqOKKneZ1cox{515UHxSyBP6CxE9#UQwxqbu
z_JXiU4Jg+K&~N#YK_kMLo^@4qAg4+_??10*=qdmFm^8v~Z(F7u5}f8M^ES2``Rww{
zps1!vC#JQF+H>xq6KjB)6j!y=xtE=F%QztW;m6sfn<kSdT3=osMZ=?>-XG)2p1^
z%JEb42;^@#ntE@dB_P>5@RE@ZF`{(~5*KlpO