Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
This commit is contained in:
commit
4afc9f601e
52 changed files with 2722 additions and 1319 deletions
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Auto-Organize</title>
|
<title>${TitleAutoOrganize}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="libraryFileOrganizerLogPage" data-role="page" class="page type-interior adminPage organizePage">
|
<div id="libraryFileOrganizerLogPage" data-role="page" class="page type-interior adminPage organizePage">
|
||||||
|
@ -10,8 +10,8 @@
|
||||||
<div class="content-primary">
|
<div class="content-primary">
|
||||||
|
|
||||||
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
|
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
|
||||||
<a href="#" data-role="button" class="ui-btn-active">Activity Log</a>
|
<a href="#" data-role="button" class="ui-btn-active">${TabActivityLog}</a>
|
||||||
<a href="autoorganizetv.html" data-role="button">TV Settings</a>
|
<a href="autoorganizetv.html" data-role="button">${TabTV}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin: -25px 0 1em; text-align: right;">
|
<div style="margin: -25px 0 1em; text-align: right;">
|
||||||
|
@ -25,9 +25,9 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th data-priority="1"></th>
|
<th data-priority="1"></th>
|
||||||
<th data-priority="2">Date</th>
|
<th data-priority="2">${HeaderDate}</th>
|
||||||
<th data-priority="1">Source</th>
|
<th data-priority="1">${HeaderSource}</th>
|
||||||
<th data-priority="3">Destination</th>
|
<th data-priority="3">${HeaderDestination}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="resultBody">
|
<tbody class="resultBody">
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
<br />
|
<br />
|
||||||
<div style="text-align: right;" class="legend">
|
<div style="text-align: right;" class="legend">
|
||||||
<div style="display: inline-block; height: 10px; width: 10px; background: green;"></div>
|
<div style="display: inline-block; height: 10px; width: 10px; background: green;"></div>
|
||||||
<span>Completed</span>
|
<span>${LabelCompleted}</span>
|
||||||
<div style="display: inline-block; height: 10px; width: 10px; background: red; margin-left: 1em;"></div>
|
<div style="display: inline-block; height: 10px; width: 10px; background: red; margin-left: 1em;"></div>
|
||||||
<span>Failed</span>
|
<span>${LabelFailed}</span>
|
||||||
<div style="display: inline-block; height: 10px; width: 10px; background: blue; margin-left: 1em;"></div>
|
<div style="display: inline-block; height: 10px; width: 10px; background: blue; margin-left: 1em;"></div>
|
||||||
<span>Skipped</span>
|
<span>${LabelSkipped}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="listBottomPaging">
|
<div class="listBottomPaging">
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
<div data-role="popup" data-transition="slidefade" class="popup episodeCorrectionPopup">
|
<div data-role="popup" data-transition="slidefade" class="popup episodeCorrectionPopup">
|
||||||
|
|
||||||
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
|
<div class="ui-bar-a" style="text-align: center; padding: 0 20px;">
|
||||||
<h3>Episode Organization</h3>
|
<h3>${HeaderEpisodeOrganization}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-role="content">
|
<div data-role="content">
|
||||||
|
@ -59,33 +59,29 @@
|
||||||
<p><span class="inputFile"></span></p>
|
<p><span class="inputFile"></span></p>
|
||||||
|
|
||||||
<div style="margin: 1em 0 1em; min-width: 250px;">
|
<div style="margin: 1em 0 1em; min-width: 250px;">
|
||||||
<label for="selectSeries">Series:</label>
|
<label for="selectSeries">${LabelSeries}</label>
|
||||||
<select id="selectSeries" data-mini="true" required="required"></select>
|
<select id="selectSeries" data-mini="true" required="required"></select>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin: 1em 0;">
|
<div style="margin: 1em 0;">
|
||||||
<label for="txtSeason">Season number:</label>
|
<label for="txtSeason">${LabelSeasonNumber}</label>
|
||||||
<input id="txtSeason" type="number" data-mini="true" pattern="[0-9]*" required="required" min="0" />
|
<input id="txtSeason" type="number" data-mini="true" pattern="[0-9]*" required="required" min="0" />
|
||||||
</div>
|
</div>
|
||||||
<div style="margin: 1em 0;">
|
<div style="margin: 1em 0;">
|
||||||
<label for="txtEpisode">Episode number:</label>
|
<label for="txtEpisode">${LabelEpisodeNumber}</label>
|
||||||
<input id="txtEpisode" type="number" data-mini="true" pattern="[0-9]*" required="required" min="0" />
|
<input id="txtEpisode" type="number" data-mini="true" pattern="[0-9]*" required="required" min="0" />
|
||||||
</div>
|
</div>
|
||||||
<div style="margin: 1em 0;">
|
<div style="margin: 1em 0;">
|
||||||
<label for="txtEndingEpisode">Ending episode number:</label>
|
<label for="txtEndingEpisode">${LabelEndingEpisodeNumber}</label>
|
||||||
<input id="txtEndingEpisode" type="number" data-mini="true" pattern="[0-9]*" min="0" />
|
<input id="txtEndingEpisode" type="number" data-mini="true" pattern="[0-9]*" min="0" />
|
||||||
<div class="fieldDescription">Only required for multi-episode files</div>
|
<div class="fieldDescription">${LabelEndingEpisodeNumberHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="margin: 1em 0;" id="fldRememberCorrection">
|
|
||||||
<label for="chkRememberEpisodeCorrection">Remember this correction future episodes of the same series.</label>
|
|
||||||
<input id="chkRememberEpisodeCorrection" type="checkbox" data-mini="true" />
|
|
||||||
</div>
|
|
||||||
<p>
|
<p>
|
||||||
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
|
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
|
||||||
Ok
|
${ButtonOk}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" data-icon="delete" onclick="$(this).parents('.popup').popup('close');" data-mini="true">
|
<button type="button" data-icon="delete" onclick="$(this).parents('.popup').popup('close');" data-mini="true">
|
||||||
Cancel
|
${ButtonCancel}
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<input id="hfResultId" type="hidden" />
|
<input id="hfResultId" type="hidden" />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Auto-Organize</title>
|
<title>${TitleAutoOrganize}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="libraryFileOrganizerPage" data-role="page" class="page type-interior organizePage">
|
<div id="libraryFileOrganizerPage" data-role="page" class="page type-interior organizePage">
|
||||||
|
@ -9,70 +9,70 @@
|
||||||
<div data-role="content">
|
<div data-role="content">
|
||||||
<div class="content-primary">
|
<div class="content-primary">
|
||||||
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
|
<div data-role="controlgroup" data-type="horizontal" class="localnav" data-mini="true">
|
||||||
<a href="autoorganizelog.html" data-role="button">Activity Log</a>
|
<a href="autoorganizelog.html" data-role="button">${TabActivityLog}</a>
|
||||||
<a href="#" data-role="button" class="ui-btn-active">TV Settings</a>
|
<a href="#" data-role="button" class="ui-btn-active">${TabTV}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form class="libraryFileOrganizerForm">
|
<form class="libraryFileOrganizerForm">
|
||||||
|
|
||||||
<p>Auto-organize monitors your download folders for new files and moves them to your media directories.</p>
|
<p>${AutoOrganizeHelp}</p>
|
||||||
|
|
||||||
<p>TV file organizing will only add episodes to existing series. It will not create new series folders.</p>
|
<p>${AutoOrganizeTvHelp}</p>
|
||||||
<ul data-role="listview" class="ulForm" style="margin-bottom: 0!important;">
|
<ul data-role="listview" class="ulForm" style="margin-bottom: 0!important;">
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="chkEnableTvSorting" name="chkEnableTvSorting" />
|
<input type="checkbox" id="chkEnableTvSorting" name="chkEnableTvSorting" />
|
||||||
<label for="chkEnableTvSorting">Enable new episode organization</label>
|
<label for="chkEnableTvSorting">${OptionEnableEpisodeOrganization}</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="txtWatchFolder">Watch folder: </label>
|
<label for="txtWatchFolder">${LabelWatchFolder}</label>
|
||||||
<div style="display: inline-block; width: 92%;">
|
<div style="display: inline-block; width: 92%;">
|
||||||
<input type="text" id="txtWatchFolder" name="txtWatchFolder" />
|
<input type="text" id="txtWatchFolder" name="txtWatchFolder" />
|
||||||
</div>
|
</div>
|
||||||
<button id="btnSelectWatchFolder" type="button" data-icon="search" data-iconpos="notext" data-inline="true">${ButtonSelectDirectory}</button>
|
<button id="btnSelectWatchFolder" type="button" data-icon="search" data-iconpos="notext" data-inline="true">${ButtonSelectDirectory}</button>
|
||||||
<div class="fieldDescription">
|
<div class="fieldDescription">
|
||||||
The server will poll this folder during the "Organize new media files" <a href="scheduledtasks.html">scheduled task</a>.
|
<div>${LabelWatchFolderHelp}</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="txtMinFileSize">Minimum file size (MB): </label>
|
<label for="txtMinFileSize">${LabelMinFileSizeForOrganize}</label>
|
||||||
<input type="number" id="txtMinFileSize" name="txtMinFileSize" pattern="[0-9]*" required="required" min="0" data-mini="true" />
|
<input type="number" id="txtMinFileSize" name="txtMinFileSize" pattern="[0-9]*" required="required" min="0" data-mini="true" />
|
||||||
<div class="fieldDescription">Files under this size will be ignored.</div>
|
<div class="fieldDescription">${LabelMinFileSizeForOrganizeHelp}</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="txtSeasonFolderPattern">Season folder pattern: </label>
|
<label for="txtSeasonFolderPattern">${LabelSeasonFolderPattern}</label>
|
||||||
<input type="text" id="txtSeasonFolderPattern" name="txtSeasonFolderPattern" required="required" data-mini="true" />
|
<input type="text" id="txtSeasonFolderPattern" name="txtSeasonFolderPattern" required="required" data-mini="true" />
|
||||||
<div class="fieldDescription seasonFolderFieldDescription"></div>
|
<div class="fieldDescription seasonFolderFieldDescription"></div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="txtSeasonZeroName">Season zero folder name: </label>
|
<label for="txtSeasonZeroName">${LabelSeasonZeroFolderName}</label>
|
||||||
<input type="text" id="txtSeasonZeroName" name="txtSeasonZeroName" required="required" data-mini="true" />
|
<input type="text" id="txtSeasonZeroName" name="txtSeasonZeroName" required="required" data-mini="true" />
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div data-role="collapsible">
|
<div data-role="collapsible">
|
||||||
<h3>Episode file pattern</h3>
|
<h3>${HeaderEpisodeFilePattern}</h3>
|
||||||
<div>
|
<div>
|
||||||
<br />
|
<br />
|
||||||
<div>
|
<div>
|
||||||
<label for="txtEpisodePattern">Episode pattern: </label>
|
<label for="txtEpisodePattern">${LabelEpisodePattern}</label>
|
||||||
<input type="text" id="txtEpisodePattern" name="txtEpisodePattern" required="required" data-mini="true" />
|
<input type="text" id="txtEpisodePattern" name="txtEpisodePattern" required="required" data-mini="true" />
|
||||||
<div class="fieldDescription episodePatternDescription"></div>
|
<div class="fieldDescription episodePatternDescription"></div>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div>
|
<div>
|
||||||
<label for="txtMultiEpisodePattern">Multi-Episode pattern: </label>
|
<label for="txtMultiEpisodePattern">${LabelMultiEpisodePattern}</label>
|
||||||
<input type="text" id="txtMultiEpisodePattern" name="txtMultiEpisodePattern" required="required" data-mini="true" />
|
<input type="text" id="txtMultiEpisodePattern" name="txtMultiEpisodePattern" required="required" data-mini="true" />
|
||||||
<div class="fieldDescription multiEpisodePatternDescription"></div>
|
<div class="fieldDescription multiEpisodePatternDescription"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<p>Supported Patterns</p>
|
<p>${HeaderSupportedPatterns}</p>
|
||||||
|
|
||||||
<table data-role="table" id="movie-table" data-mode="reflow" class="ui-responsive">
|
<table data-role="table" id="movie-table" data-mode="reflow" class="ui-responsive">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Term</th>
|
<th>${HeaderTerm}</th>
|
||||||
<th>Pattern</th>
|
<th>${HeaderPattern}</th>
|
||||||
<th>Result</th>
|
<th>${HeaderResult}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -144,36 +144,36 @@
|
||||||
<br />
|
<br />
|
||||||
<ul data-role="listview" class="ulForm">
|
<ul data-role="listview" class="ulForm">
|
||||||
<li>
|
<li>
|
||||||
<label for="copyOrMoveFile">Transfer Method</label>
|
<label for="copyOrMoveFile">${LabelTransferMethod}</label>
|
||||||
<select id="copyOrMoveFile" data-mini="true">
|
<select id="copyOrMoveFile" data-mini="true">
|
||||||
<option value="true">Copy</option>
|
<option value="true">${OptionCopy}</option>
|
||||||
<option value="false">Move</option>
|
<option value="false">${OptionMove}</option>
|
||||||
</select>
|
</select>
|
||||||
<div class="fieldDescription">Copy or move files from the watch folder</div>
|
<div class="fieldDescription">${LabelTransferMethodHelp}</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="chkOverwriteExistingEpisodes" name="chkOverwriteExistingEpisodes" />
|
<input type="checkbox" id="chkOverwriteExistingEpisodes" name="chkOverwriteExistingEpisodes" />
|
||||||
<label for="chkOverwriteExistingEpisodes">Overwrite existing episodes</label>
|
<label for="chkOverwriteExistingEpisodes">${OptionOverwriteExistingEpisodes}</label>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<label for="txtDeleteLeftOverFiles">Delete left over files with the following extensions: </label>
|
<label for="txtDeleteLeftOverFiles">${LabelDeleteLeftOverFiles}</label>
|
||||||
<input type="text" id="txtDeleteLeftOverFiles" name="txtDeleteLeftOverFiles" data-mini="true" />
|
<input type="text" id="txtDeleteLeftOverFiles" name="txtDeleteLeftOverFiles" data-mini="true" />
|
||||||
<div class="fieldDescription">Separate with ;. For example: .nfo;.txt</div>
|
<div class="fieldDescription">${LabelDeleteLeftOverFilesHelp}</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<input type="checkbox" id="chkDeleteEmptyFolders" name="chkDeleteEmptyFolders" data-mini="true" />
|
<input type="checkbox" id="chkDeleteEmptyFolders" name="chkDeleteEmptyFolders" data-mini="true" />
|
||||||
<label for="chkDeleteEmptyFolders">Delete empty folders after organizing</label>
|
<label for="chkDeleteEmptyFolders">${LabelDeleteEmptyFolders}</label>
|
||||||
<div class="fieldDescription">Enable this to keep the download directory clean.</div>
|
<div class="fieldDescription">${LabelDeleteEmptyFoldersHelp}</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul data-role="listview" class="ulForm">
|
<ul data-role="listview" class="ulForm">
|
||||||
<li>
|
<li>
|
||||||
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
|
<button type="submit" data-theme="b" data-icon="check" data-mini="true">
|
||||||
Save
|
${ButtonSave}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onclick="Dashboard.navigate('dashboard.html');" data-icon="delete" data-mini="true">
|
<button type="button" onclick="Dashboard.navigate('dashboard.html');" data-icon="delete" data-mini="true">
|
||||||
Cancel
|
${ButtonCancel}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,11 @@
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detailTableButtonsCell button {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.detailTableButtonsCell button + button {
|
.detailTableButtonsCell button + button {
|
||||||
margin-left: .5em;
|
margin-left: .5em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
.ui-icon-play:after {
|
.ui-icon-play:after {
|
||||||
background-image: url("images/icons/play.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M386.161%20258.649l-370.536%20205.915q-6.417%203.627-11.021%200.837t-4.604-10.044v-410.714q0-7.254%204.604-10.044t11.021%200.837l370.536%20205.915q6.417%203.627%206.417%208.649t-6.417%208.649z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 6px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-play:after {
|
.ui-nosvg .ui-icon-play:after {
|
||||||
|
@ -7,7 +9,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-stop:after {
|
.ui-icon-stop:after {
|
||||||
background-image: url("images/icons/stop.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M428.571%2053.571v392.857q0%207.254-5.301%2012.556t-12.556%205.301h-392.857q-7.254%200-12.556-5.301t-5.301-12.556v-392.857q0-7.254%205.301-12.556t12.556-5.301h392.857q7.254%200%2012.556%205.301t5.301%2012.556z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 4px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-stop:after {
|
.ui-nosvg .ui-icon-stop:after {
|
||||||
|
@ -15,14 +19,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-pause:after {
|
.ui-icon-pause:after {
|
||||||
background-image: url("images/icons/pause.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M428.571%2053.571v392.857q0%207.254-5.301%2012.556t-12.556%205.301h-142.857q-7.254%200-12.556-5.301t-5.301-12.556v-392.857q0-7.254%205.301-12.556t12.556-5.301h142.857q7.254%200%2012.556%205.301t5.301%2012.556zM178.571%2053.571v392.857q0%207.254-5.301%2012.556t-12.556%205.301h-142.857q-7.254%200-12.556-5.301t-5.301-12.556v-392.857q0-7.254%205.301-12.556t12.556-5.301h142.857q7.254%200%2012.556%205.301t5.301%2012.556z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 4px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-pause:after {
|
.ui-nosvg .ui-icon-pause:after {
|
||||||
background-image: url("images/icons/pause.png");
|
background-image: url("images/icons/pause.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-volume-off:after {
|
.ui-icon-volume-off:after {
|
||||||
background-image: url("images/icons/mute.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M214.286%2098.214v303.571q0%207.254-5.301%2012.556t-12.556%205.301-12.556-5.301l-92.913-92.913h-73.103q-7.254%200-12.556-5.301t-5.301-12.556v-107.143q0-7.254%205.301-12.556t12.556-5.301h73.103l92.913-92.913q5.301-5.301%2012.556-5.301t12.556%205.301%205.301%2012.556z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 6px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-volume-off:after {
|
.ui-nosvg .ui-icon-volume-off:after {
|
||||||
|
@ -30,47 +39,63 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-volume-up:after {
|
.ui-icon-volume-up:after {
|
||||||
background-image: url("images/icons/volumeup.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M214.286%2098.214v303.571q0%207.254-5.301%2012.556t-12.556%205.301-12.556-5.301l-92.913-92.913h-73.103q-7.254%200-12.556-5.301t-5.301-12.556v-107.143q0-7.254%205.301-12.556t12.556-5.301h73.103l92.913-92.913q5.301-5.301%2012.556-5.301t12.556%205.301%205.301%2012.556zM321.429%20250q0%2021.206-11.858%2039.481t-31.39%2026.088q-2.79%201.395-6.976%201.395-7.254%200-12.556-5.162t-5.301-12.695q0-5.859%203.348-9.905t8.091-6.976%209.487-6.417%208.091-9.905%203.348-15.904-3.348-15.904-8.091-9.905-9.487-6.417-8.091-6.976-3.348-9.905q0-7.534%205.301-12.695t12.556-5.162q4.185%200%206.976%201.395%2019.531%207.534%2031.39%2025.949t11.858%2039.621zM392.857%20250q0%2042.69-23.716%2078.823t-62.779%2052.595q-3.627%201.395-6.976%201.395-7.534%200-12.835-5.301t-5.301-12.556q0-10.882%2010.882-16.462%2015.625-8.091%2021.206-12.277%2020.647-15.067%2032.227-37.807t11.579-48.41-11.579-48.41-32.227-37.807q-5.581-4.185-21.206-12.277-10.882-5.581-10.882-16.462%200-7.254%205.301-12.556t12.556-5.301q3.627%200%207.254%201.395%2039.063%2016.462%2062.779%2052.595t23.716%2078.823zM464.286%20250q0%2064.174-35.435%20117.885t-94.308%2079.102q-3.627%201.395-7.254%201.395-7.254%200-12.556-5.301t-5.301-12.556q0-10.044%2010.882-16.462%201.953-1.116%206.278-2.93t6.278-2.93q12.835-6.976%2022.879-14.23%2034.319-25.391%2053.571-63.337t19.252-80.636-19.252-80.636-53.571-63.337q-10.044-7.254-22.879-14.23-1.953-1.116-6.278-2.93t-6.278-2.93q-10.882-6.417-10.882-16.462%200-7.254%205.301-12.556t12.556-5.301q3.627%200%207.254%201.395%2058.873%2025.391%2094.308%2079.102t35.435%20117.885z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-volume-up:after {
|
.ui-nosvg .ui-icon-volume-up:after {
|
||||||
background-image: url("images/icons/volumeup.png");
|
background-image: url("images/icons/volumeup.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-volume-down:after {
|
.ui-icon-volume-down:after {
|
||||||
background-image: url("images/icons/volumedown.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M214.286%2098.214v303.571q0%207.254-5.301%2012.556t-12.556%205.301-12.556-5.301l-92.913-92.913h-73.103q-7.254%200-12.556-5.301t-5.301-12.556v-107.143q0-7.254%205.301-12.556t12.556-5.301h73.103l92.913-92.913q5.301-5.301%2012.556-5.301t12.556%205.301%205.301%2012.556zM321.429%20250q0%2021.206-11.858%2039.481t-31.39%2026.088q-2.79%201.395-6.976%201.395-7.254%200-12.556-5.162t-5.301-12.695q0-5.859%203.348-9.905t8.091-6.976%209.487-6.417%208.091-9.905%203.348-15.904-3.348-15.904-8.091-9.905-9.487-6.417-8.091-6.976-3.348-9.905q0-7.534%205.301-12.695t12.556-5.162q4.185%200%206.976%201.395%2019.531%207.534%2031.39%2025.949t11.858%2039.621z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-volume-down:after {
|
.ui-nosvg .ui-icon-volume-down:after {
|
||||||
background-image: url("images/icons/volumedown.png");
|
background-image: url("images/icons/volumedown.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-previous-track:after {
|
.ui-icon-previous-track:after {
|
||||||
background-image: url("images/icons/previoustrack.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M273.159%2039.341q5.301-5.301%208.929-3.627t3.627%208.929v410.714q0%207.254-3.627%208.929t-8.929-3.627l-198.103-198.103q-2.511-2.511-3.627-5.301v189.174q0%207.254-5.301%2012.556t-12.556%205.301h-35.714q-7.254%200-12.556-5.301t-5.301-12.556v-392.857q0-7.254%205.301-12.556t12.556-5.301h35.714q7.254%200%2012.556%205.301t5.301%2012.556v189.174q1.116-3.069%203.627-5.301z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 6px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-previous-track:after {
|
.ui-nosvg .ui-icon-previous-track:after {
|
||||||
background-image: url("images/icons/previoustrack.png");
|
background-image: url("images/icons/previoustrack.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-next-track:after {
|
.ui-icon-next-track:after {
|
||||||
background-image: url("images/icons/nexttrack.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M12.556%20460.659q-5.301%205.301-8.929%203.627t-3.627-8.929v-410.714q0-7.254%203.627-8.929t8.929%203.627l198.103%20198.103q2.232%202.232%203.627%205.301v-189.174q0-7.254%205.301-12.556t12.556-5.301h35.714q7.254%200%2012.556%205.301t5.301%2012.556v392.857q0%207.254-5.301%2012.556t-12.556%205.301h-35.714q-7.254%200-12.556-5.301t-5.301-12.556v-189.174q-1.395%202.79-3.627%205.301z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 6px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-next-track:after {
|
.ui-nosvg .ui-icon-next-track:after {
|
||||||
background-image: url("images/icons/nexttrack.png");
|
background-image: url("images/icons/nexttrack.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-sort:after {
|
.ui-icon-sort:after {
|
||||||
background-image: url("images/icons/sort.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M285.714%20303.571q0%207.254-5.301%2012.556l-125%20125q-5.301%205.301-12.556%205.301t-12.556-5.301l-125-125q-5.301-5.301-5.301-12.556t5.301-12.556%2012.556-5.301h250q7.254%200%2012.556%205.301t5.301%2012.556zM285.714%20196.429q0%207.254-5.301%2012.556t-12.556%205.301h-250q-7.254%200-12.556-5.301t-5.301-12.556%205.301-12.556l125-125q5.301-5.301%2012.556-5.301t12.556%205.301l125%20125q5.301%205.301%205.301%2012.556z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 6px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-sort:after {
|
.ui-nosvg .ui-icon-sort:after {
|
||||||
background-image: url("images/icons/sort.png");
|
background-image: url("images/icons/sort.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-filter:after {
|
.ui-icon-filter:after {
|
||||||
background-image: url("images/icons/filter.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M391.462%2082.31q4.743%2011.44-3.906%2019.531l-137.556%20137.556v207.031q0%2011.719-10.882%2016.462-3.627%201.395-6.976%201.395-7.534%200-12.556-5.301l-71.429-71.429q-5.301-5.301-5.301-12.556v-135.603l-137.556-137.556q-8.649-8.091-3.906-19.531%204.743-10.882%2016.462-10.882h357.143q11.719%200%2016.462%2010.882z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 4px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-filter:after {
|
.ui-nosvg .ui-icon-filter:after {
|
||||||
background-image: url("images/icons/filter.png");
|
background-image: url("images/icons/filter.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-audiocd:after {
|
.ui-icon-audiocd:after {
|
||||||
background-image: url("images/icons/audiocd.png");
|
background-image: url("images/icons/audiocd.png");
|
||||||
}
|
}
|
||||||
|
@ -78,17 +103,31 @@
|
||||||
.ui-nosvg .ui-icon-audiocd:after {
|
.ui-nosvg .ui-icon-audiocd:after {
|
||||||
background-image: url("images/icons/audiocd.png");
|
background-image: url("images/icons/audiocd.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-subtitles:after {
|
.ui-icon-subtitles:after {
|
||||||
background-image: url("images/icons/subtitles.png");
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M22.601%2035.993l15.067%207.534q5.581%201.395%2058.873%201.395h36.272l5.301-0.837%2032.087-0.279%20213.169%200.279%209.487%200.558q3.906%200.279%207.813-1.953t5.859-4.464l1.953-2.232%2011.719-0.279q4.185%200%207.813%200.279v29.157t0.279%2036.691l0.279%2027.902-0.279%2016.183q0%208.929-1.116%2014.23-10.882%204.185-18.973%205.022-6.976-11.998-15.067-35.714-2.232-6.696-4.325-17.438t-3.208-18.276-1.674-8.091q-3.627-4.185-7.534-5.301-1.953-0.558-16.323-0.558t-38.644%200.279-35.714%200.279q-26.228%200-35.435%201.395-2.79%2027.065-2.232%2037.946l0.279%2042.411v-14.509l0.837%20100.167-0.279%2041.016q-0.279%2012.835%203.069%2023.716%2013.672%206.976%2024.833%208.929%200.558%200%205.022%201.395t12.277%203.627%2011.998%203.348q8.371%202.232%2013.951%205.022%201.395%2012.556%201.395%2013.951%200%202.79-0.837%208.091-3.906%200.279-9.487%200.279-30.692%200-52.176-2.79-20.089-2.232-66.406-2.232-22.879%200-65.011%203.627-12.556%201.395-19.531%201.395-0.558-6.138-0.558-7.254l-0.279-7.254v-2.511q5.859-9.208%2022.042-13.672%2038.784-10.603%2044.364-13.951%202.511-5.859%203.348-15.625%201.674-38.226%201.674-120.815l-1.395-12.277q0-73.94-0.558-77.567-0.558-3.069-1.674-4.185-1.674-1.395-3.906-1.674-10.603-1.674-41.294-1.674-13.951%200-47.015%203.906t-36.97%206.696q-3.627%202.511-6.138%209.208t-6.138%2020.926-6.696%2023.438q-1.674%205.301-5.441%208.929t-5.72%203.627q-12.277-7.534-15.625-12.277v-106.864zM419.922%20397.042q7.254%205.581%207.254%2013.672t-7.254%2013.672l-45.201%2035.156q-7.254%205.581-12.417%203.069t-5.162-11.719v-22.321h-285.714v22.321q0%209.208-5.162%2011.719t-12.417-3.069l-45.201-35.156q-7.254-5.581-7.254-13.672t7.254-13.672l45.201-35.156q7.254-5.581%2012.417-3.069t5.162%2011.719v22.321h285.714v-22.321q0-9.208%205.162-11.719t12.417%203.069z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 4px 3px;
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-subtitles:after {
|
.ui-nosvg .ui-icon-subtitles:after {
|
||||||
background-image: url("images/icons/subtitles.png");
|
background-image: url("images/icons/subtitles.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-icon-wireless:after {
|
.ui-icon-wireless:after {
|
||||||
background-image: url("images/icons/wireless.png");
|
background-image: url("images/icons/wireless.png");
|
||||||
}
|
}
|
||||||
/* Fallback */
|
/* Fallback */
|
||||||
.ui-nosvg .ui-icon-wireless:after {
|
.ui-nosvg .ui-icon-wireless:after {
|
||||||
background-image: url("images/icons/wireless.png");
|
background-image: url("images/icons/wireless.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui-icon-expand:after {
|
||||||
|
background-image: url("data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22utf-8%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%20Tiny%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11-tiny.dtd%22%3E%3Csvg%20version%3D%221.1%22%20baseProfile%3D%22tiny%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20width%3D%2216px%22%20height%3D%2216px%22%20viewBox%3D%220%200%20500%20500%22%20xml%3Aspace%3D%22preserve%22%3E%20%3Cpath%20d%3D%22M210.659%20294.643q0%203.627-2.79%206.417l-92.634%2092.634%2040.179%2040.179q5.301%205.301%205.301%2012.556t-5.301%2012.556-12.556%205.301h-125q-7.254%200-12.556-5.301t-5.301-12.556v-125q0-7.254%205.301-12.556t12.556-5.301%2012.556%205.301l40.179%2040.179%2092.634-92.634q2.79-2.79%206.417-2.79t6.417%202.79l31.808%2031.808q2.79%202.79%202.79%206.417zM428.571%2053.571v125q0%207.254-5.301%2012.556t-12.556%205.301-12.556-5.301l-40.179-40.179-92.634%2092.634q-2.79%202.79-6.417%202.79t-6.417-2.79l-31.808-31.808q-2.79-2.79-2.79-6.417t2.79-6.417l92.634-92.634-40.179-40.179q-5.301-5.301-5.301-12.556t5.301-12.556%2012.556-5.301h125q7.254%200%2012.556%205.301t5.301%2012.556z%22%20fill%3D%22%23ffffff%22%20%2F%3E%3C%2Fsvg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 4px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-nosvg .ui-icon-expand:after {
|
||||||
|
background-image: url("images/icons/expand.png");
|
||||||
|
}
|
||||||
|
|
BIN
dashboard-ui/css/images/icons/expand.png
Normal file
BIN
dashboard-ui/css/images/icons/expand.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 313 B |
|
@ -590,7 +590,7 @@ a.itemTag:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.lblDetailTab {
|
.lblDetailTab {
|
||||||
font-size: 16px!important;
|
font-size: 15px!important;
|
||||||
font-weight: 400!important;
|
font-weight: 400!important;
|
||||||
font-family: 'Open Sans';
|
font-family: 'Open Sans';
|
||||||
padding: .5em 1em;
|
padding: .5em 1em;
|
||||||
|
@ -710,14 +710,12 @@ a.itemTag:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemBackdrop {
|
.itemBackdrop {
|
||||||
background-image: none!important;
|
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemBackdropContent {
|
.itemBackdropContent {
|
||||||
position: static;
|
position: static;
|
||||||
padding: 1em 1em 0;
|
padding: 1em 1em .5em;
|
||||||
background-color: transparent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.itemDetailImage {
|
.itemDetailImage {
|
||||||
|
|
|
@ -26,15 +26,15 @@
|
||||||
|
|
||||||
.itemVideo {
|
.itemVideo {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
margin: 20px 20px 80px;
|
margin: 5px 5px 75px;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
height: 181px;
|
height: 181px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#videoControls {
|
#videoControls {
|
||||||
z-index: 99999;
|
z-index: 99999;
|
||||||
padding: 0 20px 5px;
|
padding: 0 5px 5px;
|
||||||
height: 80px;
|
height: 75px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: auto;
|
top: auto;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
|
|
||||||
#videoControls #video-basic-controls {
|
#videoControls #video-basic-controls {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 30px;
|
top: 25px;
|
||||||
left: 20px;
|
left: 20px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
|
|
||||||
#videoControls #video-advanced-controls {
|
#videoControls #video-advanced-controls {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 30px;
|
top: 25px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
@ -104,14 +104,14 @@
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mediaPlayer .ui-slider-track {
|
#mediaPlayer .ui-slider-track, .nowPlayingBar .ui-slider-track {
|
||||||
border-color: #2ad !important;
|
border-color: #2ad !important;
|
||||||
height: 10px!important;
|
height: 2px!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mediaPlayer .ui-slider-handle {
|
#mediaPlayer .ui-slider-handle, .nowPlayingBar .ui-slider-handle {
|
||||||
height: 12px !important;
|
height: 10px !important;
|
||||||
margin-top: -7px !important;
|
margin-top: -6px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#videoPlayer.fullscreenVideo #videoControls {
|
#videoPlayer.fullscreenVideo #videoControls {
|
||||||
|
@ -139,7 +139,12 @@
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 83px;
|
bottom: 85px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mediaPlayer .volumeSliderContainer {
|
||||||
|
position: relative;
|
||||||
|
top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Media queries
|
/* Media queries
|
||||||
|
@ -191,10 +196,6 @@
|
||||||
margin-left: -550px;
|
margin-left: -550px;
|
||||||
margin-top: -329px;
|
margin-top: -329px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#video-videoPlayerMenuButton {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (min-width: 1440px) and (min-height: 720px) {
|
@media all and (min-width: 1440px) and (min-height: 720px) {
|
||||||
|
@ -212,10 +213,6 @@
|
||||||
/****************************************/
|
/****************************************/
|
||||||
|
|
||||||
@media all and (max-width: 1200px), all and (max-height: 720px) {
|
@media all and (max-width: 1200px), all and (max-height: 720px) {
|
||||||
#videoControls .nowPlayingMediaInfo {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#videoControls .currentTime {
|
#videoControls .currentTime {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
|
@ -249,17 +246,13 @@
|
||||||
width: 250px;
|
width: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mediaPlayer #video-basic-controls .volumeSliderContainer {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#mediaPlayer #video-basic-controls, #mediaPlayer #video-advanced-controls {
|
#mediaPlayer #video-basic-controls, #mediaPlayer #video-advanced-controls {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 120px;
|
height: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mediaPlayer #videoControls .mediaPlayerFlyout {
|
#mediaPlayer #videoControls .mediaPlayerFlyout {
|
||||||
bottom: 148px;
|
bottom: 150px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,14 +266,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 500px) {
|
@media all and (max-width: 600px) {
|
||||||
#mediaPlayer .previousTrackButton, #mediaPlayer .nextTrackButton {
|
#mediaPlayer .volumeSliderContainer, #mediaPlayer .muteButton, #mediaPlayer .unmuteButton {
|
||||||
|
display: none!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mediaPlayer .nowPlayingImage, #mediaPlayer .nowPlayingText {
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 400px) {
|
@media all and (max-width: 500px) {
|
||||||
#mediaPlayer .playlistButton {
|
#mediaPlayer .previousTrackButton, #mediaPlayer .nextTrackButton {
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,3 +368,86 @@
|
||||||
.cursor-inactive {
|
.cursor-inactive {
|
||||||
cursor: none;
|
cursor: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutContainer {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaPlayerFlyout {
|
||||||
|
width: 200px;
|
||||||
|
color: #000;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #999;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 99999;
|
||||||
|
bottom: 78px;
|
||||||
|
margin-left: -125px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chaptersFlyout, .audioTracksFlyout {
|
||||||
|
width: 250px;
|
||||||
|
margin-left: -150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOption {
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #000;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOption:hover, .mediaFlyoutOption:focus {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectedMediaFlyoutOption {
|
||||||
|
background-color: #d9F4FF;
|
||||||
|
background-image: url(images/media/selected.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right top;
|
||||||
|
background-size: 16px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionImage {
|
||||||
|
display: inline-block;
|
||||||
|
width: 15%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
||||||
|
vertical-align: top;
|
||||||
|
display: inline-block;
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chaptersFlyout .mediaFlyoutOptionImage {
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chaptersFlyout .mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionName {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-left: 5px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaFlyoutOptionSecondaryText {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-top: 3px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,9 @@
|
||||||
/* Now playing bar */
|
/* Now playing bar */
|
||||||
.nowPlayingBar {
|
.nowPlayingBar {
|
||||||
padding: 6px 0 20px 0;
|
padding: 6px 0 14px 0;
|
||||||
border-top: 2px solid green;
|
border-top: 2px solid green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingBar .barBackground {
|
|
||||||
border-top: 2px solid green;
|
|
||||||
position: absolute;
|
|
||||||
margin: -8px -0.5em -22px !important;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBar > *:not(#mediaElement):not(.mediaFlyoutContainer):not(.barBackground ) {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingBarImage {
|
.nowPlayingBarImage {
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
@ -29,27 +17,32 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowPlayingMediaInfo div {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingMediaInfo a {
|
|
||||||
margin-right: .25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.nowPlayingMediaInfo {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nowPlayingText {
|
.nowPlayingText {
|
||||||
position: relative;
|
display: inline-block;
|
||||||
top: -3px;
|
|
||||||
margin-left: 3px;
|
|
||||||
margin-right: 2em;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
position: relative;
|
||||||
|
top: -7px;
|
||||||
|
margin-left: 3px;
|
||||||
|
max-width: 200px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin-right: 2em;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nowPlayingDoubleText {
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingImage {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nowPlayingImage img {
|
||||||
|
height: 40px;
|
||||||
|
margin-right: .5em;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
.mediaButton img {
|
.mediaButton img {
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
@ -60,10 +53,13 @@
|
||||||
top: -10px;
|
top: -10px;
|
||||||
max-width: 110px;
|
max-width: 110px;
|
||||||
margin-right: 2em;
|
margin-right: 2em;
|
||||||
font-size: 14px;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nowPlayingBar .currentTime {
|
||||||
|
top: -15px;
|
||||||
|
}
|
||||||
|
|
||||||
.mediaSlider {
|
.mediaSlider {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -10px;
|
top: -10px;
|
||||||
|
@ -79,8 +75,8 @@
|
||||||
width: 130px;
|
width: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#nowPlayingBar .positionSliderContainer {
|
#nowPlayingBar .sliderContainer {
|
||||||
margin-top: 8px;
|
margin-top: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.volumeSliderContainer {
|
.volumeSliderContainer {
|
||||||
|
@ -127,125 +123,27 @@ input[type="range"]::-ms-fill-upper {
|
||||||
}
|
}
|
||||||
|
|
||||||
@media all and (max-width: 800px) {
|
@media all and (max-width: 800px) {
|
||||||
#nowPlayingBar .volumeButton, #nowPlayingBar .volumeSliderContainer, #nowPlayingBar .muteButton, #nowPlayingBar .unmuteButton, #nowPlayingBar .nowPlayingMediaInfo {
|
|
||||||
display: none; /*!important;*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 650px) {
|
#nowPlayingBar .mediaButton {
|
||||||
#nowPlayingBar .nowPlayingMediaInfo {
|
margin-top: 0;
|
||||||
display: none;
|
margin-bottom: 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 600px) {
|
|
||||||
#nowPlayingBar .chaptersButton, #nowPlayingBar .audioTracksButton {
|
|
||||||
display: none; /*!important;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#nowPlayingBar .positionSliderContainer, #nowPlayingBar .currentTime {
|
#nowPlayingBar .mediaButton:not(#playButton):not(#pauseButton) {
|
||||||
top: 0!important;
|
display: none;
|
||||||
position: relative!important;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 500px) {
|
#nowPlayingBar #playButton, #nowPlayingBar #pauseButton {
|
||||||
#nowPlayingBar .positionSliderContainer {
|
float: right;
|
||||||
width: 80px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#nowPlayingBar .previousTrackButton, #nowPlayingBar .nextTrackButton {
|
#nowPlayingBar .currentTime, #nowPlayingBar .positionSliderContainer, #nowPlayingBar .volumeSliderContainer, #nowPlayingBar .muteButton, #nowPlayingBar .unmuteButton {
|
||||||
display: none; /*!important;*/
|
display: none !important;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media all and (max-width: 400px) {
|
|
||||||
#nowPlayingBar .playlistButton {
|
|
||||||
display: none; /*!important;*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutContainer {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaPlayerFlyout {
|
|
||||||
width: 200px;
|
|
||||||
color: #000;
|
|
||||||
background-color: #fff;
|
|
||||||
border: 1px solid #999;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 99999;
|
|
||||||
bottom: 78px;
|
|
||||||
margin-left: -125px;
|
|
||||||
max-height: 300px;
|
|
||||||
overflow-y: auto;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chaptersFlyout,.audioTracksFlyout {
|
|
||||||
width: 250px;
|
|
||||||
margin-left: -150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOption {
|
|
||||||
display: block;
|
|
||||||
text-decoration: none;
|
|
||||||
color: #000;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOption:hover, .mediaFlyoutOption:focus {
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectedMediaFlyoutOption {
|
.nowPlayingBar {
|
||||||
background-color: #d9F4FF;
|
padding: 10px 5px 10px 0;
|
||||||
background-image: url(images/media/selected.png);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: right top;
|
|
||||||
background-size: 16px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionImage {
|
|
||||||
display: inline-block;
|
|
||||||
width: 15%;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
|
||||||
vertical-align: top;
|
|
||||||
display: inline-block;
|
|
||||||
width: 85%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.chaptersFlyout .mediaFlyoutOptionImage {
|
|
||||||
width: 40%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chaptersFlyout .mediaFlyoutOptionImage + .mediaFlyoutOptionContent {
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionName {
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-left: 5px;
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mediaFlyoutOptionSecondaryText {
|
|
||||||
font-size: 13px;
|
|
||||||
color: #333;
|
|
||||||
font-weight: normal;
|
|
||||||
margin-top: 3px;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1440px) {
|
@media (min-width: 1440px) {
|
||||||
|
@ -253,3 +151,16 @@ input[type="range"]::-ms-fill-upper {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mediaPlayerAudioContainer {
|
||||||
|
position: fixed;
|
||||||
|
top: 40%;
|
||||||
|
text-align: center;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mediaPlayerAudioContainerInner {
|
||||||
|
padding: 1em;
|
||||||
|
background: #222;
|
||||||
|
}
|
||||||
|
|
|
@ -655,24 +655,6 @@ h1 .imageLink {
|
||||||
top: -3px;
|
top: -3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dashboard home */
|
|
||||||
.tblConnections td {
|
|
||||||
padding: 1em 0 1em .75em;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tblConnections td:first-child {
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tblConnections img:not(.clientNowPlayingImage) {
|
|
||||||
height: 28px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clientNowPlayingImage {
|
|
||||||
height: 52px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
#footer {
|
#footer {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -870,3 +852,142 @@ progress {
|
||||||
.btnShowStatusMessage:hover {
|
.btnShowStatusMessage:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.activeSession {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
margin: 5px;
|
||||||
|
width: 250px;
|
||||||
|
height: 140.625px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionNowPlayingContent {
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionNowPlayingInnerContent {
|
||||||
|
background-color: rgba(0, 0, 0, .6);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 400;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionAppInfo {
|
||||||
|
padding: .5em;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionAppName {
|
||||||
|
vertical-align: top;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionUserInfo {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 7px;
|
||||||
|
padding: .5em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionUserInfo img {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionNowPlayingInfo {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
bottom: 7px;
|
||||||
|
padding: .5em;
|
||||||
|
max-width: 150px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionAppInfo img {
|
||||||
|
max-width: 32px;
|
||||||
|
max-height: 32px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeSession progress {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 7px;
|
||||||
|
width: 100%;
|
||||||
|
opacity: .95;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notPlayingSession .sessionNowPlayingContent {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notPlayingSession .sessionNowPlayingInnerContent {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notPlayingSession .sessionUserInfo, .notPlayingSession .sessionNowPlayingInfo {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeSession:hover {
|
||||||
|
-moz-box-shadow: 0 0 20px 1px #38c;
|
||||||
|
-webkit-box-shadow: 0 0 20px 1px #38c;
|
||||||
|
box-shadow: 0 0 20px 1px #38c;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 1000px) {
|
||||||
|
|
||||||
|
.activeSession {
|
||||||
|
width: 230px;
|
||||||
|
height: 129.375px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 550px) {
|
||||||
|
|
||||||
|
.activeSession {
|
||||||
|
width: 210px;
|
||||||
|
height: 118.125px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionAppName {
|
||||||
|
max-width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 500px) {
|
||||||
|
|
||||||
|
.activeSession {
|
||||||
|
width: 200px;
|
||||||
|
height: 112.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sessionAppName {
|
||||||
|
max-width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media all and (max-width: 400px) {
|
||||||
|
|
||||||
|
.activeSession {
|
||||||
|
width: 250px;
|
||||||
|
height: 140.625px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,67 +19,63 @@
|
||||||
<div class="readOnlyContent dashboardHomeLeftColumn">
|
<div class="readOnlyContent dashboardHomeLeftColumn">
|
||||||
|
|
||||||
<div data-role="collapsible" data-collapsed="false">
|
<div data-role="collapsible" data-collapsed="false">
|
||||||
<h3>Server Information</h3>
|
<h3>${HeaerServerInformation}</h3>
|
||||||
<div>
|
<div>
|
||||||
<p>
|
<p id="appVersionNumber">
|
||||||
Version <span id="appVersionNumber"></span>
|
|
||||||
</p>
|
</p>
|
||||||
<p id="pUpToDate" style="display: none;">
|
<p id="pUpToDate" style="display: none;">
|
||||||
<img src="css/images/checkmarkgreen.png" style="height: 20px; margin-right: 3px; position: relative; top: 5px; border-radius: 3px;" />
|
<img src="css/images/checkmarkgreen.png" style="height: 20px; margin-right: 3px; position: relative; top: 5px; border-radius: 3px;" />
|
||||||
Media Browser Server is up to date
|
${ServerUpToDate}
|
||||||
</p>
|
</p>
|
||||||
<div id="pUpdateNow" style="display: none;">
|
<div id="pUpdateNow" style="display: none;">
|
||||||
<p><strong>A new version of Media Browser Server is available!</strong></p>
|
<p><strong>${NewServerVersionAvailable}</strong></p>
|
||||||
<p id="newVersionNumber"></p>
|
<p id="newVersionNumber"></p>
|
||||||
<div id="btnUpdateApplicationContainer">
|
<div id="btnUpdateApplicationContainer">
|
||||||
<button id="btnUpdateApplication" type="button" data-icon="arrow-d" data-theme="b" onclick="DashboardPage.updateApplication();">Update Now</button>
|
<button id="btnUpdateApplication" type="button" data-icon="arrow-d" data-theme="b" onclick="DashboardPage.updateApplication();">${ButtonUpdateNow}</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="btnManualUpdateContainer">
|
<div id="btnManualUpdateContainer">
|
||||||
Please shutdown the server and <a href="http://www.mediabrowser3.com/download" target="_blank">update manually.</a>
|
<a href="http://www.mediabrowser3.com/download" target="_blank">${PleaseUpdateManually}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="updateFail" style="color: #cc0000; display: none;">There was an error connecting to the remote Media Browser repository.</div>
|
<div id="updateFail" style="color: #cc0000; display: none;">${ErrorConnectingToMediaBrowserRepository}</div>
|
||||||
<p id="ports"></p>
|
<p id="ports"></p>
|
||||||
<div id="pPluginUpdates"></div>
|
<div id="pPluginUpdates"></div>
|
||||||
|
|
||||||
<p class="externalUrl"></p>
|
<p class="externalUrl"></p>
|
||||||
<div style="margin-top: 1em;">
|
<div style="margin-top: 1em;">
|
||||||
<button class="btnRestartContainer hide" id="btnRestartServer" type="button" data-icon="refresh" data-mini="true" data-inline="true" onclick="DashboardPage.restart();">Restart</button>
|
<button class="btnRestartContainer hide" id="btnRestartServer" type="button" data-icon="refresh" data-mini="true" data-inline="true" onclick="DashboardPage.restart();">${ButtonRestart}</button>
|
||||||
<button id="btnShutdown" type="button" data-icon="delete" data-mini="true" data-inline="true" onclick="DashboardPage.shutdown();">Shutdown</button>
|
<button id="btnShutdown" type="button" data-icon="delete" data-mini="true" data-inline="true" onclick="DashboardPage.shutdown();">${ButtonShutdown}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="collapsiblePendingInstallations" data-role="collapsible" data-collapsed="false" style="margin-top: 2em; display: none;">
|
<div id="collapsiblePendingInstallations" data-role="collapsible" data-collapsed="false" style="margin-top: 2em; display: none;">
|
||||||
<h3>Pending Installations</h3>
|
<h3>${HeaderPendingInstallations}</h3>
|
||||||
<p>The following components have been installed or updated:</p>
|
<p>${LabelComponentsUpdated}</p>
|
||||||
<div id="pendingInstallations">
|
<div id="pendingInstallations">
|
||||||
</div>
|
</div>
|
||||||
<p>Please restart the server to finish applying updates.</p>
|
<p>${MessagePleaseRestartServerToFinishUpdating}</p>
|
||||||
<div class="btnRestartContainer hide">
|
<div class="btnRestartContainer hide">
|
||||||
<button type="button" data-icon="refresh" data-theme="b" onclick="Dashboard.restartServer();" data-mini="true" data-inline="true">Restart Now</button>
|
<button type="button" data-icon="refresh" data-theme="b" onclick="Dashboard.restartServer();" data-mini="true" data-inline="true">${ButtonRestartNow}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-role="collapsible" data-collapsed="false" style="margin-top: 2em;">
|
<div data-role="collapsible" data-collapsed="false" style="margin-top: 2em;">
|
||||||
<h3>Active Devices</h3>
|
<h3>${HeaderActiveDevices}</h3>
|
||||||
<div>
|
<div class="activeDevices">
|
||||||
<table class="tblConnections" style="border-collapse: collapse;">
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="runningTasksCollapsible" data-role="collapsible" data-collapsed="false" style="margin-top: 2em; display: none;">
|
<div id="runningTasksCollapsible" data-role="collapsible" data-collapsed="false" style="margin-top: 2em; display: none;">
|
||||||
<h3>Running Tasks</h3>
|
<h3>${HeaderRunningTasks}</h3>
|
||||||
<div>
|
<div>
|
||||||
<div id="divRunningTasks">
|
<div id="divRunningTasks">
|
||||||
</div>
|
</div>
|
||||||
<p><a href="scheduledtasks.html">Manage Scheduled Tasks</a></p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="contribute" style="margin-top: 4em; display: none;">
|
<div id="contribute" style="margin-top: 4em; display: none;">
|
||||||
<h2 style="margin: 0 0 .35em;">Help Improve Media Browser</h2>
|
<h2 style="margin: 0 0 .35em;">${HeaderHelpImproveMediaBrowser}</h2>
|
||||||
<div>
|
<div>
|
||||||
<a data-role="button" data-icon="mail" data-mini="true" href="supporter.html">
|
<a data-role="button" data-icon="mail" data-mini="true" href="supporter.html">
|
||||||
<img src="css/images/supporter/donatepaypal.png" /></a>
|
<img src="css/images/supporter/donatepaypal.png" /></a>
|
||||||
|
@ -113,7 +109,7 @@
|
||||||
|
|
||||||
<div class="readOnlyContent dashboardHomeRightColumn">
|
<div class="readOnlyContent dashboardHomeRightColumn">
|
||||||
<div data-role="collapsible" data-collapsed="false">
|
<div data-role="collapsible" data-collapsed="false">
|
||||||
<h3>Latest News</h3>
|
<h3>${HeaderLatestNews}</h3>
|
||||||
<div class="latestNewsItems">
|
<div class="latestNewsItems">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -138,19 +138,18 @@
|
||||||
<a class="btnPlayExternal hide" data-role="button" data-icon="play" data-inline="true" data-mini="true" href="#" target="_blank">${ButtonPlay}</a>
|
<a class="btnPlayExternal hide" data-role="button" data-icon="play" data-inline="true" data-mini="true" href="#" target="_blank">${ButtonPlay}</a>
|
||||||
<a class="btnEdit hide" data-role="button" data-icon="edit" data-inline="true" data-mini="true" href="#">${ButtonEdit}</a>
|
<a class="btnEdit hide" data-role="button" data-icon="edit" data-inline="true" data-mini="true" href="#">${ButtonEdit}</a>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="itemGenres mobileGenres"></p>
|
||||||
|
<p class="itemOverview mobileOverview"></p>
|
||||||
</div>
|
</div>
|
||||||
<a href="#" id="lnkPreviousItem" class="lnkPreviousItem lnkSibling hide" data-role="button" title="${ButtonPrevious}" data-icon="carat-l" data-mini="true" data-inline="true" data-iconpos="notext">${ButtonPrevious}</a>
|
<a href="#" id="lnkPreviousItem" class="lnkPreviousItem lnkSibling hide" data-role="button" title="${ButtonPrevious}" data-icon="carat-l" data-mini="true" data-inline="true" data-iconpos="notext">${ButtonPrevious}</a>
|
||||||
<a href="#" id="lnkNextItem" class="lnkNextItem lnkSibling hide" data-role="button" title="${ButtonNext}" data-icon="carat-r" data-mini="true" data-inline="true" data-iconpos="notext">${ButtonNext}</a>
|
<a href="#" id="lnkNextItem" class="lnkNextItem lnkSibling hide" data-role="button" title="${ButtonNext}" data-icon="carat-r" data-mini="true" data-inline="true" data-iconpos="notext">${ButtonNext}</a>
|
||||||
<p class="itemGenres mobileGenres"></p>
|
|
||||||
<p class="itemOverview mobileOverview"></p>
|
|
||||||
</div>
|
</div>
|
||||||
<div data-role="content">
|
<div data-role="content">
|
||||||
<div class="detailPageContent">
|
<div class="detailPageContent">
|
||||||
|
|
||||||
<div id="detailsSection" class="detailSection hide">
|
<div id="detailsSection" class="detailSection hide">
|
||||||
|
|
||||||
<br />
|
<div class="tabButtons" style="margin-top: .75em;"></div>
|
||||||
<div class="tabButtons"></div>
|
|
||||||
|
|
||||||
<div class="detailSectionContent" style="padding: .25em .7em 0;">
|
<div class="detailSectionContent" style="padding: .25em .7em 0;">
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,11 @@
|
||||||
<table data-role="table" data-mode="reflow" class="tblTuners stripedTable ui-responsive table-stroke">
|
<table data-role="table" data-mode="reflow" class="tblTuners stripedTable ui-responsive table-stroke">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>${HeaderName}</th>
|
||||||
<th>Source</th>
|
<th>${HeaderSource}</th>
|
||||||
<th>Status</th>
|
<th>${HeaderStatus}</th>
|
||||||
<th>Program</th>
|
<th>${HeaderProgram}</th>
|
||||||
<th>Clients</th>
|
<th>${HeaderClients}</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
13
dashboard-ui/nowplaying.html
Normal file
13
dashboard-ui/nowplaying.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>${TitleMediaBrowser}</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="nowPlayingPage" data-role="page" class="page libraryPage" data-theme="b">
|
||||||
|
|
||||||
|
<div data-role="content">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,7 +1,7 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title></title>
|
<title>${TitleMediaBrowser}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="playlistPage" data-role="page" class="page libraryPage" data-theme="b">
|
<div id="playlistPage" data-role="page" class="page libraryPage" data-theme="b">
|
||||||
|
|
|
@ -80,14 +80,6 @@
|
||||||
|
|
||||||
$('#hfResultId', popup).val(item.Id);
|
$('#hfResultId', popup).val(item.Id);
|
||||||
|
|
||||||
if (item.ExtractedName) {
|
|
||||||
$('#fldRememberCorrection', popup).hide();
|
|
||||||
} else {
|
|
||||||
$('#fldRememberCorrection', popup).hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#chkRememberEpisodeCorrection', popup).checked(false).checkboxradio('refresh');
|
|
||||||
|
|
||||||
var seriesHtml = allSeries.map(function (s) {
|
var seriesHtml = allSeries.map(function (s) {
|
||||||
|
|
||||||
return '<option value="' + s.Id + '">' + s.Name + '</option>';
|
return '<option value="' + s.Id + '">' + s.Name + '</option>';
|
||||||
|
@ -157,8 +149,7 @@
|
||||||
SeriesId: $('#selectSeries', form).val(),
|
SeriesId: $('#selectSeries', form).val(),
|
||||||
SeasonNumber: $('#txtSeason', form).val(),
|
SeasonNumber: $('#txtSeason', form).val(),
|
||||||
EpisodeNumber: $('#txtEpisode', form).val(),
|
EpisodeNumber: $('#txtEpisode', form).val(),
|
||||||
EndingEpisodeNumber: $('#txtEndingEpisode', form).val(),
|
EndingEpisodeNumber: $('#txtEndingEpisode', form).val()
|
||||||
RememberCorrection: $('#chkRememberEpisodeCorrection', form).checked()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ApiClient.performEpisodeOrganization(resultId, options).done(function () {
|
ApiClient.performEpisodeOrganization(resultId, options).done(function () {
|
||||||
|
|
|
@ -66,6 +66,17 @@
|
||||||
|
|
||||||
this.hasReceivers = false;
|
this.hasReceivers = false;
|
||||||
|
|
||||||
|
this.currentMediaOffset = 0;
|
||||||
|
|
||||||
|
// Progress bar element id
|
||||||
|
this.progressBar = "positionSlider";
|
||||||
|
|
||||||
|
// Timec display element id
|
||||||
|
this.duration = "currentTime";
|
||||||
|
|
||||||
|
// Playback display element id
|
||||||
|
this.playback = "playTime";
|
||||||
|
|
||||||
this.initializeCastPlayer();
|
this.initializeCastPlayer();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,7 +100,7 @@
|
||||||
|
|
||||||
// v1 Id AE4DA10A
|
// v1 Id AE4DA10A
|
||||||
// v2 Id 472F0435
|
// v2 Id 472F0435
|
||||||
var applicationID = 'AE4DA10A';
|
var applicationID = '472F0435';
|
||||||
|
|
||||||
// request session
|
// request session
|
||||||
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
|
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
|
||||||
|
@ -230,6 +241,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
function getCodecLimits() {
|
function getCodecLimits() {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
maxVideoAudioChannels: 6,
|
maxVideoAudioChannels: 6,
|
||||||
|
@ -445,6 +457,8 @@
|
||||||
|
|
||||||
function getMetadata(item) {
|
function getMetadata(item) {
|
||||||
|
|
||||||
|
console.log("md item", item);
|
||||||
|
|
||||||
var metadata = {};
|
var metadata = {};
|
||||||
|
|
||||||
if (item.Type == 'Episode') {
|
if (item.Type == 'Episode') {
|
||||||
|
@ -512,7 +526,7 @@
|
||||||
|
|
||||||
else if (item.MediaType == 'Movie') {
|
else if (item.MediaType == 'Movie') {
|
||||||
metadata = new chrome.cast.media.MovieMediaMetadata();
|
metadata = new chrome.cast.media.MovieMediaMetadata();
|
||||||
metadata.type = chrome.cast.media.MetadataType.MUSIC_TRACK;
|
metadata.type = chrome.cast.media.MetadataType.MOVIE;
|
||||||
|
|
||||||
if (item.ProductionYear) {
|
if (item.ProductionYear) {
|
||||||
metadata.releaseYear = item.ProductionYear;
|
metadata.releaseYear = item.ProductionYear;
|
||||||
|
@ -595,7 +609,7 @@
|
||||||
url += '&maxheight=' + codecLimits.maxHeight;
|
url += '&maxheight=' + codecLimits.maxHeight;
|
||||||
|
|
||||||
url += '&videoCodec=h264';
|
url += '&videoCodec=h264';
|
||||||
url += '&audioCodec=aac';
|
url += '&audioCodec=aac,mp3';
|
||||||
|
|
||||||
url += '&audiosamplerate=' + codecLimits.maxSampleRate;
|
url += '&audiosamplerate=' + codecLimits.maxSampleRate;
|
||||||
url += '&mediasourceid=' + mediaSourceInfo.mediaSource.Id;
|
url += '&mediasourceid=' + mediaSourceInfo.mediaSource.Id;
|
||||||
|
@ -617,6 +631,8 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.currentMediaOffset = startTimeTicks || 0;
|
||||||
|
|
||||||
var maxBitrate = 12000000;
|
var maxBitrate = 12000000;
|
||||||
var mediaInfo = getMediaSourceInfo(user, item, maxBitrate, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
|
var mediaInfo = getMediaSourceInfo(user, item, maxBitrate, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
|
||||||
|
|
||||||
|
@ -653,40 +669,62 @@
|
||||||
|
|
||||||
console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
|
console.log("chromecast new media session ID:" + mediaSession.mediaSessionId + ' (' + how + ')');
|
||||||
this.currentMediaSession = mediaSession;
|
this.currentMediaSession = mediaSession;
|
||||||
|
this.currentMediaTime = this.session.media[0].currentTime;
|
||||||
|
|
||||||
if (how == 'loadMedia') {
|
if (how == 'loadMedia') {
|
||||||
this.castPlayerState = PLAYER_STATE.PLAYING;
|
this.castPlayerState = PLAYER_STATE.PLAYING;
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.startProgressTimer(this.incrementMediaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (how == 'activeSession') {
|
if (how == 'activeSession') {
|
||||||
this.castPlayerState = this.session.media[0].playerState;
|
this.castPlayerState = this.session.media[0].playerState;
|
||||||
this.currentMediaTime = this.session.media[0].currentTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.castPlayerState == PLAYER_STATE.PLAYING) {
|
if (this.castPlayerState == PLAYER_STATE.PLAYING) {
|
||||||
// start progress timer
|
// start progress timer
|
||||||
//this.startProgressTimer(this.incrementMediaTime);
|
this.startProgressTimer(this.incrementMediaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
|
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
|
||||||
|
this.currentMediaDuration = this.currentMediaSession.media.duration;
|
||||||
|
|
||||||
//this.currentMediaDuration = this.currentMediaSession.media.duration;
|
//var playTime = document.getElementById(this.playback);
|
||||||
//var duration = this.currentMediaDuration;
|
//if (!playTime) {
|
||||||
//var hr = parseInt(duration / 3600);
|
// // Set duration time
|
||||||
//duration -= hr * 3600;
|
// var totalTime = document.getElementById(this.duration);
|
||||||
//var min = parseInt(duration / 60);
|
// totalTime.innerHTML = " / " + formatTime(this.currentMediaDuration);
|
||||||
//var sec = parseInt(duration % 60);
|
|
||||||
//if (hr > 0) {
|
// // Set play time
|
||||||
// duration = hr + ":" + min + ":" + sec;
|
// playTime = document.createElement("div");
|
||||||
|
// playTime.id = this.playback;
|
||||||
|
// playTime.className = "currentTime";
|
||||||
|
// playTime.style.marginRight = "5px";
|
||||||
|
// totalTime.parentNode.insertBefore(playTime, totalTime);
|
||||||
|
// playTime.innerHTML = formatTime(this.currentMediaTime);
|
||||||
//}
|
//}
|
||||||
//else {
|
};
|
||||||
// if (min > 0) {
|
|
||||||
// duration = min + ":" + sec;
|
function formatTime(duration) {
|
||||||
// }
|
var hr = parseInt(duration / 3600);
|
||||||
// else {
|
duration -= hr * 3600;
|
||||||
// duration = sec;
|
var min = parseInt(duration / 60);
|
||||||
// }
|
var sec = parseInt(duration % 60);
|
||||||
//}
|
|
||||||
//document.getElementById("duration").innerHTML = duration;
|
hr = "" + hr;
|
||||||
|
min = "" + min;
|
||||||
|
sec = "" + sec;
|
||||||
|
var hh = pad(hr);
|
||||||
|
var mm = pad(min);
|
||||||
|
var ss = pad(sec);
|
||||||
|
|
||||||
|
duration = hh + ":" + mm + ":" + ss;
|
||||||
|
|
||||||
|
return duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
function pad(s) {
|
||||||
|
return "00".substring(0, 2 - s.length) + s;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -707,7 +745,7 @@
|
||||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
this.castPlayerState = PLAYER_STATE.IDLE;
|
||||||
}
|
}
|
||||||
console.log("chromecast updating media");
|
console.log("chromecast updating media");
|
||||||
//this.updateProgressBar(e);
|
this.updateProgressBarByTimer();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -745,6 +783,7 @@
|
||||||
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
|
this.currentMediaSession.addUpdateListener(this.onMediaStatusUpdate.bind(this));
|
||||||
this.castPlayerState = PLAYER_STATE.PLAYING;
|
this.castPlayerState = PLAYER_STATE.PLAYING;
|
||||||
// start progress timer
|
// start progress timer
|
||||||
|
clearInterval(this.timer);
|
||||||
this.startProgressTimer(this.incrementMediaTime);
|
this.startProgressTimer(this.incrementMediaTime);
|
||||||
break;
|
break;
|
||||||
case PLAYER_STATE.IDLE:
|
case PLAYER_STATE.IDLE:
|
||||||
|
@ -791,6 +830,10 @@
|
||||||
this.onError.bind(this));
|
this.onError.bind(this));
|
||||||
this.castPlayerState = PLAYER_STATE.STOPPED;
|
this.castPlayerState = PLAYER_STATE.STOPPED;
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
|
//var playTime = document.getElementById(this.playback);
|
||||||
|
//if (playTime) {
|
||||||
|
// playTime.parentNode.removeChild(playTime);
|
||||||
|
//}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -849,19 +892,9 @@
|
||||||
* @param {Event} e An event object from seek
|
* @param {Event} e An event object from seek
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.seekMedia = function (event) {
|
CastPlayer.prototype.seekMedia = function (event) {
|
||||||
var pos = parseInt(event.offsetX);
|
var pos = parseInt(event);
|
||||||
var pi = document.getElementById("progress_indicator");
|
|
||||||
var p = document.getElementById("progress");
|
var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos);
|
||||||
if (event.currentTarget.id == 'progress_indicator') {
|
|
||||||
var curr = parseInt(this.currentMediaTime + this.currentMediaDuration * pos / PROGRESS_BAR_WIDTH);
|
|
||||||
var pp = parseInt(pi.style.marginLeft) + pos;
|
|
||||||
var pw = parseInt(p.style.width) + pos;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var curr = parseInt(pos * this.currentMediaDuration / PROGRESS_BAR_WIDTH);
|
|
||||||
var pp = pos - 21 - PROGRESS_BAR_WIDTH;
|
|
||||||
var pw = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.castPlayerState != PLAYER_STATE.PLAYING && this.castPlayerState != PLAYER_STATE.PAUSED) {
|
if (this.castPlayerState != PLAYER_STATE.PLAYING && this.castPlayerState != PLAYER_STATE.PAUSED) {
|
||||||
return;
|
return;
|
||||||
|
@ -899,21 +932,21 @@
|
||||||
* @param {Object} e An media status update object
|
* @param {Object} e An media status update object
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.updateProgressBar = function (e) {
|
CastPlayer.prototype.updateProgressBar = function (e) {
|
||||||
var p = document.getElementById("progress");
|
//var p = document.getElementById(this.progressBar);
|
||||||
var pi = document.getElementById("progress_indicator");
|
//if (e.idleReason == 'FINISHED' && e.playerState == 'IDLE') {
|
||||||
if (e.idleReason == 'FINISHED' && e.playerState == 'IDLE') {
|
// p.value = 0;
|
||||||
p.style.width = '0px';
|
// clearInterval(this.timer);
|
||||||
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + 'px';
|
// this.castPlayerState = PLAYER_STATE.STOPPED;
|
||||||
clearInterval(this.timer);
|
// if (e.idleReason == 'FINISHED') {
|
||||||
this.castPlayerState = PLAYER_STATE.STOPPED;
|
// $.publish("/playback/complete", e);
|
||||||
}
|
// console.log("playback complete", e);
|
||||||
else {
|
// }
|
||||||
p.style.width = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration + 1) + 'px';
|
//}
|
||||||
this.progressFlag = false;
|
//else {
|
||||||
setTimeout(this.setProgressFlag.bind(this), 1000); // don't update progress in 1 second
|
// p.value = Number(e.currentTime / this.currentMediaSession.media.duration + 1).toFixed(3);
|
||||||
var pp = Math.ceil(PROGRESS_BAR_WIDTH * e.currentTime / this.currentMediaSession.media.duration);
|
// this.progressFlag = false;
|
||||||
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px';
|
// setTimeout(this.setProgressFlag.bind(this), 1000); // don't update progress in 1 second
|
||||||
}
|
//}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -928,26 +961,46 @@
|
||||||
* Update progress bar based on timer
|
* Update progress bar based on timer
|
||||||
*/
|
*/
|
||||||
CastPlayer.prototype.updateProgressBarByTimer = function () {
|
CastPlayer.prototype.updateProgressBarByTimer = function () {
|
||||||
var p = document.getElementById("progress");
|
//var p = document.getElementById(this.progressBar);
|
||||||
if (isNaN(parseInt(p.style.width))) {
|
//if (isNaN(parseInt(p.value))) {
|
||||||
p.style.width = 0;
|
// p.value = 0;
|
||||||
}
|
//}
|
||||||
if (this.currentMediaDuration > 0) {
|
|
||||||
var pp = Math.floor(PROGRESS_BAR_WIDTH * this.currentMediaTime / this.currentMediaDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.progressFlag) {
|
//if (this.currentMediaDuration > 0) {
|
||||||
// don't update progress if it's been updated on media status update event
|
// var pp = Number(this.currentMediaTime / this.currentMediaDuration).toFixed(3);
|
||||||
p.style.width = pp + 'px';
|
|
||||||
var pi = document.getElementById("progress_indicator");
|
|
||||||
pi.style.marginLeft = -21 - PROGRESS_BAR_WIDTH + pp + 'px';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pp > PROGRESS_BAR_WIDTH) {
|
// var startTime = this.currentMediaOffset / 10000000;
|
||||||
|
// var playTime = document.getElementById(this.playback);
|
||||||
|
// if (playTime) {
|
||||||
|
// playTime.innerHTML = formatTime(startTime + this.currentMediaTime);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (this.progressFlag) {
|
||||||
|
// // don't update progress if it's been updated on media status update event
|
||||||
|
// p.value = pp;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//if (pp > 100 || this.castPlayerState == PLAYER_STATE.IDLE) {
|
||||||
|
// clearInterval(this.timer);
|
||||||
|
// this.deviceState = DEVICE_STATE.IDLE;
|
||||||
|
// this.castPlayerState = PLAYER_STATE.IDLE;
|
||||||
|
// $.publish("/playback/complete", true);
|
||||||
|
// console.log("playback complete");
|
||||||
|
//}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {function} A callback function for the fucntion to start timer
|
||||||
|
*/
|
||||||
|
CastPlayer.prototype.startProgressTimer = function(callback) {
|
||||||
|
if(this.timer) {
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
this.deviceState = DEVICE_STATE.IDLE;
|
this.timer = null;
|
||||||
this.castPlayerState = PLAYER_STATE.IDLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start progress timer
|
||||||
|
this.timer = setInterval(callback.bind(this), this.timerStep);
|
||||||
};
|
};
|
||||||
|
|
||||||
var castPlayer = new CastPlayer();
|
var castPlayer = new CastPlayer();
|
||||||
|
@ -956,19 +1009,112 @@
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
var isPositionSliderActive = false;
|
||||||
|
var currentPlaylistIndex;
|
||||||
|
|
||||||
self.name = PlayerName;
|
self.name = PlayerName;
|
||||||
|
|
||||||
self.play = function (options) {
|
self.isPaused = false;
|
||||||
|
|
||||||
if (options.items) {
|
self.playlist = [];
|
||||||
|
|
||||||
Dashboard.getCurrentUser().done(function (user) {
|
self.playlistIndex = 0;
|
||||||
|
|
||||||
castPlayer.loadMedia(user, options.items[0], options.startTimeTicks);
|
//$.subscribe("/playback/complete", function (e) {
|
||||||
|
// if (self.playlistIndex < (self.playlist.items || []).length) {
|
||||||
|
// self.play(self.playlist);
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
////$(".positionSlider", "#footer").off("slidestart slidestop")
|
||||||
|
//// .on('slidestart', function (e) {
|
||||||
|
//// isPositionSliderActive = true;
|
||||||
|
////}).on('slidestop', positionSliderChange);
|
||||||
|
|
||||||
|
////function positionSliderChange() {
|
||||||
|
//// isPositionSliderActive = false;
|
||||||
|
//// var newPercent = parseInt(this.value);
|
||||||
|
//// self.changeStream(newPercent);
|
||||||
|
////}
|
||||||
|
|
||||||
|
function getItemsForPlayback(query) {
|
||||||
|
var userId = Dashboard.getCurrentUserId();
|
||||||
|
|
||||||
|
query.Limit = query.Limit || 100;
|
||||||
|
query.Fields = getItemFields;
|
||||||
|
query.ExcludeLocationTypes = "Virtual";
|
||||||
|
|
||||||
|
return ApiClient.getItems(userId, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
function queueItems (items) {
|
||||||
|
for (var i = 0, length = items.length; i < length; i++) {
|
||||||
|
self.playlist.push(items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function queueItemsNext(items) {
|
||||||
|
var insertIndex = 1;
|
||||||
|
for (var i = 0, length = items.length; i < length; i++) {
|
||||||
|
self.playlist.splice(insertIndex, 0, items[i]);
|
||||||
|
insertIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function translateItemsForPlayback(items) {
|
||||||
|
var deferred = $.Deferred();
|
||||||
|
var firstItem = items[0];
|
||||||
|
var promise;
|
||||||
|
if (firstItem.IsFolder) {
|
||||||
|
promise = self.getItemsForPlayback({
|
||||||
|
ParentId: firstItem.Id,
|
||||||
|
Filters: "IsNotFolder",
|
||||||
|
Recursive: true,
|
||||||
|
SortBy: "SortName",
|
||||||
|
MediaTypes: "Audio,Video"
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
else if (firstItem.Type == "MusicArtist") {
|
||||||
|
promise = self.getItemsForPlayback({
|
||||||
|
Artists: firstItem.Name,
|
||||||
|
Filters: "IsNotFolder",
|
||||||
|
Recursive: true,
|
||||||
|
SortBy: "SortName",
|
||||||
|
MediaTypes: "Audio"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (firstItem.Type == "MusicGenre") {
|
||||||
|
promise = self.getItemsForPlayback({
|
||||||
|
Genres: firstItem.Name,
|
||||||
|
Filters: "IsNotFolder",
|
||||||
|
Recursive: true,
|
||||||
|
SortBy: "SortName",
|
||||||
|
MediaTypes: "Audio"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (promise) {
|
||||||
|
promise.done(function (result) {
|
||||||
|
deferred.resolveWith(null, [result.Items]);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
|
deferred.resolveWith(null, [items]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.play = function (options) {
|
||||||
|
console.log("play", options);
|
||||||
|
$("#nowPlayingBar", "#footer").show();
|
||||||
|
if (self.isPaused) {
|
||||||
|
self.isPaused = !self.isPaused;
|
||||||
|
castPlayer.playMedia();
|
||||||
|
} else if (options.items) {
|
||||||
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
castPlayer.loadMedia(user, options.items[self.playlistIndex++], options.startPositionTicks);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
var userId = Dashboard.getCurrentUserId();
|
var userId = Dashboard.getCurrentUserId();
|
||||||
|
|
||||||
var query = {};
|
var query = {};
|
||||||
|
@ -978,46 +1124,158 @@
|
||||||
query.Ids = options.ids.join(',');
|
query.Ids = options.ids.join(',');
|
||||||
|
|
||||||
ApiClient.getItems(userId, query).done(function (result) {
|
ApiClient.getItems(userId, query).done(function (result) {
|
||||||
|
|
||||||
options.items = result.Items;
|
options.items = result.Items;
|
||||||
|
|
||||||
self.play(options);
|
self.play(options);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.unpause = function () {
|
||||||
|
console.log("unpause");
|
||||||
|
self.isPaused = !self.isPaused;
|
||||||
|
castPlayer.playMedia();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.pause = function () {
|
||||||
|
console.log("pause");
|
||||||
|
self.isPaused = true;
|
||||||
|
castPlayer.pauseMedia();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.shuffle = function (id) {
|
self.shuffle = function (id) {
|
||||||
self.play({ ids: [id] });
|
var userId = Dashboard.getCurrentUserId();
|
||||||
|
ApiClient.getItem(userId, id).done(function (item) {
|
||||||
|
var query = {
|
||||||
|
UserId: userId,
|
||||||
|
Fields: getItemFields,
|
||||||
|
Limit: 50,
|
||||||
|
Filters: "IsNotFolder",
|
||||||
|
Recursive: true,
|
||||||
|
SortBy: "Random"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (item.IsFolder) {
|
||||||
|
query.ParentId = id;
|
||||||
|
}
|
||||||
|
else if (item.Type == "MusicArtist") {
|
||||||
|
query.MediaTypes = "Audio";
|
||||||
|
query.Artists = item.Name;
|
||||||
|
}
|
||||||
|
else if (item.Type == "MusicGenre") {
|
||||||
|
query.MediaTypes = "Audio";
|
||||||
|
query.Genres = item.Name;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getItemsForPlayback(query).done(function (result) {
|
||||||
|
self.playlist = { items: result.Items };
|
||||||
|
console.log("shuffle items", result.Items);
|
||||||
|
self.play(self.playlist);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.instantMix = function (id) {
|
self.instantMix = function (id) {
|
||||||
self.play({ ids: [id] });
|
var userId = Dashboard.getCurrentUserId();
|
||||||
};
|
ApiClient.getItem(userId, id).done(function (item) {
|
||||||
|
var promise;
|
||||||
|
var getItemFields = "MediaSources,Chapters";
|
||||||
|
var mixLimit = 3;
|
||||||
|
|
||||||
self.queue = function (options) {
|
if (item.Type == "MusicArtist") {
|
||||||
|
promise = ApiClient.getInstantMixFromArtist(name, {
|
||||||
|
UserId: userId,
|
||||||
|
Fields: getItemFields,
|
||||||
|
Limit: mixLimit
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (item.Type == "MusicGenre") {
|
||||||
|
promise = ApiClient.getInstantMixFromMusicGenre(name, {
|
||||||
|
UserId: userId,
|
||||||
|
Fields: getItemFields,
|
||||||
|
Limit: mixLimit
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (item.Type == "MusicAlbum") {
|
||||||
|
promise = ApiClient.getInstantMixFromAlbum(id, {
|
||||||
|
UserId: userId,
|
||||||
|
Fields: getItemFields,
|
||||||
|
Limit: mixLimit
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (item.Type == "Audio") {
|
||||||
|
promise = ApiClient.getInstantMixFromSong(id, {
|
||||||
|
UserId: userId,
|
||||||
|
Fields: getItemFields,
|
||||||
|
Limit: mixLimit
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
promise.done(function (result) {
|
||||||
|
self.playlist = { items: result.Items };
|
||||||
self.queueNext = function (options) {
|
console.log("instant mix items", result.Items);
|
||||||
|
self.play(self.playlist);
|
||||||
};
|
});
|
||||||
|
});
|
||||||
self.stop = function () {
|
|
||||||
castPlayer.stop();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.canQueueMediaType = function (mediaType) {
|
self.canQueueMediaType = function (mediaType) {
|
||||||
|
return mediaType == "Audio";
|
||||||
|
};
|
||||||
|
|
||||||
|
self.queue = function (options) {
|
||||||
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
if (options.items) {
|
||||||
|
translateItemsForPlayback(options.items).done(function (items) {
|
||||||
|
queueItems(items);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
getItemsForPlayback({
|
||||||
|
Ids: options.ids.join(',')
|
||||||
|
}).done(function (result) {
|
||||||
|
translateItemsForPlayback(result.Items).done(function (items) {
|
||||||
|
queueItems(items);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.queueNext = function (options) {
|
||||||
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
if (options.items) {
|
||||||
|
queueItemsNext(options.items);
|
||||||
|
} else {
|
||||||
|
self.getItemsForPlayback({
|
||||||
|
Ids: options.ids.join(',')
|
||||||
|
}).done(function (result) {
|
||||||
|
options.items = result.Items;
|
||||||
|
queueItemsNext(options.items);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.stop = function () {
|
||||||
|
$("#nowPlayingBar", "#footer").hide();
|
||||||
|
self.playlist = [];
|
||||||
|
self.playlistIndex = 0;
|
||||||
|
castPlayer.stopMedia();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.displayContent = function (options) {
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.mute = function () {
|
self.mute = function () {
|
||||||
castPlayer.mute();
|
castPlayer.mute();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.unMute = function () {
|
self.unmute = function () {
|
||||||
castPlayer.unMute();
|
castPlayer.unMute();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1026,18 +1284,20 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getTargets = function () {
|
self.getTargets = function () {
|
||||||
|
|
||||||
var targets = [];
|
var targets = [];
|
||||||
|
|
||||||
targets.push(self.getCurrentTargetInfo());
|
if (castPlayer.hasReceivers) {
|
||||||
|
targets.push(self.getCurrentTargetInfo());
|
||||||
|
}
|
||||||
|
|
||||||
return targets;
|
return targets;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getCurrentTargetInfo = function () {
|
self.getCurrentTargetInfo = function () {
|
||||||
|
|
||||||
var appName = null;
|
var appName = null;
|
||||||
|
|
||||||
if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) {
|
if (castPlayer.session && castPlayer.session.receiver && castPlayer.session.friendlyName) {
|
||||||
appName = castPlayer.session.friendlyName;
|
appName = castPlayer.session.friendlyName;
|
||||||
}
|
}
|
||||||
|
@ -1048,9 +1308,105 @@
|
||||||
playerName: self.name,
|
playerName: self.name,
|
||||||
playableMediaTypes: ["Audio", "Video"],
|
playableMediaTypes: ["Audio", "Video"],
|
||||||
isLocalPlayer: false,
|
isLocalPlayer: false,
|
||||||
appName: appName
|
appName: appName,
|
||||||
|
supportedCommands: []
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.setCurrentTime = function (ticks, item, updateSlider) {
|
||||||
|
// Convert to ticks
|
||||||
|
ticks = Math.floor(ticks);
|
||||||
|
var timeText = Dashboard.getDisplayTime(ticks);
|
||||||
|
if (self.currentDurationTicks) {
|
||||||
|
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
|
||||||
|
if (updateSlider) {
|
||||||
|
var percent = ticks / self.currentDurationTicks;
|
||||||
|
percent *= 100;
|
||||||
|
self.positionSlider.val(percent).slider('enable').slider('refresh');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.positionSlider.slider('disable').slider('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
self.currentTimeElement.html(timeText);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.changeStream = function (position) {
|
||||||
|
console.log("seek", position);
|
||||||
|
////castPlayer.seekMedia(position);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.removeFromPlaylist = function (i) {
|
||||||
|
self.playlist.remove(i);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.currentPlaylistIndex = function (i) {
|
||||||
|
if (i == null) {
|
||||||
|
return currentPlaylistIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newItem = self.playlist[i];
|
||||||
|
|
||||||
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
self.playInternal(newItem, 0, user);
|
||||||
|
currentPlaylistIndex = i;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.nextTrack = function () {
|
||||||
|
var newIndex = currentPlaylistIndex + 1;
|
||||||
|
var newItem = self.playlist[newIndex];
|
||||||
|
|
||||||
|
if (newItem) {
|
||||||
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
self.playInternal(newItem, 0, user);
|
||||||
|
currentPlaylistIndex = newIndex;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.previousTrack = function () {
|
||||||
|
var newIndex = currentPlaylistIndex - 1;
|
||||||
|
if (newIndex >= 0) {
|
||||||
|
var newItem = self.playlist[newIndex];
|
||||||
|
if (newItem) {
|
||||||
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
self.playInternal(newItem, 0, user);
|
||||||
|
currentPlaylistIndex = newIndex;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.beginPlayerUpdates = function () {
|
||||||
|
// Setup polling here
|
||||||
|
};
|
||||||
|
|
||||||
|
self.endPlayerUpdates = function () {
|
||||||
|
// Stop polling here
|
||||||
|
};
|
||||||
|
|
||||||
|
self.volumeDown = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
self.volumeUp = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getPlayerState = function () {
|
||||||
|
|
||||||
|
var deferred = $.Deferred();
|
||||||
|
|
||||||
|
var result = self.getPlayerStateInternal();
|
||||||
|
|
||||||
|
deferred.resolveWith(null, [result]);
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getPlayerStateInternal = function () {
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaController.registerPlayer(new chromecastPlayer());
|
MediaController.registerPlayer(new chromecastPlayer());
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
|
|
||||||
Dashboard.updateSystemInfo(systemInfo);
|
Dashboard.updateSystemInfo(systemInfo);
|
||||||
|
|
||||||
$('#appVersionNumber', page).html(systemInfo.Version);
|
$('#appVersionNumber', page).html('Version ' + systemInfo.Version);
|
||||||
|
|
||||||
var port = systemInfo.HttpServerPortNumber;
|
var port = systemInfo.HttpServerPortNumber;
|
||||||
|
|
||||||
|
@ -190,17 +190,15 @@
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
|
|
||||||
var table = $('.tblConnections', page);
|
var parentElement = $('.activeDevices', page);
|
||||||
|
|
||||||
$('.trSession', table).addClass('deadSession');
|
$('.activeSession', parentElement).addClass('deadSession');
|
||||||
|
|
||||||
var deviceId = ApiClient.deviceId();
|
|
||||||
|
|
||||||
for (var i = 0, length = sessions.length; i < length; i++) {
|
for (var i = 0, length = sessions.length; i < length; i++) {
|
||||||
|
|
||||||
var connection = sessions[i];
|
var connection = sessions[i];
|
||||||
|
|
||||||
var rowId = 'trSession' + connection.Id;
|
var rowId = 'session' + connection.Id;
|
||||||
|
|
||||||
var elem = $('#' + rowId, page);
|
var elem = $('#' + rowId, page);
|
||||||
|
|
||||||
|
@ -209,93 +207,184 @@
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
html += '<tr class="trSession" id="' + rowId + '">';
|
var nowPlayingItem = connection.NowPlayingItem;
|
||||||
|
|
||||||
html += '<td class="clientType" style="text-align:center;">';
|
var className = nowPlayingItem ? 'activeSession' : 'notPlayingSession activeSession';
|
||||||
html += DashboardPage.getClientType(connection);
|
|
||||||
html += '</td>';
|
|
||||||
|
|
||||||
html += '<td>';
|
html += '<a class="' + className + '" id="' + rowId + '" href="nowplaying.html">';
|
||||||
|
|
||||||
html += '<div style="max-width:200px;">';
|
html += '<div class="sessionNowPlayingContent"';
|
||||||
if (deviceId == connection.DeviceId) {
|
|
||||||
html += connection.DeviceName;
|
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem);
|
||||||
|
|
||||||
|
if (imgUrl) {
|
||||||
|
html += ' data-src="' + imgUrl + '" style="display:inline-block;background-image:url(\'' + imgUrl + '\');"';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '></div>';
|
||||||
|
|
||||||
|
html += '<div class="sessionNowPlayingInnerContent">';
|
||||||
|
|
||||||
|
html += '<div class="sessionAppInfo">';
|
||||||
|
|
||||||
|
var clientImage = DashboardPage.getClientImage(connection);
|
||||||
|
|
||||||
|
if (clientImage) {
|
||||||
|
html += clientImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<div class="sessionAppName" style="display:inline-block;">' + connection.DeviceName;
|
||||||
|
html += '<br/>' + connection.ApplicationVersion;
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="sessionUserInfo">';
|
||||||
|
|
||||||
|
var userImage = DashboardPage.getUserImage(connection);
|
||||||
|
if (userImage) {
|
||||||
|
html += '<div class="sessionUserImage" data-src="' + userImage + '">';
|
||||||
|
html += '<img src="' + userImage + '" />';
|
||||||
} else {
|
} else {
|
||||||
html += '<a href="#" onclick="RemoteControl.showMenu({sessionId:\'' + connection.Id + '\'});">' + connection.DeviceName + '</a>';
|
html += '<div class="sessionUserImage">';
|
||||||
}
|
}
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
html += '<div>' + connection.ApplicationVersion + '</div>';
|
html += '<div class="sessionUserName">';
|
||||||
|
|
||||||
html += '<div class="username">';
|
|
||||||
html += DashboardPage.getUsersHtml(connection);
|
html += DashboardPage.getUsersHtml(connection);
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
html += '</td>';
|
|
||||||
|
|
||||||
var nowPlayingItem = connection.NowPlayingItem;
|
|
||||||
|
|
||||||
html += '<td>';
|
|
||||||
|
|
||||||
html += '<div class="nowPlayingImage">';
|
|
||||||
html += DashboardPage.getNowPlayingImage(nowPlayingItem);
|
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
html += '<div class="clientNowPlayingText">';
|
html += '<div class="sessionNowPlayingInfo">';
|
||||||
html += DashboardPage.getNowPlayingText(connection, nowPlayingItem);
|
if (nowPlayingItem) {
|
||||||
|
html += DashboardPage.getNowPlayingName(connection);
|
||||||
|
}
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
html += '</td>';
|
if (nowPlayingItem) {
|
||||||
|
|
||||||
|
var value = (100 * connection.NowPlayingPositionTicks) / nowPlayingItem.RunTimeTicks;
|
||||||
|
|
||||||
html += '</tr>';
|
html += '<progress class="itemProgressBar" min="0" max="100" value="' + value + '"></progress>';
|
||||||
|
} else {
|
||||||
|
html += '<progress class="itemProgressBar" min="0" max="100" style="display:none;"></progress>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
html += '</a>';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table.append(html).trigger('create');
|
parentElement.append(html).trigger('create');
|
||||||
|
|
||||||
|
$('.deadSession', parentElement).remove();
|
||||||
|
},
|
||||||
|
|
||||||
|
getNowPlayingName: function (session) {
|
||||||
|
|
||||||
|
var nowPlayingItem = session.NowPlayingItem;
|
||||||
|
|
||||||
|
if (!nowPlayingItem) {
|
||||||
|
|
||||||
|
return 'Last seen ' + humane_date(session.LastActivityDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
var topText = nowPlayingItem.Name;
|
||||||
|
|
||||||
|
if (nowPlayingItem.MediaType == 'Video') {
|
||||||
|
if (nowPlayingItem.IndexNumber != null) {
|
||||||
|
topText = nowPlayingItem.IndexNumber + " - " + topText;
|
||||||
|
}
|
||||||
|
if (nowPlayingItem.ParentIndexNumber != null) {
|
||||||
|
topText = nowPlayingItem.ParentIndexNumber + "." + topText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bottomText = '';
|
||||||
|
|
||||||
|
if (nowPlayingItem.Artists && nowPlayingItem.Artists.length) {
|
||||||
|
bottomText = topText;
|
||||||
|
topText = nowPlayingItem.Artists[0];
|
||||||
|
}
|
||||||
|
else if (nowPlayingItem.SeriesName || nowPlayingItem.Album) {
|
||||||
|
bottomText = topText;
|
||||||
|
topText = nowPlayingItem.SeriesName || nowPlayingItem.Album;
|
||||||
|
}
|
||||||
|
else if (nowPlayingItem.ProductionYear) {
|
||||||
|
bottomText = nowPlayingItem.ProductionYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bottomText ? topText + '<br/>' + bottomText : topText;
|
||||||
|
|
||||||
$('.deadSession', table).remove();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getUsersHtml: function (session) {
|
getUsersHtml: function (session) {
|
||||||
|
|
||||||
var html = '';
|
var html = [];
|
||||||
|
|
||||||
if (session.UserId) {
|
if (session.UserId) {
|
||||||
html += '<div>' + session.UserName + '</div>';
|
html.push(session.UserName);
|
||||||
}
|
}
|
||||||
|
|
||||||
html += session.AdditionalUsers.map(function (currentSession) {
|
for (var i = 0, length = session.AdditionalUsers.length; i < length; i++) {
|
||||||
|
|
||||||
return '<div>' + currentSession.UserName + '</div>';
|
html.push(session.AdditionalUsers[i].UserName);
|
||||||
});
|
}
|
||||||
|
|
||||||
return html;
|
return html.join(', ');
|
||||||
|
},
|
||||||
|
|
||||||
|
getUserImage: function (session) {
|
||||||
|
|
||||||
|
if (session.UserId && session.UserPrimaryImageTag) {
|
||||||
|
return ApiClient.getUserImageUrl(session.UserId, {
|
||||||
|
|
||||||
|
tag: session.UserPrimaryImageTag,
|
||||||
|
height: 24,
|
||||||
|
type: 'Primary'
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSession: function (row, session) {
|
updateSession: function (row, session) {
|
||||||
|
|
||||||
row.removeClass('deadSession');
|
row.removeClass('deadSession');
|
||||||
|
|
||||||
$('.username', row).html(DashboardPage.getUsersHtml(session));
|
|
||||||
|
|
||||||
var nowPlayingItem = session.NowPlayingItem;
|
var nowPlayingItem = session.NowPlayingItem;
|
||||||
|
|
||||||
$('.clientNowPlayingText', row).html(DashboardPage.getNowPlayingText(session, nowPlayingItem)).trigger('create');
|
if (nowPlayingItem) {
|
||||||
|
row.removeClass('notPlayingSession');
|
||||||
|
} else {
|
||||||
|
row.addClass('notPlayingSession');
|
||||||
|
}
|
||||||
|
|
||||||
var imageRow = $('.nowPlayingImage', row);
|
$('.sessionUserName', row).html(DashboardPage.getUsersHtml(session));
|
||||||
|
|
||||||
var image = $('img', imageRow)[0];
|
$('.sessionNowPlayingInfo', row).html(DashboardPage.getNowPlayingName(session));
|
||||||
|
|
||||||
var nowPlayingItemId = nowPlayingItem ? nowPlayingItem.Id : null;
|
if (nowPlayingItem && nowPlayingItem.RunTimeTicks) {
|
||||||
var nowPlayingItemImageTag = nowPlayingItem ? nowPlayingItem.PrimaryImageTag : null;
|
|
||||||
|
|
||||||
if (!image || image.getAttribute('data-itemid') != nowPlayingItemId || image.getAttribute('data-tag') != nowPlayingItemImageTag) {
|
var value = (100 * session.NowPlayingPositionTicks) / nowPlayingItem.RunTimeTicks;
|
||||||
imageRow.html(DashboardPage.getNowPlayingImage(nowPlayingItem));
|
|
||||||
|
$('progress', row).show().val(value);
|
||||||
|
} else {
|
||||||
|
$('progress', row).hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
var imgUrl = DashboardPage.getNowPlayingImageUrl(nowPlayingItem) || '';
|
||||||
|
var imgElem = $('.sessionNowPlayingContent', row)[0];
|
||||||
|
|
||||||
|
if (imgUrl != imgElem.getAttribute('data-src')) {
|
||||||
|
imgElem.style.backgroundImage = imgUrl ? 'url(\'' + imgUrl + '\')' : '';
|
||||||
|
imgElem.setAttribute('data-src', imgUrl);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
getClientType: function (connection) {
|
getClientImage: function (connection) {
|
||||||
|
|
||||||
var clientLowered = connection.Client.toLowerCase();
|
var clientLowered = connection.Client.toLowerCase();
|
||||||
|
|
||||||
|
@ -325,89 +414,81 @@
|
||||||
}
|
}
|
||||||
if (clientLowered == "mb-classic") {
|
if (clientLowered == "mb-classic") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/mbc.png' alt='Media Browser Classic' />";
|
return "<img src='css/images/clients/mbc.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "media browser theater") {
|
if (clientLowered == "media browser theater") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/mb.png' alt='Media Browser Theater' />";
|
return "<img src='css/images/clients/mb.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "android") {
|
if (clientLowered == "android") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/android.png' alt='Android' />";
|
return "<img src='css/images/clients/android.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "roku") {
|
if (clientLowered == "roku") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/roku.jpg' alt='Roku' />";
|
return "<img src='css/images/clients/roku.jpg' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "ios") {
|
if (clientLowered == "ios") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/ios.png' alt='iOS' />";
|
return "<img src='css/images/clients/ios.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "windows rt") {
|
if (clientLowered == "windows rt") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/windowsrt.png' alt='Windows RT' />";
|
return "<img src='css/images/clients/windowsrt.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "windows phone") {
|
if (clientLowered == "windows phone") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/windowsphone.png' alt='Windows Phone' />";
|
return "<img src='css/images/clients/windowsphone.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "dlna") {
|
if (clientLowered == "dlna") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/dlna.png' alt='Dlna' />";
|
return "<img src='css/images/clients/dlna.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "mbkinect") {
|
if (clientLowered == "mbkinect") {
|
||||||
|
|
||||||
return "<img src='css/images/clients/mbkinect.png' alt='MB Kinect' />";
|
return "<img src='css/images/clients/mbkinect.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "xbmc") {
|
if (clientLowered == "xbmc") {
|
||||||
return "<img src='css/images/clients/xbmc.png' alt='Xbmc' />";
|
return "<img src='css/images/clients/xbmc.png' />";
|
||||||
}
|
}
|
||||||
if (clientLowered == "chromecast") {
|
if (clientLowered == "chromecast") {
|
||||||
|
|
||||||
return "<img src='css/images/chromecast/ic_media_route_on_holo_light.png' alt='Chromecast' />";
|
return "<img src='css/images/chromecast/ic_media_route_on_holo_light.png' />";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
return connection.Client;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getNowPlayingImage: function (item) {
|
getNowPlayingImageUrl: function (item) {
|
||||||
|
|
||||||
|
if (item && item.BackdropImageTag) {
|
||||||
|
|
||||||
|
return ApiClient.getImageUrl(item.BackdropItemId, {
|
||||||
|
type: "Backdrop",
|
||||||
|
width: 810,
|
||||||
|
tag: item.BackdropImageTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item && item.ThumbImageTag) {
|
||||||
|
|
||||||
|
return ApiClient.getImageUrl(item.ThumbItemId, {
|
||||||
|
type: "Thumb",
|
||||||
|
width: 810,
|
||||||
|
tag: item.ThumbImageTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (item && item.PrimaryImageTag) {
|
if (item && item.PrimaryImageTag) {
|
||||||
var url = ApiClient.getImageUrl(item.Id, {
|
|
||||||
|
return ApiClient.getImageUrl(item.PrimaryImageItemId, {
|
||||||
type: "Primary",
|
type: "Primary",
|
||||||
height: 100,
|
width: 810,
|
||||||
tag: item.PrimaryImageTag
|
tag: item.PrimaryImageTag
|
||||||
});
|
});
|
||||||
|
|
||||||
url += "&xxx=" + new Date().getTime();
|
|
||||||
|
|
||||||
return "<img data-itemid='" + item.Id + "' data-tag='" + item.PrimaryImageTag + "' class='clientNowPlayingImage' src='" + url + "' alt='" + item.Name + "' title='" + item.Name + "' />";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return null;
|
||||||
},
|
|
||||||
|
|
||||||
getNowPlayingText: function (connection, item) {
|
|
||||||
|
|
||||||
var html = "";
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
|
|
||||||
html += "<div><a href='itemdetails.html?id=" + item.Id + "'>" + item.Name + "</a></div>";
|
|
||||||
|
|
||||||
html += "<div>";
|
|
||||||
|
|
||||||
if (item.RunTimeTicks) {
|
|
||||||
html += Dashboard.getDisplayTime(connection.NowPlayingPositionTicks || 0) + " / ";
|
|
||||||
|
|
||||||
html += Dashboard.getDisplayTime(item.RunTimeTicks);
|
|
||||||
}
|
|
||||||
|
|
||||||
html += "</div>";
|
|
||||||
}
|
|
||||||
|
|
||||||
return html;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
systemUpdateTaskKey: "SystemUpdateTask",
|
systemUpdateTaskKey: "SystemUpdateTask",
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
if (person.PrimaryImageTag) {
|
if (person.PrimaryImageTag) {
|
||||||
|
|
||||||
imgUrl = ApiClient.getPersonImageUrl(person.Name, {
|
imgUrl = ApiClient.getPersonImageUrl(person.Name, {
|
||||||
height: 280,
|
width: 150,
|
||||||
tag: person.PrimaryImageTag,
|
tag: person.PrimaryImageTag,
|
||||||
type: "primary"
|
type: "primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
overlayText: true,
|
overlayText: true,
|
||||||
selectionPanel: true
|
selectionPanel: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
|
|
|
@ -66,18 +66,11 @@
|
||||||
renderDetails(page, item);
|
renderDetails(page, item);
|
||||||
renderTabs(page, item);
|
renderTabs(page, item);
|
||||||
|
|
||||||
if (ApiClient.isWebSocketOpen()) {
|
$(page).trigger('displayingitem', [{
|
||||||
|
|
||||||
var vals = [item.Type, item.Id, item.Name];
|
item: item,
|
||||||
|
context: getParameterByName('context')
|
||||||
var context = getParameterByName('context');
|
}]);
|
||||||
|
|
||||||
if (context) {
|
|
||||||
vals.push(vals);
|
|
||||||
}
|
|
||||||
|
|
||||||
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
|
|
||||||
}
|
|
||||||
|
|
||||||
Dashboard.getCurrentUser().done(function (user) {
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
|
||||||
|
@ -403,7 +396,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
query = $.extend(query, options || {});
|
query = $.extend(query, options || {});
|
||||||
|
|
||||||
if (query.IncludeItemTypes == "Audio") {
|
if (query.IncludeItemTypes == "Audio") {
|
||||||
query.SortBy = "Album,SortName";
|
query.SortBy = "Album,SortName";
|
||||||
}
|
}
|
||||||
|
@ -426,7 +419,8 @@
|
||||||
|
|
||||||
html += LibraryBrowser.getSongTableHtml(result.Items, {
|
html += LibraryBrowser.getSongTableHtml(result.Items, {
|
||||||
showAlbum: true,
|
showAlbum: true,
|
||||||
showArtist: true
|
showArtist: true,
|
||||||
|
showAlbumArtist: true
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,11 +75,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!item.LocalTrailerCount && item.RemoteTrailers.length && item.PlayAccess == 'Full') {
|
if (!item.LocalTrailerCount && item.RemoteTrailers.length && item.PlayAccess == 'Full') {
|
||||||
|
|
||||||
$('.btnPlayExternalTrailer', page).removeClass('hide').attr('href', item.RemoteTrailers[0].Url);
|
$('.btnPlayExternalTrailer', page).removeClass('hide').attr('href', item.RemoteTrailers[0].Url);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$('.btnPlayExternalTrailer', page).addClass('hide').attr('href', '#');
|
$('.btnPlayExternalTrailer', page).addClass('hide').attr('href', '#');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +120,11 @@
|
||||||
|
|
||||||
setPeopleHeader(page, item);
|
setPeopleHeader(page, item);
|
||||||
|
|
||||||
if (ApiClient.isWebSocketOpen()) {
|
$(page).trigger('displayingitem', [{
|
||||||
ApiClient.sendWebSocketMessage("Context", [item.Type, item.Id, item.Name, context].join('|'));
|
|
||||||
}
|
item: item,
|
||||||
|
context: context
|
||||||
|
}]);
|
||||||
|
|
||||||
Dashboard.hideLoadingMsg();
|
Dashboard.hideLoadingMsg();
|
||||||
});
|
});
|
||||||
|
@ -265,8 +267,7 @@
|
||||||
$('#musicVideosCollapsible', page).hide();
|
$('#musicVideosCollapsible', page).hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderThemeSongs(page, item, user);
|
renderThemeMedia(page, item, user);
|
||||||
renderThemeVideos(page, item, user);
|
|
||||||
renderCriticReviews(page, item, 1);
|
renderCriticReviews(page, item, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,22 +905,51 @@
|
||||||
|
|
||||||
$('#criticReviewsContent', page).html(html).trigger('create');
|
$('#criticReviewsContent', page).html(html).trigger('create');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderThemeMedia(page, item) {
|
||||||
|
|
||||||
|
ApiClient.getThemeMedia(Dashboard.getCurrentUserId(), item.Id, true).done(function (result) {
|
||||||
|
|
||||||
function renderThemeSongs(page, item) {
|
var themeSongs = result.ThemeSongsResult.OwnerId == item.Id ?
|
||||||
|
result.ThemeSongsResult.Items :
|
||||||
|
[];
|
||||||
|
|
||||||
|
var themeVideos = result.ThemeVideosResult.OwnerId == item.Id ?
|
||||||
|
result.ThemeVideosResult.Items :
|
||||||
|
[];
|
||||||
|
|
||||||
ApiClient.getThemeSongs(Dashboard.getCurrentUserId(), item.Id).done(function (result) {
|
renderThemeSongs(page, themeSongs);
|
||||||
if (result.Items.length) {
|
renderThemeVideos(page, themeVideos);
|
||||||
|
|
||||||
$('#themeSongsCollapsible', page).show();
|
$(page).trigger('thememediadownload', [result]);
|
||||||
|
|
||||||
$('#themeSongsContent', page).html(LibraryBrowser.getSongTableHtml(result.Items, { showArtist: true, showAlbum: true })).trigger('create');
|
|
||||||
} else {
|
|
||||||
$('#themeSongsCollapsible', page).hide();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderThemeSongs(page, items) {
|
||||||
|
|
||||||
|
if (items.length) {
|
||||||
|
|
||||||
|
$('#themeSongsCollapsible', page).show();
|
||||||
|
|
||||||
|
$('#themeSongsContent', page).html(LibraryBrowser.getSongTableHtml(items, { showArtist: true, showAlbum: true, showAlbumArtist: true })).trigger('create');
|
||||||
|
} else {
|
||||||
|
$('#themeSongsCollapsible', page).hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderThemeVideos(page, items, user) {
|
||||||
|
|
||||||
|
if (items.length) {
|
||||||
|
|
||||||
|
$('#themeVideosCollapsible', page).show();
|
||||||
|
|
||||||
|
$('#themeVideosContent', page).html(getVideosHtml(items, user)).trigger('create');
|
||||||
|
} else {
|
||||||
|
$('#themeVideosCollapsible', page).hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function renderMusicVideos(page, item, user) {
|
function renderMusicVideos(page, item, user) {
|
||||||
|
|
||||||
ApiClient.getItems(user.Id, {
|
ApiClient.getItems(user.Id, {
|
||||||
|
@ -944,21 +974,6 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderThemeVideos(page, item, user) {
|
|
||||||
|
|
||||||
ApiClient.getThemeVideos(user.Id, item.Id).done(function (result) {
|
|
||||||
if (result.Items.length) {
|
|
||||||
|
|
||||||
$('#themeVideosCollapsible', page).show();
|
|
||||||
|
|
||||||
$('#themeVideosContent', page).html(getVideosHtml(result.Items, user)).trigger('create');
|
|
||||||
} else {
|
|
||||||
$('#themeVideosCollapsible', page).hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderAdditionalParts(page, item, user) {
|
function renderAdditionalParts(page, item, user) {
|
||||||
|
|
||||||
ApiClient.getAdditionalVideoParts(user.Id, item.Id).done(function (result) {
|
ApiClient.getAdditionalVideoParts(user.Id, item.Id).done(function (result) {
|
||||||
|
@ -1238,7 +1253,7 @@
|
||||||
if (cast.PrimaryImageTag) {
|
if (cast.PrimaryImageTag) {
|
||||||
|
|
||||||
imgUrl = ApiClient.getPersonImageUrl(cast.Name, {
|
imgUrl = ApiClient.getPersonImageUrl(cast.Name, {
|
||||||
width: 130,
|
width: 100,
|
||||||
tag: cast.PrimaryImageTag,
|
tag: cast.PrimaryImageTag,
|
||||||
type: "primary"
|
type: "primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -93,9 +93,10 @@
|
||||||
|
|
||||||
Dashboard.setPageTitle(name);
|
Dashboard.setPageTitle(name);
|
||||||
|
|
||||||
if (ApiClient.isWebSocketOpen()) {
|
$(page).trigger('displayingitem', [{
|
||||||
ApiClient.sendWebSocketMessage("Context", [item.Type, item.Id, item.Name].join('|'));
|
|
||||||
}
|
item: item
|
||||||
|
}]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -203,7 +204,7 @@
|
||||||
}).on('pageshow', "#itemListPage", function () {
|
}).on('pageshow', "#itemListPage", function () {
|
||||||
|
|
||||||
var page = this;
|
var page = this;
|
||||||
|
|
||||||
query.Limit = LibraryBrowser.getDefaultPageSize();
|
query.Limit = LibraryBrowser.getDefaultPageSize();
|
||||||
query.ParentId = getParameterByName('parentId');
|
query.ParentId = getParameterByName('parentId');
|
||||||
query.Filters = "";
|
query.Filters = "";
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
var LibraryBrowser = (function (window, document, $, screen, localStorage) {
|
var LibraryBrowser = (function (window, document, $, screen, localStorage) {
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
$("body").on("create", function () {
|
||||||
|
$(".lazy").unveil(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var defaultBackground = "#333";
|
var defaultBackground = "#333";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -185,14 +191,17 @@
|
||||||
html += '<tr>';
|
html += '<tr>';
|
||||||
|
|
||||||
html += LibraryBrowser.getSongHeaderCellHtml('', '', options.enableColumnSorting);
|
html += LibraryBrowser.getSongHeaderCellHtml('', '', options.enableColumnSorting);
|
||||||
html += LibraryBrowser.getSongHeaderCellHtml('', '', options.enableColumnSorting);
|
html += LibraryBrowser.getSongHeaderCellHtml('Disc', 'desktopColumn', options.enableColumnSorting);
|
||||||
|
html += LibraryBrowser.getSongHeaderCellHtml('#', 'desktopColumn', options.enableColumnSorting);
|
||||||
html += LibraryBrowser.getSongHeaderCellHtml('Track', '', options.enableColumnSorting, 'Name', options.sortBy, options.sortOrder);
|
html += LibraryBrowser.getSongHeaderCellHtml('Track', '', options.enableColumnSorting, 'Name', options.sortBy, options.sortOrder);
|
||||||
|
|
||||||
if (options.showAlbum) {
|
if (options.showAlbum) {
|
||||||
html += LibraryBrowser.getSongHeaderCellHtml('Album', '', options.enableColumnSorting, 'Album,SortName', options.sortBy, options.sortOrder);
|
html += LibraryBrowser.getSongHeaderCellHtml('Album', '', options.enableColumnSorting, 'Album,SortName', options.sortBy, options.sortOrder);
|
||||||
}
|
}
|
||||||
if (options.showArtist) {
|
if (options.showArtist) {
|
||||||
html += LibraryBrowser.getSongHeaderCellHtml('Artist', '', options.enableColumnSorting, 'Artist,Album,SortName', options.sortBy, options.sortOrder);
|
html += LibraryBrowser.getSongHeaderCellHtml('Artist', 'tabletColumn', options.enableColumnSorting, 'Artist,Album,SortName', options.sortBy, options.sortOrder);
|
||||||
|
}
|
||||||
|
if (options.showAlbumArtist) {
|
||||||
html += LibraryBrowser.getSongHeaderCellHtml('Album Artist', 'tabletColumn', options.enableColumnSorting, 'AlbumArtist,Album,SortName', options.sortBy, options.sortOrder);
|
html += LibraryBrowser.getSongHeaderCellHtml('Album Artist', 'tabletColumn', options.enableColumnSorting, 'AlbumArtist,Album,SortName', options.sortBy, options.sortOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,12 +223,8 @@
|
||||||
html += '<button class="btnQueue" data-icon="plus" type="button" data-iconpos="notext" onclick="MediaController.queue(\'' + item.Id + '\');" data-inline="true" title="Queue">Queue</button>';
|
html += '<button class="btnQueue" data-icon="plus" type="button" data-iconpos="notext" onclick="MediaController.queue(\'' + item.Id + '\');" data-inline="true" title="Queue">Queue</button>';
|
||||||
html += '</td>';
|
html += '</td>';
|
||||||
|
|
||||||
var num = item.IndexNumber;
|
html += '<td class="desktopColumn">' + (item.ParentIndexNumber || "") + '</td>';
|
||||||
|
html += '<td class="desktopColumn">' + (item.IndexNumber || "") + '</td>';
|
||||||
if (num && item.ParentIndexNumber) {
|
|
||||||
num = item.ParentIndexNumber + "." + num;
|
|
||||||
}
|
|
||||||
html += '<td>' + (num || "") + '</td>';
|
|
||||||
|
|
||||||
html += '<td><a href="' + LibraryBrowser.getHref(item, "music") + '">' + (item.Name || "") + '</a></td>';
|
html += '<td><a href="' + LibraryBrowser.getHref(item, "music") + '">' + (item.Name || "") + '</a></td>';
|
||||||
|
|
||||||
|
@ -237,14 +242,14 @@
|
||||||
|
|
||||||
var artistLinksHtml = LibraryBrowser.getArtistLinksHtml(item.Artists);
|
var artistLinksHtml = LibraryBrowser.getArtistLinksHtml(item.Artists);
|
||||||
|
|
||||||
html += '<td>' + artistLinksHtml + '</td>';
|
html += '<td class="tabletColumn">' + artistLinksHtml + '</td>';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
html += '<td></td>';
|
html += '<td class="tabletColumn"></td>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.showArtist) {
|
if (options.showAlbumArtist) {
|
||||||
|
|
||||||
if (item.AlbumArtist) {
|
if (item.AlbumArtist) {
|
||||||
|
|
||||||
|
@ -667,8 +672,8 @@
|
||||||
html += '<a data-itemid="' + item.Id + '" class="' + cssClass + '" data-mediasourcecount="' + mediaSourceCount + '" href="' + href + '">';
|
html += '<a data-itemid="' + item.Id + '" class="' + cssClass + '" data-mediasourcecount="' + mediaSourceCount + '" href="' + href + '">';
|
||||||
|
|
||||||
var style = "";
|
var style = "";
|
||||||
|
options.lazy = false;
|
||||||
if (imgUrl) {
|
if (imgUrl && !options.lazy) {
|
||||||
style += 'background-image:url(\'' + imgUrl + '\');';
|
style += 'background-image:url(\'' + imgUrl + '\');';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -681,9 +686,16 @@
|
||||||
imageCssClass += " coveredPosterItemImage";
|
imageCssClass += " coveredPosterItemImage";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var dataSrc = "";
|
||||||
|
|
||||||
|
if (options.lazy) {
|
||||||
|
imageCssClass += " lazy";
|
||||||
|
dataSrc = ' data-src="' + imgUrl + '"';
|
||||||
|
}
|
||||||
|
|
||||||
var progressHtml = options.showProgress === false ? '' : LibraryBrowser.getItemProgressBarHtml(item);
|
var progressHtml = options.showProgress === false ? '' : LibraryBrowser.getItemProgressBarHtml(item);
|
||||||
|
|
||||||
html += '<div class="' + imageCssClass + '" style="' + style + '">';
|
html += '<div class="' + imageCssClass + '" style="' + style + '"' + dataSrc + '>';
|
||||||
|
|
||||||
html += '<div class="posterItemOverlayTarget"></div>';
|
html += '<div class="posterItemOverlayTarget"></div>';
|
||||||
|
|
||||||
|
@ -756,6 +768,10 @@
|
||||||
|
|
||||||
var itemCountHtml = LibraryBrowser.getItemCountsHtml(options, item);
|
var itemCountHtml = LibraryBrowser.getItemCountsHtml(options, item);
|
||||||
|
|
||||||
|
if (item.Type == "Person" && !itemCountHtml) {
|
||||||
|
itemCountHtml = " ";
|
||||||
|
}
|
||||||
|
|
||||||
if (itemCountHtml) {
|
if (itemCountHtml) {
|
||||||
html += "<div class='" + cssClass + "'>";
|
html += "<div class='" + cssClass + "'>";
|
||||||
html += itemCountHtml;
|
html += itemCountHtml;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
html += '<a class="desktopHomeLink" href="index.html"><img src="css/images/mblogoicon.png" /></a>';
|
html += '<a class="desktopHomeLink" href="index.html"><img src="css/images/mblogoicon.png" /></a>';
|
||||||
|
|
||||||
html += '<button class="viewMenuRemoteControlButton" onclick="RemoteControl.showMenu();" type="button" data-icon="wireless" data-inline="true" data-iconpos="notext" title="Remote Control">Remote Control</button>';
|
html += '<a class="viewMenuRemoteControlButton" href="nowplaying.html" data-role="button" data-icon="wireless" data-inline="true" data-iconpos="notext" title="Now Playing">Remote Control</a>';
|
||||||
|
|
||||||
if (user.Configuration.IsAdministrator) {
|
if (user.Configuration.IsAdministrator) {
|
||||||
html += '<a class="editorMenuLink" href="edititemmetadata.html" data-role="button" data-icon="edit" data-inline="true" data-iconpos="notext" title="Metadata Manager">Metadata Manager</a>';
|
html += '<a class="editorMenuLink" href="edititemmetadata.html" data-role="button" data-icon="edit" data-inline="true" data-iconpos="notext" title="Metadata Manager">Metadata Manager</a>';
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var url = ApiClient.getUserImageUrl(user.Id, {
|
var url = ApiClient.getUserImageUrl(user.Id, {
|
||||||
height: 40,
|
height: 24,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -135,14 +135,11 @@
|
||||||
|
|
||||||
$('.userDataIcons', page).html(LibraryBrowser.getUserDataIconsHtml(item));
|
$('.userDataIcons', page).html(LibraryBrowser.getUserDataIconsHtml(item));
|
||||||
|
|
||||||
if (ApiClient.isWebSocketOpen()) {
|
$(page).trigger('displayingitem', [{
|
||||||
|
|
||||||
var vals = [item.Type, item.Id, item.Name];
|
item: item,
|
||||||
|
context: 'livetv'
|
||||||
vals.push('livetv');
|
}]);
|
||||||
|
|
||||||
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
|
|
||||||
}
|
|
||||||
|
|
||||||
Dashboard.getCurrentUser().done(function (user) {
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
|
||||||
|
|
|
@ -50,14 +50,11 @@
|
||||||
|
|
||||||
LiveTvHelpers.renderMiscProgramInfo($('.miscTvProgramInfo', page), item);
|
LiveTvHelpers.renderMiscProgramInfo($('.miscTvProgramInfo', page), item);
|
||||||
|
|
||||||
if (ApiClient.isWebSocketOpen()) {
|
$(page).trigger('displayingitem', [{
|
||||||
|
|
||||||
var vals = [item.Type, item.Id, item.Name];
|
item: item,
|
||||||
|
context: 'livetv'
|
||||||
vals.push('livetv');
|
}]);
|
||||||
|
|
||||||
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.TimerId) {
|
if (item.TimerId) {
|
||||||
$('#cancelRecordingButtonContainer', page).show();
|
$('#cancelRecordingButtonContainer', page).show();
|
||||||
|
|
|
@ -55,14 +55,11 @@
|
||||||
|
|
||||||
LiveTvHelpers.renderMiscProgramInfo($('.miscTvProgramInfo', page), item);
|
LiveTvHelpers.renderMiscProgramInfo($('.miscTvProgramInfo', page), item);
|
||||||
|
|
||||||
if (ApiClient.isWebSocketOpen()) {
|
$(page).trigger('displayingitem', [{
|
||||||
|
|
||||||
var vals = [item.Type, item.Id, item.Name];
|
item: item,
|
||||||
|
context: 'livetv'
|
||||||
vals.push('livetv');
|
}]);
|
||||||
|
|
||||||
ApiClient.sendWebSocketMessage("Context", vals.join('|'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.recordingStatus', page).html('Status: ' + item.Status);
|
$('.recordingStatus', page).html('Status: ' + item.Status);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,26 @@
|
||||||
(function ($, window) {
|
(function ($, window) {
|
||||||
|
|
||||||
|
var enableMirrorMode;
|
||||||
|
var currentDisplayInfo;
|
||||||
|
|
||||||
|
function mirrorItem(info) {
|
||||||
|
|
||||||
|
var item = info.item;
|
||||||
|
|
||||||
|
MediaController.getCurrentPlayer().displayContent({
|
||||||
|
|
||||||
|
itemName: item.Name,
|
||||||
|
itemId: item.Id,
|
||||||
|
itemType: item.Type,
|
||||||
|
context: info.context
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function mediaController() {
|
function mediaController() {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var currentPlayer;
|
var currentPlayer;
|
||||||
var currentTargetInfo;
|
var currentTargetInfo;
|
||||||
|
|
||||||
var players = [];
|
var players = [];
|
||||||
|
|
||||||
self.registerPlayer = function (player) {
|
self.registerPlayer = function (player) {
|
||||||
|
@ -21,7 +36,8 @@
|
||||||
isLocalPlayer: currentPlayer.isLocalPlayer,
|
isLocalPlayer: currentPlayer.isLocalPlayer,
|
||||||
id: currentTargetInfo.id,
|
id: currentTargetInfo.id,
|
||||||
deviceName: currentTargetInfo.deviceName,
|
deviceName: currentTargetInfo.deviceName,
|
||||||
playableMediaTypes: currentTargetInfo.playableMediaTypes
|
playableMediaTypes: currentTargetInfo.playableMediaTypes,
|
||||||
|
supportedCommands: currentTargetInfo.supportedCommands
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,12 +59,12 @@
|
||||||
$(self).trigger('playerchange');
|
$(self).trigger('playerchange');
|
||||||
};
|
};
|
||||||
|
|
||||||
self.setDefaultPlayerActive = function() {
|
self.setDefaultPlayerActive = function () {
|
||||||
self.setActivePlayer(self.getDefaultPlayer());
|
self.setActivePlayer(self.getDefaultPlayer());
|
||||||
};
|
};
|
||||||
|
|
||||||
self.removeActivePlayer = function (name) {
|
self.removeActivePlayer = function (name) {
|
||||||
|
|
||||||
if (self.getPlayerInfo().name == name) {
|
if (self.getPlayerInfo().name == name) {
|
||||||
self.setDefaultPlayerActive();
|
self.setDefaultPlayerActive();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +94,7 @@
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
targets = targets.sort(function(a,b) {
|
targets = targets.sort(function (a, b) {
|
||||||
|
|
||||||
var aVal = a.isLocalPlayer ? 0 : 1;
|
var aVal = a.isLocalPlayer ? 0 : 1;
|
||||||
var bVal = b.isLocalPlayer ? 0 : 1;
|
var bVal = b.isLocalPlayer ? 0 : 1;
|
||||||
|
@ -174,20 +190,79 @@
|
||||||
return p.isDefaultPlayer;
|
return p.isDefaultPlayer;
|
||||||
})[0];
|
})[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.getCurrentPlayer = function () {
|
||||||
|
|
||||||
|
return currentPlayer;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.pause = function () {
|
||||||
|
currentPlayer.pause();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.stop = function () {
|
||||||
|
currentPlayer.stop();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.unpause = function () {
|
||||||
|
currentPlayer.unpause();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.seek = function (position) {
|
||||||
|
currentPlayer.seek(position);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.currentPlaylistIndex = function (i) {
|
||||||
|
currentPlayer.currentPlaylistIndex(i);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.removeFromPlaylist = function (i) {
|
||||||
|
currentPlayer.removeFromPlaylist(i);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.nextTrack = function () {
|
||||||
|
currentPlayer.nextTrack();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.previousTrack = function () {
|
||||||
|
currentPlayer.previousTrack();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.mute = function () {
|
||||||
|
currentPlayer.mute();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.unmute = function () {
|
||||||
|
currentPlayer.unmute();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.toggleMute = function () {
|
||||||
|
currentPlayer.toggleMute();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.volumeDown = function () {
|
||||||
|
currentPlayer.volumeDown();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.volumeUp = function () {
|
||||||
|
currentPlayer.volumeUp();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.shuffle = function (id) {
|
||||||
|
currentPlayer.shuffle(id);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
window.MediaController = new mediaController();
|
window.MediaController = new mediaController();
|
||||||
|
|
||||||
function onWebSocketMessageReceived(e, msg) {
|
function onWebSocketMessageReceived(e, msg) {
|
||||||
|
|
||||||
var localPlayer = msg.MessageType === "Play" ||
|
var localPlayer;
|
||||||
msg.MessageType === "Playstate" ||
|
|
||||||
msg.MessageType === "GeneralCommand" ?
|
|
||||||
MediaController.getLocalPlayer() :
|
|
||||||
null;
|
|
||||||
|
|
||||||
if (msg.MessageType === "Play") {
|
if (msg.MessageType === "Play") {
|
||||||
|
|
||||||
|
localPlayer = MediaController.getLocalPlayer();
|
||||||
|
|
||||||
if (msg.Data.PlayCommand == "PlayNext") {
|
if (msg.Data.PlayCommand == "PlayNext") {
|
||||||
localPlayer.queueNext({ ids: msg.Data.ItemIds });
|
localPlayer.queueNext({ ids: msg.Data.ItemIds });
|
||||||
}
|
}
|
||||||
|
@ -207,6 +282,8 @@
|
||||||
}
|
}
|
||||||
else if (msg.MessageType === "Playstate") {
|
else if (msg.MessageType === "Playstate") {
|
||||||
|
|
||||||
|
localPlayer = MediaController.getLocalPlayer();
|
||||||
|
|
||||||
if (msg.Data.Command === 'Stop') {
|
if (msg.Data.Command === 'Stop') {
|
||||||
localPlayer.stop();
|
localPlayer.stop();
|
||||||
}
|
}
|
||||||
|
@ -225,14 +302,13 @@
|
||||||
else if (msg.Data.Command === 'PreviousTrack') {
|
else if (msg.Data.Command === 'PreviousTrack') {
|
||||||
localPlayer.previousTrack();
|
localPlayer.previousTrack();
|
||||||
}
|
}
|
||||||
else if (msg.Data.Command === 'Fullscreen') {
|
|
||||||
localPlayer.remoteFullscreen();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (msg.MessageType === "GeneralCommand") {
|
else if (msg.MessageType === "GeneralCommand") {
|
||||||
|
|
||||||
var cmd = msg.Data;
|
var cmd = msg.Data;
|
||||||
|
|
||||||
|
localPlayer = MediaController.getLocalPlayer();
|
||||||
|
|
||||||
if (cmd.Name === 'Mute') {
|
if (cmd.Name === 'Mute') {
|
||||||
localPlayer.mute();
|
localPlayer.mute();
|
||||||
}
|
}
|
||||||
|
@ -248,6 +324,12 @@
|
||||||
else if (cmd.Name === 'ToggleMute') {
|
else if (cmd.Name === 'ToggleMute') {
|
||||||
localPlayer.toggleMute();
|
localPlayer.toggleMute();
|
||||||
}
|
}
|
||||||
|
else if (cmd.Name === 'Fullscreen') {
|
||||||
|
localPlayer.remoteFullscreen();
|
||||||
|
}
|
||||||
|
else if (cmd.Name === 'SetVolume') {
|
||||||
|
localPlayer.setVolume(parseFloat(cmd.Arguments.Volume));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +340,9 @@
|
||||||
var playerInfo = MediaController.getPlayerInfo();
|
var playerInfo = MediaController.getPlayerInfo();
|
||||||
|
|
||||||
var html = '';
|
var html = '';
|
||||||
html += '<h3>Select Player:</h3>';
|
html += '<form>';
|
||||||
|
|
||||||
|
html += '<form><h3>Select Player:</h3>';
|
||||||
html += '<fieldset data-role="controlgroup" data-mini="true">';
|
html += '<fieldset data-role="controlgroup" data-mini="true">';
|
||||||
|
|
||||||
for (var i = 0, length = targets.length; i < length; i++) {
|
for (var i = 0, length = targets.length; i < length; i++) {
|
||||||
|
@ -270,7 +354,9 @@
|
||||||
var isChecked = target.id == playerInfo.id;
|
var isChecked = target.id == playerInfo.id;
|
||||||
var checkedHtml = isChecked ? ' checked="checked"' : '';
|
var checkedHtml = isChecked ? ' checked="checked"' : '';
|
||||||
|
|
||||||
html += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
|
var mirror = (!target.isLocalPlayer && target.supportedCommands.indexOf('DisplayContent') != -1) ? 'true' : 'false';
|
||||||
|
|
||||||
|
html += '<input type="radio" class="radioSelectPlayerTarget" name="radioSelectPlayerTarget" data-mirror="' + mirror + '" data-commands="' + target.supportedCommands.join(',') + '" data-mediatypes="' + target.playableMediaTypes.join(',') + '" data-playername="' + target.playerName + '" data-targetid="' + target.id + '" data-targetname="' + target.name + '" id="' + id + '" value="' + target.id + '"' + checkedHtml + '>';
|
||||||
html += '<label for="' + id + '" style="font-weight:normal;">' + target.name;
|
html += '<label for="' + id + '" style="font-weight:normal;">' + target.name;
|
||||||
|
|
||||||
if (target.appName) {
|
if (target.appName) {
|
||||||
|
@ -284,6 +370,11 @@
|
||||||
|
|
||||||
html += '<p class="fieldDescription">All plays will be sent to the selected player.</p>';
|
html += '<p class="fieldDescription">All plays will be sent to the selected player.</p>';
|
||||||
|
|
||||||
|
var checkedHtml = enableMirrorMode ? ' checked="checked"' : '';
|
||||||
|
html += '<div style="margin-top:1.5em;" class="fldMirrorMode"><label for="chkEnableMirrorMode">Enable Mirror Mode</label><input type="checkbox" class="chkEnableMirrorMode" id="chkEnableMirrorMode" data-mini="true"' + checkedHtml + ' /></div>';
|
||||||
|
|
||||||
|
html += '</form>';
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,17 +399,47 @@
|
||||||
|
|
||||||
$('.players', elem).html(getTargetsHtml(targets)).trigger('create');
|
$('.players', elem).html(getTargetsHtml(targets)).trigger('create');
|
||||||
|
|
||||||
|
$('.chkEnableMirrorMode', elem).on().on('change', function () {
|
||||||
|
enableMirrorMode = this.checked;
|
||||||
|
|
||||||
|
if (this.checked && currentDisplayInfo) {
|
||||||
|
|
||||||
|
mirrorItem(currentDisplayInfo);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
$('.radioSelectPlayerTarget', elem).on('change', function () {
|
$('.radioSelectPlayerTarget', elem).on('change', function () {
|
||||||
|
|
||||||
|
var supportsMirror = this.getAttribute('data-mirror') == 'true';
|
||||||
|
|
||||||
|
if (supportsMirror) {
|
||||||
|
$('.fldMirrorMode', elem).show();
|
||||||
|
} else {
|
||||||
|
$('.fldMirrorMode', elem).hide();
|
||||||
|
$('.chkEnableMirrorMode', elem).checked(false).trigger('change').checkboxradio('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
}).each(function () {
|
||||||
|
|
||||||
|
if (this.checked) {
|
||||||
|
$(this).trigger('change');
|
||||||
|
}
|
||||||
|
|
||||||
|
}).on('change', function () {
|
||||||
|
|
||||||
var playerName = this.getAttribute('data-playername');
|
var playerName = this.getAttribute('data-playername');
|
||||||
var targetId = this.getAttribute('data-targetid');
|
var targetId = this.getAttribute('data-targetid');
|
||||||
var targetName = this.getAttribute('data-targetname');
|
var targetName = this.getAttribute('data-targetname');
|
||||||
var playableMediaTypes = this.getAttribute('data-mediatypes').split(',');
|
var playableMediaTypes = this.getAttribute('data-mediatypes').split(',');
|
||||||
|
var supportedCommands = this.getAttribute('data-commands').split(',');
|
||||||
|
|
||||||
MediaController.setActivePlayer(playerName, {
|
MediaController.setActivePlayer(playerName, {
|
||||||
id: targetId,
|
id: targetId,
|
||||||
name: targetName,
|
name: targetName,
|
||||||
playableMediaTypes: playableMediaTypes
|
playableMediaTypes: playableMediaTypes,
|
||||||
|
supportedCommands: supportedCommands
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -335,4 +456,21 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('pagebeforeshow', ".page", function () {
|
||||||
|
|
||||||
|
var page = this;
|
||||||
|
|
||||||
|
currentDisplayInfo = null;
|
||||||
|
|
||||||
|
}).on('displayingitem', ".libraryPage", function (e, info) {
|
||||||
|
|
||||||
|
var page = this;
|
||||||
|
|
||||||
|
currentDisplayInfo = info;
|
||||||
|
|
||||||
|
if (enableMirrorMode) {
|
||||||
|
mirrorItem(info);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
})(jQuery, window);
|
})(jQuery, window);
|
|
@ -23,8 +23,16 @@
|
||||||
var idleState = true;
|
var idleState = true;
|
||||||
var remoteFullscreen = false;
|
var remoteFullscreen = false;
|
||||||
|
|
||||||
|
var muteButton = null;
|
||||||
|
var unmuteButton = null;
|
||||||
|
var volumeSlider = null;
|
||||||
|
var positionSlider;
|
||||||
|
var isPositionSliderActive;
|
||||||
|
var currentTimeElement;
|
||||||
|
|
||||||
self.initVideoPlayer = function () {
|
self.initVideoPlayer = function () {
|
||||||
video = playVideo(item, mediaSource, startPosition, user);
|
video = playVideo(item, mediaSource, startPosition, user);
|
||||||
|
|
||||||
return video;
|
return video;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -66,7 +74,7 @@
|
||||||
self.resetEnhancements = function () {
|
self.resetEnhancements = function () {
|
||||||
$("#mediaPlayer").hide();
|
$("#mediaPlayer").hide();
|
||||||
$('#videoPlayer').removeClass('fullscreenVideo');
|
$('#videoPlayer').removeClass('fullscreenVideo');
|
||||||
$("#videoControls").removeClass("inactive")
|
$("#videoControls").removeClass("inactive");
|
||||||
$("video").remove();
|
$("video").remove();
|
||||||
$("html").css("cursor", "default");
|
$("html").css("cursor", "default");
|
||||||
$(".ui-loader").hide();
|
$(".ui-loader").hide();
|
||||||
|
@ -155,7 +163,38 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function onPositionSliderChange() {
|
||||||
|
|
||||||
|
isPositionSliderActive = false;
|
||||||
|
|
||||||
|
var newPercent = parseInt(this.value);
|
||||||
|
|
||||||
|
var newPositionTicks = (newPercent / 100) * currentMediaSource.RunTimeTicks;
|
||||||
|
|
||||||
|
self.changeStream(Math.floor(newPositionTicks));
|
||||||
|
}
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
|
var parent = $("#mediaPlayer");
|
||||||
|
muteButton = $('.muteButton', parent);
|
||||||
|
unmuteButton = $('.unmuteButton', parent);
|
||||||
|
currentTimeElement = $('.currentTime', parent);
|
||||||
|
|
||||||
|
positionSlider = $(".positionSlider", parent).on('slidestart', function (e) {
|
||||||
|
|
||||||
|
isPositionSliderActive = true;
|
||||||
|
|
||||||
|
}).on('slidestop', onPositionSliderChange);
|
||||||
|
|
||||||
|
volumeSlider = $('.volumeSlider', parent).on('slidestop', function () {
|
||||||
|
|
||||||
|
var vol = this.value;
|
||||||
|
|
||||||
|
updateVolumeButtons(vol);
|
||||||
|
self.setVolume(vol * 100);
|
||||||
|
});
|
||||||
|
|
||||||
$('#video-chaptersFlyout').on('click', '.mediaFlyoutOption', function () {
|
$('#video-chaptersFlyout').on('click', '.mediaFlyoutOption', function () {
|
||||||
|
|
||||||
var ticks = parseInt(this.getAttribute('data-positionticks'));
|
var ticks = parseInt(this.getAttribute('data-positionticks'));
|
||||||
|
@ -264,6 +303,17 @@
|
||||||
}, 4000);
|
}, 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateVolumeButtons(vol) {
|
||||||
|
|
||||||
|
if (vol) {
|
||||||
|
muteButton.show();
|
||||||
|
unmuteButton.hide();
|
||||||
|
} else {
|
||||||
|
muteButton.hide();
|
||||||
|
unmuteButton.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function requestFullScreen(element) {
|
function requestFullScreen(element) {
|
||||||
|
|
||||||
// Supports most browsers and their versions.
|
// Supports most browsers and their versions.
|
||||||
|
@ -649,7 +699,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just use the first audio stream
|
// Just use the first audio stream
|
||||||
return audioStreams[0].Index;
|
return audioStreams.length ? audioStreams[0].Index : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getVideoQualityOptions(mediaStreams) {
|
function getVideoQualityOptions(mediaStreams) {
|
||||||
|
@ -729,7 +779,7 @@
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
function playVideo(item, mediaSource, startPosition, user) {
|
function playVideo(item, mediaSource, startPosition, user) {
|
||||||
|
|
||||||
var mediaStreams = mediaSource.MediaStreams || [];
|
var mediaStreams = mediaSource.MediaStreams || [];
|
||||||
|
@ -771,7 +821,10 @@
|
||||||
videoBitrate: mp4Quality.videoBitrate,
|
videoBitrate: mp4Quality.videoBitrate,
|
||||||
audioBitrate: mp4Quality.audioBitrate,
|
audioBitrate: mp4Quality.audioBitrate,
|
||||||
VideoCodec: mp4Quality.videoCodec,
|
VideoCodec: mp4Quality.videoCodec,
|
||||||
AudioCodec: mp4Quality.audioCodec
|
AudioCodec: mp4Quality.audioCodec,
|
||||||
|
|
||||||
|
// None of the browsers seem to like this
|
||||||
|
EnableAutoStreamCopy: false
|
||||||
|
|
||||||
})) + seekParam;
|
})) + seekParam;
|
||||||
|
|
||||||
|
@ -781,7 +834,8 @@
|
||||||
AudioCodec: 'Vorbis',
|
AudioCodec: 'Vorbis',
|
||||||
maxWidth: webmQuality.maxWidth,
|
maxWidth: webmQuality.maxWidth,
|
||||||
videoBitrate: webmQuality.videoBitrate,
|
videoBitrate: webmQuality.videoBitrate,
|
||||||
audioBitrate: webmQuality.audioBitrate
|
audioBitrate: webmQuality.audioBitrate,
|
||||||
|
EnableAutoStreamCopy: false
|
||||||
|
|
||||||
})) + seekParam;
|
})) + seekParam;
|
||||||
|
|
||||||
|
@ -808,9 +862,13 @@
|
||||||
|
|
||||||
// Can't autoplay in these browsers so we need to use the full controls
|
// Can't autoplay in these browsers so we need to use the full controls
|
||||||
if (requiresControls) {
|
if (requiresControls) {
|
||||||
html += '<video class="itemVideo" id="itemVideo" autoplay controls preload="none">';
|
|
||||||
|
|
||||||
|
html += '<video class="itemVideo" id="itemVideo" preload="none" autoplay controls>';
|
||||||
} else {
|
} else {
|
||||||
html += '<video class="itemVideo" id="itemVideo" autoplay preload="none">';
|
|
||||||
|
// Chrome 35 won't play with preload none
|
||||||
|
html += '<video class="itemVideo" id="itemVideo" preload="metadata" autoplay>';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isStatic) {
|
if (!isStatic) {
|
||||||
|
@ -837,7 +895,6 @@
|
||||||
$('#video-stopButton', videoControls).show();
|
$('#video-stopButton', videoControls).show();
|
||||||
$('#video-playButton', videoControls).hide();
|
$('#video-playButton', videoControls).hide();
|
||||||
$('#video-pauseButton', videoControls).show();
|
$('#video-pauseButton', videoControls).show();
|
||||||
$('#video-playlistButton', videoControls).hide();
|
|
||||||
$('#video-previousTrackButton', videoControls).hide();
|
$('#video-previousTrackButton', videoControls).hide();
|
||||||
$('#video-nextTrackButton', videoControls).hide();
|
$('#video-nextTrackButton', videoControls).hide();
|
||||||
var videoElement = $('#videoElement', mediaPlayer).prepend(html);
|
var videoElement = $('#videoElement', mediaPlayer).prepend(html);
|
||||||
|
@ -872,44 +929,26 @@
|
||||||
$('#video-fullscreenButton', videoControls).show();
|
$('#video-fullscreenButton', videoControls).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoElement = $("video", videoElement);
|
var video = $("video", videoElement);
|
||||||
|
|
||||||
initialVolume = localStorage.getItem("volume") || 0.5;
|
initialVolume = self.getSavedVolume();
|
||||||
|
|
||||||
videoElement.each(function () {
|
video.each(function () {
|
||||||
this.volume = initialVolume;
|
this.volume = initialVolume;
|
||||||
});
|
});
|
||||||
|
|
||||||
self.volumeSlider.val(initialVolume).slider('refresh');
|
volumeSlider.val(initialVolume).slider('refresh');
|
||||||
self.updateVolumeButtons(initialVolume);
|
updateVolumeButtons(initialVolume);
|
||||||
|
|
||||||
videoElement.on("volumechange", function (e) {
|
video.on("volumechange", function (e) {
|
||||||
|
|
||||||
var muted = this.muted;
|
|
||||||
|
|
||||||
var vol = this.volume;
|
var vol = this.volume;
|
||||||
|
|
||||||
if (!muted && this.volume > 0) {
|
updateVolumeButtons(vol);
|
||||||
localStorage.setItem("volume", vol);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.muted = this.volume == 0;
|
}).one("playing", function () {
|
||||||
|
|
||||||
self.updateVolumeButtons(vol);
|
self.onPlaybackStart(this, item, mediaSource);
|
||||||
|
|
||||||
}).on("play.once", function () {
|
|
||||||
|
|
||||||
videoElement.off("play.once");
|
|
||||||
|
|
||||||
}).on("playing.once", function () {
|
|
||||||
|
|
||||||
self.updateCanClientSeek(this);
|
|
||||||
|
|
||||||
videoElement.off("playing.once");
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
|
||||||
|
|
||||||
self.startProgressInterval(item.Id, mediaSource.Id);
|
|
||||||
|
|
||||||
}).on("pause", function (e) {
|
}).on("pause", function (e) {
|
||||||
|
|
||||||
|
@ -939,9 +978,9 @@
|
||||||
|
|
||||||
}).on("timeupdate", function () {
|
}).on("timeupdate", function () {
|
||||||
|
|
||||||
if (!self.isPositionSliderActive) {
|
if (!isPositionSliderActive) {
|
||||||
|
|
||||||
self.setCurrentTime(self.getCurrentTicks(this), item, true);
|
self.setCurrentTime(self.getCurrentTicks(this), positionSlider, currentTimeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
}).on("error", function () {
|
}).on("error", function () {
|
||||||
|
@ -995,8 +1034,13 @@
|
||||||
$(".ui-loader").hide();
|
$(".ui-loader").hide();
|
||||||
$("html").css("cursor", "default");
|
$("html").css("cursor", "default");
|
||||||
|
|
||||||
}).on("ended.playbackstopped", self.onPlaybackStopped)
|
}).on("ended.playbackstopped", function () {
|
||||||
.on('ended.playnext', self.playNextAfterEnded);
|
|
||||||
|
currentTimeElement.empty();
|
||||||
|
|
||||||
|
self.onPlaybackStopped.call(this);
|
||||||
|
|
||||||
|
}).on('ended.playnext', self.playNextAfterEnded);
|
||||||
|
|
||||||
// Stop playback on browser back button nav
|
// Stop playback on browser back button nav
|
||||||
$(window).on("popstate", function () {
|
$(window).on("popstate", function () {
|
||||||
|
@ -1037,7 +1081,7 @@
|
||||||
currentItem = item;
|
currentItem = item;
|
||||||
currentMediaSource = mediaSource;
|
currentMediaSource = mediaSource;
|
||||||
|
|
||||||
return videoElement[0];
|
return video[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
|
@ -13,12 +13,6 @@
|
||||||
var currentPlaylistIndex = 0;
|
var currentPlaylistIndex = 0;
|
||||||
|
|
||||||
self.currentDurationTicks = null;
|
self.currentDurationTicks = null;
|
||||||
self.currentTimeElement = null;
|
|
||||||
self.unmuteButton = null;
|
|
||||||
self.muteButton = null;
|
|
||||||
self.positionSlider = null;
|
|
||||||
self.isPositionSliderActive = null;
|
|
||||||
self.volumeSlider = null;
|
|
||||||
self.startTimeTicksOffset = null;
|
self.startTimeTicksOffset = null;
|
||||||
|
|
||||||
self.playlist = [];
|
self.playlist = [];
|
||||||
|
@ -34,7 +28,8 @@
|
||||||
id: ApiClient.deviceId(),
|
id: ApiClient.deviceId(),
|
||||||
playerName: self.name,
|
playerName: self.name,
|
||||||
playableMediaTypes: ['Audio', 'Video'],
|
playableMediaTypes: ['Audio', 'Video'],
|
||||||
isLocalPlayer: true
|
isLocalPlayer: true,
|
||||||
|
supportedCommands: Dashboard.getSupportedRemoteCommands()
|
||||||
}];
|
}];
|
||||||
|
|
||||||
return targets;
|
return targets;
|
||||||
|
@ -45,22 +40,11 @@
|
||||||
canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY;
|
canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.updateVolumeButtons = function (vol) {
|
|
||||||
|
|
||||||
if (vol) {
|
|
||||||
self.muteButton.show().prop("disabled", false);
|
|
||||||
self.unmuteButton.hide().prop("disabled", true);
|
|
||||||
} else {
|
|
||||||
self.muteButton.hide().prop("disabled", true);
|
|
||||||
self.unmuteButton.show().prop("disabled", false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.getCurrentTicks = function (mediaElement) {
|
self.getCurrentTicks = function (mediaElement) {
|
||||||
return Math.floor(10000000 * (mediaElement || currentMediaElement).currentTime) + self.startTimeTicksOffset;
|
return Math.floor(10000000 * (mediaElement || currentMediaElement).currentTime) + self.startTimeTicksOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.clearPauseStop = function() {
|
self.clearPauseStop = function () {
|
||||||
|
|
||||||
if (self.pauseStop) {
|
if (self.pauseStop) {
|
||||||
console.log('clearing pause stop timer');
|
console.log('clearing pause stop timer');
|
||||||
|
@ -69,31 +53,6 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.onPlaybackStopped = function () {
|
|
||||||
|
|
||||||
self.clearPauseStop();
|
|
||||||
|
|
||||||
$(this).off('ended.playbackstopped');
|
|
||||||
|
|
||||||
self.currentTimeElement.empty();
|
|
||||||
|
|
||||||
var endTime = this.currentTime;
|
|
||||||
|
|
||||||
clearProgressInterval();
|
|
||||||
|
|
||||||
var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset;
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentItem.Id, currentMediaSource.Id, position);
|
|
||||||
|
|
||||||
if (currentItem.MediaType == "Video") {
|
|
||||||
ApiClient.stopActiveEncodings();
|
|
||||||
if (self.isFullScreen()) {
|
|
||||||
self.exitFullScreen();
|
|
||||||
}
|
|
||||||
self.resetEnhancements();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.playNextAfterEnded = function () {
|
self.playNextAfterEnded = function () {
|
||||||
|
|
||||||
$(this).off('ended.playnext');
|
$(this).off('ended.playnext');
|
||||||
|
@ -148,11 +107,13 @@
|
||||||
|
|
||||||
var currentSrc = element.currentSrc;
|
var currentSrc = element.currentSrc;
|
||||||
|
|
||||||
if (params.AudioStreamIndex != null) {
|
if (currentItem.MediaType == "Video") {
|
||||||
currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex);
|
if (params.AudioStreamIndex != null) {
|
||||||
}
|
currentSrc = replaceQueryString(currentSrc, 'AudioStreamIndex', params.AudioStreamIndex);
|
||||||
if (params.SubtitleStreamIndex != null) {
|
}
|
||||||
currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', (params.SubtitleStreamIndex == -1 ? '' : params.SubtitleStreamIndex));
|
if (params.SubtitleStreamIndex != null) {
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'SubtitleStreamIndex', (params.SubtitleStreamIndex == -1 ? '' : params.SubtitleStreamIndex));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc);
|
var maxWidth = params.MaxWidth || getParameterByName('MaxWidth', currentSrc);
|
||||||
|
@ -164,25 +125,32 @@
|
||||||
|
|
||||||
var transcodingExtension = self.getTranscodingExtension();
|
var transcodingExtension = self.getTranscodingExtension();
|
||||||
|
|
||||||
var finalParams = self.getFinalVideoParams(currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension);
|
var isStatic;
|
||||||
currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth);
|
if (currentItem.MediaType == "Video") {
|
||||||
currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', finalParams.videoBitrate);
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'AudioBitrate', finalParams.audioBitrate);
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'Static', finalParams.isStatic);
|
|
||||||
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'AudioCodec', finalParams.audioCodec);
|
var finalParams = self.getFinalVideoParams(currentMediaSource, maxWidth, bitrate, audioStreamIndex, subtitleStreamIndex, transcodingExtension);
|
||||||
currentSrc = replaceQueryString(currentSrc, 'VideoCodec', finalParams.videoCodec);
|
|
||||||
|
|
||||||
currentSrc = replaceQueryString(currentSrc, 'profile', finalParams.profile || '');
|
currentSrc = replaceQueryString(currentSrc, 'MaxWidth', finalParams.maxWidth);
|
||||||
currentSrc = replaceQueryString(currentSrc, 'level', finalParams.level || '');
|
currentSrc = replaceQueryString(currentSrc, 'VideoBitrate', finalParams.videoBitrate);
|
||||||
|
|
||||||
if (finalParams.isStatic) {
|
currentSrc = replaceQueryString(currentSrc, 'VideoCodec', finalParams.videoCodec);
|
||||||
currentSrc = currentSrc.replace('.webm', '.mp4').replace('.m3u8', '.mp4');
|
|
||||||
} else {
|
currentSrc = replaceQueryString(currentSrc, 'profile', finalParams.profile || '');
|
||||||
currentSrc = currentSrc.replace('.mp4', transcodingExtension).replace('.m4v', transcodingExtension);
|
currentSrc = replaceQueryString(currentSrc, 'level', finalParams.level || '');
|
||||||
|
|
||||||
|
if (finalParams.isStatic) {
|
||||||
|
currentSrc = currentSrc.replace('.webm', '.mp4').replace('.m3u8', '.mp4');
|
||||||
|
} else {
|
||||||
|
currentSrc = currentSrc.replace('.mp4', transcodingExtension).replace('.m4v', transcodingExtension);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'AudioBitrate', finalParams.audioBitrate);
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'Static', finalParams.isStatic);
|
||||||
|
currentSrc = replaceQueryString(currentSrc, 'AudioCodec', finalParams.audioCodec);
|
||||||
|
isStatic = finalParams.isStatic;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finalParams.isStatic || !ticks) {
|
if (isStatic || !ticks) {
|
||||||
currentSrc = replaceQueryString(currentSrc, 'starttimeticks', '');
|
currentSrc = replaceQueryString(currentSrc, 'starttimeticks', '');
|
||||||
} else {
|
} else {
|
||||||
currentSrc = replaceQueryString(currentSrc, 'starttimeticks', ticks);
|
currentSrc = replaceQueryString(currentSrc, 'starttimeticks', ticks);
|
||||||
|
@ -190,27 +158,33 @@
|
||||||
|
|
||||||
clearProgressInterval();
|
clearProgressInterval();
|
||||||
|
|
||||||
$(element).off('ended.playbackstopped').off('ended.playnext').on("play.onceafterseek", function () {
|
$(element).off('ended.playbackstopped').off('ended.playnext').one("play", function () {
|
||||||
|
|
||||||
self.updateCanClientSeek(this);
|
self.updateCanClientSeek(this);
|
||||||
|
|
||||||
$(this).off('play.onceafterseek').on('ended.playbackstopped', self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded);
|
$(this).on('ended.playbackstopped', self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded);
|
||||||
|
|
||||||
self.startProgressInterval(currentItem.Id, currentMediaSource.Id);
|
self.startProgressInterval(currentItem.Id, currentMediaSource.Id);
|
||||||
sendProgressUpdate(currentItem.Id, currentMediaSource.Id);
|
sendProgressUpdate(currentItem.Id, currentMediaSource.Id);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ApiClient.stopActiveEncodings().done(function () {
|
if (currentItem.MediaType == "Video") {
|
||||||
|
ApiClient.stopActiveEncodings().done(function () {
|
||||||
|
|
||||||
|
self.startTimeTicksOffset = ticks;
|
||||||
|
element.src = currentSrc;
|
||||||
|
|
||||||
|
});
|
||||||
|
} else {
|
||||||
self.startTimeTicksOffset = ticks;
|
self.startTimeTicksOffset = ticks;
|
||||||
element.src = currentSrc;
|
element.src = currentSrc;
|
||||||
|
element.play();
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.setCurrentTime = function (ticks, item, updateSlider) {
|
self.setCurrentTime = function (ticks, positionSlider, currentTimeElement) {
|
||||||
|
|
||||||
// Convert to ticks
|
// Convert to ticks
|
||||||
ticks = Math.floor(ticks);
|
ticks = Math.floor(ticks);
|
||||||
|
@ -221,17 +195,28 @@
|
||||||
|
|
||||||
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
|
timeText += " / " + Dashboard.getDisplayTime(self.currentDurationTicks);
|
||||||
|
|
||||||
if (updateSlider) {
|
if (positionSlider) {
|
||||||
|
|
||||||
var percent = ticks / self.currentDurationTicks;
|
var percent = ticks / self.currentDurationTicks;
|
||||||
percent *= 100;
|
percent *= 100;
|
||||||
|
|
||||||
self.positionSlider.val(percent).slider('enable').slider('refresh');
|
positionSlider.val(percent).slider('enable').slider('refresh');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.positionSlider.slider('disable').slider('refresh');
|
|
||||||
|
if (positionSlider) {
|
||||||
|
|
||||||
|
positionSlider.slider('disable').slider('refresh');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.currentTimeElement.html(timeText);
|
if (currentTimeElement) {
|
||||||
|
currentTimeElement.html(timeText);
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = self.getPlayerStateInternal(currentMediaElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('positionchange', [state]);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.canPlayVideoDirect = function (mediaSource, videoStream, audioStream, subtitleStream, maxWidth, bitrate) {
|
self.canPlayVideoDirect = function (mediaSource, videoStream, audioStream, subtitleStream, maxWidth, bitrate) {
|
||||||
|
@ -459,8 +444,6 @@
|
||||||
|
|
||||||
var mediaElement;
|
var mediaElement;
|
||||||
|
|
||||||
var mediaControls = $('#nowPlayingBar');
|
|
||||||
|
|
||||||
if (item.MediaType === "Video") {
|
if (item.MediaType === "Video") {
|
||||||
|
|
||||||
currentItem = item;
|
currentItem = item;
|
||||||
|
@ -470,15 +453,12 @@
|
||||||
mediaElement = self.initVideoPlayer();
|
mediaElement = self.initVideoPlayer();
|
||||||
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
||||||
|
|
||||||
mediaControls = $("#videoControls");
|
|
||||||
|
|
||||||
} else if (item.MediaType === "Audio") {
|
} else if (item.MediaType === "Audio") {
|
||||||
|
|
||||||
currentItem = item;
|
currentItem = item;
|
||||||
currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources);
|
currentMediaSource = getOptimalMediaSource(item.MediaType, item.MediaSources);
|
||||||
|
|
||||||
mediaElement = playAudio(item, currentMediaSource, startPosition);
|
mediaElement = playAudio(item, currentMediaSource, startPosition);
|
||||||
mediaControls.show();
|
|
||||||
|
|
||||||
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
self.currentDurationTicks = currentMediaSource.RunTimeTicks;
|
||||||
|
|
||||||
|
@ -488,36 +468,50 @@
|
||||||
|
|
||||||
currentMediaElement = mediaElement;
|
currentMediaElement = mediaElement;
|
||||||
|
|
||||||
//display image and title
|
if (item.MediaType === "Video") {
|
||||||
var imageTags = item.ImageTags || {};
|
|
||||||
var html = '';
|
self.updateNowPlayingInfo(item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.updateNowPlayingInfo = function (item) {
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
throw new Error('item cannot be null');
|
||||||
|
}
|
||||||
|
|
||||||
|
var mediaControls = $("#videoControls");
|
||||||
|
|
||||||
|
var state = self.getPlayerStateInternal(currentMediaElement, item, currentMediaSource);
|
||||||
|
|
||||||
var url = "";
|
var url = "";
|
||||||
|
|
||||||
if (imageTags.Primary) {
|
if (state.primaryImageTag) {
|
||||||
|
|
||||||
url = ApiClient.getImageUrl(item.Id, {
|
url = ApiClient.getImageUrl(state.primaryImageItemId, {
|
||||||
type: "Primary",
|
type: "Primary",
|
||||||
height: 80,
|
height: 80,
|
||||||
tag: item.ImageTags.Primary
|
tag: state.primaryImageTag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
else if (state.backdropImageTag) {
|
||||||
|
|
||||||
url = ApiClient.getImageUrl(item.Id, {
|
url = ApiClient.getImageUrl(state.backdropItemId, {
|
||||||
type: "Backdrop",
|
type: "Backdrop",
|
||||||
height: 80,
|
height: 80,
|
||||||
tag: item.BackdropImageTags[0]
|
tag: state.backdropImageTag,
|
||||||
|
index: 0
|
||||||
});
|
});
|
||||||
} else if (imageTags.Thumb) {
|
|
||||||
|
|
||||||
url = ApiClient.getImageUrl(item.Id, {
|
} else if (state.thumbImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.thumbImageItemId, {
|
||||||
type: "Thumb",
|
type: "Thumb",
|
||||||
height: 80,
|
height: 80,
|
||||||
tag: item.ImageTags.Thumb
|
tag: state.thumbImageTag
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (item.Type == "TvChannel" || item.Type == "Recording") {
|
else if (item.Type == "TvChannel" || item.Type == "Recording") {
|
||||||
url = "css/images/items/detail/tv.png";
|
url = "css/images/items/detail/tv.png";
|
||||||
}
|
}
|
||||||
|
@ -528,40 +522,60 @@
|
||||||
url = "css/images/items/detail/video.png";
|
url = "css/images/items/detail/video.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = item.Name;
|
var nowPlayingTextElement = $('.nowPlayingText', mediaControls);
|
||||||
var seriesName = '';
|
var nameHtml = self.getNowPlayingNameHtml(state);
|
||||||
|
|
||||||
// Channel number
|
if (nameHtml.indexOf('<br/>') != -1) {
|
||||||
if (item.Number) {
|
nowPlayingTextElement.addClass('nowPlayingDoubleText');
|
||||||
name = item.Number + ' ' + name;
|
} else {
|
||||||
}
|
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
|
||||||
if (item.IndexNumber != null) {
|
|
||||||
name = item.IndexNumber + " - " + name;
|
|
||||||
}
|
|
||||||
if (item.ParentIndexNumber != null) {
|
|
||||||
name = item.ParentIndexNumber + "." + name;
|
|
||||||
}
|
|
||||||
if (item.SeriesName || item.Album || item.ProductionYear) {
|
|
||||||
seriesName = item.SeriesName || item.Album || item.ProductionYear;
|
|
||||||
}
|
|
||||||
if (item.CurrentProgram) {
|
|
||||||
seriesName = item.CurrentProgram.Name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var href = LibraryBrowser.getHref(item.CurrentProgram || item);
|
$('.nowPlayingImage', mediaControls).html('<img src="' + url + '" />');
|
||||||
|
nowPlayingTextElement.html(nameHtml);
|
||||||
|
};
|
||||||
|
|
||||||
var nowPlayingText = (name ? name + "\n" : "") + (seriesName || "---");
|
self.getNowPlayingNameHtml = function (playerState) {
|
||||||
if (item.SeriesName || item.Album || item.CurrentProgram) {
|
|
||||||
nowPlayingText = (seriesName ? seriesName : "") + "\n" + (name || "---");
|
var topText = playerState.itemName;
|
||||||
|
|
||||||
|
if (playerState.mediaType == 'Video') {
|
||||||
|
if (playerState.indexNumber != null) {
|
||||||
|
topText = playerState.indexNumber + " - " + topText;
|
||||||
|
}
|
||||||
|
if (playerState.parentIndexNumber != null) {
|
||||||
|
topText = playerState.parentIndexNumber + "." + topText;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix for apostrophes and quotes
|
var bottomText = '';
|
||||||
var htmlTitle = trimTitle(nowPlayingText).replace(/'/g, ''').replace(/"/g, '"');
|
|
||||||
html += "<div><a href='" + href + "'><img class='nowPlayingBarImage' alt='" + htmlTitle +
|
|
||||||
"' title='" + htmlTitle + "' src='" + url + "' style='height:40px;display:inline-block;' /></a></div>";
|
|
||||||
html += "<div class='nowPlayingText' title='" + htmlTitle + "'>" + titleHtml(nowPlayingText) + "</div>";
|
|
||||||
|
|
||||||
$('.nowPlayingMediaInfo', mediaControls).html(html);
|
if (playerState.artists && playerState.artists.length) {
|
||||||
|
bottomText = topText;
|
||||||
|
topText = playerState.artists[0];
|
||||||
|
}
|
||||||
|
else if (playerState.seriesName || playerState.album) {
|
||||||
|
bottomText = topText;
|
||||||
|
topText = playerState.seriesName || playerState.album;
|
||||||
|
}
|
||||||
|
else if (playerState.productionYear) {
|
||||||
|
bottomText = playerState.productionYear;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bottomText ? topText + '<br/>' + bottomText : topText;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.displayContent = function (options) {
|
||||||
|
|
||||||
|
// Handle it the same as a remote control command
|
||||||
|
Dashboard.onBrowseCommand({
|
||||||
|
|
||||||
|
ItemName: options.itemName,
|
||||||
|
ItemType: options.itemType,
|
||||||
|
ItemId: options.itemId,
|
||||||
|
Context: options.context
|
||||||
|
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getItemsForPlayback = function (query) {
|
self.getItemsForPlayback = function (query) {
|
||||||
|
@ -712,6 +726,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
self.pause = function () {
|
self.pause = function () {
|
||||||
|
|
||||||
currentMediaElement.pause();
|
currentMediaElement.pause();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -722,56 +737,69 @@
|
||||||
self.seek = function (position) {
|
self.seek = function (position) {
|
||||||
|
|
||||||
self.changeStream(position);
|
self.changeStream(position);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.mute = function () {
|
self.mute = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
self.setVolume(0);
|
||||||
currentMediaElement.volume = 0;
|
|
||||||
currentMediaElement.muted = true;
|
|
||||||
self.volumeSlider.val(0).slider('refresh');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.unmute = function () {
|
self.unMute = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
self.setVolume(self.getSavedVolume() * 100);
|
||||||
var volume = localStorage.getItem("volume") || self.volumeSlider.val();
|
|
||||||
currentMediaElement.volume = volume;
|
|
||||||
currentMediaElement.muted = false;
|
|
||||||
self.volumeSlider.val(volume).slider('refresh');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.toggleMute = function () {
|
self.toggleMute = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
if (currentMediaElement) {
|
||||||
var volume = localStorage.getItem("volume") || self.volumeSlider.val();
|
|
||||||
currentMediaElement.volume = currentMediaElement.volume ? 0 : volume;
|
if (currentMediaElement.volume) {
|
||||||
currentMediaElement.muted = currentMediaElement.volume == 0;
|
self.mute();
|
||||||
self.volumeSlider.val(volume).slider('refresh');
|
} else {
|
||||||
|
self.unMute();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.volumeDown = function () {
|
self.volumeDown = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
if (currentMediaElement) {
|
||||||
currentMediaElement.volume = Math.max(currentMediaElement.volume - .02, 0);
|
self.setVolume(Math.max(currentMediaElement.volume - .02, 0) * 100);
|
||||||
localStorage.setItem("volume", currentMediaElement.volume);
|
|
||||||
self.volumeSlider.val(currentMediaElement.volume).slider('refresh');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.volumeUp = function () {
|
self.volumeUp = function () {
|
||||||
|
|
||||||
if (currentMediaElement) {
|
if (currentMediaElement) {
|
||||||
currentMediaElement.volume = Math.min(currentMediaElement.volume + .02, 1);
|
self.setVolume(Math.min(currentMediaElement.volume + .02, 1) * 100);
|
||||||
localStorage.setItem("volume", currentMediaElement.volume);
|
|
||||||
self.volumeSlider.val(currentMediaElement.volume).slider('refresh');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Sets volume using a 0-100 scale
|
||||||
|
self.setVolume = function (val) {
|
||||||
|
|
||||||
|
if (currentMediaElement) {
|
||||||
|
|
||||||
|
currentMediaElement.volume = val / 100;
|
||||||
|
|
||||||
|
self.onVolumeChanged(currentMediaElement);
|
||||||
|
|
||||||
|
self.saveVolume();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.saveVolume = function (val) {
|
||||||
|
|
||||||
|
if (val) {
|
||||||
|
localStorage.setItem("volume", val);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getSavedVolume = function () {
|
||||||
|
return localStorage.getItem("volume") || 0.5;
|
||||||
|
};
|
||||||
|
|
||||||
self.shuffle = function (id) {
|
self.shuffle = function (id) {
|
||||||
|
|
||||||
var userId = Dashboard.getCurrentUserId();
|
var userId = Dashboard.getCurrentUserId();
|
||||||
|
@ -880,77 +908,193 @@
|
||||||
|
|
||||||
elem.pause();
|
elem.pause();
|
||||||
|
|
||||||
|
var isVideo = currentItem.MediaType == "Video";
|
||||||
|
|
||||||
$(elem).off("ended.playnext").on("ended", function () {
|
$(elem).off("ended.playnext").on("ended", function () {
|
||||||
|
|
||||||
$(this).remove();
|
$(this).off();
|
||||||
|
|
||||||
|
if (this.tagName.toLowerCase() != 'audio') {
|
||||||
|
$(this).remove();
|
||||||
|
}
|
||||||
|
|
||||||
elem.src = "";
|
elem.src = "";
|
||||||
currentMediaElement = null;
|
currentMediaElement = null;
|
||||||
|
currentItem = null;
|
||||||
|
currentMediaSource = null;
|
||||||
|
|
||||||
}).trigger("ended");
|
}).trigger("ended");
|
||||||
|
|
||||||
if (currentItem.MediaType == "Video") {
|
if (isVideo) {
|
||||||
if (self.isFullScreen()) {
|
if (self.isFullScreen()) {
|
||||||
self.exitFullScreen();
|
self.exitFullScreen();
|
||||||
}
|
}
|
||||||
self.resetEnhancements();
|
self.resetEnhancements();
|
||||||
} else {
|
|
||||||
$('#nowPlayingBar').hide();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.isPlaying = function () {
|
self.isPlaying = function () {
|
||||||
return currentMediaElement;
|
return currentMediaElement != null;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.bindPositionSlider = function () {
|
self.getPlayerState = function () {
|
||||||
self.positionSlider.on('slidestart', function (e) {
|
|
||||||
|
|
||||||
self.isPositionSliderActive = true;
|
var deferred = $.Deferred();
|
||||||
|
|
||||||
}).on('slidestop', onPositionSliderChange);
|
var result = self.getPlayerStateInternal(currentMediaElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
deferred.resolveWith(null, [result]);
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
};
|
};
|
||||||
|
|
||||||
self.bindVolumeSlider = function () {
|
self.getPlayerStateInternal = function (playerElement, item, mediaSource) {
|
||||||
self.volumeSlider.on('slidestop', function () {
|
|
||||||
|
|
||||||
var vol = this.value;
|
var state = {};
|
||||||
|
|
||||||
self.updateVolumeButtons(vol);
|
if (playerElement) {
|
||||||
currentMediaElement.volume = vol;
|
|
||||||
});
|
state.volumeLevel = playerElement.volume * 100;
|
||||||
|
state.isMuted = playerElement.volume == 0;
|
||||||
|
state.isPaused = playerElement.paused;
|
||||||
|
state.positionTicks = self.getCurrentTicks(playerElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaSource) {
|
||||||
|
|
||||||
|
state.mediaSourceId = mediaSource.Id;
|
||||||
|
state.runtimeTicks = mediaSource.RunTimeTicks;
|
||||||
|
|
||||||
|
state.canSeek = mediaSource.RunTimeTicks && mediaSource.RunTimeTicks > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
|
||||||
|
state.itemId = item.Id;
|
||||||
|
state.mediaType = item.MediaType;
|
||||||
|
state.itemType = item.Type;
|
||||||
|
state.indexNumber = item.IndexNumber;
|
||||||
|
state.indexNumberEnd = item.IndexNumberEnd;
|
||||||
|
state.parentIndexNumber = item.ParentIndexNumber;
|
||||||
|
state.productionYear = item.ProductionYear;
|
||||||
|
state.premiereDate = item.PremiereDate;
|
||||||
|
state.seriesName = item.SeriesName;
|
||||||
|
state.album = item.Album;
|
||||||
|
state.itemName = item.Name;
|
||||||
|
state.artists = item.Artists;
|
||||||
|
|
||||||
|
var imageTags = item.ImageTags || {};
|
||||||
|
|
||||||
|
if (imageTags.Primary) {
|
||||||
|
|
||||||
|
state.primaryImageItemId = item.Id;
|
||||||
|
state.primaryImageTag = imageTags.Primary;
|
||||||
|
}
|
||||||
|
else if (item.AlbumPrimaryImageTag) {
|
||||||
|
|
||||||
|
state.primaryImageItemId = item.AlbumId;
|
||||||
|
state.primaryImageTag = item.AlbumPrimaryImageTag;
|
||||||
|
}
|
||||||
|
else if (item.SeriesPrimaryImageTag) {
|
||||||
|
|
||||||
|
state.primaryImageItemId = item.SeriesId;
|
||||||
|
state.primaryImageTag = item.SeriesPrimaryImageTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.BackdropImageTags && item.BackdropImageTags.length) {
|
||||||
|
|
||||||
|
state.backdropItemId = item.Id;
|
||||||
|
state.backdropImageTag = item.BackdropImageTags[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageTags.Thumb) {
|
||||||
|
|
||||||
|
state.thumbItemId = item.Id;
|
||||||
|
state.thumbImageTag = imageTags.Thumb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.beginPlayerUpdates = function () {
|
||||||
|
// Nothing to setup here
|
||||||
|
};
|
||||||
|
|
||||||
|
self.endPlayerUpdates = function () {
|
||||||
|
// Nothing to setup here
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onPlaybackStart = function (playerElement, item, mediaSource) {
|
||||||
|
|
||||||
|
self.updateCanClientSeek(playerElement);
|
||||||
|
|
||||||
|
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
||||||
|
|
||||||
|
self.startProgressInterval(item.Id, mediaSource.Id);
|
||||||
|
|
||||||
|
var state = self.getPlayerStateInternal(playerElement, item, mediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('playbackstart', [state]);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onVolumeChanged = function (playerElement) {
|
||||||
|
|
||||||
|
self.saveVolume(playerElement.volume);
|
||||||
|
|
||||||
|
var state = self.getPlayerStateInternal(playerElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('volumechange', [state]);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onPlaybackStopped = function () {
|
||||||
|
|
||||||
|
self.clearPauseStop();
|
||||||
|
|
||||||
|
var playerElement = this;
|
||||||
|
|
||||||
|
$(playerElement).off('ended.playbackstopped');
|
||||||
|
|
||||||
|
var endTime = playerElement.currentTime;
|
||||||
|
|
||||||
|
clearProgressInterval();
|
||||||
|
|
||||||
|
var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset;
|
||||||
|
|
||||||
|
var item = currentItem;
|
||||||
|
var mediaSource = currentMediaSource;
|
||||||
|
|
||||||
|
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, position);
|
||||||
|
|
||||||
|
if (item.MediaType == "Video") {
|
||||||
|
ApiClient.stopActiveEncodings();
|
||||||
|
if (self.isFullScreen()) {
|
||||||
|
self.exitFullScreen();
|
||||||
|
}
|
||||||
|
self.resetEnhancements();
|
||||||
|
}
|
||||||
|
|
||||||
|
var state = self.getPlayerStateInternal(playerElement, item, mediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('playbackstop', [state]);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onPlaystateChange = function (playerElement) {
|
||||||
|
|
||||||
|
var state = self.getPlayerStateInternal(playerElement, currentItem, currentMediaSource);
|
||||||
|
|
||||||
|
$(self).trigger('playstatechange', [state]);
|
||||||
};
|
};
|
||||||
|
|
||||||
$(window).on("beforeunload popstate", function () {
|
$(window).on("beforeunload popstate", function () {
|
||||||
|
|
||||||
var item = currentItem;
|
|
||||||
var media = currentMediaElement;
|
|
||||||
|
|
||||||
// Try to report playback stopped before the browser closes
|
// Try to report playback stopped before the browser closes
|
||||||
if (item && media && currentProgressInterval) {
|
if (currentItem && currentMediaElement && currentProgressInterval) {
|
||||||
|
|
||||||
var endTime = currentMediaElement.currentTime;
|
self.onPlaybackStopped.call(currentMediaElement);
|
||||||
|
|
||||||
var position = Math.floor(10000000 * endTime) + self.startTimeTicksOffset;
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStopped(Dashboard.getCurrentUserId(), currentItem.Id, currentMediaSource.Id, position);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(function () {
|
|
||||||
initPlayer();
|
|
||||||
});
|
|
||||||
|
|
||||||
function initPlayer() {
|
|
||||||
self.muteButton = $('.muteButton');
|
|
||||||
self.unmuteButton = $('.unmuteButton');
|
|
||||||
self.currentTimeElement = $('.currentTime');
|
|
||||||
self.volumeSlider = $('.volumeSlider');
|
|
||||||
self.positionSlider = $(".positionSlider");
|
|
||||||
|
|
||||||
self.bindVolumeSlider();
|
|
||||||
self.bindPositionSlider();
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceQueryString(url, param, value) {
|
function replaceQueryString(url, param, value) {
|
||||||
var re = new RegExp("([?|&])" + param + "=.*?(&|$)", "i");
|
var re = new RegExp("([?|&])" + param + "=.*?(&|$)", "i");
|
||||||
if (url.match(re))
|
if (url.match(re))
|
||||||
|
@ -977,17 +1121,42 @@
|
||||||
return testableVideoElement.canPlayType('video/webm').replace(/no/, '');
|
return testableVideoElement.canPlayType('video/webm').replace(/no/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPositionSliderChange() {
|
self.canAutoPlayAudio = function () {
|
||||||
|
|
||||||
self.isPositionSliderActive = false;
|
if ($.browser.android || ($.browser.webkit && !$.browser.chrome)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var newPercent = parseInt(this.value);
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
var newPositionTicks = (newPercent / 100) * currentMediaSource.RunTimeTicks;
|
function getAudioElement() {
|
||||||
|
|
||||||
self.changeStream(Math.floor(newPositionTicks));
|
var elem = $('.mediaPlayerAudio');
|
||||||
|
|
||||||
|
if (elem.length) {
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
var requiresControls = !self.canAutoPlayAudio();
|
||||||
|
|
||||||
|
if (requiresControls) {
|
||||||
|
html += '<div class="mediaPlayerAudioContainer"><div class="mediaPlayerAudioContainerInner">';;
|
||||||
|
} else {
|
||||||
|
html += '<div class="mediaPlayerAudioContainer" style="display:none;"><div class="mediaPlayerAudioContainerInner">';;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<audio class="mediaPlayerAudio" controls>';
|
||||||
|
html += '</audio></div></div>';
|
||||||
|
|
||||||
|
$(document.body).append(html);
|
||||||
|
|
||||||
|
return $('.mediaPlayerAudio');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var supportsAac = document.createElement('audio').canPlayType('audio/aac').replace(/no/, '');
|
||||||
function playAudio(item, mediaSource, startPositionTicks) {
|
function playAudio(item, mediaSource, startPositionTicks) {
|
||||||
|
|
||||||
startPositionTicks = startPositionTicks || 0;
|
startPositionTicks = startPositionTicks || 0;
|
||||||
|
@ -999,130 +1168,70 @@
|
||||||
mediaSourceId: mediaSource.Id
|
mediaSourceId: mediaSource.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
var mp3Url = ApiClient.getUrl('Audio/' + item.Id + '/stream.mp3', $.extend({}, baseParams, {
|
var sourceContainer = (mediaSource.Container || '').toLowerCase();
|
||||||
audioCodec: 'mp3'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var aacUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.aac', $.extend({}, baseParams, {
|
|
||||||
audioCodec: 'aac'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var webmUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.webm', $.extend({}, baseParams, {
|
|
||||||
audioCodec: 'Vorbis'
|
|
||||||
}));
|
|
||||||
|
|
||||||
var mediaStreams = mediaSource.MediaStreams;
|
|
||||||
|
|
||||||
var isStatic = false;
|
var isStatic = false;
|
||||||
var seekParam = isStatic && startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : '';
|
|
||||||
|
|
||||||
for (var i = 0, length = mediaStreams.length; i < length; i++) {
|
if (sourceContainer == 'mp3' ||
|
||||||
|
(sourceContainer == 'aac' && supportsAac)) {
|
||||||
|
|
||||||
var stream = mediaStreams[i];
|
for (var i = 0, length = mediaSource.MediaStreams.length; i < length; i++) {
|
||||||
|
|
||||||
if (stream.Type == "Audio") {
|
var stream = mediaSource.MediaStreams[i];
|
||||||
|
|
||||||
var container = (mediaSource.Container || '').toLowerCase();
|
if (stream.Type == "Audio") {
|
||||||
// Stream statically when possible
|
|
||||||
if (container == 'aac' && stream.BitRate <= 256000) {
|
// Stream statically when possible
|
||||||
aacUrl += "&static=true" + seekParam;
|
if (stream.BitRate <= 256000) {
|
||||||
isStatic = true;
|
isStatic = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (container == 'mp3' && stream.BitRate <= 256000) {
|
|
||||||
mp3Url += "&static=true" + seekParam;
|
|
||||||
isStatic = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var outputContainer = isStatic ? sourceContainer : 'mp3';
|
||||||
|
var audioUrl = ApiClient.getUrl('Audio/' + item.Id + '/stream.' + outputContainer, $.extend({}, baseParams, {
|
||||||
|
audioCodec: outputContainer
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (isStatic) {
|
||||||
|
var seekParam = startPositionTicks ? '#t=' + (startPositionTicks / 10000000) : '';
|
||||||
|
audioUrl += "&static=true" + seekParam;
|
||||||
|
}
|
||||||
|
|
||||||
self.startTimeTicksOffset = isStatic ? 0 : startPositionTicks;
|
self.startTimeTicksOffset = isStatic ? 0 : startPositionTicks;
|
||||||
|
|
||||||
var html = '';
|
var initialVolume = self.getSavedVolume();
|
||||||
|
|
||||||
var requiresControls = $.browser.android || ($.browser.webkit && !$.browser.chrome);
|
return getAudioElement().each(function () {
|
||||||
|
|
||||||
// Can't autoplay in these browsers so we need to use the full controls
|
this.src = audioUrl;
|
||||||
if (requiresControls) {
|
|
||||||
html += '<audio preload="auto" autoplay controls>';
|
|
||||||
} else {
|
|
||||||
html += '<audio preload="auto" style="display:none;" autoplay>';
|
|
||||||
}
|
|
||||||
html += '<source type="audio/mpeg" src="' + mp3Url + '" />';
|
|
||||||
html += '<source type="audio/aac" src="' + aacUrl + '" />';
|
|
||||||
html += '<source type="audio/webm" src="' + webmUrl + '" />';
|
|
||||||
html += '</audio>';
|
|
||||||
|
|
||||||
var nowPlayingBar = $('#nowPlayingBar').show();
|
|
||||||
//show stop button
|
|
||||||
$('#stopButton', nowPlayingBar).show();
|
|
||||||
$('#playButton', nowPlayingBar).hide();
|
|
||||||
$('#pauseButton', nowPlayingBar).show();
|
|
||||||
$('#fullscreenButton', nowPlayingBar).hide();
|
|
||||||
|
|
||||||
$('#previousTrackButton', nowPlayingBar).show();
|
|
||||||
$('#nextTrackButton', nowPlayingBar).show();
|
|
||||||
$('#playlistButton', nowPlayingBar).show();
|
|
||||||
|
|
||||||
$('#qualityButton', nowPlayingBar).hide();
|
|
||||||
$('#audioTracksButton', nowPlayingBar).hide();
|
|
||||||
$('#subtitleButton', nowPlayingBar).hide();
|
|
||||||
$('#chaptersButton', nowPlayingBar).hide();
|
|
||||||
|
|
||||||
var mediaElement = $('#mediaElement', nowPlayingBar).html(html);
|
|
||||||
var audioElement = $("audio", mediaElement);
|
|
||||||
|
|
||||||
var initialVolume = localStorage.getItem("volume") || 0.5;
|
|
||||||
|
|
||||||
audioElement.each(function () {
|
|
||||||
this.volume = initialVolume;
|
this.volume = initialVolume;
|
||||||
});
|
this.play();
|
||||||
|
|
||||||
self.volumeSlider.val(initialVolume).slider('refresh');
|
}).on("volumechange", function () {
|
||||||
self.updateVolumeButtons(initialVolume);
|
|
||||||
|
|
||||||
audioElement.on("volumechange", function () {
|
self.onVolumeChanged(this);
|
||||||
|
|
||||||
var vol = this.volume;
|
}).one("playing", function () {
|
||||||
|
|
||||||
localStorage.setItem("volume", vol);
|
$('.mediaPlayerAudioContainer').hide();
|
||||||
|
|
||||||
self.updateVolumeButtons(vol);
|
self.onPlaybackStart(this, item, mediaSource);
|
||||||
|
|
||||||
}).on("play.once", function () {
|
|
||||||
|
|
||||||
if (!requiresControls) {
|
|
||||||
audioElement.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.updateCanClientSeek(this);
|
|
||||||
|
|
||||||
audioElement.off("play.once");
|
|
||||||
|
|
||||||
ApiClient.reportPlaybackStart(Dashboard.getCurrentUserId(), item.Id, mediaSource.Id, true, item.MediaType);
|
|
||||||
|
|
||||||
self.startProgressInterval(item.Id, mediaSource.Id);
|
|
||||||
|
|
||||||
}).on("pause", function () {
|
}).on("pause", function () {
|
||||||
|
|
||||||
$('#playButton', nowPlayingBar).show();
|
self.onPlaystateChange(this);
|
||||||
$('#pauseButton', nowPlayingBar).hide();
|
|
||||||
|
|
||||||
}).on("playing", function () {
|
}).on("playing", function () {
|
||||||
|
|
||||||
$('#playButton', nowPlayingBar).hide();
|
self.onPlaystateChange(this);
|
||||||
$('#pauseButton', nowPlayingBar).show();
|
|
||||||
|
|
||||||
}).on("timeupdate", function () {
|
}).on("timeupdate", function () {
|
||||||
|
|
||||||
if (!self.isPositionSliderActive) {
|
self.setCurrentTime(self.getCurrentTicks(this));
|
||||||
|
|
||||||
self.setCurrentTime(self.getCurrentTicks(this), item, true);
|
}).on("ended.playbackstopped", self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded)[0];
|
||||||
}
|
|
||||||
|
|
||||||
}).on("ended.playbackstopped", self.onPlaybackStopped).on('ended.playnext', self.playNextAfterEnded);
|
|
||||||
|
|
||||||
return audioElement[0];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function canPlayAudioStreamDirect(audioStream) {
|
function canPlayAudioStreamDirect(audioStream) {
|
||||||
|
@ -1146,27 +1255,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
function trunc(string, len) {
|
|
||||||
if (string.length > 0 && string.length < len) return string;
|
|
||||||
var trimmed = $.trim(string).substring(0, len).split(" ").slice(0, -1).join(" ");
|
|
||||||
if (trimmed) {
|
|
||||||
trimmed += "...";
|
|
||||||
} else {
|
|
||||||
trimmed = "---"
|
|
||||||
}
|
|
||||||
return trimmed;
|
|
||||||
};
|
|
||||||
|
|
||||||
function trimTitle(title) {
|
|
||||||
return title.replace("\n---", "");
|
|
||||||
};
|
|
||||||
|
|
||||||
function titleHtml(title) {
|
|
||||||
var titles = title.split("\n");
|
|
||||||
return (trunc(titles[0], 30) + "<br />" + trunc(titles[1], 30)).replace("---", " ");
|
|
||||||
};
|
|
||||||
|
|
||||||
var getItemFields = "MediaSources,Chapters";
|
var getItemFields = "MediaSources,Chapters";
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
shape: "portrait",
|
shape: "portrait",
|
||||||
context: 'movies',
|
context: 'movies',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
centerText: true
|
centerText: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
context: 'movies',
|
context: 'movies',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showItemCounts: true,
|
showItemCounts: true,
|
||||||
coverImage: true
|
coverImage: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
|
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
shape: "backdrop",
|
shape: "backdrop",
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
context: 'movies',
|
context: 'movies',
|
||||||
selectionPanel: true
|
selectionPanel: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,8 @@
|
||||||
items: result.Items,
|
items: result.Items,
|
||||||
shape: "banner",
|
shape: "banner",
|
||||||
preferBanner: true,
|
preferBanner: true,
|
||||||
context: 'movies'
|
context: 'movies',
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,8 @@
|
||||||
context: 'movies',
|
context: 'movies',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
centerText: true,
|
centerText: true,
|
||||||
selectionPanel: true
|
selectionPanel: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
@ -68,7 +71,8 @@
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
timeline: true,
|
timeline: true,
|
||||||
centerText: true,
|
centerText: true,
|
||||||
selectionPanel: true
|
selectionPanel: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
context: 'music',
|
context: 'music',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
coverImage: true,
|
coverImage: true,
|
||||||
centerText: true
|
centerText: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
shape: "square",
|
shape: "square",
|
||||||
context: 'music',
|
context: 'music',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showParentTitle: true
|
showParentTitle: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,8 @@
|
||||||
context: 'music',
|
context: 'music',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showParentTitle: true,
|
showParentTitle: true,
|
||||||
timeline: true
|
timeline: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@
|
||||||
context: 'music',
|
context: 'music',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
coverImage: true,
|
coverImage: true,
|
||||||
centerText: true
|
centerText: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||||
|
|
|
@ -32,7 +32,8 @@
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
context: 'music',
|
context: 'music',
|
||||||
showItemCounts: true,
|
showItemCounts: true,
|
||||||
centerText: true
|
centerText: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount);
|
||||||
|
@ -55,8 +56,8 @@
|
||||||
reloadItems(page);
|
reloadItems(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
LibraryBrowser.saveQueryValues('musicgenres', query);
|
LibraryBrowser.saveQueryValues('musicgenres', query);
|
||||||
|
|
||||||
Dashboard.hideLoadingMsg();
|
Dashboard.hideLoadingMsg();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
396
dashboard-ui/scripts/nowplayingbar.js
Normal file
396
dashboard-ui/scripts/nowplayingbar.js
Normal file
|
@ -0,0 +1,396 @@
|
||||||
|
(function (window, document, $, setTimeout, clearTimeout) {
|
||||||
|
|
||||||
|
var currentPlayer;
|
||||||
|
|
||||||
|
var currentTimeElement;
|
||||||
|
var nowPlayingImageElement;
|
||||||
|
var nowPlayingTextElement;
|
||||||
|
var unmuteButton;
|
||||||
|
var muteButton;
|
||||||
|
var volumeSlider;
|
||||||
|
var isVolumeSliderActive;
|
||||||
|
var unpauseButton;
|
||||||
|
var pauseButton;
|
||||||
|
var positionSlider;
|
||||||
|
var isPositionSliderActive;
|
||||||
|
|
||||||
|
var lastPlayerState;
|
||||||
|
|
||||||
|
function getNowPlayingBarHtml() {
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
html += '<div id="nowPlayingBar" class="nowPlayingBar" style="display:none;">';
|
||||||
|
html += '<div style="display:inline-block;width:12px;"></div>';
|
||||||
|
html += '<a id="playlistButton" class="mediaButton playlistButton" href="playlist.html" data-role="button" data-icon="bullets" data-iconpos="notext" data-inline="true" title="Playlist">Playlist</a>';
|
||||||
|
html += '<button id="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
||||||
|
html += '<button id="playButton" class="mediaButton unpauseButton" title="Play" type="button" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
||||||
|
html += '<button id="pauseButton" class="mediaButton pauseButton" title="Pause" type="button" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
||||||
|
|
||||||
|
html += '<button id="stopButton" class="mediaButton stopButton" title="Stop" type="button" data-icon="stop" data-iconpos="notext" data-inline="true">Stop</button>';
|
||||||
|
html += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
||||||
|
|
||||||
|
html += '<div id="mediaElement"></div>';
|
||||||
|
|
||||||
|
html += '<div class="positionSliderContainer sliderContainer">';
|
||||||
|
html += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="currentTime"></div>';
|
||||||
|
html += '<div class="nowPlayingImage"></div>';
|
||||||
|
html += '<div class="nowPlayingText"></div>';
|
||||||
|
|
||||||
|
html += '<button id="muteButton" class="mediaButton muteButton" title="Mute" type="button" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
||||||
|
html += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
||||||
|
|
||||||
|
html += '<div class="volumeSliderContainer sliderContainer">';
|
||||||
|
html += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindEvents(elem) {
|
||||||
|
|
||||||
|
currentTimeElement = $('.currentTime', elem);
|
||||||
|
nowPlayingImageElement = $('.nowPlayingImage', elem);
|
||||||
|
nowPlayingTextElement = $('.nowPlayingText', elem);
|
||||||
|
|
||||||
|
unmuteButton = $('.unmuteButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.unMute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
muteButton = $('.muteButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.mute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.stopButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pauseButton = $('.pauseButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.pause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
unpauseButton = $('.unpauseButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.unpause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.nextTrackButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.nextTrack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.previousTrackButton', elem).on('click', function () {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.previousTrack();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
volumeSlider = $('.volumeSlider', elem).on('slidestart', function () {
|
||||||
|
|
||||||
|
isVolumeSliderActive = true;
|
||||||
|
|
||||||
|
}).on('slidestop', function () {
|
||||||
|
|
||||||
|
isVolumeSliderActive = false;
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
currentPlayer.setVolume(this.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
positionSlider = $('.positionSlider', elem).on('slidestart', function () {
|
||||||
|
|
||||||
|
isPositionSliderActive = true;
|
||||||
|
|
||||||
|
}).on('slidestop', function () {
|
||||||
|
|
||||||
|
isPositionSliderActive = false;
|
||||||
|
|
||||||
|
if (currentPlayer && lastPlayerState) {
|
||||||
|
|
||||||
|
var newPercent = parseFloat(this.value);
|
||||||
|
var newPositionTicks = (newPercent / 100) * lastPlayerState.runtimeTicks;
|
||||||
|
currentPlayer.seek(Math.floor(newPositionTicks));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNowPlayingBar() {
|
||||||
|
|
||||||
|
var elem = $('.nowPlayingBar');
|
||||||
|
|
||||||
|
if (elem.length) {
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
elem = $(getNowPlayingBarHtml()).insertBefore('#footerNotifications').trigger('create');
|
||||||
|
|
||||||
|
bindEvents(elem);
|
||||||
|
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePlayerState(state) {
|
||||||
|
|
||||||
|
if (state.itemName) {
|
||||||
|
showNowPlayingBar();
|
||||||
|
} else {
|
||||||
|
hideNowPlayingBar();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPlayerState = state;
|
||||||
|
|
||||||
|
if (!muteButton) {
|
||||||
|
getNowPlayingBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerInfo = MediaController.getPlayerInfo();
|
||||||
|
|
||||||
|
var supportedCommands = playerInfo.supportedCommands;
|
||||||
|
|
||||||
|
if (supportedCommands.indexOf('SetVolume') == -1) {
|
||||||
|
volumeSlider.prop('disabled', 'disabled');
|
||||||
|
} else {
|
||||||
|
volumeSlider.prop('disabled', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportedCommands.indexOf('Mute') == -1) {
|
||||||
|
muteButton.prop('disabled', 'disabled');
|
||||||
|
} else {
|
||||||
|
muteButton.prop('disabled', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportedCommands.indexOf('Unmute') == -1) {
|
||||||
|
unmuteButton.prop('disabled', 'disabled');
|
||||||
|
} else {
|
||||||
|
unmuteButton.prop('disabled', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.isMuted) {
|
||||||
|
|
||||||
|
muteButton.hide();
|
||||||
|
unmuteButton.show();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
muteButton.show();
|
||||||
|
unmuteButton.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state.isPaused) {
|
||||||
|
|
||||||
|
pauseButton.hide();
|
||||||
|
unpauseButton.show();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
pauseButton.show();
|
||||||
|
unpauseButton.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVolumeSliderActive) {
|
||||||
|
volumeSlider.val(state.volumeLevel || 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
volumeSlider.slider('refresh');
|
||||||
|
|
||||||
|
if (!isPositionSliderActive) {
|
||||||
|
if (state.canSeek) {
|
||||||
|
|
||||||
|
var pct = state.positionTicks / state.runtimeTicks;
|
||||||
|
pct *= 100;
|
||||||
|
|
||||||
|
positionSlider.val(pct).prop('disabled', '');
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
positionSlider.val(0).prop('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
positionSlider.slider('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
var timeText = Dashboard.getDisplayTime(state.positionTicks);
|
||||||
|
|
||||||
|
if (state.runtimeTicks) {
|
||||||
|
|
||||||
|
timeText += " / " + Dashboard.getDisplayTime(state.runtimeTicks);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTimeElement.html(timeText);
|
||||||
|
|
||||||
|
updateNowPlayingInfo(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentImgUrl;
|
||||||
|
function updateNowPlayingInfo(state) {
|
||||||
|
|
||||||
|
var nameHtml = MediaPlayer.getNowPlayingNameHtml(state);
|
||||||
|
|
||||||
|
if (nameHtml.indexOf('<br/>') != -1) {
|
||||||
|
nowPlayingTextElement.addClass('nowPlayingDoubleText');
|
||||||
|
} else {
|
||||||
|
nowPlayingTextElement.removeClass('nowPlayingDoubleText');
|
||||||
|
}
|
||||||
|
|
||||||
|
nowPlayingTextElement.html(nameHtml);
|
||||||
|
|
||||||
|
var url;
|
||||||
|
|
||||||
|
if (state.primaryImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.primaryImageItemId, {
|
||||||
|
type: "Primary",
|
||||||
|
height: 80,
|
||||||
|
tag: state.primaryImageTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (state.backdropImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.backdropItemId, {
|
||||||
|
type: "Backdrop",
|
||||||
|
height: 80,
|
||||||
|
tag: state.backdropImageTag,
|
||||||
|
index: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
} else if (state.thumbImageTag) {
|
||||||
|
|
||||||
|
url = ApiClient.getImageUrl(state.thumbImageItemId, {
|
||||||
|
type: "Thumb",
|
||||||
|
height: 80,
|
||||||
|
tag: state.thumbImageTag
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (state.itemType == "TvChannel" || state.itemType == "Recording") {
|
||||||
|
url = "css/images/items/detail/tv.png";
|
||||||
|
}
|
||||||
|
else if (state.mediaType == "Audio") {
|
||||||
|
url = "css/images/items/detail/audio.png";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
url = "css/images/items/detail/video.png";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url == currentImgUrl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentImgUrl = url;
|
||||||
|
|
||||||
|
nowPlayingImageElement.html('<img src="' + url + '" />');
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPlaybackStart(e, state) {
|
||||||
|
|
||||||
|
var player = this;
|
||||||
|
|
||||||
|
player.beginPlayerUpdates();
|
||||||
|
|
||||||
|
onStateChanged.call(player, e, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showNowPlayingBar() {
|
||||||
|
|
||||||
|
var nowPlayingBar = getNowPlayingBar();
|
||||||
|
|
||||||
|
nowPlayingBar.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideNowPlayingBar() {
|
||||||
|
|
||||||
|
// Use a timeout to prevent the bar from hiding and showing quickly
|
||||||
|
// in the event of a stop->play command
|
||||||
|
getNowPlayingBar().hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPlaybackStopped(e, state) {
|
||||||
|
|
||||||
|
var player = this;
|
||||||
|
|
||||||
|
player.endPlayerUpdates();
|
||||||
|
|
||||||
|
hideNowPlayingBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStateChanged(e, state) {
|
||||||
|
|
||||||
|
var player = this;
|
||||||
|
|
||||||
|
if (player.isDefaultPlayer && state.mediaType == 'Video') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePlayerState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
function releaseCurrentPlayer() {
|
||||||
|
|
||||||
|
if (currentPlayer) {
|
||||||
|
|
||||||
|
$(currentPlayer).off('.nowplayingbar');
|
||||||
|
currentPlayer.endPlayerUpdates();
|
||||||
|
currentPlayer = null;
|
||||||
|
|
||||||
|
hideNowPlayingBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bindToPlayer(player) {
|
||||||
|
|
||||||
|
releaseCurrentPlayer();
|
||||||
|
|
||||||
|
currentPlayer = player;
|
||||||
|
|
||||||
|
player.getPlayerState().done(function (state) {
|
||||||
|
|
||||||
|
if (state.itemName) {
|
||||||
|
player.beginPlayerUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
onStateChanged.call(player, null, state);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(player).on('playbackstart.nowplayingbar', onPlaybackStart)
|
||||||
|
.on('playbackstop.nowplayingbar', onPlaybackStopped)
|
||||||
|
.on('volumechange.nowplayingbar', onStateChanged)
|
||||||
|
.on('playstatechange.nowplayingbar', onStateChanged)
|
||||||
|
.on('positionchange.nowplayingbar', onStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
|
||||||
|
$(MediaController).on('playerchange', function () {
|
||||||
|
|
||||||
|
bindToPlayer(MediaController.getCurrentPlayer());
|
||||||
|
});
|
||||||
|
|
||||||
|
bindToPlayer(MediaController.getCurrentPlayer());
|
||||||
|
});
|
||||||
|
|
||||||
|
})(window, document, jQuery, setTimeout, clearTimeout);
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
html += '<tbody>';
|
html += '<tbody>';
|
||||||
|
|
||||||
$.each(MediaPlayer.playlist, function (i, item) {
|
$.each(MediaController.playlist, function (i, item) {
|
||||||
|
|
||||||
var name = LibraryBrowser.getPosterViewDisplayName(item);
|
var name = LibraryBrowser.getPosterViewDisplayName(item);
|
||||||
|
|
||||||
|
@ -65,14 +65,14 @@
|
||||||
|
|
||||||
var index = parseInt(this.getAttribute('data-index'));
|
var index = parseInt(this.getAttribute('data-index'));
|
||||||
|
|
||||||
MediaPlayer.currentPlaylistIndex(index);
|
MediaController.currentPlaylistIndex(index);
|
||||||
reloadPlaylist(page);
|
reloadPlaylist(page);
|
||||||
|
|
||||||
}).on('click', '.lnkRemove', function () {
|
}).on('click', '.lnkRemove', function () {
|
||||||
|
|
||||||
var index = parseInt(this.getAttribute('data-index'));
|
var index = parseInt(this.getAttribute('data-index'));
|
||||||
|
|
||||||
MediaPlayer.removeFromPlaylist(index);
|
MediaController.removeFromPlaylist(index);
|
||||||
reloadPlaylist(page);
|
reloadPlaylist(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
var page = this;
|
var page = this;
|
||||||
|
|
||||||
reloadPlaylist(page);
|
//reloadPlaylist(page);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -96,14 +96,14 @@
|
||||||
|
|
||||||
var id = $('#selectSession', popup).val();
|
var id = $('#selectSession', popup).val();
|
||||||
|
|
||||||
ApiClient.sendSystemCommand(id, 'GoHome');
|
ApiClient.sendCommand(id, 'GoHome');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.btnGoToSettings', popup).on('click', function () {
|
$('.btnGoToSettings', popup).on('click', function () {
|
||||||
|
|
||||||
var id = $('#selectSession', popup).val();
|
var id = $('#selectSession', popup).val();
|
||||||
|
|
||||||
ApiClient.sendSystemCommand(id, 'GoToSettings');
|
ApiClient.sendCommand(id, 'GoToSettings');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.btnSendMessage', popup).on('click', function () {
|
$('.btnSendMessage', popup).on('click', function () {
|
||||||
|
@ -129,21 +129,21 @@
|
||||||
|
|
||||||
var id = $('#selectSession', popup).val();
|
var id = $('#selectSession', popup).val();
|
||||||
|
|
||||||
ApiClient.sendSystemCommand(id, 'VolumeDown');
|
ApiClient.sendCommand(id, 'VolumeDown');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.btnVolumeUp', popup).on('click', function () {
|
$('.btnVolumeUp', popup).on('click', function () {
|
||||||
|
|
||||||
var id = $('#selectSession', popup).val();
|
var id = $('#selectSession', popup).val();
|
||||||
|
|
||||||
ApiClient.sendSystemCommand(id, 'VolumeUp');
|
ApiClient.sendCommand(id, 'VolumeUp');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.btnToggleMute', popup).on('click', function () {
|
$('.btnToggleMute', popup).on('click', function () {
|
||||||
|
|
||||||
var id = $('#selectSession', popup).val();
|
var id = $('#selectSession', popup).val();
|
||||||
|
|
||||||
ApiClient.sendSystemCommand(id, 'ToggleMute');
|
ApiClient.sendCommand(id, 'ToggleMute');
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.btnStop', popup).on('click', function () {
|
$('.btnStop', popup).on('click', function () {
|
||||||
|
@ -432,6 +432,20 @@
|
||||||
ApiClient.sendPlayCommand(sessionId, remoteOptions);
|
ApiClient.sendPlayCommand(sessionId, remoteOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendPlayStateCommand(command, options) {
|
||||||
|
|
||||||
|
var sessionId = MediaController.getPlayerInfo().id;
|
||||||
|
|
||||||
|
ApiClient.sendPlayStateCommand(sessionId, command, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendCommand(command, options) {
|
||||||
|
|
||||||
|
var sessionId = MediaController.getPlayerInfo().id;
|
||||||
|
|
||||||
|
ApiClient.sendCommand(sessionId, command, options);
|
||||||
|
}
|
||||||
|
|
||||||
function remoteControlPlayer() {
|
function remoteControlPlayer() {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -469,19 +483,126 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
self.stop = function () {
|
self.stop = function () {
|
||||||
|
sendPlayStateCommand('stop');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.nextTrack = function () {
|
||||||
|
sendPlayStateCommand('nextTrack');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.previousTrack = function () {
|
||||||
|
sendPlayStateCommand('previousTrack');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.seek = function (positionTicks) {
|
||||||
|
sendPlayStateCommand('seek',
|
||||||
|
{
|
||||||
|
SeekPositionTicks: positionTicks
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.pause = function () {
|
||||||
|
sendPlayStateCommand('Pause');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.unpause = function () {
|
||||||
|
sendPlayStateCommand('Unpause');
|
||||||
};
|
};
|
||||||
|
|
||||||
self.mute = function () {
|
self.mute = function () {
|
||||||
|
sendCommand('Mute');
|
||||||
};
|
};
|
||||||
|
|
||||||
self.unMute = function () {
|
self.unMute = function () {
|
||||||
|
sendCommand('Unmnute');
|
||||||
};
|
};
|
||||||
|
|
||||||
self.toggleMute = function () {
|
self.toggleMute = function () {
|
||||||
|
sendCommand('ToggleMute');
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setVolume = function (vol) {
|
||||||
|
sendCommand('SetVolume', {
|
||||||
|
|
||||||
|
Volume: vol
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.displayContent = function (options) {
|
||||||
|
|
||||||
|
sendCommand('DisplayContent', {
|
||||||
|
|
||||||
|
ItemName: options.itemName,
|
||||||
|
ItemType: options.itemType,
|
||||||
|
ItemId: options.itemId,
|
||||||
|
Context: options.context
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getPlayerState = function () {
|
||||||
|
|
||||||
|
var deferred = $.Deferred();
|
||||||
|
|
||||||
|
ApiClient.getSessions().done(function (sessions) {
|
||||||
|
|
||||||
|
var currentTargetId = MediaController.getPlayerInfo().id;
|
||||||
|
|
||||||
|
// Update existing data
|
||||||
|
//updateSessionInfo(popup, msg.Data);
|
||||||
|
var session = sessions.filter(function (s) {
|
||||||
|
return s.Id == currentTargetId;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
session = getPlayerState(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
deferred.resolveWith(null, [session]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise();
|
||||||
|
};
|
||||||
|
|
||||||
|
function subscribeToPlayerUpdates() {
|
||||||
|
|
||||||
|
if (ApiClient.isWebSocketOpen()) {
|
||||||
|
|
||||||
|
ApiClient.sendWebSocketMessage("SessionsStart", "100,700");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unsubscribeFromPlayerUpdates() {
|
||||||
|
|
||||||
|
if (ApiClient.isWebSocketOpen()) {
|
||||||
|
|
||||||
|
ApiClient.sendWebSocketMessage("SessionsStop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var playerListenerCount = 0;
|
||||||
|
self.beginPlayerUpdates = function () {
|
||||||
|
|
||||||
|
if (playerListenerCount <= 0) {
|
||||||
|
|
||||||
|
playerListenerCount = 0;
|
||||||
|
|
||||||
|
subscribeToPlayerUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
|
playerListenerCount++;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.endPlayerUpdates = function () {
|
||||||
|
|
||||||
|
playerListenerCount--;
|
||||||
|
|
||||||
|
if (playerListenerCount <= 0) {
|
||||||
|
|
||||||
|
unsubscribeFromPlayerUpdates();
|
||||||
|
playerListenerCount = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.getTargets = function () {
|
self.getTargets = function () {
|
||||||
|
@ -506,7 +627,8 @@
|
||||||
playerName: self.name,
|
playerName: self.name,
|
||||||
appName: s.Client,
|
appName: s.Client,
|
||||||
playableMediaTypes: s.PlayableMediaTypes,
|
playableMediaTypes: s.PlayableMediaTypes,
|
||||||
isLocalPlayer: false
|
isLocalPlayer: false,
|
||||||
|
supportedCommands: s.SupportedCommands
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -521,11 +643,75 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MediaController.registerPlayer(new remoteControlPlayer());
|
var player = new remoteControlPlayer();
|
||||||
|
|
||||||
|
MediaController.registerPlayer(player);
|
||||||
|
|
||||||
|
function getPlayerState(session) {
|
||||||
|
|
||||||
|
var state = {
|
||||||
|
volumeLevel: session.VolumeLevel,
|
||||||
|
isMuted: session.IsMuted,
|
||||||
|
isPaused: session.IsPaused,
|
||||||
|
canSeek: session.CanSeek
|
||||||
|
};
|
||||||
|
|
||||||
|
var item = session.NowPlayingItem;
|
||||||
|
|
||||||
|
if (item) {
|
||||||
|
|
||||||
|
state.itemId = item.Id;
|
||||||
|
state.mediaType = item.MediaType;
|
||||||
|
state.itemType = item.Type;
|
||||||
|
state.indexNumber = item.IndexNumber;
|
||||||
|
state.indexNumberEnd = item.IndexNumberEnd;
|
||||||
|
state.parentIndexNumber = item.ParentIndexNumber;
|
||||||
|
state.productionYear = item.ProductionYear;
|
||||||
|
state.premiereDate = item.PremiereDate;
|
||||||
|
state.seriesName = item.SeriesName;
|
||||||
|
state.album = item.Album;
|
||||||
|
state.itemName = item.Name;
|
||||||
|
state.artists = item.Artists;
|
||||||
|
|
||||||
|
state.primaryImageItemId = item.PrimaryImageItemId;
|
||||||
|
state.primaryImageTag = item.PrimaryImageTag;
|
||||||
|
|
||||||
|
state.backdropItemId = item.BackdropItemId;
|
||||||
|
state.backdropImageTag = item.BackdropImageTag;
|
||||||
|
|
||||||
|
state.thumbItemId = item.ThumbItemId;
|
||||||
|
state.thumbImageTag = item.ThumbImageTag;
|
||||||
|
|
||||||
|
state.mediaSource = item.MediaSourceId;
|
||||||
|
state.positionTicks = session.NowPlayingPositionTicks || 0;
|
||||||
|
state.runtimeTicks = item.RunTimeTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function firePlaybackEvent(name, session) {
|
||||||
|
|
||||||
|
$(player).trigger(name, [getPlayerState(session)]);
|
||||||
|
}
|
||||||
|
|
||||||
function onWebSocketMessageReceived(e, msg) {
|
function onWebSocketMessageReceived(e, msg) {
|
||||||
|
|
||||||
if (msg.MessageType === "SessionEnded") {
|
if (msg.MessageType === "Sessions") {
|
||||||
|
|
||||||
|
var currentTargetId = MediaController.getPlayerInfo().id;
|
||||||
|
|
||||||
|
// Update existing data
|
||||||
|
//updateSessionInfo(popup, msg.Data);
|
||||||
|
var session = msg.Data.filter(function (s) {
|
||||||
|
return s.Id == currentTargetId;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
firePlaybackEvent('playstatechange', session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg.MessageType === "SessionEnded") {
|
||||||
|
|
||||||
console.log("Server reports another session ended");
|
console.log("Server reports another session ended");
|
||||||
|
|
||||||
|
@ -533,6 +719,12 @@
|
||||||
MediaController.setDefaultPlayerActive();
|
MediaController.setDefaultPlayerActive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (msg.MessageType === "PlaybackStart") {
|
||||||
|
firePlaybackEvent('playbackstart', msg.Data);
|
||||||
|
}
|
||||||
|
else if (msg.MessageType === "PlaybackStopped") {
|
||||||
|
firePlaybackEvent('playbackstop', msg.Data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$(ApiClient).on("websocketmessage", onWebSocketMessageReceived);
|
$(ApiClient).on("websocketmessage", onWebSocketMessageReceived);
|
||||||
|
|
|
@ -263,6 +263,8 @@ var Dashboard = {
|
||||||
|
|
||||||
var html = '<span style="margin-right: 1em;">Please refresh this page to receive new updates from the server.</span>';
|
var html = '<span style="margin-right: 1em;">Please refresh this page to receive new updates from the server.</span>';
|
||||||
|
|
||||||
|
html += '<button type="button" data-icon="refresh" onclick="$(this).buttonEnabled(false);Dashboard.reloadPage();" data-theme="b" data-inline="true" data-mini="true">Refresh</button>';
|
||||||
|
|
||||||
Dashboard.showFooterNotification({ id: "dashboardVersionWarning", html: html, forceShow: true, allowHide: false });
|
Dashboard.showFooterNotification({ id: "dashboardVersionWarning", html: html, forceShow: true, allowHide: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -475,14 +477,14 @@ var Dashboard = {
|
||||||
|
|
||||||
Dashboard.getCurrentUser().done(function (user) {
|
Dashboard.getCurrentUser().done(function (user) {
|
||||||
|
|
||||||
var html = '<div data-role="panel" data-position="right" data-display="overlay" id="userFlyout" data-position-fixed="true" data-theme="a">';
|
var html = '<div data-role="panel" data-position="right" data-display="overlay" id="userFlyout" data-position-fixed="true" data-theme="b">';
|
||||||
|
|
||||||
html += '<h3>';
|
html += '<h3>';
|
||||||
|
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
||||||
|
|
||||||
width: 60,
|
width: 28,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
|
|
||||||
|
@ -490,21 +492,27 @@ var Dashboard = {
|
||||||
|
|
||||||
html += '<img style="max-width:28px;vertical-align:middle;margin-right:5px;" src="' + imageUrl + '" />';
|
html += '<img style="max-width:28px;vertical-align:middle;margin-right:5px;" src="' + imageUrl + '" />';
|
||||||
}
|
}
|
||||||
|
|
||||||
html += user.Name;
|
html += user.Name;
|
||||||
html += '</h3>';
|
html += '</h3>';
|
||||||
|
|
||||||
|
html += '<form>';
|
||||||
|
|
||||||
|
html += '<p><label for="chkEnableThemeSongs">Play theme songs</label><input onchange="ThemeSongManager.enabled(this.checked);" type="checkbox" id="chkEnableThemeSongs" data-mini="true" /></a>';
|
||||||
|
|
||||||
html += '<p><a data-mini="true" data-role="button" href="useredit.html?userId=' + user.Id + '" data-icon="user">Preferences</button></a>';
|
html += '<p><a data-mini="true" data-role="button" href="useredit.html?userId=' + user.Id + '" data-icon="user">Preferences</button></a>';
|
||||||
html += '<p><button data-mini="true" type="button" onclick="Dashboard.logout();" data-icon="lock">Sign Out</button></p>';
|
html += '<p><button data-mini="true" type="button" onclick="Dashboard.logout();" data-icon="lock">Sign Out</button></p>';
|
||||||
|
|
||||||
|
html += '</form>';
|
||||||
html += '</div>';
|
html += '</div>';
|
||||||
|
|
||||||
$(document.body).append(html);
|
$(document.body).append(html);
|
||||||
|
|
||||||
$('#userFlyout').panel({}).trigger('create').panel("open").on("panelafterclose", function () {
|
var elem = $('#userFlyout').panel({}).trigger('create').panel("open").on("panelafterclose", function () {
|
||||||
|
|
||||||
$(this).off("panelafterclose").remove();
|
$(this).off("panelafterclose").remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#chkEnableThemeSongs', elem).checked(window.ThemeSongManager.enabled()).checkboxradio('refresh');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -589,7 +597,7 @@ var Dashboard = {
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var url = ApiClient.getUserImageUrl(user.Id, {
|
var url = ApiClient.getUserImageUrl(user.Id, {
|
||||||
width: 225,
|
width: 28,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
@ -801,6 +809,16 @@ var Dashboard = {
|
||||||
ApiClient.openWebSocket(webSocketUrl);
|
ApiClient.openWebSocket(webSocketUrl);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onWebSocketOpened: function () {
|
||||||
|
|
||||||
|
ApiClient.reportCapabilities({
|
||||||
|
PlayableMediaTypes: "Audio,Video",
|
||||||
|
|
||||||
|
SupportedCommands: Dashboard.getSupportedRemoteCommands().join(',')
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
onWebSocketMessageReceived: function (e, data) {
|
onWebSocketMessageReceived: function (e, data) {
|
||||||
|
|
||||||
var msg = data;
|
var msg = data;
|
||||||
|
@ -878,10 +896,6 @@ var Dashboard = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (msg.MessageType === "Browse") {
|
|
||||||
|
|
||||||
Dashboard.onBrowseCommand(msg.Data);
|
|
||||||
}
|
|
||||||
else if (msg.MessageType === "GeneralCommand") {
|
else if (msg.MessageType === "GeneralCommand") {
|
||||||
|
|
||||||
var cmd = msg.Data;
|
var cmd = msg.Data;
|
||||||
|
@ -892,6 +906,9 @@ var Dashboard = {
|
||||||
else if (cmd.Name === 'GoToSettings') {
|
else if (cmd.Name === 'GoToSettings') {
|
||||||
Dashboard.navigate('dashboard.html');
|
Dashboard.navigate('dashboard.html');
|
||||||
}
|
}
|
||||||
|
else if (cmd.Name === 'DisplayContent') {
|
||||||
|
Dashboard.onBrowseCommand(cmd.Arguments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (msg.MessageType === "MessageCommand") {
|
else if (msg.MessageType === "MessageCommand") {
|
||||||
|
|
||||||
|
@ -1237,6 +1254,27 @@ var Dashboard = {
|
||||||
}
|
}
|
||||||
|
|
||||||
$(select).html(html).selectmenu("refresh");
|
$(select).html(html).selectmenu("refresh");
|
||||||
|
},
|
||||||
|
|
||||||
|
getSupportedRemoteCommands: function () {
|
||||||
|
|
||||||
|
// Full list
|
||||||
|
// https://github.com/MediaBrowser/MediaBrowser/blob/master/MediaBrowser.Model/Session/GeneralCommand.cs
|
||||||
|
return [
|
||||||
|
"GoHome",
|
||||||
|
"GoToSettings",
|
||||||
|
"VolumeUp",
|
||||||
|
"VolumeDown",
|
||||||
|
"Mute",
|
||||||
|
"Unmute",
|
||||||
|
"ToggleMute",
|
||||||
|
"SetVolume",
|
||||||
|
"ToggleFullscreen",
|
||||||
|
"SetAudioStreamIndex",
|
||||||
|
"SetSubtitleStreamIndex",
|
||||||
|
"DisplayContent"
|
||||||
|
];
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1252,7 +1290,7 @@ else if (!IsStorageEnabled()) {
|
||||||
|
|
||||||
var ApiClient = MediaBrowser.ApiClient.create("Dashboard", window.dashboardVersion);
|
var ApiClient = MediaBrowser.ApiClient.create("Dashboard", window.dashboardVersion);
|
||||||
|
|
||||||
$(ApiClient).on("websocketmessage", Dashboard.onWebSocketMessageReceived);
|
$(ApiClient).on("websocketopen", Dashboard.onWebSocketOpened).on("websocketmessage", Dashboard.onWebSocketMessageReceived);
|
||||||
|
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
@ -1277,7 +1315,6 @@ $(function () {
|
||||||
|
|
||||||
videoPlayerHtml += '<div id="video-basic-controls">';
|
videoPlayerHtml += '<div id="video-basic-controls">';
|
||||||
|
|
||||||
videoPlayerHtml += '<a id="video-playlistButton" class="mediaButton playlistButton" href="playlist.videoPlayerHtml" data-role="button" data-icon="bullets" data-iconpos="notext" data-inline="true" title="Playlist">Playlist</a>';
|
|
||||||
videoPlayerHtml += '<button id="video-previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaPlayer.previousTrack();" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
videoPlayerHtml += '<button id="video-previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaPlayer.previousTrack();" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
||||||
videoPlayerHtml += '<button id="video-playButton" class="mediaButton" title="Play" type="button" onclick="MediaPlayer.unpause();" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
videoPlayerHtml += '<button id="video-playButton" class="mediaButton" title="Play" type="button" onclick="MediaPlayer.unpause();" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
||||||
videoPlayerHtml += '<button id="video-pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaPlayer.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
videoPlayerHtml += '<button id="video-pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaPlayer.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
||||||
|
@ -1286,7 +1323,8 @@ $(function () {
|
||||||
videoPlayerHtml += '<button id="video-nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
videoPlayerHtml += '<button id="video-nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
||||||
|
|
||||||
videoPlayerHtml += '<div class="currentTime"></div>';
|
videoPlayerHtml += '<div class="currentTime"></div>';
|
||||||
videoPlayerHtml += '<div class="nowPlayingMediaInfo"></div>';
|
videoPlayerHtml += '<div class="nowPlayingImage"></div>';
|
||||||
|
videoPlayerHtml += '<div class="nowPlayingText"></div>';
|
||||||
|
|
||||||
videoPlayerHtml += '<button id="video-muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
videoPlayerHtml += '<button id="video-muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
||||||
videoPlayerHtml += '<button id="video-unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
videoPlayerHtml += '<button id="video-unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
||||||
|
@ -1310,7 +1348,7 @@ $(function () {
|
||||||
videoPlayerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="video-chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
|
videoPlayerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="video-chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
|
||||||
videoPlayerHtml += '<div class="mediaFlyoutContainer"><div id="video-chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>';
|
videoPlayerHtml += '<div class="mediaFlyoutContainer"><div id="video-chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>';
|
||||||
|
|
||||||
videoPlayerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="video-fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="action" data-iconpos="notext" data-inline="true">Fullscreen</button>';
|
videoPlayerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="video-fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="expand" data-iconpos="notext" data-inline="true">Fullscreen</button>';
|
||||||
|
|
||||||
videoPlayerHtml += '</div>'; // video-advanced-controls
|
videoPlayerHtml += '</div>'; // video-advanced-controls
|
||||||
|
|
||||||
|
@ -1326,48 +1364,6 @@ $(function () {
|
||||||
mediaPlayerElem.trigger('create');
|
mediaPlayerElem.trigger('create');
|
||||||
|
|
||||||
var footerHtml = '<div id="footer" data-theme="b" class="ui-bar-b">';
|
var footerHtml = '<div id="footer" data-theme="b" class="ui-bar-b">';
|
||||||
footerHtml += '<div id="nowPlayingBar" class="nowPlayingBar" style="display:none;">';
|
|
||||||
footerHtml += '<div class="barBackground ui-bar-b"></div>';
|
|
||||||
footerHtml += '<div style="display:inline-block;width:12px;"></div>';
|
|
||||||
footerHtml += '<a id="playlistButton" class="mediaButton playlistButton" href="playlist.html" data-role="button" data-icon="bullets" data-iconpos="notext" data-inline="true" title="Playlist">Playlist</a>';
|
|
||||||
footerHtml += '<button id="previousTrackButton" class="mediaButton previousTrackButton" title="Previous Track" type="button" onclick="MediaPlayer.previousTrack();" data-icon="previous-track" data-iconpos="notext" data-inline="true">Previous Track</button>';
|
|
||||||
footerHtml += '<button id="playButton" class="mediaButton" title="Play" type="button" onclick="MediaPlayer.unpause();" data-icon="play" data-iconpos="notext" data-inline="true">Play</button>';
|
|
||||||
footerHtml += '<button id="pauseButton" class="mediaButton" title="Pause" type="button" onclick="MediaPlayer.pause();" data-icon="pause" data-iconpos="notext" data-inline="true">Pause</button>';
|
|
||||||
|
|
||||||
footerHtml += '<div id="mediaElement"></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button id="stopButton" class="mediaButton" title="Stop" type="button" onclick="MediaPlayer.stop();" data-icon="stop" data-iconpos="notext" data-inline="true">Stop</button>';
|
|
||||||
footerHtml += '<button id="nextTrackButton" class="mediaButton nextTrackButton" title="Next Track" type="button" onclick="MediaPlayer.nextTrack();" data-icon="next-track" data-iconpos="notext" data-inline="true">Next Track</button>';
|
|
||||||
|
|
||||||
footerHtml += '<div class="positionSliderContainer sliderContainer">';
|
|
||||||
footerHtml += '<input type="range" class="mediaSlider positionSlider slider" step=".001" min="0" max="100" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
footerHtml += '</div>';
|
|
||||||
|
|
||||||
footerHtml += '<div class="currentTime"></div>';
|
|
||||||
footerHtml += '<div class="nowPlayingMediaInfo"></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button id="muteButton" class="mediaButton muteButton" title="Mute" type="button" onclick="MediaPlayer.mute();" data-icon="audio" data-iconpos="notext" data-inline="true">Mute</button>';
|
|
||||||
footerHtml += '<button id="unmuteButton" class="mediaButton unmuteButton" title="Unmute" type="button" onclick="MediaPlayer.unMute();" data-icon="volume-off" data-iconpos="notext" data-inline="true">Unmute</button>';
|
|
||||||
|
|
||||||
footerHtml += '<div class="volumeSliderContainer sliderContainer">';
|
|
||||||
footerHtml += '<input type="range" class="mediaSlider volumeSlider slider" step=".05" min="0" max="1" value="0" style="display:none;" data-mini="true" data-theme="a" data-highlight="true" />';
|
|
||||||
footerHtml += '</div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showQualityFlyout();" id="qualityButton" class="mediaButton qualityButton" title="Quality" type="button" data-icon="gear" data-iconpos="notext" data-inline="true">Quality</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="qualityFlyout" style="display:none;" class="mediaPlayerFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showAudioTracksFlyout();" id="audioTracksButton" class="imageButton mediaButton audioTracksButton" title="Audio tracks" type="button" data-icon="audiocd" data-iconpos="notext" data-inline="true">Audio Tracks</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="audioTracksFlyout" style="display:none;" class="mediaPlayerFlyout audioTracksFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showSubtitleMenu();" id="subtitleButton" class="imageButton mediaButton subtitleButton" title="Subtitles" type="button" data-icon="subtitles" data-iconpos="notext" data-inline="true">Subtitles</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="subtitleFlyout" style="display:none;" class="mediaPlayerFlyout subtitleFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.showChaptersFlyout();" id="chaptersButton" class="mediaButton chaptersButton" title="Scenes" type="button" data-icon="video" data-iconpos="notext" data-inline="true">Scenes</button>';
|
|
||||||
footerHtml += '<div class="mediaFlyoutContainer"><div id="chaptersFlyout" style="display:none;" class="mediaPlayerFlyout chaptersFlyout"></div></div>';
|
|
||||||
|
|
||||||
footerHtml += '<button onclick="MediaPlayer.toggleFullscreen();" id="fullscreenButton" class="mediaButton fullscreenButton" title="Fullscreen" type="button" data-icon="action" data-iconpos="notext" data-inline="true">Fullscreen</button>';
|
|
||||||
|
|
||||||
footerHtml += '</div>';
|
|
||||||
|
|
||||||
footerHtml += '<div id="footerNotifications"></div>';
|
footerHtml += '<div id="footerNotifications"></div>';
|
||||||
footerHtml += '</div>';
|
footerHtml += '</div>';
|
||||||
|
@ -1427,5 +1423,4 @@ $(document).on('pagebeforeshow', ".page", function () {
|
||||||
if (!ApiClient.isWebSocketOpen()) {
|
if (!ApiClient.isWebSocketOpen()) {
|
||||||
Dashboard.refreshSystemInfoFromServer();
|
Dashboard.refreshSystemInfoFromServer();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
html += LibraryBrowser.getSongTableHtml(result.Items, {
|
html += LibraryBrowser.getSongTableHtml(result.Items, {
|
||||||
showAlbum: true,
|
showAlbum: true,
|
||||||
showArtist: true,
|
showArtist: true,
|
||||||
|
showAlbumArtist: true,
|
||||||
enableColumnSorting: true,
|
enableColumnSorting: true,
|
||||||
sortBy: query.SortBy,
|
sortBy: query.SortBy,
|
||||||
sortOrder: query.SortOrder
|
sortOrder: query.SortOrder
|
||||||
|
|
|
@ -1,29 +1,11 @@
|
||||||
var SupporterPage = {
|
(function () {
|
||||||
|
|
||||||
onPageShow: function () {
|
$(document).on('pageshow', "#supporterPage", function () {
|
||||||
SupporterPage.load();
|
|
||||||
},
|
|
||||||
|
|
||||||
onPageHide: function () {
|
var page = this;
|
||||||
|
|
||||||
|
$('#paypalReturnUrl', page).val(ApiClient.getUrl("supporterkey.html"));
|
||||||
|
|
||||||
},
|
});
|
||||||
|
|
||||||
load: function() {
|
})();
|
||||||
Dashboard.showLoadingMsg();
|
|
||||||
var page = $.mobile.activePage;
|
|
||||||
|
|
||||||
ApiClient.getPluginSecurityInfo().done(function (info) {
|
|
||||||
$('#txtSupporterKey', page).val(info.SupporterKey);
|
|
||||||
if (info.IsMBSupporter) {
|
|
||||||
$('.supporterOnly', page).show();
|
|
||||||
} else {
|
|
||||||
$('.supporterOnly', page).hide();
|
|
||||||
}
|
|
||||||
$('#paypalReturnUrl', page).val(ApiClient.getUrl("supporterkey.html"));
|
|
||||||
Dashboard.hideLoadingMsg();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$(document).on('pageshow', "#supporterPage", SupporterPage.onPageShow)
|
|
||||||
.on('pagehide', "#supporterPage", SupporterPage.onPageHide);
|
|
82
dashboard-ui/scripts/thememediaplayer.js
Normal file
82
dashboard-ui/scripts/thememediaplayer.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
(function (document, $, localStorage) {
|
||||||
|
|
||||||
|
var currentOwnerId;
|
||||||
|
var currentThemeIds = [];
|
||||||
|
|
||||||
|
function playThemeSongs(items, ownerId) {
|
||||||
|
|
||||||
|
var player = getPlayer();
|
||||||
|
|
||||||
|
if (items.length && player.isDefaultPlayer && player.canAutoPlayAudio()) {
|
||||||
|
|
||||||
|
// Stop if a theme song from another ownerId
|
||||||
|
// Leave it alone if anything else (e.g user playing a movie)
|
||||||
|
if (!currentOwnerId && player.isPlaying()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentThemeIds = items.map(function (i) {
|
||||||
|
return i.Id;
|
||||||
|
});
|
||||||
|
|
||||||
|
currentOwnerId = ownerId;
|
||||||
|
|
||||||
|
player.play({
|
||||||
|
items: items
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
currentOwnerId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPlayItem(item) {
|
||||||
|
|
||||||
|
// User played something manually
|
||||||
|
if (currentThemeIds.indexOf(item.Id) == -1) {
|
||||||
|
|
||||||
|
currentOwnerId = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function enabled(isEnabled) {
|
||||||
|
|
||||||
|
var userId = Dashboard.getCurrentUserId();
|
||||||
|
|
||||||
|
var key = userId + '-themesongs';
|
||||||
|
|
||||||
|
if (isEnabled == null) {
|
||||||
|
return localStorage.getItem(key) == '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var val = isEnabled ? '1' : '0';
|
||||||
|
|
||||||
|
localStorage.setItem(key, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPlayer() {
|
||||||
|
return MediaController.getCurrentPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on('thememediadownload', ".libraryPage", function (e, themeMediaResult) {
|
||||||
|
|
||||||
|
if (!enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ownerId = themeMediaResult.ThemeSongsResult.OwnerId;
|
||||||
|
|
||||||
|
if (ownerId != currentOwnerId) {
|
||||||
|
playThemeSongs(themeMediaResult.ThemeSongsResult.Items, ownerId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.ThemeSongManager = {
|
||||||
|
enabled: function (isEnabled) {
|
||||||
|
return enabled(isEnabled);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})(document, jQuery, window.localStorage);
|
|
@ -34,7 +34,8 @@
|
||||||
context: 'tv',
|
context: 'tv',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
showItemCounts: true,
|
showItemCounts: true,
|
||||||
coverImage: true
|
coverImage: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
|
html += LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, false, [], false);
|
||||||
|
|
|
@ -34,7 +34,8 @@
|
||||||
items: result.Items,
|
items: result.Items,
|
||||||
shape: "backdrop",
|
shape: "backdrop",
|
||||||
preferThumb: true,
|
preferThumb: true,
|
||||||
context: 'tv'
|
context: 'tv',
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
|
@ -45,7 +46,8 @@
|
||||||
items: result.Items,
|
items: result.Items,
|
||||||
shape: "banner",
|
shape: "banner",
|
||||||
preferBanner: true,
|
preferBanner: true,
|
||||||
context: 'tv'
|
context: 'tv',
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,8 @@
|
||||||
shape: "portrait",
|
shape: "portrait",
|
||||||
context: 'tv',
|
context: 'tv',
|
||||||
showTitle: true,
|
showTitle: true,
|
||||||
centerText: true
|
centerText: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
$('.itemsContainer', page).removeClass('timelineItemsContainer');
|
||||||
}
|
}
|
||||||
|
@ -67,7 +70,8 @@
|
||||||
shape: "portrait",
|
shape: "portrait",
|
||||||
context: 'tv',
|
context: 'tv',
|
||||||
timeline: true,
|
timeline: true,
|
||||||
showTitle: true
|
showTitle: true,
|
||||||
|
lazy: true
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
$('.itemsContainer', page).addClass('timelineItemsContainer');
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
var imageUrl = ApiClient.getUserImageUrl(user.Id, {
|
||||||
height: 450,
|
height: 200,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
if (user.PrimaryImageTag) {
|
if (user.PrimaryImageTag) {
|
||||||
|
|
||||||
var url = ApiClient.getUserImageUrl(user.Id, {
|
var url = ApiClient.getUserImageUrl(user.Id, {
|
||||||
width: 225,
|
width: 80,
|
||||||
tag: user.PrimaryImageTag,
|
tag: user.PrimaryImageTag,
|
||||||
type: "Primary"
|
type: "Primary"
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,29 @@
|
||||||
(function ($, window, document) {
|
(function ($, window, document) {
|
||||||
|
|
||||||
|
function populateLanguages(select, languages) {
|
||||||
|
|
||||||
|
var html = "";
|
||||||
|
|
||||||
|
html += "<option value=''></option>";
|
||||||
|
|
||||||
|
for (var i = 0, length = languages.length; i < length; i++) {
|
||||||
|
|
||||||
|
var culture = languages[i];
|
||||||
|
|
||||||
|
html += "<option value='" + culture.ThreeLetterISOLanguageName + "'>" + culture.DisplayName + "</option>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$(select).html(html).selectmenu("refresh");
|
||||||
|
}
|
||||||
|
|
||||||
function loadUser(page, user, loggedInUser, allCulturesPromise) {
|
function loadUser(page, user, loggedInUser, allCulturesPromise) {
|
||||||
|
|
||||||
Dashboard.setPageTitle(user.Name);
|
Dashboard.setPageTitle(user.Name);
|
||||||
|
|
||||||
allCulturesPromise.done(function (allCultures) {
|
allCulturesPromise.done(function (allCultures) {
|
||||||
|
|
||||||
Dashboard.populateLanguages($('#selectAudioLanguage', page), allCultures);
|
populateLanguages($('#selectAudioLanguage', page), allCultures);
|
||||||
Dashboard.populateLanguages($('#selectSubtitleLanguage', page), allCultures);
|
populateLanguages($('#selectSubtitleLanguage', page), allCultures);
|
||||||
|
|
||||||
$('#selectAudioLanguage', page).val(user.Configuration.AudioLanguagePreference || "").selectmenu("refresh");
|
$('#selectAudioLanguage', page).val(user.Configuration.AudioLanguagePreference || "").selectmenu("refresh");
|
||||||
$('#selectSubtitleLanguage', page).val(user.Configuration.SubtitleLanguagePreference || "").selectmenu("refresh");
|
$('#selectSubtitleLanguage', page).val(user.Configuration.SubtitleLanguagePreference || "").selectmenu("refresh");
|
||||||
|
|
|
@ -16,23 +16,14 @@
|
||||||
<a href="supporterkey.html" data-role="button">${TabSupporterKey}</a>
|
<a href="supporterkey.html" data-role="button">${TabSupporterKey}</a>
|
||||||
<a href="about.html" data-role="button">${TabAbout}</a>
|
<a href="about.html" data-role="button">${TabAbout}</a>
|
||||||
</div>
|
</div>
|
||||||
<h3>Support the Media Browser Team</h3>
|
<h3>${HeaderSupportTheTeam}</h3>
|
||||||
<p>
|
<p>${HeaderSupportTheTeamHelp}</p>
|
||||||
Help ensure the continued development of this product by donating a minimum of $10 (greater amounts greatly appreciated). A portion of all donations will be contributed to other <a href="about.html">free tools</a> we depend on.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p style="display: none; padding: 1em; border-radius: 5px; font-weight: normal;" class="ui-bar-a supporterOnly">
|
|
||||||
<strong>Thank You</strong> for your past support of the Media Browser Team. Users like you make it possible for
|
|
||||||
Media Browser to exist and keep getting better and better. You can always support us again if you feel you are getting maximum
|
|
||||||
value from the product.
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<br />
|
<br />
|
||||||
<form name="_xclick" action="https://www.paypal.com/cgi-bin/webscr"
|
<form name="_xclick" action="https://www.paypal.com/cgi-bin/webscr"
|
||||||
method="post">
|
method="post">
|
||||||
<label for="donateAmt">Amount (USD)</label>
|
<label for="donateAmt">${LabelSupportAmount}</label>
|
||||||
<select id="donateAmt" name="amount">
|
<select id="donateAmt" name="amount">
|
||||||
<option value="10">$10</option>
|
|
||||||
<option value="15" selected="selected">$15</option>
|
<option value="15" selected="selected">$15</option>
|
||||||
<option value="20">$20</option>
|
<option value="20">$20</option>
|
||||||
<option value="30">$30</option>
|
<option value="30">$30</option>
|
||||||
|
@ -46,10 +37,11 @@
|
||||||
<input type="hidden" name="item_number" value="MBSupporter">
|
<input type="hidden" name="item_number" value="MBSupporter">
|
||||||
<input type="hidden" name="notify_url" value="http://mb3admin.com/admin/service/services/ppipn.php">
|
<input type="hidden" name="notify_url" value="http://mb3admin.com/admin/service/services/ppipn.php">
|
||||||
<input type="hidden" name="return" id="paypalReturnUrl" value="#">
|
<input type="hidden" name="return" id="paypalReturnUrl" value="#">
|
||||||
<a data-role="button" onclick="$(this).parents('form')[0].submit();">
|
<a data-role="button" data-icon="arrow-r" data-iconpos="right" onclick="$(this).parents('form')[0].submit();">
|
||||||
<img src="css/images/supporter/donatepaypal.png" /></a>
|
<img src="css/images/supporter/donatepaypal.png" /></a>
|
||||||
</form>
|
</form>
|
||||||
<p>Once complete, please return and <a href="supporterkey.html">enter your supporter key</a>, which you will receive by email.</p>
|
<p>${DonationNextStep}</p>
|
||||||
|
<p><a href="supporterkey.html">Enter supporter key</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
62
dashboard-ui/thirdparty/jquery.unveil-custom.js
vendored
Normal file
62
dashboard-ui/thirdparty/jquery.unveil-custom.js
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
* jQuery Unveil
|
||||||
|
* A very lightweight jQuery plugin to lazy load images
|
||||||
|
* http://luis-almeida.github.com/unveil
|
||||||
|
*
|
||||||
|
* Licensed under the MIT license.
|
||||||
|
* Copyright 2013 Luís Almeida
|
||||||
|
* https://github.com/luis-almeida
|
||||||
|
*/
|
||||||
|
|
||||||
|
; (function ($) {
|
||||||
|
|
||||||
|
$.fn.unveil = function (threshold, callback) {
|
||||||
|
|
||||||
|
var $w = $(window),
|
||||||
|
th = threshold || 0,
|
||||||
|
retina = window.devicePixelRatio > 1,
|
||||||
|
attrib = retina ? "data-src-retina" : "data-src",
|
||||||
|
images = this,
|
||||||
|
loaded;
|
||||||
|
|
||||||
|
this.one("unveil", function () {
|
||||||
|
var elemType = $(this).get(0).tagName;
|
||||||
|
var source = this.getAttribute(attrib);
|
||||||
|
source = source || this.getAttribute("data-src");
|
||||||
|
if (source) {
|
||||||
|
if (elemType === "DIV") {
|
||||||
|
this.style.backgroundImage = "url('" + source + "')";
|
||||||
|
} else {
|
||||||
|
this.setAttribute("src", source);
|
||||||
|
}
|
||||||
|
if (typeof callback === "function") callback.call(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function unveil() {
|
||||||
|
var inview = images.filter(function () {
|
||||||
|
var $e = $(this);
|
||||||
|
if ($e.is(":hidden")) return;
|
||||||
|
|
||||||
|
var wt = $w.scrollTop(),
|
||||||
|
wb = wt + $w.height(),
|
||||||
|
et = $e.offset().top,
|
||||||
|
eb = et + $e.height();
|
||||||
|
|
||||||
|
return eb >= wt - th && et <= wb + th;
|
||||||
|
});
|
||||||
|
|
||||||
|
loaded = inview.trigger("unveil");
|
||||||
|
images = images.not(loaded);
|
||||||
|
}
|
||||||
|
|
||||||
|
$w.scroll(unveil);
|
||||||
|
$w.resize(unveil);
|
||||||
|
|
||||||
|
unveil();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
})(window.jQuery || window.Zepto);
|
|
@ -1728,6 +1728,16 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.reportCapabilities = function (options) {
|
||||||
|
|
||||||
|
var url = self.getUrl("Sessions/Capabilities", options);
|
||||||
|
|
||||||
|
return self.ajax({
|
||||||
|
type: "POST",
|
||||||
|
url: url
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
self.updateItemImageIndex = function (itemId, itemType, itemName, imageType, imageIndex, newIndex) {
|
self.updateItemImageIndex = function (itemId, itemType, itemName, imageType, imageIndex, newIndex) {
|
||||||
|
|
||||||
if (!imageType) {
|
if (!imageType) {
|
||||||
|
@ -2198,6 +2208,28 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function normalizeImageOptions(options) {
|
||||||
|
|
||||||
|
var ratio = window.devicePixelRatio;
|
||||||
|
|
||||||
|
if (ratio) {
|
||||||
|
|
||||||
|
if (options.width) {
|
||||||
|
options.width = options.width * ratio;
|
||||||
|
}
|
||||||
|
if (options.height) {
|
||||||
|
options.height = options.height * ratio;
|
||||||
|
}
|
||||||
|
if (options.maxWidth) {
|
||||||
|
options.maxWidth = options.maxWidth * ratio;
|
||||||
|
}
|
||||||
|
if (options.maxHeight) {
|
||||||
|
options.maxHeight = options.maxHeight * ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a url for a user image
|
* Constructs a url for a user image
|
||||||
* @param {String} userId
|
* @param {String} userId
|
||||||
|
@ -2230,6 +2262,8 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
delete options.type;
|
delete options.type;
|
||||||
delete options.index;
|
delete options.index;
|
||||||
|
|
||||||
|
normalizeImageOptions(options);
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
return self.getUrl(url, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2265,215 +2299,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
delete options.type;
|
delete options.type;
|
||||||
delete options.index;
|
delete options.index;
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
normalizeImageOptions(options);
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a year image
|
|
||||||
* @param {String} year
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getYearImageUrl = function (year, options) {
|
|
||||||
|
|
||||||
if (!year) {
|
|
||||||
throw new Error("null year");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Years/" + year + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a genre image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getGenreImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Genres/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a genre image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getMusicGenreImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "MusicGenres/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a genre image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getGameGenreImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "GameGenres/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a artist image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getArtistImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Artists/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a url for a studio image
|
|
||||||
* @param {String} name
|
|
||||||
* @param {Object} options
|
|
||||||
* Options supports the following properties:
|
|
||||||
* width - download the image at a fixed width
|
|
||||||
* height - download the image at a fixed height
|
|
||||||
* maxWidth - download the image at a maxWidth
|
|
||||||
* maxHeight - download the image at a maxHeight
|
|
||||||
* quality - A scale of 0-100. This should almost always be omitted as the default will suffice.
|
|
||||||
* For best results do not specify both width and height together, as aspect ratio might be altered.
|
|
||||||
*/
|
|
||||||
self.getStudioImageUrl = function (name, options) {
|
|
||||||
|
|
||||||
if (!name) {
|
|
||||||
throw new Error("null name");
|
|
||||||
}
|
|
||||||
|
|
||||||
options = options || {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Studios/" + self.encodeName(name) + "/Images/" + options.type;
|
|
||||||
|
|
||||||
if (options.index != null) {
|
|
||||||
url += "/" + options.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't put these on the query string
|
|
||||||
delete options.type;
|
|
||||||
delete options.index;
|
|
||||||
|
|
||||||
return self.getUrl(url, options);
|
return self.getUrl(url, options);
|
||||||
};
|
};
|
||||||
|
@ -2498,9 +2324,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
throw new Error("itemId cannot be empty");
|
throw new Error("itemId cannot be empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
options = options || {
|
options = options || {};
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var url = "Items/" + itemId + "/Images/" + options.type;
|
var url = "Items/" + itemId + "/Images/" + options.type;
|
||||||
|
|
||||||
|
@ -3183,10 +3007,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
self.getThemeMedia = function (userId, itemId, inherit) {
|
||||||
* Gets theme songs for an item
|
|
||||||
*/
|
|
||||||
self.getThemeSongs = function (userId, itemId) {
|
|
||||||
|
|
||||||
if (!itemId) {
|
if (!itemId) {
|
||||||
throw new Error("null itemId");
|
throw new Error("null itemId");
|
||||||
|
@ -3198,28 +3019,9 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
options.userId = userId;
|
options.userId = userId;
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = self.getUrl("Items/" + itemId + "/ThemeSongs", options);
|
options.InheritFromParent = inherit || false;
|
||||||
|
|
||||||
return self.ajax({
|
var url = self.getUrl("Items/" + itemId + "/ThemeMedia", options);
|
||||||
type: "GET",
|
|
||||||
url: url,
|
|
||||||
dataType: "json"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
self.getThemeVideos = function (userId, itemId) {
|
|
||||||
|
|
||||||
if (!itemId) {
|
|
||||||
throw new Error("null itemId");
|
|
||||||
}
|
|
||||||
|
|
||||||
var options = {};
|
|
||||||
|
|
||||||
if (userId) {
|
|
||||||
options.userId = userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = self.getUrl("Items/" + itemId + "/ThemeVideos", options);
|
|
||||||
|
|
||||||
return self.ajax({
|
return self.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
|
@ -3944,24 +3746,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.sendBrowseCommand = function (sessionId, options) {
|
|
||||||
|
|
||||||
if (!sessionId) {
|
|
||||||
throw new Error("null sessionId");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options) {
|
|
||||||
throw new Error("null options");
|
|
||||||
}
|
|
||||||
|
|
||||||
var url = self.getUrl("Sessions/" + sessionId + "/Viewing", options);
|
|
||||||
|
|
||||||
return self.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: url
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
self.sendPlayCommand = function (sessionId, options) {
|
self.sendPlayCommand = function (sessionId, options) {
|
||||||
|
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
|
@ -3980,7 +3764,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
self.sendSystemCommand = function (sessionId, command) {
|
self.sendCommand = function (sessionId, command, options) {
|
||||||
|
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
throw new Error("null sessionId");
|
throw new Error("null sessionId");
|
||||||
|
@ -3990,12 +3774,22 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
|
||||||
throw new Error("null command");
|
throw new Error("null command");
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = self.getUrl("Sessions/" + sessionId + "/System/" + command);
|
var url = self.getUrl("Sessions/" + sessionId + "/Command");
|
||||||
|
|
||||||
return self.ajax({
|
var ajaxOptions = {
|
||||||
type: "POST",
|
type: "POST",
|
||||||
url: url
|
url: url
|
||||||
});
|
};
|
||||||
|
|
||||||
|
options = {
|
||||||
|
Arguments: options || {},
|
||||||
|
Name: command
|
||||||
|
};
|
||||||
|
|
||||||
|
ajaxOptions.data = JSON.stringify(options);
|
||||||
|
ajaxOptions.contentType = "application/json";
|
||||||
|
|
||||||
|
return self.ajax(ajaxOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.sendMessageCommand = function (sessionId, options) {
|
self.sendMessageCommand = function (sessionId, options) {
|
Loading…
Add table
Add a link
Reference in a new issue