mirror of
https://github.com/tubearchivist/tubearchivist-frontend.git
synced 2024-11-25 13:10:15 +00:00
Improved Cast Support (#143)
* Added cast integration requirements. HTTPS and a supported browser are required for this integration. * Improved cast handeling. * Theme cast button. * Improved cast support. * Added proper cast button. * Moved cast button location * Moved button location * Reorder cast button * Fix typo * Revert cast setting description. * Match master branch * Added comments * Added id `cast-script` to cast-videos.js * Reworked event listener * Add cast button to home player * Check if active media on cast, pause browser video * Commented out console logging * Uncommented cast failed console log * Cast video at current playback position * use theme vars for cast color buttons * add cast variable to base ArchivistViewConfig class Co-authored-by: simon <simobilleter@gmail.com>
This commit is contained in:
parent
c703105c5e
commit
b7922d171d
@ -29,15 +29,8 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<script type="text/javascript" src="{% static 'script.js' %}"></script>
|
<script type="text/javascript" src="{% static 'script.js' %}"></script>
|
||||||
{% if cast %}
|
{% if cast %}
|
||||||
<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
|
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
|
||||||
<script>
|
<script id="cast-script" type="text/javascript" src="{% static 'cast-videos.js' %}"></script>
|
||||||
window['__onGCastApiAvailable'] = function(isAvailable) {
|
|
||||||
if (isAvailable) {
|
|
||||||
initializeCastApi();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="{% static 'cast-videos.js' %}"></script>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -107,8 +107,8 @@
|
|||||||
{{ app_form.downloads_integrate_ryd }}
|
{{ app_form.downloads_integrate_ryd }}
|
||||||
</div>
|
</div>
|
||||||
<div class="settings-item">
|
<div class="settings-item">
|
||||||
<p><span class="danger-zone">Untested!</span> Current Cast integration: <span class="settings-current">{{ config.application.enable_cast }}</span></p>
|
<p>Current Cast integration: <span class="settings-current">{{ config.application.enable_cast }}</span></p>
|
||||||
<i>Enabling Cast will load an additional JS library from google.</i><br>
|
<i>Enabling Cast will load an additional JS library from Google. HTTPS and a supported browser are required for this integration.</i><br>
|
||||||
{{ app_form.application_enable_cast }}
|
{{ app_form.application_enable_cast }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -11,11 +11,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="boxed-content">
|
<div class="boxed-content">
|
||||||
<div class="title-bar">
|
<div class="title-bar">
|
||||||
<h1>{{ video.title }}</h1>
|
|
||||||
{% if cast %}
|
{% if cast %}
|
||||||
<button onclick="startCast()">Start Cast</button>
|
<google-cast-launcher id="castbutton"></google-cast-launcher>
|
||||||
<button onclick="stopCast()">Stop Cast</button>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<h1 id="video-title">{{ video.title }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="info-box info-box-3">
|
<div class="info-box info-box-3">
|
||||||
<div class="info-box-item">
|
<div class="info-box-item">
|
||||||
|
@ -111,6 +111,7 @@ class ArchivistViewConfig(View):
|
|||||||
|
|
||||||
self.context = {
|
self.context = {
|
||||||
"colors": self.default_conf["application"]["colors"],
|
"colors": self.default_conf["application"]["colors"],
|
||||||
|
"cast": self.default_conf["application"]["enable_cast"],
|
||||||
"sort_by": self._get_sort_by(),
|
"sort_by": self._get_sort_by(),
|
||||||
"sort_order": self._get_sort_order(),
|
"sort_order": self._get_sort_order(),
|
||||||
"view_style": self._get_view_style(),
|
"view_style": self._get_view_style(),
|
||||||
|
@ -1,91 +1,82 @@
|
|||||||
var session = null;
|
|
||||||
|
|
||||||
function initializeCastApi() {
|
function initializeCastApi() {
|
||||||
var applicationID = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
|
cast.framework.CastContext.getInstance().setOptions({
|
||||||
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
|
receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID, // Use built in reciver app on cast device, see https://developers.google.com/cast/docs/styled_receiver if you want to be able to add a theme, splash screen or watermark. Has a $5 one time fee.
|
||||||
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
|
autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
|
||||||
sessionListener,
|
});
|
||||||
receiverListener);
|
|
||||||
chrome.cast.initialize(apiConfig, onInitSuccess, onInitError);
|
|
||||||
};
|
|
||||||
|
|
||||||
function sessionListener(e) {
|
var player = new cast.framework.RemotePlayer();
|
||||||
session = e;
|
var playerController = new cast.framework.RemotePlayerController(player);
|
||||||
console.log('New session');
|
|
||||||
if (session.media.length != 0) {
|
// Add event listerner to check if a connection to a cast device is initiated
|
||||||
console.log('Found ' + session.media.length + ' sessions.');
|
playerController.addEventListener(
|
||||||
|
cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
|
||||||
|
castConnectionChange(player)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function castConnectionChange(player) {
|
||||||
|
// If cast connection is initialized start cast
|
||||||
|
if (player.isConnected) {
|
||||||
|
// console.log("Cast Connected.");
|
||||||
|
castStart();
|
||||||
|
} else if (!player.isConnected) {
|
||||||
|
// console.log("Cast Disconnected.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function receiverListener(e) {
|
function castStart() {
|
||||||
if( e === 'available' ) {
|
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
|
||||||
console.log("Chromecast was found on the network.");
|
|
||||||
|
// Check if there is already media playing on the cast target to prevent recasting on page reload or switching to another video page
|
||||||
|
if (!castSession.getMediaSession()) {
|
||||||
|
contentId = document.getElementById("video-item").src; // Get video URL
|
||||||
|
contentTitle = document.getElementById('video-title').innerHTML; // Get video title
|
||||||
|
contentImage = document.getElementById("video-item").poster; // Get video thumbnail URL
|
||||||
|
contentType = 'video/mp4'; // Set content type, only videos right now so it is hard coded
|
||||||
|
contentCurrentTime = document.getElementById("video-item").currentTime; // Get video's current position
|
||||||
|
|
||||||
|
mediaInfo = new chrome.cast.media.MediaInfo(contentId, contentType); // Create MediaInfo var that contains url and content type
|
||||||
|
// mediaInfo.streamType = chrome.cast.media.StreamType.BUFFERED; // Set type of stream, BUFFERED, LIVE, OTHER
|
||||||
|
mediaInfo.metadata = new chrome.cast.media.GenericMediaMetadata(); // Create metadata var and add it to MediaInfo
|
||||||
|
mediaInfo.metadata.title = contentTitle; // Set the video title
|
||||||
|
mediaInfo.metadata.images = [new chrome.cast.Image(contentImage)]; // Set the video thumbnail
|
||||||
|
|
||||||
|
var request = new chrome.cast.media.LoadRequest(mediaInfo); // Create request with the previously set MediaInfo.
|
||||||
|
// request.queueData = new chrome.cast.media.QueueData(); // See https://developers.google.com/cast/docs/reference/web_sender/chrome.cast.media.QueueData for playlist support.
|
||||||
|
request.currentTime = shiftCurrentTime(contentCurrentTime); // Set video start position based on the browser video position
|
||||||
|
// request.autoplay = false; // Set content to auto play, true by default
|
||||||
|
castSession.loadMedia(request).then(
|
||||||
|
function() {
|
||||||
|
castSuccessful();
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
castFailed(errorCode);
|
||||||
}
|
}
|
||||||
else {
|
); // Send request to cast device
|
||||||
console.log("There are no Chromecasts available.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInitSuccess() {
|
function shiftCurrentTime(contentCurrentTime) { // Shift media back 3 seconds to prevent missing some of the content
|
||||||
console.log("Initialization succeeded");
|
if (contentCurrentTime > 5) {
|
||||||
}
|
return(contentCurrentTime - 3);
|
||||||
|
} else {
|
||||||
function onInitError() {
|
return(0);
|
||||||
console.log("Initialization failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
function startCast() {
|
|
||||||
console.log("Starting cast...");
|
|
||||||
chrome.cast.requestSession(onRequestSessionSuccess, onLaunchError);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRequestSessionSuccess(e) {
|
|
||||||
console.log("Successfully created session: " + e.sessionId);
|
|
||||||
session = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLaunchError() {
|
|
||||||
console.log("Error connecting to the Chromecast.");
|
|
||||||
}
|
|
||||||
|
|
||||||
function onRequestSessionSuccess(e) {
|
|
||||||
console.log("Successfully created session: " + e.sessionId);
|
|
||||||
session = e;
|
|
||||||
loadMedia();
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadMedia() {
|
|
||||||
if (!session) {
|
|
||||||
console.log("No session.");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var videoSrc = document.getElementById("video-item").src;
|
|
||||||
var mediaInfo = new chrome.cast.media.MediaInfo(videoSrc);
|
|
||||||
mediaInfo.contentType = 'video/mp4';
|
|
||||||
|
|
||||||
var request = new chrome.cast.media.LoadRequest(mediaInfo);
|
|
||||||
request.autoplay = true;
|
|
||||||
|
|
||||||
session.loadMedia(request, onLoadSuccess, onLoadError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLoadSuccess() {
|
function castSuccessful() {
|
||||||
console.log('Successfully loaded video.');
|
// console.log('Cast Successful.');
|
||||||
|
document.getElementById("video-item").pause(); // Pause browser video on successful cast
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLoadError() {
|
function castFailed(errorCode) {
|
||||||
console.log('Failed to load video.');
|
console.log('Error code: ' + errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopCast() {
|
window['__onGCastApiAvailable'] = function(isAvailable) {
|
||||||
session.stop(onStopCastSuccess, onStopCastError);
|
if (isAvailable) {
|
||||||
}
|
initializeCastApi();
|
||||||
|
}
|
||||||
function onStopCastSuccess() {
|
|
||||||
console.log('Successfully stopped casting.');
|
|
||||||
}
|
|
||||||
|
|
||||||
function onStopCastError() {
|
|
||||||
console.log('Error stopping cast.');
|
|
||||||
}
|
}
|
||||||
|
@ -267,6 +267,14 @@ button:hover {
|
|||||||
filter: var(--img-filter);
|
filter: var(--img-filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#castbutton {
|
||||||
|
float: right;
|
||||||
|
width: 40px;
|
||||||
|
padding: 0 5px;
|
||||||
|
--disconnected-color: var(--accent-font-dark);
|
||||||
|
--connected-color: var(--accent-font-light);
|
||||||
|
}
|
||||||
|
|
||||||
/* top of page */
|
/* top of page */
|
||||||
.title-bar {
|
.title-bar {
|
||||||
padding-top: 30px;
|
padding-top: 30px;
|
||||||
|
@ -309,6 +309,7 @@ function createPlayer(button) {
|
|||||||
videoPlayer.setAttribute('width', '100%');
|
videoPlayer.setAttribute('width', '100%');
|
||||||
videoPlayer.setAttribute('playsinline', true);
|
videoPlayer.setAttribute('playsinline', true);
|
||||||
videoPlayer.setAttribute('poster', mediaThumb);
|
videoPlayer.setAttribute('poster', mediaThumb);
|
||||||
|
videoPlayer.setAttribute('id', 'video-item'); // Set ID to get URL for casting
|
||||||
playerElement.appendChild(videoPlayer);
|
playerElement.appendChild(videoPlayer);
|
||||||
// title bar
|
// title bar
|
||||||
var titleBar = document.createElement('div');
|
var titleBar = document.createElement('div');
|
||||||
@ -335,7 +336,14 @@ function createPlayer(button) {
|
|||||||
var videoTitleLink = document.createElement('a');
|
var videoTitleLink = document.createElement('a');
|
||||||
videoTitleLink.setAttribute('href', '/video/' + dataId + '/');
|
videoTitleLink.setAttribute('href', '/video/' + dataId + '/');
|
||||||
var videoTitle = document.createElement('h2');
|
var videoTitle = document.createElement('h2');
|
||||||
|
videoTitle.setAttribute('id', "video-title"); // Set ID to get title for casting
|
||||||
videoTitle.innerText = mediaTitle;
|
videoTitle.innerText = mediaTitle;
|
||||||
|
var castScript = document.getElementById('cast-script'); // Get cast-script
|
||||||
|
if(typeof(castScript) != 'undefined' && castScript != null) { // Check if cast integration is enabled
|
||||||
|
var castButton = document.createElement("google-cast-launcher"); // Create cast button
|
||||||
|
castButton.setAttribute('id', "castbutton"); // Set ID to apply theme
|
||||||
|
titleBar.appendChild(castButton); // Add cast button to title
|
||||||
|
}
|
||||||
videoTitleLink.appendChild(videoTitle);
|
videoTitleLink.appendChild(videoTitle);
|
||||||
titleBar.appendChild(videoTitleLink);
|
titleBar.appendChild(videoTitleLink);
|
||||||
// add titlebar
|
// add titlebar
|
||||||
|
Loading…
Reference in New Issue
Block a user