From 841422885824f0a06d048c83ea8569c050ae5ca9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 26 May 2013 00:52:14 -0400 Subject: [PATCH] restored audio and subtitle menus --- dashboard-ui/css/images/media/audioflyout.png | Bin 0 -> 1497 bytes .../css/images/media/subtitleflyout.png | Bin 0 -> 789 bytes dashboard-ui/css/site.css | 15 +- dashboard-ui/scripts/extensions.js | 4 +- dashboard-ui/scripts/mediaplayer.js | 250 ++++++++++++++++-- dashboard-ui/scripts/site.js | 11 +- 6 files changed, 245 insertions(+), 35 deletions(-) create mode 100644 dashboard-ui/css/images/media/audioflyout.png create mode 100644 dashboard-ui/css/images/media/subtitleflyout.png diff --git a/dashboard-ui/css/images/media/audioflyout.png b/dashboard-ui/css/images/media/audioflyout.png new file mode 100644 index 0000000000000000000000000000000000000000..cd13df0978d21b30457a6a0a1866020ebf788679 GIT binary patch literal 1497 zcmV;~1t$85P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1#U@1K~#8N?U`Fh zWmOo*y)p{t#5@?ND9yt>iGz2Ui2+A&m~KLW10&Q!G%ryPLNm}nQ8C3d&`>cDJqQ&M z1wJSgR3xM!Dc%@qu!p2E8q^2F11c(c>G$7f?ZfeS^qjNzK60S-gXQ|x+G}su_pNVz z>vHle7K_DVu~;k?i^XF3|B-LtYxL0ot-7uc*KgmoHBq>{4K=iqc!P)g7;AL9oG=X04fhT4GzJN0RoQ! zbmnzB{TpIN$_w7BC+nBuOqr5sZFULF0O~Nxe~EYtMZ9)?jMP3oJ>5P$JiHmL$}WKz zKml%bb@f}sj7QxC_wU7x&!uvA7wr+6o13rTEzg)LPXuCswY4>kdWR`y49X9N!{L`D zqf`gVeNUP&Q{n(EEiLuD^Ec^h+Q{&p@ofN&0@<}_$r}XB+qnF;QLLY;CrHgC?f&*r zQ&SUSXQ&NQY?|?o=jr0h0Gjvw^IN9q3Ep3toSYn#%+hw3EF?J*8Ao|>aj`Z>rzOXs z*x?CZ2Eg@u$WBE|-e4pT9X*UQ7z%|(%&7M(H*5cQ(H2gd`-O#t-KLl^z6`)Wf5nKN z;Ts`$$wPjT^bO)X`KOzko6l)#l$4an%TAS+mO4R}K-r1mE+V!QI~pb?CYDt11nrem&e`B&xp-Y&-AUS?=lj}CDj3G|D8`a81HsP}s5N;i zA{>Ca4|7wk`xxjtVh`;eV2~B^6_nTVmZ-dpnHT_l;n@Imu-u5LxHCRJ{!oH8Oeokz z`p}K)0=MoZn~RnXE`9Oji~;C~jtlt^pSd4@*7zTctnbtr@kreN8x($40q4F>3KQV&nd%tYw6K1!AoeoHoqfKL+iT>d zynEs^Z6ENxlviLFpp);#HbQ>!GX-Xpa$=RMl3F=~B^{-!#HMjlVPOPg0sRVv2Z6(uNqU5TO8 zA7o|B`D%@Lv^I(v_0LH0X9XQv6zvu8nlMZU%BQ=Uh&S<`ca0nfg(mkzWo6~RWL?_0 zEG{nosydBob#?U}6#Il?;+igHA16IUs;A8(s!Wpz-uBYM!oog7`^A?BXk){P@OMVC zimmH8f}0dh9QB~k<>=c+4h&xg5W2y^06!sW-9K^{=Yu&`jWgM}C-gN11TOg}Q$dE* zElxJjYI1RObacU#1I4!i1oMBWqN1Xfj@Fo}K)|!M`DQn+|BI;#9M8*OBH?gYw=y3@ zOa4LmWrE(5+B2A{tl&EaB%(`Ff}z%S&p&LU{0N7o7moVfFem~yfG`&tuOVK;5Sjc) zq9gJ3Y>#?8Suuc%_5>$RoOl*jzQm|rz!>{BJ=7_xOX&fg{fOde9f^Y^s|H9$Yin!O z*4CDO9*^MS&XL(-u~;k?i^XEGSS*&~Broqj&3H4tI=&}v00000NkvXXu0mjfBYVd> literal 0 HcmV?d00001 diff --git a/dashboard-ui/css/images/media/subtitleflyout.png b/dashboard-ui/css/images/media/subtitleflyout.png new file mode 100644 index 0000000000000000000000000000000000000000..821005c50c695a690409681beccebd2fb2ad3dfb GIT binary patch literal 789 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1qt-3{0y$T^vIy;@-~Om@OPAbG&$`G>hj{S{_mKgbt*gpY43AD7UJDPQz>onBlxxX_uE zowK!M$LXJc@BS64Qd@h^`hC-$`|NV}@4vsR`u?8z{_pF)JY{hdfFfSQh^Z^CW__={ zU+=atQKEfklCe;ShA4aQB_Dk@vZ3*l%J6@=I z%=IS2n%%RPXdIQj%B#V-H}1Va@?_4=05gW>$-nOhu%1rz|CZn!bFjF^?T6u;PX9&M z7ij%per5K=dq%J2SJN3{p7)vl+a@ur-qyjm=9UuMhOBOh1FLkg3YUs#;?|$9p7&ieaS2yKL$<^*+1uN;@6Z-DGHy_Nx9c6V z&nL@EncfNpjGx%P@6i_FijJIPwlvRSXN=y=Wk2O6cgZaN&sy?n^FxbsLeE!D=wzIh zx>Zo_{u4ffo%j1scpGT0;E9>-p5s`ac;M=TRSFzUQ1nN+XlJ}d!n>+VQtw-VNtwaZ L)z4*}Q$iB}Rq$d+ literal 0 HcmV?d00001 diff --git a/dashboard-ui/css/site.css b/dashboard-ui/css/site.css index 509f2aabdf..4c0b2ba12a 100644 --- a/dashboard-ui/css/site.css +++ b/dashboard-ui/css/site.css @@ -663,7 +663,6 @@ progress { progress::-moz-progress-bar { border-radius: 5px; background-image: -moz-linear-gradient( center bottom, rgb(43,194,83) 37%, rgb(84,240,84) 69% ); - s; } /* Chrome */ @@ -894,6 +893,10 @@ input[type="range"]::-ms-fill-upper { width: 250px; } +.audioTracksFlyout { + width: 250px; +} + .mediaFlyoutOption { display: block; text-decoration: none; @@ -912,13 +915,21 @@ input[type="range"]::-ms-fill-upper { .mediaFlyoutOptionImage { display: inline-block; - width: 40%; + width: 15%; vertical-align: middle; } .mediaFlyoutOptionImage + .mediaFlyoutOptionContent { vertical-align: top; display: inline-block; + width: 85%; + } + +.chaptersFlyout .mediaFlyoutOptionImage { + width: 40%; +} + + .chaptersFlyout .mediaFlyoutOptionImage + .mediaFlyoutOptionContent { width: 60%; } diff --git a/dashboard-ui/scripts/extensions.js b/dashboard-ui/scripts/extensions.js index 753c59b0a9..6e06d47d4f 100644 --- a/dashboard-ui/scripts/extensions.js +++ b/dashboard-ui/scripts/extensions.js @@ -188,11 +188,11 @@ function humane_elapsed(firstDateStr, secondDateStr) { } -function getParameterByName(name) { +function getParameterByName(name, url) { name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); var regexS = "[\\?&]" + name + "=([^&#]*)"; var regex = new RegExp(regexS); - var results = regex.exec(window.location.search); + var results = regex.exec(url || window.location.search); if (results == null) return ""; else diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index fcea5e514e..56e2200bda 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -18,6 +18,7 @@ var startTimeTicksOffset; var curentDurationTicks; var isStaticStream; + var culturesPromise; self.playing = ''; self.queue = []; @@ -69,6 +70,10 @@ } } + function getCurrentTicks(mediaElement) { + return Math.floor(10000000 * (mediaElement || currentMediaElement).currentTime) + startTimeTicksOffset; + } + function onPlaybackStopped() { currentTimeElement.hide(); @@ -102,9 +107,8 @@ } function sendProgressUpdate(itemId) { - var position = Math.floor(10000000 * currentMediaElement.currentTime) + startTimeTicksOffset; - ApiClient.reportPlaybackProgress(Dashboard.getCurrentUserId(), itemId, position); + ApiClient.reportPlaybackProgress(Dashboard.getCurrentUserId(), itemId, getCurrentTicks()); } function clearProgressInterval() { @@ -115,24 +119,27 @@ } } - function seek(ticks) { + function changeStream(ticks, params) { var element = currentMediaElement; - if (isStaticStream) { + if (isStaticStream && params == null) { element.currentTime = ticks / (1000 * 10000); } else { + params = params || {}; + var currentSrc = element.currentSrc; - if (currentSrc.toLowerCase().indexOf('starttimeticks') == -1) { + currentSrc = replaceQueryString(currentSrc, 'starttimeticks', ticks); - currentSrc += "&starttimeticks=" + ticks; - - } else { - currentSrc = replaceQueryString(currentSrc, 'starttimeticks', ticks); + if (params.AudioStreamIndex != null) { + currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex); + } + if (params.SubtitleStreamIndex != null) { + currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', params.SubtitleStreamIndex); } clearProgressInterval(); @@ -158,7 +165,7 @@ var newPositionTicks = (newPercent / 100) * currentItem.RunTimeTicks; - seek(newPositionTicks); + changeStream(newPositionTicks); } $(function () { @@ -213,10 +220,32 @@ var ticks = parseInt(this.getAttribute('data-positionticks')); - seek(ticks); - + changeStream(ticks); + hideFlyout($('#chaptersFlyout')); }); + + $('#audioTracksFlyout').on('click', '.mediaFlyoutOption', function () { + + if (!$(this).hasClass('selectedMediaFlyoutOption')) { + var index = parseInt(this.getAttribute('data-index')); + + changeStream(getCurrentTicks(), { AudioStreamIndex: index }); + } + + hideFlyout($('#audioTracksFlyout')); + }); + + $('#subtitleFlyout').on('click', '.mediaFlyoutOption', function () { + + if (!$(this).hasClass('selectedMediaFlyoutOption')) { + var index = parseInt(this.getAttribute('data-index')); + + changeStream(getCurrentTicks(), { SubtitleStreamIndex: index }); + } + + hideFlyout($('#subtitleFlyout')); + }); }); function endsWith(text, pattern) { @@ -385,9 +414,7 @@ if (!isPositionSliderActive) { - var ticks = startTimeTicksOffset + this.currentTime * 1000 * 10000; - - setCurrentTime(ticks, item, true); + setCurrentTime(getCurrentTicks(this), item, true); } }).on("ended.playbackstopped", onPlaybackStopped); @@ -484,6 +511,7 @@ $('#mediaElement', nowPlayingBar).html(html); $('#qualityButton', nowPlayingBar).show(); + $('#audioTracksButton', nowPlayingBar).show(); if (item.MediaStreams.filter(function (i) { @@ -552,9 +580,7 @@ if (!isPositionSliderActive) { - var ticks = startTimeTicksOffset + this.currentTime * 1000 * 10000; - - setCurrentTime(ticks, item, true); + setCurrentTime(getCurrentTicks(this), item, true); } }).on("ended.playbackstopped", onPlaybackStopped); @@ -569,10 +595,14 @@ function getInitialAudioStreamIndex(mediaStreams, user) { + var audioStreams = mediaStreams.filter(function (stream) { + return stream.Type == "Audio"; + }); + if (user.Configuration.AudioLanguagePreference) { - for (var i = 0, length = mediaStreams.length; i < length; i++) { - var mediaStream = mediaStreams[i]; + for (var i = 0, length = audioStreams.length; i < length; i++) { + var mediaStream = audioStreams[i]; if (mediaStream.Type == "Audio" && mediaStream.Language == user.Configuration.AudioLanguagePreference) { return mediaStream.Index; @@ -581,7 +611,8 @@ } } - return null; + // Just use the first audio stream + return audioStreams.length ? audioStreams[0].Index : null; } function getInitialSubtitleStreamIndex(mediaStreams, user) { @@ -951,8 +982,8 @@ var html = ''; - var currentTicks = Math.floor(10000000 * currentMediaElement.currentTime) + startTimeTicksOffset; - + var currentTicks = getCurrentTicks(); + for (var i = 0, length = item.Chapters.length; i < length; i++) { var chapter = item.Chapters[i]; @@ -1004,14 +1035,174 @@ return html; } + function getAudioTracksHtml(item, cultures) { + + var streams = item.MediaStreams.filter(function (i) { + return i.Type == "Audio"; + }); + + var currentIndex = getParameterByName('AudioStreamIndex', currentMediaElement.currentSrc); + + var html = ''; + + for (var i = 0, length = streams.length; i < length; i++) { + + var stream = streams[i]; + + if (stream.Index == currentIndex) { + html += '
'; + } else { + html += '
'; + } + + html += ''; + + html += '
'; + + var language = null; + + if (stream.Language && stream.Language != "und") { + + var culture = cultures.filter(function (current) { + return current.ThreeLetterISOLanguageName.toLowerCase() == stream.Language.toLowerCase(); + }); + + if (culture.length) { + language = culture[0].DisplayName; + } + } + + html += '
' + (language || 'Unknown language') + '
'; + + var options = []; + + if (stream.Codec) { + options.push(stream.Codec); + } + if (stream.Profile) { + options.push(stream.Profile); + } + + if (stream.BitRate) { + options.push((parseInt(stream.BitRate / 1000)) + ' kbps'); + } + + if (stream.Channels) { + options.push(stream.Channels + ' ch'); + } + + if (options.length) { + html += '
' + options.join(' • ') + '
'; + } + + options = []; + + if (stream.IsDefault) { + options.push('Default'); + } + if (stream.IsForced) { + options.push('Forced'); + } + + if (options.length) { + html += '
' + options.join(' • ') + '
'; + } + + html += "
"; + + html += "
"; + } + + return html; + } + + function getSubtitleTracksHtml(item, cultures) { + + var streams = item.MediaStreams.filter(function (i) { + return i.Type == "Subtitle"; + }); + + var currentIndex = getParameterByName('SubtitleStreamIndex', currentMediaElement.currentSrc); + + var html = ''; + + for (var i = 0, length = streams.length; i < length; i++) { + + var stream = streams[i]; + + if (stream.Index == currentIndex) { + html += '
'; + } else { + html += '
'; + } + + html += ''; + + html += '
'; + + var language = null; + + if (stream.Language && stream.Language != "und") { + + var culture = cultures.filter(function (current) { + return current.ThreeLetterISOLanguageName.toLowerCase() == stream.Language.toLowerCase(); + }); + + if (culture.length) { + language = culture[0].DisplayName; + } + } + + html += '
' + (language || 'Unknown language') + '
'; + + var options = []; + + if (stream.Codec) { + options.push(stream.Codec); + } + + if (options.length) { + html += '
' + options.join(' • ') + '
'; + } + + options = []; + + if (stream.IsDefault) { + options.push('Default'); + } + if (stream.IsForced) { + options.push('Forced'); + } + if (stream.IsExternal) { + options.push('External'); + } + + if (options.length) { + html += '
' + options.join(' • ') + '
'; + } + + html += "
"; + + html += "
"; + } + + return html; + } + self.showAudioTracksFlyout = function () { var flyout = $('#audioTracksFlyout'); if (!flyout.is(':visible')) { - showFlyout(flyout, '#audioTracksButton'); + culturesPromise = culturesPromise || ApiClient.getCultures(); + culturesPromise.done(function (cultures) { + + showFlyout(flyout, '#audioTracksButton'); + + flyout.html(getAudioTracksHtml(currentItem, cultures)).scrollTop(0); + }); } }; @@ -1023,7 +1214,7 @@ showFlyout(flyout, '#chaptersButton'); - flyout.html(getChaptersFlyoutHtml(currentItem)); + flyout.html(getChaptersFlyoutHtml(currentItem)).scrollTop(0); } }; @@ -1044,7 +1235,14 @@ if (!flyout.is(':visible')) { - showFlyout(flyout, '#subtitleButton'); + culturesPromise = culturesPromise || ApiClient.getCultures(); + + culturesPromise.done(function (cultures) { + + showFlyout(flyout, '#subtitleButton'); + + flyout.html(getSubtitleTracksHtml(currentItem, cultures)).scrollTop(0); + }); } }; diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 94c61592ac..0054f3db29 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -1118,19 +1118,20 @@ $(function () { footerHtml += ''; footerHtml += ''; footerHtml += ''; - footerHtml += ''; footerHtml += ''; - footerHtml += '
'; + footerHtml += '
'; footerHtml += ''; - footerHtml += '
'; + footerHtml += '
'; footerHtml += ''; - footerHtml += '
'; + footerHtml += '
'; footerHtml += ''; - footerHtml += '
'; + footerHtml += '
'; + + footerHtml += ''; footerHtml += '
';