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

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

Graphics equalizer tidyup. Tooltips on Game On sections

File size: 13.4 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");
30var trackEditor = null;
31
32function initialiseMediaPlayer() {
33
34 setPlaybackMode();
35
36 mediaStartPlayTime = null;
37 mediaStartPauseTime = null;
38 mediaPlayedNotes = {};
39
40 // Get a handle to the player
41 mediaPlayer = document.getElementById('video');
42
43 // Get handles to each of the buttons and required elements
44 playPauseBtn = document.getElementById('play-pause-button');
45 muteBtn = document.getElementById('mute-button');
46 progressBar = document.getElementById('progress-bar');
47
48 // Hide the browser's default controls
49 mediaPlayer.controls = false;
50
51 // Add a listener for the timeupdate event so we can update the progress bar
52 mediaPlayer.addEventListener('timeupdate', updateProgressBar, false);
53
54 // Add a listener so the video can be advanced if the progress bar is clicked on
55 progressBar.addEventListener("change", progressBarChanged);
56
57
58 // Pause the video when the slider handle is being dragged
59 progressBar.addEventListener("mousedown", function() {
60 mediaPlayer.pause();
61 });
62
63 // Play the video when the slider handle is dropped
64 progressBar.addEventListener("mouseup", function() {
65 mediaPlayer.play();
66 });
67
68 // Add a listener for the play and pause events so the buttons state can be updated
69 mediaPlayer.addEventListener('play', function() {
70 // Change the button to be a pause button
71 changeButtonType(playPauseBtn, 'buttonx2 pause');
72 }, false);
73 mediaPlayer.addEventListener('pause', function() {
74 // Change the button to be a play button
75 changeButtonType(playPauseBtn, 'buttonx2 play');
76 }, false);
77
78 // need to work on this one more...how to know it's muted?
79 mediaPlayer.addEventListener('volumechange', function(e) {
80 // Update the button to be mute/unmute
81 if (mediaPlayer.muted) changeButtonType(muteBtn, 'button unmute');
82 else changeButtonType(muteBtn, 'button mute');
83 }, false);
84
85 mediaPlayer.addEventListener('ended', stopPlayer, false);
86}
87
88function togglePlayPause() {
89 //e = e || window.event;
90 // If the mediaPlayer is currently paused or has ended
91 console.log("togglePlayPause()");
92
93 //console.log("**** event e = " + e);
94
95 //console.log("*** mediaPlayer (paused,ended): (" + mediaPlayer.paused + "," + mediaPlayer.ended + ")");
96 //console.log("*** currentTime = " + mediaPlayer.currentTime);
97
98 if (mediaPlayer.paused || mediaPlayer.ended) {
99 if (mediaStartPlayTime == null) {
100 // Fresh play start
101 console.log("**** mediaPlaybackMode = " + mediaPlaybackMode);
102
103 mediaStartPlayTime = Date.now();
104 //console.log("*** mediaStartPlayTime=" + mediaStartPlayTime);
105 mediaPlayedNotes[String(mediaStartPlayTime)] = [];
106
107 }
108 else {
109 // Resume playing
110 var mediaPauseBuildup = mediaStartPauseTime - Date.now();
111
112 // adjust the start play time to the pause is effectively ignored
113 mediaStartPlayTime += mediaPauseBuildup;
114 mediaStartPauseTime = null;
115
116 }
117
118 // Change the button to be a pause button
119 changeButtonType(playPauseBtn, 'buttonx2 pause');
120 // Play the media
121 mediaPlayer.play();
122 }
123 // Otherwise it must currently be playing
124 else {
125 // put into pause state
126
127 mediaStartPauseTime = Date.now();
128
129 // Change the button to be a play button
130 changeButtonType(playPauseBtn, 'buttonx2 play');
131 // Pause the media
132 mediaPlayer.pause();
133
134 console.log("*** mediaPlayedNotes = " + JSON.stringify(mediaPlayedNotes));
135 }
136
137 // Loose keyboard focus so space-bar for global pause doesn't cause a focused play-button event
138 $('#play-pause-button').blur();
139
140
141}
142
143function _pad(n, width, z) {
144 z = z || '0';
145 n = n + '';
146 return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
147}
148
149function convertSecsToTimeStr(time)
150{
151 var int_mins = Math.floor(time / 60);
152 var float_secs = time % 60;
153
154 var padded_secs = _pad(float_secs.toFixed(1),4); // (2), 5 for 2 dec place
155 return int_mins + ":" + padded_secs
156}
157
158
159function displayCurrentTime()
160{
161 var currentTime = mediaPlayer.currentTime;
162 var formattedTime = convertSecsToTimeStr(currentTime);
163 $('#mediaPlayerCurrentTime').html(formattedTime);
164
165 updateGameOnCurrentTimeline();
166}
167
168function displayDuration(duration)
169{
170 var formattedTime = convertSecsToTimeStr(duration);
171 $('#mediaPlayerTotalTime').html(formattedTime);
172}
173
174
175// Stop the current media from playing, and return it to the start position
176
177function stopPlayer()
178{
179 console.log("stopPlayer()");
180 mediaPlayer.pause();
181
182 if (mediaPlaybackMode == "record") {
183 recordedNotesArray = mediaPlayedNotes[String(mediaStartPlayTime)];
184 if (recordedNotesArray.length>0) {
185 // non-trival data recorded
186 $('#save-recording-popup').dialog('open');
187 }
188 }
189
190 mediaStartPlayTime = null;
191 mediaStartPauseTime = null;
192
193 mediaPlayer.currentTime = 0;
194 displayCurrentTime();
195
196}
197
198// Changes the volume on the media player
199function changeVolume(direction) {
200 if (direction === '+') mediaPlayer.volume += mediaPlayer.volume == 1 ? 0 : 0.1;
201 else mediaPlayer.volume -= (mediaPlayer.volume == 0 ? 0 : 0.1);
202 mediaPlayer.volume = parseFloat(mediaPlayer.volume).toFixed(1);
203}
204
205// Toggles the media player's mute and unmute status
206function toggleMute() {
207 if (mediaPlayer.muted) {
208 // Change the cutton to be a mute button
209 changeButtonType(muteBtn, 'button mute');
210 // Unmute the media player
211 mediaPlayer.muted = false;
212 }
213 else {
214 // Change the button to be an unmute button
215 changeButtonType(muteBtn, 'button unmute');
216 // Mute the media player
217 mediaPlayer.muted = true;
218 }
219}
220
221// Replays the media currently loaded in the player
222function replayMedia() {
223 resetPlayer();
224 mediaPlayer.play();
225}
226
227
228
229
230// Update the progress bar
231function updateProgressBar() {
232 // Work out how much of the media has played via the duration and currentTime parameters
233 var percentage = (100 / mediaPlayer.duration) * mediaPlayer.currentTime;
234
235 // Update the progress bar's value
236 progressBar.value = percentage;
237
238 // Update the progress bar's text (for browsers that don't support the progress element)
239 progressBar.innerHTML = Math.floor(percentage) + '% played';
240
241 displayCurrentTime();
242}
243
244function progressBarChanged() {
245 //console.log("**** progress bar changed!")
246 // Calculate the new time
247 var time = mediaPlayer.duration * (progressBar.value / 100);
248
249 // Update the video time
250 mediaPlayer.currentTime = time;
251 displayCurrentTime();
252}
253
254// Updates a button's title, innerHTML and CSS class to a certain value
255function changeButtonType(btn, value) {
256 //btn.title = value;
257 btn.innerHTML = value;
258 btn.className = value;
259}
260
261// Loads a video item into the media player
262function loadVideo() {
263 for (var i = 0; i < arguments.length; i++) {
264 var file = arguments[i].split('.');
265 var ext = file[file.length - 1];
266 // Check if this media can be played
267 if (canPlayVideo(ext)) {
268 // Reset the player, change the source file and load it
269 resetPlayer();
270 mediaPlayer.src = arguments[i];
271 mediaPlayer.load();
272 break;
273 }
274 }
275}
276
277// Checks if the browser can play this particular type of file or not
278function canPlayVideo(ext) {
279 var ableToPlay = mediaPlayer.canPlayType('video/' + ext);
280 if (ableToPlay == '') return false;
281 else return true;
282}
283
284
285// Resets the media player
286function resetPlayer() {
287 mediaStartPlayTime = null;
288 mediaStartPauseTime = null;
289
290 // Reset the progress bar to 0
291 progressBar.value = 0;
292 // Move the media back to the start
293 mediaPlayer.currentTime = 0;
294 displayCurrentTime();
295 // Ensure that the play pause button is set as 'play'
296 changeButtonType(playPauseBtn, 'buttonx2 play');
297}
298
299
300function setPlaybackMode()
301{
302 //console.log("setPlaybackMode()");
303 mediaPlaybackMode = $('input[name=mpm-radio]:checked', '#mpmForm').val();
304}
305
306
307function toggleGraphicEQ()
308{
309 $('#grapheqControlL').toggle();
310 $('#grapheqControlR').toggle();
311
312 return false;
313
314}
315
316function saveRecording()
317{
318 var valid = true;
319
320 var $save_name_input = $("#save-recording-name");
321 var save_name = $save_name_input.val();
322
323 if (save_name.match(/^\s*$/)) {
324 valid = false;
325 $save_name_input.addClass( "ui-state-error" );
326 }
327 else {
328
329 if (hasLocalStorage) {
330 var docOID = gs.cgiParams.d;
331
332
333 // Force reset of what has been stored for this item
334 //localStorage.setItem(docOID, JSON.stringify(null));
335
336 var docStorage = getDocStorage(docOID);
337
338 //var docStorageStr = localStorage.getItem(docOID);
339 //console.log("*** retrived docStorageStr: " + JSON.stringify(docStorage));
340
341 //// var docStorage = (docStorageStr != null) ? eval("("+docStorageStr+")") : {palTracks:{}, popTracks:{}};
342 //var docStorage = eval("("+docStorageStr+")") || {palTracks:{}, popTracks:{}};
343 //console.log("*** set up docStorage: " + JSON.stringify(docStorage));
344
345 var palTracks = docStorage.palTracks;
346
347 // Make timing information relative to ba base value
348 var num_rec_notes = recordedNotesArray.length;
349
350 var base_time_sct = recordedNotesArray[0].startCurrentTime;
351 var base_time_mnon = recordedNotesArray[0].midiNoteOn;
352 var base_time_moff = recordedNotesArray[0].midiNoteOff;
353 var base_time_spt = recordedNotesArray[0].startPercTime;
354
355 for (var i=0; i<num_rec_notes; i++) {
356 recordedNotesArray[i].startCurrentTime -= base_time_sct;
357 recordedNotesArray[i].midiNoteOn -= base_time_mnon;
358 recordedNotesArray[i].midiNoteOff -= base_time_moff;
359 recordedNotesArray[i].startPercTime -= base_time_spt;
360 }
361
362 palTracks[save_name] = [ { name: save_name + " 1", baseCTime: base_time_sct, events: recordedNotesArray } ]
363
364 console.log("Storing " + num_rec_notes + " recorded notes as layer '" + save_name +"'");
365 console.log("**** saved: " + JSON.stringify(palTracks[save_name]));
366
367 localStorage.setItem(docOID, JSON.stringify(docStorage));
368 }
369 else {
370 console.log("Warning: unable to save '" + save_name +"' as browser does not support LocalStorage");
371 }
372
373 var cb_name = save_name.replace(/[ -]/g,"");
374 var cb_value = save_name;
375 var name = save_name;
376
377 $('#palList').append('<div id="pal'+cb_name+'"><input type="checkbox" '
378 + '" name="'+cb_name+'" value="' + cb_value + '"'
379 + ' checked="checked">'
380 + name + '</div>');
381
382 var $dialog = $('#save-recording-popup');
383 $dialog.dialog( "close" );
384 }
385
386 return valid;
387}
388
389
390$(document).ready(function() {
391 // Setup dialog
392
393 var dialog = $('#save-recording-popup').dialog({
394 width : 500,
395 height: 350,
396 autoOpen: false, // Do not open on page load
397 modal: true, // Freeze the background behind the overlay
398
399 show: {
400 effect: "blind",
401 duration: 800
402 },
403 hide: {
404 effect: "blind",
405 duration: 300
406 },
407
408 buttons: {
409 "Save Recording": saveRecording,
410 Cancel: function() {
411 dialog.dialog("close");
412 }
413 },
414 close: function() {
415 form[0].reset();
416 $( "#save-recording-name" ).removeClass( "ui-state-error" );
417 }
418 });
419
420 var form = dialog.find( "form" ).on( "submit", function( event ) {
421 event.preventDefault();
422 });
423
424
425 var delete_dialog = $('#delete-recording-popup').dialog({
426 resizable: false,
427 autoOpen: false,
428 width: 500,
429 height:200,
430 modal: true,
431
432 show: {
433 effect: "blind",
434 duration: 800
435 },
436 hide: {
437 effect: "blind",
438 duration: 300
439 },
440
441 buttons: {
442 "Delete selected items": function() {
443 // call delete
444 palDeleteConfirmed();
445 $( this ).dialog( "close" );
446 },
447 Cancel: function() {
448 $( this ).dialog( "close" );
449 }
450 }
451 });
452
453
454 var edit_dialog = $('#edit-recording-popup').dialog({
455 resizable: true,
456 autoOpen: false,
457 width: 800,
458 height:600,
459 modal: true,
460
461 show: {
462 effect: "blind",
463 duration: 800
464 },
465 hide: {
466 effect: "blind",
467 duration: 300
468 },
469
470 buttons: {
471 "Save": function() {
472 // call delete
473 palSave();
474 $( this ).dialog( "close" );
475 },
476 Cancel: function() {
477 $( this ).dialog( "close" );
478 }
479 }
480 });
481
482 trackEditor = ace.edit("trackEditor");
483 trackEditor.getSession().setMode("ace/mode/json");
484 trackEditor.getSession().setUseSoftTabs(false);
485 var UndoManager = require("ace/undomanager").UndoManager;
486 trackEditor.getSession().setUndoManager(new UndoManager());
487
488
489});
490
Note: See TracBrowser for help on using the repository browser.