Skip to content

Commit

Permalink
Merge pull request #5755 from avalonmediasystem/embedded_ramp
Browse files Browse the repository at this point in the history
Use Ramp for embedded player
  • Loading branch information
masaball authored Apr 10, 2024
2 parents aae0d9c + 7108c1e commit fc6e3da
Show file tree
Hide file tree
Showing 15 changed files with 194 additions and 305 deletions.
4 changes: 0 additions & 4 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,4 @@
// include all of our vendored js
//= require_tree ../../../vendor/assets/javascripts/.

// Require VideoJS and VideoJS quality selector for embedded player
//= require video.js/dist/video.min.js
//= require @silvermine/videojs-quality-selector/dist/js/silvermine-videojs-quality-selector.min.js

//= require_tree .
3 changes: 0 additions & 3 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,3 @@
@import 'avalon';

@import "datatables";

@import "video.js/dist/video-js.css";
@import "@silvermine/videojs-quality-selector/dist/css/quality-selector.css";
116 changes: 0 additions & 116 deletions app/assets/stylesheets/embed.scss

This file was deleted.

8 changes: 0 additions & 8 deletions app/controllers/master_files_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,6 @@ def show
end

def embed
if can? :read, @master_file
@stream_info = secure_streams(@master_file.stream_details, @master_file.media_object_id)
@stream_info['t'] = view_context.parse_media_fragment(params[:t]) # add MediaFragment from params
@stream_info['link_back_url'] = view_context.share_link_for(@master_file)
end

@player_width = "100%"
@player_height = "100%"
respond_to do |format|
format.html do
response.headers.delete "X-Frame-Options"
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/MediaObjectRamp.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2023, The Trustees of Indiana University and Northwestern
* Copyright 2011-2024, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/PlaylistRamp.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2023, The Trustees of Indiana University and Northwestern
* Copyright 2011-2024, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
Expand Down
119 changes: 119 additions & 0 deletions app/javascript/components/embeds/EmbeddedRamp.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Copyright 2011-2024, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* --- END LICENSE_HEADER BLOCK ---
*/

import React from 'react';
import {
IIIFPlayer,
MediaPlayer
} from '@samvera/ramp';
import 'video.js/dist/video-js.css';
import "@samvera/ramp/dist/ramp.css";
import './Ramp.scss';

const Ramp = ({
urls,
media_object_id
}) => {
const [manifestUrl, setManifestUrl] = React.useState('');
const [startCanvasId, setStartCanvasId] = React.useState();
const [startCanvasTime, setStartCanvasTime] = React.useState();
let interval;

React.useEffect(() => {
const { base_url, fullpath_url } = urls;
// Split the current path from the time fragment in the format .../:id?t=time
let [fullpath, start_time] = fullpath_url.split('?t=');
// Split the current path in the format /master_files/:mf_id/embed
let [_, __, mf_id, ___] = fullpath.split('/');
// Build the manifest URL
let url = `${base_url}/media_objects/${media_object_id}/manifest.json`;

// Set start Canvas ID and start time in the state for Ramp
setStartCanvasId(
mf_id && mf_id != undefined
? `${base_url}/media_objects/${media_object_id}/manifest/canvas/${mf_id}`
: undefined
);
setStartCanvasTime(
start_time && start_time != undefined
? parseFloat(start_time)
: undefined
);
setManifestUrl(url);

interval = setInterval(addControls, 500);

// Clear interval upon component unmounting
return () => clearInterval(interval);
}, []);

const addControls = () => {
let player = document.getElementById('iiif-media-player');
if (player && player.player) {
let embeddedPlayer = player.player

// Player API handling
window.addEventListener('message', function(event) {
var command = event.data.command;

if (command=='play') embeddedPlayer.play();
else if (command=='pause') embeddedPlayer.pause();
else if (command=='toggle_loop') {
embeddedPlayer.loop() ? embeddedPlayer.loop(false): embeddedPlayer.loop(true);
embeddedPlayer.autoplay() ? embeddedPlayer.autoplay(false) : embeddedPlayer.autoplay(true);
}
else if (command=='set_offset') embeddedPlayer.currentTime(event.data.offset); // time is in seconds
else if (command=='get_offset') event.source.postMessage({'command': 'currentTime','currentTime': embeddedPlayer.currentTime()}, event.origin);
});

/*
Quality selector extends outside iframe for audio items, so we need to disable that control
and rely on the quality automatically selected by the user's system.
*/
if (embeddedPlayer.isAudio()) { embeddedPlayer.controlBar.removeChild('qualitySelector'); }

// Create button component for "View in Repository" and add to control bar
let repositoryUrl = Object.values(urls).join('/').replace('/embed', '');
let position = embeddedPlayer.isAudio() ? embeddedPlayer.controlBar.children_.length : embeddedPlayer.controlBar.children_.length - 1;
var viewInRepoButton = embeddedPlayer.getChild('ControlBar').addChild('button', {
clickHandler: function(event) {
window.open(repositoryUrl, '_blank').focus();
}
}, position);

viewInRepoButton.addClass('vjs-custom-external-link');
viewInRepoButton.el_.setAttribute('style', 'cursor: pointer;');
viewInRepoButton.controlText('View in Repository');

// Add button icon
document.querySelector('.vjs-custom-external-link .vjs-icon-placeholder').innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" height="1em" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><style>svg{fill:#ffffff}</style><path d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32h82.7L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3V192c0 17.7 14.3 32 32 32s32-14.3 32-32V32c0-17.7-14.3-32-32-32H320zM80 32C35.8 32 0 67.8 0 112V432c0 44.2 35.8 80 80 80H400c44.2 0 80-35.8 80-80V320c0-17.7-14.3-32-32-32s-32 14.3-32 32V432c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16H192c17.7 0 32-14.3 32-32s-14.3-32-32-32H80z"/></svg>'

// This function only needs to run once, so we clear the interval here
clearInterval(interval);
}
};

return (
<IIIFPlayer manifestUrl={manifestUrl}
customErrorMessage='This embed encountered an error. Please refresh or contact an administrator.'
startCanvasId={startCanvasId}
startCanvasTime={startCanvasTime}>
<MediaPlayer enableFileDownload={false} />
</IIIFPlayer>
);
};

export default Ramp;
40 changes: 40 additions & 0 deletions app/javascript/components/embeds/Ramp.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2011-2024, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* --- END LICENSE_HEADER BLOCK ---
*/

[class*="ramp--"] {
font-family: Arial, Helvetica, sans-serif;
}

.ramp--media_player {
.video-js .vjs-big-play-button {
left: 55% !important;
}
@media (max-width: 585px) {
.video-js .vjs-big-play-button {
scale: 1.5;
}

.video-js .vjs-control-bar {
font-size: 90% !important;
}

// reduce player height to match with adjusted font-size
// for smaller screens
.video-js.vjs-audio {
min-height: 2.9em;
}
}
}
7 changes: 6 additions & 1 deletion app/javascript/packs/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@

// console.log('Hello World from Webpacker')
// Support component names relative to this directory:
var componentRequireContext = require.context("components", true)

/*
* For some reason including the `embeds` directory in this `require.context` breaks
* the player. Filtering out the directory allows everything to operate as intended.
*/
var componentRequireContext = require.context("components", true, /^(?!embed)/)
var ReactRailsUJS = require("react_ujs")
ReactRailsUJS.useContext(componentRequireContext)
18 changes: 18 additions & 0 deletions app/javascript/packs/embed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright 2011-2024, The Trustees of Indiana University and Northwestern
* University. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* --- END LICENSE_HEADER BLOCK ---
*/
var embedRequireContext = require.context("components/embeds", false)
var ReactRailsUJS = require("react_ujs")
ReactRailsUJS.useContext(embedRequireContext)
10 changes: 3 additions & 7 deletions app/views/layouts/embed.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ Unless required by applicable law or agreed to in writing, software distributed
specific language governing permissions and limitations under the License.
--- END LICENSE_HEADER BLOCK ---
%>
<% content_for :page_styles do %>
<%= stylesheet_link_tag 'embed' %>
<% end %>

<!DOCTYPE html>
<html lang="en">
<head>
Expand All @@ -26,16 +22,16 @@ Unless required by applicable law or agreed to in writing, software distributed

<%= csrf_meta_tags %>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<%= favicon_link_tag %>
<%= stylesheet_link_tag "application", media: "all" %>
<%= favicon_link_tag %>
<%= stylesheet_pack_tag 'embed' %>
<%= javascript_pack_tag 'embed' %>
<%= yield :page_styles %>
<%= yield :additional_head_content %>
<%= render "modules/google_analytics" %>
</head>

<body>
<%= yield %>
<%= javascript_include_tag "application" %>
<%= yield :page_scripts %>
</body>
</html>
Loading

0 comments on commit fc6e3da

Please sign in to comment.