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+Cr~%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