From 9d5dd4eb2922b0219cc372f2c63b17ff4fbf6fbc Mon Sep 17 00:00:00 2001 From: riccardo Date: Tue, 31 May 2011 15:33:13 +0200 Subject: [PATCH] separation timeside vs telemeta, moved/added/removed folder/files, restyle of code, --- telemeta/htdocs/css/player.css | 13 +- telemeta/htdocs/js/application.js | 104 +- .../htdocs/{timeside => }/js/divmarker.js | 35 +- telemeta/htdocs/js/playerLoader.js | 383 ++++++ telemeta/htdocs/js/playlist.js | 26 +- .../js/libs}/jquery-1.6.min.js | 0 .../timeside/js/{ => libs}/raphael-min.js | 0 .../{ => libs}/soundmanager2-nodebug-jsmin.js | 0 .../timeside/js/{ => libs}/soundmanager2.js | 0 telemeta/htdocs/timeside/js/markermap.js | 161 +-- telemeta/htdocs/timeside/js/player.js | 549 ++++---- telemeta/htdocs/timeside/js/playerLoader.js | 215 ---- telemeta/htdocs/timeside/js/ruler.js | 41 +- telemeta/htdocs/timeside/js/rulermarker.js | 4 +- telemeta/htdocs/timeside/js/timeside.js | 528 ++++++-- telemeta/htdocs/timeside/js/wz_jsgraphics.js | 1108 ----------------- .../htdocs/timeside/skins/lab/img/forward.png | Bin 622 -> 620 bytes .../htdocs/timeside/skins/lab/img/pause.png | Bin 446 -> 442 bytes .../htdocs/timeside/skins/lab/img/play.png | Bin 584 -> 582 bytes .../htdocs/timeside/skins/lab/img/rewind.png | Bin 628 -> 623 bytes .../timeside/skins/lab/img/setmarker.png | Bin 668 -> 666 bytes .../htdocs/timeside/skins/lab/img/wait.gif | Bin 0 -> 10819 bytes .../htdocs/timeside/skins/lab/img/wait2.gif | Bin 0 -> 2248 bytes telemeta/htdocs/timeside/skins/lab/style.css | 71 +- telemeta/templates/telemeta_default/base.html | 3 +- .../telemeta_default/collection_detail.html | 32 +- telemeta/templates/telemeta_default/home.html | 6 +- .../telemeta_default/mediaitem_detail.html | 72 +- 28 files changed, 1349 insertions(+), 2002 deletions(-) rename telemeta/htdocs/{timeside => }/js/divmarker.js (92%) create mode 100644 telemeta/htdocs/js/playerLoader.js rename telemeta/htdocs/{js => timeside/js/libs}/jquery-1.6.min.js (100%) rename telemeta/htdocs/timeside/js/{ => libs}/raphael-min.js (100%) rename telemeta/htdocs/timeside/js/{ => libs}/soundmanager2-nodebug-jsmin.js (100%) rename telemeta/htdocs/timeside/js/{ => libs}/soundmanager2.js (100%) delete mode 100644 telemeta/htdocs/timeside/js/playerLoader.js delete mode 100755 telemeta/htdocs/timeside/js/wz_jsgraphics.js create mode 100644 telemeta/htdocs/timeside/skins/lab/img/wait.gif create mode 100644 telemeta/htdocs/timeside/skins/lab/img/wait2.gif diff --git a/telemeta/htdocs/css/player.css b/telemeta/htdocs/css/player.css index 7e9c2630..7a07bd0f 100644 --- a/telemeta/htdocs/css/player.css +++ b/telemeta/htdocs/css/player.css @@ -84,16 +84,21 @@ ALONE ARE PARSED (eg ".ts-blabla, .ts-marker-canvas{...}" WILL NOT BE RECOGNIZED background: url('../images/player_controlbg.png'); } -.ts-skin-lab .ts-player .ts-control .ts-playback a { +/*.ts-skin-lab .ts-player .ts-control .ts-playback a { padding: 28px 0 0 0; - height /**/:20px; /* for IE5/Win only */ + height :20px; for IE5/Win only + margin-right: 0px; +} + +.ts-skin-lab .ts-player .ts-control a { + height:28px; margin-right: 0px; } .ts-skin-lab .ts-player .ts-control .ts-layout { margin-left: 0px; } - +*/ #player_maximized, #player_minimized { position: relative; } @@ -122,7 +127,7 @@ ALONE ARE PARSED (eg ".ts-blabla, .ts-marker-canvas{...}" WILL NOT BE RECOGNIZED display: none; } -#player .ts-visualizer, .ts-wait{ +#player .ts-visualizer{ margin:5px; } diff --git a/telemeta/htdocs/js/application.js b/telemeta/htdocs/js/application.js index 6f79329f..d616a543 100644 --- a/telemeta/htdocs/js/application.js +++ b/telemeta/htdocs/js/application.js @@ -210,103 +210,13 @@ var json = function(param,method,onSuccessFcn,onErrorFcn){ }; -/** - * Returns an uniqid by creating the current local time in millisecond + a random number. Used for markers and some json calls - */ -var uniqid = function() { - var d = new Date(); - return new String(d.getTime() + '' + Math.floor(Math.random() * 1000000)).substr(0, 18); -}; - -/** - * Loads scripts asynchronously - * can take up to four arguments: - * root (optional): a string specifying the root (such as '/usr/local/'). Must end with slash, otherwise - * each element in scriptArray must begin with a slash - * scriptArray: a string array of js script filenames, such as ['script1.js','script2.js'] - * callback (optional): callback to be executed when ALL scripts are succesfully loaded - * loadInSeries (optional): if true scripts are loaded in synchronously, ie each script is loaded only once the - * previous has been loaded. The default (argument missing) is false - * - * Examples. Given scripts = ['s1.js', 's2.js'] - * loadScripts(scripts) //loads (asynchronously) scripts - * loadScripts('/usr/', scripts) //loads (asynchronously) ['/usr/s1.js', '/usr/s2.js'] - * loadScripts(scripts, callback) //loads (asynchronously) scripts. When loaded, executes callback - * loadScripts('/usr/', scripts, callback) //loads (asynchronously) ['/usr/s1.js', '/usr/s2.js']. When loaded, executes callback - * loadScripts(scripts, callback, true) //loads (synchronously) scripts. When loaded, executes callback - * loadScripts('/usr/', scripts, callback, true) //loads (synchronously) ['/usr/s1.js', '/usr/s2.js']. When loaded, executes callback - * - */ -function loadScripts(){ - var optionalRoot='', scriptArray=[], callback=undefined, loadInSeries=false; - var len = arguments.length; - if(len==1){ - scriptArray = arguments[0]; - }else if(len==2){ - if(typeof arguments[0] == 'string'){ - optionalRoot = arguments[0]; - scriptArray = arguments[1]; - }else{ - scriptArray = arguments[0]; - callback = arguments[1]; - } - }else if(len>2){ - if(typeof arguments[0] == 'string'){ - optionalRoot = arguments[0]; - scriptArray = arguments[1]; - callback = arguments[2]; - if(len>3){ - loadInSeries = arguments[3]; - } - }else{ - scriptArray = arguments[0]; - callback = arguments[1]; - loadInSeries = arguments[2]; - } - } - - if(!scriptArray){ - if(callback){ - callback(); - } - return; - } - len = scriptArray.length; - var i=0; - if(optionalRoot){ - for(i =0; i=this.length){ + return; + } var div = this._super(index); div.remove(); var me = this; @@ -205,15 +211,15 @@ var MarkerMapDiv = TimesideArray.extend({ createMarkerDiv : function(index, marker){ //create html content. Use array.join cause it is usually faster than string concatenation: var html_ = ['
', //whitespace no wrap is really important to keep all content of first div on one line (without it, IE displays it on 2 lines) - '', - '', - '', - '', - 'EDIT', - '', - '
', - '
', - '
OK
', + '', + '', + '', + '', + 'EDIT', + '', + '', + '
', + '
OK
', '
'+gettrans('author')+': '+marker.author+'
'].join(""); var div = this.$J('
').attr('tabindex','0').addClass("markerdiv").html(html_); div.find('a').attr('href','#'); @@ -259,6 +265,7 @@ var MarkerMapDiv = TimesideArray.extend({ //note that marker.id (client side) is marker.public_id (server side) json([marker.id],"telemeta.get_marker_id", function(data){ var id = data.result; + //TODO: we should not call global objects, rather pass them in the construcotr: playlistUtils.showAddResourceToPlaylist(e_addplaylistButton,'marker',""+id,gettrans('marker added to the selected playlist')); }); return false; diff --git a/telemeta/htdocs/js/playerLoader.js b/telemeta/htdocs/js/playerLoader.js new file mode 100644 index 00000000..ff758c13 --- /dev/null +++ b/telemeta/htdocs/js/playerLoader.js @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * Copyright (c) 2010 Olivier Guilyardi + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Authors: Riccardo Zaccarelli + * Olivier Guilyardi + */ + +/** + * Class for loading a player. Requires a div#player, jQuery and all timeside javascript (player.js, markermap.js etcetera) + */ + +//var player; //global player variable + +function togglePlayerMaximization() { + var $ = jQuery; + var view = $('#player'); + $('#player_maximized, #player_minimized').css('display', 'none'); + var ctr; + var dynamicResize = false; + if (view.parents('#player_maximized').length) { + ctr = $('#player_minimized').append(view); + } else { + ctr = $('#player_maximized').append(view); + dynamicResize = true; + } + ctr.css({ + opacity: 0, + display: 'block' + }); + var p = Timeside.player; + if (p){ + p.resize(); + } + ctr.animate({ + opacity: 1 + }, 100); + if (p){ + p.setDynamicResize(dynamicResize); + } +} + +//end(''): clears loading span, if any +//end('msg') if loading span is there, clear loading span. If loading span is there, display alert msg + +function end(optionalErrorMsg){ + var $ = jQuery; + var elm = $('#loading_span'); + if(elm.length<1){ + return; + } + elm.empty().remove(); + if(optionalErrorMsg){ + $('#rightcol').hide(); + alert(optionalErrorMsg); + } +} + +function loadPlayer(analizerUrl, soundUrl, itemId, visualizers, currentUserName, isStaffOrSuperuser){ + var $J = jQuery; + var wdw = window; + //grab the case of soundManager init errors: + soundManager.onerror = function() { + end('SoundManager error. If your browser does not support HTML5, Flash player (version '+soundManager.flashVersion+'+) must be installed.\nIf flash is installed, try to:\n - Reload the page\n - Empty the cache (see browser preferences/options/tools) and reload the page\n - Restart the browser'); + }; + + + + //we load the player once the window is fully loaded. Note that the function Timeside.load (called within this method) + //is started on $J(wdw), so it will be executed immediately. The reason of a 'double' $K(wdw) + //is that we want to display some messages on html spans (which therefore must exist) and that if the + //div#player does not exist the Timeside.load throws an error that the + //function end (see above) will convert in an alert dialog. The problem is that the non existence of div#player + //is not always an error, (eg, the user not logged in and the item has only metadata public). + //Ideally, we should not enter here in some cases. For the moment we just catch the case div#player doesnt exist and + //we return + $J(wdw).ready(function(){ + var maxTime = 10000; + //if the loading span is still visible in 10 seconds, throw an error: + setTimeout(function(){ + end('SoundManager is not responding. Try to:\n - Reload the page\n - Empty the cache (see browser preferences) and reload the page\n - Restart the browser'); + },maxTime); + + // var playerDiv = $J('#player'); + // var markersUI = $J("#markers_div_id"); + + var playerDiv = '#player'; + if(!($J(playerDiv).length)){ + end(); + } + + var markersUI = "#markers_div_id"; + var msgElm = $J('#loading_span_text').html('Loading sound info...'); + var uinqid_ = Timeside.utils.uniqid; //defined in application.js + var pFloat = parseFloat; + //load analyser xml and proceed on success: + $J.ajax({ + url: analizerUrl, //'analyze/xml', + dataType: 'xml', + success: function(data){ + //populatetable + var content = []; //content is an array which we will transform in table innerHTML via the method join + //which is faster in some browsers than string concatenation + $J.each($J(data).find('data'),function(index,element){ + var elm = $J(element); + content.push(''); + content.push(elm.attr('name')); + content.push(''); + content.push(elm.attr('value')); + content.push(''); + content.push(elm.attr('unit')); + content.push(''); + // tableBody.append(''+elm.attr('name')+''+elm.attr('value')+'' + // +elm.attr('unit')+''); + }); + + $J('#analyzer_div_id').find('table').find('tbody:last').append(content.join("")); + + + + //loaded analizer, loading player + msgElm.html('Loading markers...'); + + var duration = $J(data).find('#duration').attr('value'); + duration = duration.split(":"); + //format duration + var pin = parseInt; + + var timeInMSecs=pin(duration[0])*3600+pin(duration[1])*60+pFloat(duration[2]); + timeInMSecs = Math.round(timeInMSecs*1000); + var callbackAfterMarkersLoading = function(data) { + var markerMap = []; + + if(data && data.result && data.result.length>0){ + var result = data.result; + + //add markers to the map. No listeners associated to it (for the moment) + //var mapAdd = map.add; + for(var i =0; i< result.length; i++){ + + var argument = result[i]; + var marker = { + id: argument.public_id, + offset: pFloat(argument.time), //IMPORTANT: IT IS A STRING!!!!!! + desc: argument.description, + title: argument.title, + author: argument.author, + isEditable: argument.author === currentUserName || isStaffOrSuperuser, + canBeAddedToPlaylist: currentUserName ? true : false, + isSavedOnServer: true + }; + markerMap.push(marker); + //mapAdd.apply(map,[result[i]]); + } + //add markers to ruler and div + // map.each(function(i,marker){ + // rulerAdd.apply(ruler,[marker, i]); + // mapuiAdd.apply(mapUI,[marker, i]); + // }); + + //tabIndex = result.length>0 ? 1 : 0; + } + + //defining the marker callback: + + var markerMode = currentUserName || false; + if(markerMode){ + //markerMode becomes a function: + markerMode = function(offset){ + var m = { + id: uinqid_(), + offset: pFloat(offset), + desc: "", + title: "", + author: currentUserName, + isEditable: true, + canBeAddedToPlaylist: true, + isSavedOnServer: false + }; + return m; + }; + } + msgElm.html('Loading player...'); + consolelog(visualizers); + var visualizersSelectElement = $J(' tag + var imageSrcFcn = function(width,height){ + var player_image_url = visualizers[""+visualizersSelectElement.val()]; + var _src_ = null; + if (player_image_url && (width || height)) { + _src_ = player_image_url.replace('WIDTH', width + '').replace('HEIGHT', height + ''); + } + return _src_; + }; + + + //function(container, soundUrl, durationInMsec, visualizers, markerMap, showAddMarkerButton, onError,onReady ){ + Timeside.load(playerDiv,soundUrl,timeInMSecs,imageSrcFcn,markerMap,markerMode, function(msg){ + end(msg); + }, + function(player){ + msgElm.html('Setting up player...'); + var mapUI = new Timeside.classes.MarkerMapDiv(markersUI); + player.getMarkerMap().each(function(i,marker){ + mapUI.add(marker,i,false); + }); + Timeside.markerMapDiv = mapUI; + //bind add marker -> markerdiv add: + player.bind('markerAdded', function(data){ + //select the marker tab: + var tab = $J('#tab_markers'); + if(tab && tab.length){ + tab.trigger('click'); + } + mapUI.add.apply(mapUI,[data.marker, data.index, true]); + }); + //bind move marker -> markerdiv move: + player.bind('markerMoved', function(data){ + mapUI.move.apply(mapUI,[data.fromIndex,data.toIndex,data.marker.offset]); + }); + //bind move marker -> markerdiv move: + player.bind('markerRemoved', function(data){ + mapUI.remove.apply(mapUI,[data.index]); + }); + + //bind remove marker -> player remove -> remove marker + //(wait for json success) + mapUI.bind('remove',function(data){ + var marker = data.marker; + + var functionOnSuccess = function(){ + player.removeMarker.apply(player,[data.marker]);//map.remove + fires markerMoved on player + }; + if(marker.isSavedOnServer){ + //json(param,method,onSuccessFcn,onErrorFcn){ + json([marker.id], "telemeta.del_marker",functionOnSuccess); + }else{ + functionOnSuccess(); + } + + }); + //bind save marker -> player save + var map = player.getMarkerMap(); + if(map){ + mapUI.bind('save',function(data){ + var marker = data.marker; + var idx = map.insertionIndex(marker); + if(idx<0 || idx>=map.length){ + this.debug('marker not found'); + return; + } + + //var itemid = this.getItemId(); //TODO2: NOt anymore used + var isSavedOnServer = marker.isSavedOnServer; + var method = isSavedOnServer ? "telemeta.update_marker" : "telemeta.add_marker"; + var param = { + 'item_id':itemId, + 'public_id': marker.id, + 'time':marker.offset, + 'author': marker.author, + 'title':marker.title, + 'description':marker.desc + }; + + //function on success: + //go back to the marker div to notify tha tis saved + var success = function(){ + if(!isSavedOnServer){ + marker.isSavedOnServer = true; + } + mapUI.setEditMode.apply(mapUI,[idx,false]); + }; + //json(param,method,onSuccessFcn,onErrorFcn){ + json([param], method, success); + }); + } + //bind focus marker - > player focus + mapUI.bind('focus', function(data){ + if(data && 'index' in data){ + if(data.index>=0 && data.index0){ + return gettrans('there is at least one unsaved marker') +' ('+ markerUnsaved+ '). '+ + gettrans('If you exit the page you will loose your changes'); + } + + }; + wdw.onbeforeunload = confirmExit; + } + + //set up the marker tab + var tabIndex = map.length ? 1 : 0; + setUpPlayerTabs($J('#tab_analysis').add($J('#tab_markers')), + [$J('#analyzer_div_id'), $J('#markers_div_id')], tabIndex, + 'tab_selected','tab_unselected'); + //2) and selects the current marker if it is present on the url + var url = wdw.location.href+""; + var lastPart = url.replace(/\/+$/,"").replace(/^.*\/([^\/]*)$/,"$1"); + var selOffs = -1; + map.each(function(i,marker){ + if(marker.id == lastPart){ + selOffs = marker.offset; + } + }); + if(selOffs >= 0){ + player.setSoundPosition(selOffs); + } + //3) assing a binding to the player maximization button: + $J('#player_maximized .toggle, #player_minimized .toggle').click(function() { + togglePlayerMaximization(); + return false; + }); + } + ); + } + json([itemId],"telemeta.get_markers", callbackAfterMarkersLoading,callbackAfterMarkersLoading); + //function(container, soundUrl, durationInMsec, visualizers, markerMap, showAddMarkerButton, onError, onReady){ + //Timeside.load(playerDiv,soundUrl,,timeInMSecs,visualizers,markerMap,) + //load_player(soundUrl, timeInMSecs, itemId, visualizers, currentUserName); + }, + error:function(){ + end('Error loading analyzer'); + } + }); + }); +} + diff --git a/telemeta/htdocs/js/playlist.js b/telemeta/htdocs/js/playlist.js index 5c79837a..c67af157 100644 --- a/telemeta/htdocs/js/playlist.js +++ b/telemeta/htdocs/js/playlist.js @@ -39,9 +39,10 @@ PopupDiv.defaultCloseOperation = 'remove'; PopupDiv.focusable = true; PopupDiv.listItemClass = "component_icon list_item icon_playlist"; + var playlistUtils = { playlists : [], - + addPlaylist: function(name, id){ //this.playlists[name]=id; this.playlists.push({ @@ -58,6 +59,7 @@ var playlistUtils = { dd[t]=''; dd[d]=''; var playlist = this; + consolelog(this); new PopupDiv({ 'content':dd, invoker:anchorElement, @@ -75,12 +77,19 @@ var playlistUtils = { }).show(); }, - - + /** + * Returns an uniqid by creating the current local time in millisecond + a random number. Used for markers and some json calls + * Copied from Timeside.utils.uniqid (Timeside might NOT ALWAYS be loaded, see home.html when user is authenitcated) + * + */ + uniqid : function() { + var d = new Date(); + return new String(d.getTime() + '' + Math.floor(Math.random() * 1000000)).substr(0, 18); + }, add : function(dictionary){ if(dictionary.public_id===undefined){ - dictionary.public_id = uniqid(); //defined in application.js + dictionary.public_id = this.uniqid(); //defined in application.js } if(dictionary.user===undefined){ dictionary.user = CURRENT_USER_NAME; @@ -97,7 +106,7 @@ var playlistUtils = { window.location.reload(); }); }, - + removeResource: function(id){ json([id],'telemeta.del_playlist_resource',function(){ window.location.reload(); @@ -115,7 +124,8 @@ var playlistUtils = { if(!ar.length){ return; } - var addFcn = this.addResourceToPlaylist; + var pl = this; + //var addFcn = this.addResourceToPlaylist; new PopupDiv({ invoker:anchorElement, content: ar, @@ -135,7 +145,7 @@ var playlistUtils = { p.show(); } } - addFcn(playlists[val].id,resourceType,objectId,callbackok); + pl.addResourceToPlaylist.apply(pl,[playlists[val].id,resourceType,objectId,callbackok]); } }).show(); @@ -144,7 +154,7 @@ var playlistUtils = { //resourceType can be: 'collection', 'item', 'marker' addResourceToPlaylist: function(playlistId,resourceType,objectId, callbackOnSuccess,callbackOnError){ var send = { - 'public_id':uniqid(), + 'public_id':this.uniqid(), 'resource_type':resourceType, 'resource_id':objectId }; diff --git a/telemeta/htdocs/js/jquery-1.6.min.js b/telemeta/htdocs/timeside/js/libs/jquery-1.6.min.js similarity index 100% rename from telemeta/htdocs/js/jquery-1.6.min.js rename to telemeta/htdocs/timeside/js/libs/jquery-1.6.min.js diff --git a/telemeta/htdocs/timeside/js/raphael-min.js b/telemeta/htdocs/timeside/js/libs/raphael-min.js similarity index 100% rename from telemeta/htdocs/timeside/js/raphael-min.js rename to telemeta/htdocs/timeside/js/libs/raphael-min.js diff --git a/telemeta/htdocs/timeside/js/soundmanager2-nodebug-jsmin.js b/telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug-jsmin.js similarity index 100% rename from telemeta/htdocs/timeside/js/soundmanager2-nodebug-jsmin.js rename to telemeta/htdocs/timeside/js/libs/soundmanager2-nodebug-jsmin.js diff --git a/telemeta/htdocs/timeside/js/soundmanager2.js b/telemeta/htdocs/timeside/js/libs/soundmanager2.js similarity index 100% rename from telemeta/htdocs/timeside/js/soundmanager2.js rename to telemeta/htdocs/timeside/js/libs/soundmanager2.js diff --git a/telemeta/htdocs/timeside/js/markermap.js b/telemeta/htdocs/timeside/js/markermap.js index 0a8345bb..c9d9cab2 100644 --- a/telemeta/htdocs/timeside/js/markermap.js +++ b/telemeta/htdocs/timeside/js/markermap.js @@ -25,45 +25,24 @@ * two TimesideArrays of the player which receive edit events (click, keys events etcetera): the ruler (ruler.js) and the markermapdiv (divmarker.js) * All bindings between these three classes are set in in the player (See player.js , in particular loadMarkers method) */ -var MarkerMap = TimesideArray.extend({ +Timeside.classes.MarkerMap = Timeside.classes.TimesideArray.extend({ - init: function(itemId, currentUserName, isStaffOrSuperuser) { + init: function() { this._super(); - var ui = uniqid; //defined in application.js (global vars and functions) - this.uniqid = function(){ - return ui(); - }; - this.getItemId = function(){ - return itemId; - } - this.getCurrentUserName = function(){ - return currentUserName; - } - this.isCurrentUserStaffOrSuperuser = function(){ - return isStaffOrSuperuser; - } - - var me = this; - var confirmExit = function(){ - var markerUnsaved=0; - me.each(function(i,marker){ - if(!marker.isSavedOnServer){ - markerUnsaved++; - } - }); - if(markerUnsaved>0){ - return gettrans('there is at least one unsaved marker') +' ('+ markerUnsaved+ '). '+ - gettrans('If you exit the page you will loose your changes'); - } - - }; - window.onbeforeunload = confirmExit; }, + pFloat: parseFloat, //reference to function parseFloat for faster lookup //overridden add: function(obj) { //var markers = this.toArray(); - var marker = this.createMarker(obj); + + if(!('offset' in obj)){ + return -1; + } + if(typeof obj.offset != 'number'){ //check to be sure: + obj.offset = this.pFloat(obj.offset); + } + var marker = obj; //this.createMarker(obj); var idx = this.insertionIndex(marker); if(idx>=0){ //it exists? there is a problem.... this.debug('adding a marker already existing!!'); //should not happen. however... @@ -77,8 +56,8 @@ var MarkerMap = TimesideArray.extend({ this.fire('add', { marker: marker, - index: idx, - isNew: (typeof obj == 'number' || typeof obj == 'string') + index: idx + //,isNew: (typeof obj == 'number' || typeof obj == 'string') }); //var temp = new MarkerDiv(); // this.debug(this.createMarkerDiv()); @@ -86,56 +65,9 @@ var MarkerMap = TimesideArray.extend({ return idx; }, - - //argument is either an object loaded from server or a number specifying the marker offset - createMarker: function(argument){ - var marker = null; - var pFloat = parseFloat; - if(typeof argument == 'string'){ //to be sure, it might be that we pass an offset in string format - argument = pFloat(argument); - } - var currentUserName = this.getCurrentUserName(); - var isStaffOrSuperuser = this.isCurrentUserStaffOrSuperuser(); - if(typeof argument == 'object'){ - var editable = isStaffOrSuperuser || currentUserName === argument.author; - var canBeAddedToPlaylist_ = currentUserName ? true : false; - marker = { - id: argument.public_id, - offset: pFloat(argument.time), //IMPORTANT: IT IS A STRING!!!!!! - desc: argument.description, - title: argument.title, - author: argument.author, - isEditable: editable, - canBeAddedToPlaylist: canBeAddedToPlaylist_, - isSavedOnServer: true - }; - }else if(typeof argument == 'number'){ - marker = { - id: this.uniqid(), - offset: pFloat(argument), - desc: "", - title: "", - author: currentUserName, - isEditable: true, - canBeAddedToPlaylist: true, - isSavedOnServer: false - }; - } - marker.toString = function(){ - var props = []; - for(var prop in this){ - if(!(prop == 'toString')){ - props.push(prop+': '+this[prop]); - } - } - return props.sort().join("\n"); - } - return marker; - - }, //overridden - //markerOrIndex can be an number (marker index) or a marker (the index will be aearched) + //identifier can be an number (marker index) or a marker (the index will be aearched) remove: function(identifier) { var idx = -1; if(typeof index == 'number'){ @@ -145,62 +77,14 @@ var MarkerMap = TimesideArray.extend({ } if(idx<0 || idx>=this.length){ this.debug('remove: marker not found'); - return; - } - - //build the function to be called if the marker is deleted - //if the marker is NOT saved on server, call the function immediately - var marker = this.toArray()[idx]; - var me = this; - var superRemove = me._super; - var functionOnSuccess = function(){ - superRemove.apply(me,[idx]); - me.fire('remove',{ - 'index':idx - }) - } - - if(marker.isSavedOnServer){ - //json(param,method,onSuccessFcn,onErrorFcn){ - json([marker.id], "telemeta.del_marker",functionOnSuccess); - }else{ - functionOnSuccess(); - } - }, - - save: function(marker){ - var idx = this.insertionIndex(marker); - if(idx<0 || idx>=this.length){ - this.debug('marker not found'); - return; + return -1; } - - var itemid = this.getItemId(); - var isSavedOnServer = marker.isSavedOnServer; - var method = isSavedOnServer ? "telemeta.update_marker" : "telemeta.add_marker"; - var param = { - 'item_id':itemid, - 'public_id': marker.id, - 'time':marker.offset, - 'author': marker.author, - 'title':marker.title, - 'description':marker.desc - }; - - //function on success: - var me = this; - var success = function(){ - if(!isSavedOnServer){ - marker.isSavedOnServer = true; - marker.isModified = false; - } - me.fire('save',{ - 'index':idx + var marker = this._super(idx); + this.fire('remove',{ + 'index':idx, + 'marker':marker }); - }; - //json(param,method,onSuccessFcn,onErrorFcn){ - json([param], method, success); - + return idx; }, //overridden method @@ -217,12 +101,13 @@ var MarkerMap = TimesideArray.extend({ var markers = this.toArray(); var marker = markers[realIndex]; + var oldOffset = marker.offset; marker.offset = newOffset; - marker.isModified = true; this.fire('move', { + marker: marker, fromIndex: markerIndex, toIndex: newIndex, - newOffset: newOffset + oldOffset: oldOffset //,newIndex: realIndex }); }, diff --git a/telemeta/htdocs/timeside/js/player.js b/telemeta/htdocs/timeside/js/player.js index ad8e90c5..7af93540 100644 --- a/telemeta/htdocs/timeside/js/player.js +++ b/telemeta/htdocs/timeside/js/player.js @@ -26,20 +26,19 @@ * The player class to instantiate a new player. Requires all necessary js (timeside, ruler, markermap etcetera...) and * jQuery */ -var Player = TimesideClass.extend({ + +//playerDiv, sound, durationInMsec, visualizers, markerMap); +Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ //sound duration is in milliseconds because the soundmanager has that unit, //player (according to timeside syntax) has durations in seconds - init: function(container, sound, soundDurationInMsec, itemId, visualizers, currentUserName, isStaffOrSuperUser) { + init: function(container, sound, soundDurationInMsec, imageCallback, newMarkerCallback) { this._super(); //container is the div #player if (!container){ - this.debug('ERROR: container is null in initializing the player') - } - this.getItemId = function(){ - return itemId; + this.debug('ERROR: container is null in initializing the player'); } this.getContainer = function(){ @@ -48,10 +47,10 @@ var Player = TimesideClass.extend({ this.getSound = function(){ return sound; } - - this.getVisualizers = function(){ - return visualizers; - } + this.imageCallback = imageCallback; +// this.getVisualizers = function(){ +// return visualizers; +// } var sd = this.toSec(soundDurationInMsec); this.getSoundDuration = function(){ @@ -85,14 +84,27 @@ var Player = TimesideClass.extend({ //initializing markermap and markerui - var map = new MarkerMap(this.getItemId(), currentUserName, isStaffOrSuperUser); + var map = new Timeside.classes.MarkerMap(); this.getMarkerMap = function(){ return map; } - var mapUI = new MarkerMapDiv(); - this.getMarkersUI = function(){ - return mapUI; + + if(newMarkerCallback){ + this.canAddMarker = function(){ + return true; + } + if(typeof newMarkerCallback === 'function'){ + this.newMarker = newMarkerCallback; + } + }else{ + this.canAddMarker = function(){ + return false; + } } + // var mapUI = new Timeside.classes.MarkerMapDiv(); + // this.getMarkersUI = function(){ + // return mapUI; + // } }, //functions for converting seconds (player unit) to milliseconds (sound manager unit) and viceversa: toSec: function(milliseconds){ @@ -150,8 +162,8 @@ var Player = TimesideClass.extend({ var sound = player.getSound(); var imgWaitDisplaying = this.isWaitVisible(); //soundManager multishot set false should prevent the play when already playing. We leave this check for safety - if(!player || player.isPlaying() || !sound){ - if(imgWaitDisplaying){ + if(!player || !sound){ + if(!player.isPlaying() && imgWaitDisplaying){ this.setWait(false); } return false; @@ -161,15 +173,18 @@ var Player = TimesideClass.extend({ var ruler = player.getRuler(); var sPosInMsec = player.toMsec(player.soundPosition); - + var waitDiv = this.getContainer().find('.ts-wait'); + var bufferingString = 'buffering'; + var forceWait = !imgWaitDisplaying || waitDiv.html() != bufferingString; var playOptions = { position: sPosInMsec, whileplaying: function(){ var sPos = this.position; var buffering = this.isBuffering; //this refers to the soundmanager sound obj - if(buffering && !imgWaitDisplaying){ - imgWaitDisplaying=true; - player.setWait.apply(player,[true]); + if(buffering && (forceWait || !imgWaitDisplaying)){ + imgWaitDisplaying = true; + forceWait = false; + player.setWait.apply(player,[bufferingString]); }else if(!buffering && sPosInMsec < sPos){ //isBuffering seems to be true at regular interval, so we could be in the case //that !buffering but is actually buffering and no sound is heard, so @@ -200,6 +215,7 @@ var Player = TimesideClass.extend({ sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play sound.play(playOptions); + return false; }, pause: function(){ @@ -208,7 +224,6 @@ var Player = TimesideClass.extend({ //if(sound && this.isPlaying()){ sound.stop(); this.setWait(false); - //} return false; }, isWaitVisible: function(){ @@ -216,18 +231,24 @@ var Player = TimesideClass.extend({ }, setWait: function(value, optionalCallback){ var c = this.getContainer(); - var imgWait = c.find('.ts-wait'); - var selectVis = c.find('.ts-visualizer'); + var waitDiv = c.find('.ts-wait'); + + var player = this; var wait = function(){}; if(value){ + var wtext = ""; + if(typeof value == 'string'){ + wtext = value; + } + waitDiv.html(wtext); wait= function(){ - selectVis.hide(); - imgWait.css('display','inline-block'); + waitDiv.css('display','inline-block'); + player.fire('waiting',{'value': wtext || true}); //assures is a string or a true boolean }; }else{ wait = function(){ - imgWait.hide(); - selectVis.css('display','inline-block'); + waitDiv.hide(); + player.fire('waiting',{'value':false}); } } var delay = 100; @@ -243,7 +264,7 @@ var Player = TimesideClass.extend({ //sets up the player interface and loads the markers. There is theoretically no need for this method, as it might be included in //the init constructor, it is separated for "historical" reasons: this method stems from the old _setupInterface, //which was a separate method in the old player code. Future releases might include it in the init constructor - setupInterface: function(callback) { + setupInterface: function(markersArray) { var sound = this.getSound(); this.debug('player _setupInterface sound.readyState:'+sound.readyState); //handle also cases 0 and 2???? @@ -265,18 +286,19 @@ var Player = TimesideClass.extend({ "
", "", "
", - "
", - "
", + //"
", + //"
", "", "", "", "", "", "", - "", - "", - "
", - "
", + "
", + //"", + //"", + //"
", + //"
", "
"]; this.getContainer().html(html.join('')); @@ -291,21 +313,21 @@ var Player = TimesideClass.extend({ //hide the wait image and set the src - var waitImg = container.find('.ts-wait'); - waitImg.attr('src','/images/wait_small.gif').attr('title','wait...').attr('alt','wait').hide(); + + //waitImg.attr('src','/images/wait_small.gif').attr('title','wait...').attr('alt','wait').hide(); //setting the select option for visualizers: - var visualizers = this.getVisualizers(); - var select = container.find('.ts-visualizer'); - for(var name in visualizers){ - //$J('