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:
Nathan DeTar 2022-01-14 22:33:16 -08:00 committed by GitHub
parent c703105c5e
commit b7922d171d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 90 additions and 90 deletions

View File

@ -29,15 +29,8 @@
{% endif %}
<script type="text/javascript" src="{% static 'script.js' %}"></script>
{% if cast %}
<script src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
<script>
window['__onGCastApiAvailable'] = function(isAvailable) {
if (isAvailable) {
initializeCastApi();
}
};
</script>
<script type="text/javascript" src="{% static 'cast-videos.js' %}"></script>
<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
<script id="cast-script" type="text/javascript" src="{% static 'cast-videos.js' %}"></script>
{% endif %}
</head>
<body>

View File

@ -107,8 +107,8 @@
{{ app_form.downloads_integrate_ryd }}
</div>
<div class="settings-item">
<p><span class="danger-zone">Untested!</span> 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>
<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. HTTPS and a supported browser are required for this integration.</i><br>
{{ app_form.application_enable_cast }}
</div>
</div>
@ -293,4 +293,4 @@
{% endif %}
</div>
<script type="text/javascript" src="{% static 'progress.js' %}"></script>
{% endblock content %}
{% endblock content %}

View File

@ -11,11 +11,10 @@
</div>
<div class="boxed-content">
<div class="title-bar">
<h1>{{ video.title }}</h1>
{% if cast %}
<button onclick="startCast()">Start Cast</button>
<button onclick="stopCast()">Stop Cast</button>
<google-cast-launcher id="castbutton"></google-cast-launcher>
{% endif %}
<h1 id="video-title">{{ video.title }}</h1>
</div>
<div class="info-box info-box-3">
<div class="info-box-item">

View File

@ -111,6 +111,7 @@ class ArchivistViewConfig(View):
self.context = {
"colors": self.default_conf["application"]["colors"],
"cast": self.default_conf["application"]["enable_cast"],
"sort_by": self._get_sort_by(),
"sort_order": self._get_sort_order(),
"view_style": self._get_view_style(),

View File

@ -1,91 +1,82 @@
var session = null;
function initializeCastApi() {
var applicationID = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
var sessionRequest = new chrome.cast.SessionRequest(applicationID);
var apiConfig = new chrome.cast.ApiConfig(sessionRequest,
sessionListener,
receiverListener);
chrome.cast.initialize(apiConfig, onInitSuccess, onInitError);
};
cast.framework.CastContext.getInstance().setOptions({
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.
autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED
});
function sessionListener(e) {
session = e;
console.log('New session');
if (session.media.length != 0) {
console.log('Found ' + session.media.length + ' sessions.');
}
}
function receiverListener(e) {
if( e === 'available' ) {
console.log("Chromecast was found on the network.");
}
else {
console.log("There are no Chromecasts available.");
var player = new cast.framework.RemotePlayer();
var playerController = new cast.framework.RemotePlayerController(player);
// Add event listerner to check if a connection to a cast device is initiated
playerController.addEventListener(
cast.framework.RemotePlayerEventType.IS_CONNECTED_CHANGED, function() {
castConnectionChange(player)
}
);
}
function onInitSuccess() {
console.log("Initialization succeeded");
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 onInitError() {
console.log("Initialization failed");
function castStart() {
var castSession = cast.framework.CastContext.getInstance().getCurrentSession();
// 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);
}
); // Send request to cast device
}
}
function startCast() {
console.log("Starting cast...");
chrome.cast.requestSession(onRequestSessionSuccess, onLaunchError);
function shiftCurrentTime(contentCurrentTime) { // Shift media back 3 seconds to prevent missing some of the content
if (contentCurrentTime > 5) {
return(contentCurrentTime - 3);
} else {
return(0);
}
}
function onRequestSessionSuccess(e) {
console.log("Successfully created session: " + e.sessionId);
session = e;
function castSuccessful() {
// console.log('Cast Successful.');
document.getElementById("video-item").pause(); // Pause browser video on successful cast
}
function onLaunchError() {
console.log("Error connecting to the Chromecast.");
function castFailed(errorCode) {
console.log('Error code: ' + errorCode);
}
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() {
console.log('Successfully loaded video.');
}
function onLoadError() {
console.log('Failed to load video.');
}
function stopCast() {
session.stop(onStopCastSuccess, onStopCastError);
}
function onStopCastSuccess() {
console.log('Successfully stopped casting.');
}
function onStopCastError() {
console.log('Error stopping cast.');
window['__onGCastApiAvailable'] = function(isAvailable) {
if (isAvailable) {
initializeCastApi();
}
}

View File

@ -267,6 +267,14 @@ button:hover {
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 */
.title-bar {
padding-top: 30px;

View File

@ -309,6 +309,7 @@ function createPlayer(button) {
videoPlayer.setAttribute('width', '100%');
videoPlayer.setAttribute('playsinline', true);
videoPlayer.setAttribute('poster', mediaThumb);
videoPlayer.setAttribute('id', 'video-item'); // Set ID to get URL for casting
playerElement.appendChild(videoPlayer);
// title bar
var titleBar = document.createElement('div');
@ -335,7 +336,14 @@ function createPlayer(button) {
var videoTitleLink = document.createElement('a');
videoTitleLink.setAttribute('href', '/video/' + dataId + '/');
var videoTitle = document.createElement('h2');
videoTitle.setAttribute('id', "video-title"); // Set ID to get title for casting
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);
titleBar.appendChild(videoTitleLink);
// add titlebar