source: main/trunk/model-sites-dev/respooled/collect/popup-video-respooled/js/media-player.js@ 29885

Last change on this file since 29885 was 29885, checked in by davidb, 9 years ago

Notes played stored in LocalStorage. Game On view area shows the events for a hard-wired track name

File size: 11.0 KB
Line 
1//"use strict";
2
3// Based on:
4// Sample Media Player using HTML5's Media API
5//
6// Ian Devlin (c) 2012
7// http://iandevlin.com
8// http://twitter.com/iandevlin
9//
10// This was written as part of an article for the February 2013 edition of .net magazine (http://netmagazine.com/)
11
12// Wait for the DOM to be loaded before initialising the media player
13document.addEventListener("DOMContentLoaded", function() { initialiseMediaPlayer(); }, false);
14
15// Variables to store handles to various required elements
16var mediaPlayer;
17var playPauseBtn;
18var muteBtn;
19var progressBar;
20
21var mediaPlaybackMode = null;
22
23var mediaStartPlayTime;
24var mediaStartPauseTime;
25var mediaPlayedNotes;
26
27var recordedNotesArray = null;
28
29var hasLocalStorage = (typeof(Storage) !== "undefined");
30
31function initialiseMediaPlayer() {
32
33 setPlaybackMode();
34
35 mediaStartPlayTime = null;
36 mediaStartPauseTime = null;
37 mediaPlayedNotes = {};
38
39 // Get a handle to the player
40 mediaPlayer = document.getElementById('video');
41
42 // Get handles to each of the buttons and required elements
43 playPauseBtn = document.getElementById('play-pause-button');
44 muteBtn = document.getElementById('mute-button');
45 progressBar = document.getElementById('progress-bar');
46
47 // Hide the browser's default controls
48 mediaPlayer.controls = false;
49
50 // Add a listener for the timeupdate event so we can update the progress bar
51 mediaPlayer.addEventListener('timeupdate', updateProgressBar, false);
52
53 // Add a listener so the video can be advanced if the progress bar is clicked on
54 progressBar.addEventListener("change", progressBarChanged);
55
56
57 // Pause the video when the slider handle is being dragged
58 progressBar.addEventListener("mousedown", function() {
59 mediaPlayer.pause();
60 });
61
62 // Play the video when the slider handle is dropped
63 progressBar.addEventListener("mouseup", function() {
64 mediaPlayer.play();
65 });
66
67 // Add a listener for the play and pause events so the buttons state can be updated
68 mediaPlayer.addEventListener('play', function() {
69 // Change the button to be a pause button
70 changeButtonType(playPauseBtn, 'buttonx2 pause');
71 }, false);
72 mediaPlayer.addEventListener('pause', function() {
73 // Change the button to be a play button
74 changeButtonType(playPauseBtn, 'buttonx2 play');
75 }, false);
76
77 // need to work on this one more...how to know it's muted?
78 mediaPlayer.addEventListener('volumechange', function(e) {
79 // Update the button to be mute/unmute
80 if (mediaPlayer.muted) changeButtonType(muteBtn, 'button unmute');
81 else changeButtonType(muteBtn, 'button mute');
82 }, false);
83
84 mediaPlayer.addEventListener('ended', stopPlayer, false);
85}
86
87function togglePlayPause() {
88 // If the mediaPlayer is currently paused or has ended
89 console.log("togglePlayPause()");
90 //console.log("*** mediaPlayer (paused,ended): (" + mediaPlayer.paused + "," + mediaPlayer.ended + ")");
91 //console.log("*** currentTime = " + mediaPlayer.currentTime);
92
93 if (mediaPlayer.paused || mediaPlayer.ended) {
94 if (mediaStartPlayTime == null) {
95 // Fresh play start
96 console.log("**** mediaPlaybackMode = " + mediaPlaybackMode);
97
98 mediaStartPlayTime = Date.now();
99 //console.log("*** mediaStartPlayTime=" + mediaStartPlayTime);
100 mediaPlayedNotes[String(mediaStartPlayTime)] = [];
101
102 }
103 else {
104 // Resume playing
105 var mediaPauseBuildup = mediaStartPauseTime - Date.now();
106
107 // adjust the start play time to the pause is effectively ignored
108 mediaStartPlayTime += mediaPauseBuildup;
109 mediaStartPauseTime = null;
110
111 }
112
113 // Change the button to be a pause button
114 changeButtonType(playPauseBtn, 'buttonx2 pause');
115 // Play the media
116 mediaPlayer.play();
117 }
118 // Otherwise it must currently be playing
119 else {
120 // put into pause state
121
122 mediaStartPauseTime = Date.now();
123
124 // Change the button to be a play button
125 changeButtonType(playPauseBtn, 'buttonx2 play');
126 // Pause the media
127 mediaPlayer.pause();
128
129 console.log("*** mediaPlayedNotes = " + JSON.stringify(mediaPlayedNotes));
130 }
131}
132
133function _pad(n, width, z) {
134 z = z || '0';
135 n = n + '';
136 return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
137}
138
139function convertSecsToTimeStr(time)
140{
141 var int_mins = Math.floor(time / 60);
142 var float_secs = time % 60;
143
144 var padded_secs = _pad(float_secs.toFixed(1),4); // (2), 5 for 2 dec place
145 return int_mins + ":" + padded_secs
146}
147
148
149function displayCurrentTime()
150{
151 var currentTime = mediaPlayer.currentTime;
152 var formattedTime = convertSecsToTimeStr(currentTime);
153 $('#mediaPlayerCurrentTime').html(formattedTime);
154
155 updateGameOnCurrentTimeline();
156}
157
158function displayDuration(duration)
159{
160 var formattedTime = convertSecsToTimeStr(duration);
161 $('#mediaPlayerTotalTime').html(formattedTime);
162}
163
164
165// Stop the current media from playing, and return it to the start position
166
167function stopPlayer()
168{
169 console.log("stopPlayer()");
170 mediaPlayer.pause();
171
172 if (mediaPlaybackMode == "record") {
173 recordedNotesArray = mediaPlayedNotes[String(mediaStartPlayTime)];
174 if (recordedNotesArray.length>0) {
175 // non-trival data recorded
176 $('#save-recording-popup').dialog('open');
177 }
178 }
179
180 mediaStartPlayTime = null;
181 mediaStartPauseTime = null;
182
183 mediaPlayer.currentTime = 0;
184 displayCurrentTime();
185
186}
187
188// Changes the volume on the media player
189function changeVolume(direction) {
190 if (direction === '+') mediaPlayer.volume += mediaPlayer.volume == 1 ? 0 : 0.1;
191 else mediaPlayer.volume -= (mediaPlayer.volume == 0 ? 0 : 0.1);
192 mediaPlayer.volume = parseFloat(mediaPlayer.volume).toFixed(1);
193}
194
195// Toggles the media player's mute and unmute status
196function toggleMute() {
197 if (mediaPlayer.muted) {
198 // Change the cutton to be a mute button
199 changeButtonType(muteBtn, 'button mute');
200 // Unmute the media player
201 mediaPlayer.muted = false;
202 }
203 else {
204 // Change the button to be an unmute button
205 changeButtonType(muteBtn, 'button unmute');
206 // Mute the media player
207 mediaPlayer.muted = true;
208 }
209}
210
211// Replays the media currently loaded in the player
212function replayMedia() {
213 resetPlayer();
214 mediaPlayer.play();
215}
216
217
218
219
220// Update the progress bar
221function updateProgressBar() {
222 // Work out how much of the media has played via the duration and currentTime parameters
223 var percentage = (100 / mediaPlayer.duration) * mediaPlayer.currentTime;
224
225 // Update the progress bar's value
226 progressBar.value = percentage;
227
228 // Update the progress bar's text (for browsers that don't support the progress element)
229 progressBar.innerHTML = Math.floor(percentage) + '% played';
230
231 displayCurrentTime();
232}
233
234function progressBarChanged() {
235 //console.log("**** progress bar changed!")
236 // Calculate the new time
237 var time = mediaPlayer.duration * (progressBar.value / 100);
238
239 // Update the video time
240 mediaPlayer.currentTime = time;
241 displayCurrentTime();
242}
243
244// Updates a button's title, innerHTML and CSS class to a certain value
245function changeButtonType(btn, value) {
246 //btn.title = value;
247 btn.innerHTML = value;
248 btn.className = value;
249}
250
251// Loads a video item into the media player
252function loadVideo() {
253 for (var i = 0; i < arguments.length; i++) {
254 var file = arguments[i].split('.');
255 var ext = file[file.length - 1];
256 // Check if this media can be played
257 if (canPlayVideo(ext)) {
258 // Reset the player, change the source file and load it
259 resetPlayer();
260 mediaPlayer.src = arguments[i];
261 mediaPlayer.load();
262 break;
263 }
264 }
265}
266
267// Checks if the browser can play this particular type of file or not
268function canPlayVideo(ext) {
269 var ableToPlay = mediaPlayer.canPlayType('video/' + ext);
270 if (ableToPlay == '') return false;
271 else return true;
272}
273
274
275// Resets the media player
276function resetPlayer() {
277 mediaStartPlayTime = null;
278 mediaStartPauseTime = null;
279
280 // Reset the progress bar to 0
281 progressBar.value = 0;
282 // Move the media back to the start
283 mediaPlayer.currentTime = 0;
284 displayCurrentTime();
285 // Ensure that the play pause button is set as 'play'
286 changeButtonType(playPauseBtn, 'buttonx2 play');
287}
288
289
290function setPlaybackMode()
291{
292 //console.log("setPlaybackMode()");
293 mediaPlaybackMode = $('input[name=mpm-radio]:checked', '#mpmForm').val();
294}
295
296
297
298function saveRecording()
299{
300 var valid = true;
301
302 var $save_name_input = $("#save-recording-name");
303 var save_name = $save_name_input.val();
304
305 if (save_name.match(/^\s*$/)) {
306 valid = false;
307 $save_name_input.addClass( "ui-state-error" );
308 }
309 else {
310
311 if (hasLocalStorage) {
312 var docOID = gs.cgiParams.d;
313
314 var docStorageStr = localStorage.getItem(docOID);
315 var docStorage = (docStorageStr != null) ? eval("("+docStorageStr+")") : {palTracks:{}, popTracks:{}};
316
317 var palTracks = docStorage.palTracks;
318
319 // Make timing information relative to ba base value
320 var num_rec_notes = recordedNotesArray.length;
321
322 var base_time_sct = recordedNotesArray[0].startCurrentTime;
323 var base_time_mnon = recordedNotesArray[0].midiNoteOn;
324 var base_time_moff = recordedNotesArray[0].midiNoteOff;
325 var base_time_spt = recordedNotesArray[0].startPercTime;
326
327 for (var i=0; i<num_rec_notes; i++) {
328 recordedNotesArray[i].startCurrentTime -= base_time_sct;
329 recordedNotesArray[i].midiNoteOn -= base_time_mnon;
330 recordedNotesArray[i].midiNoteOff -= base_time_moff;
331 recordedNotesArray[i].startPercTime -= base_time_spt;
332 }
333
334 palTracks[save_name] = [ { name: save_name + " 1", baseCTime: base_time_sct, events: recordedNotesArray } ]
335
336 console.log("Storing " + num_rec_notes + " recorded notes as layer '" + save_name +"'");
337 console.log("**** saved: " + JSON.stringify(palTracks[save_name]));
338
339 localStorage.setItem(docOID, JSON.stringify(docStorage));
340 }
341 else {
342 console.log("Warning: unable to save '" + save_name +"' as browser does not support LocalStorage");
343 }
344
345
346 var $dialog = $('#save-recording-popup');
347 $dialog.dialog( "close" );
348 }
349
350 return valid;
351}
352
353
354$(document).ready(function() {
355 // Setup dialog
356
357 var dialog = $('#save-recording-popup').dialog({
358 width : 500,
359 height: 350,
360 autoOpen: false, // Do not open on page load
361 modal: true, // Freeze the background behind the overlay
362
363 show: {
364 effect: "blind",
365 duration: 1000
366 },
367 hide: {
368 effect: "blind",
369 duration: 500
370 },
371
372 buttons: {
373 "Save Recording": saveRecording,
374 Cancel: function() {
375 dialog.dialog("close");
376 }
377 },
378 close: function() {
379 form[0].reset();
380 $( "#save-recording-name" ).removeClass( "ui-state-error" );
381 }
382 });
383
384 var form = dialog.find( "form" ).on( "submit", function( event ) {
385 event.preventDefault();
386 });
387
388
389});
390
Note: See TracBrowser for help on using the repository browser.