From 7d95e4ffa759d5e1d9df995a20e037713df55fb7 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 27 Feb 2012 17:06:34 -0500 Subject: [PATCH] CC-2430 : Preview tracks in the library + better preview (ability to jump around in clip) - added accept ranges header to the response to enable seek ahead in the music file. --- .../application/controllers/ApiController.php | 45 ++++++- .../layouts/scripts/audio-player.phtml | 13 ++ .../public/js/airtime/library/preview.js | 72 ++++++++++ .../js/airtime/library/preview_jplayer.js | 124 ++++++++++++++++++ .../skin/jplayer.blue.monday.seeking.gif | Bin 0 -> 3284 bytes 5 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 airtime_mvc/application/layouts/scripts/audio-player.phtml create mode 100644 airtime_mvc/public/js/airtime/library/preview.js create mode 100644 airtime_mvc/public/js/airtime/library/preview_jplayer.js create mode 100644 airtime_mvc/public/js/jplayer/skin/jplayer.blue.monday.seeking.gif diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 9b0273a35..805bacbef 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -96,6 +96,37 @@ class ApiController extends Zend_Controller_Action */ public function getMediaAction() { + //Logging::log(print_r($_SERVER, true)); + Logging::log($_SERVER['HTTP_RANGE']); + if (isset($_SERVER['HTTP_RANGE'])) { +/** + if (!preg_match('^bytes=\d*-\d*(,\d*-\d*)*$', $_SERVER['HTTP_RANGE'])) { + header('HTTP/1.1 416 Requested Range Not Satisfiable'); + header('Content-Range: bytes /' . filelength); // Required in 416. + exit; + } +**/ + $ranges = explode(',', substr($_SERVER['HTTP_RANGE'], 6)); + foreach ($ranges as $range) { + $parts = explode('-', $range); + $start = $parts[0]; // If this is empty, this should be 0. + $end = $parts[1]; // If this is empty or greater than than filelength - 1, this should be filelength - 1. + + //the $end shouldn't be specified. + + //if ($start > $end) { + // header('HTTP/1.1 416 Requested Range Not Satisfiable'); + // header('Content-Range: bytes */' );//. filelength); // Required in 416. + // exit; + //} + + // ... + } + Logging::log("the starting point for the download is $start"); + } + + //Logging::log(print_r($_REQUEST, true)); + //Logging::log("in the get media action!"); global $CC_CONFIG; // disable the view and the layout @@ -146,10 +177,16 @@ class ApiController extends Zend_Controller_Action } $logger->info("Sending $filepath"); header("Content-Length: " . filesize($filepath)); - + header('Accept-Ranges: bytes'); + // !! binary mode !! $fp = fopen($filepath, 'rb'); - + if (isset($start) && $start != 0){ + Logging::log("updating the start of the file to be sent."); + fseek($fp, $start); + header("Content-Range: bytes $start-".(filesize($filepath)-1).'/'. filesize($filepath)); + Logging::log("done"); + } //We can have multiple levels of output buffering. Need to //keep looping until all have been disabled!!! //http://www.php.net/manual/en/function.ob-end-flush.php @@ -157,7 +194,7 @@ class ApiController extends Zend_Controller_Action fpassthru($fp); fclose($fp); - +Logging::log(print_r($this->getResponse(), true)); //make sure to exit here so that no other output is sent. exit; } else { @@ -171,6 +208,8 @@ class ApiController extends Zend_Controller_Action } header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); $logger->info("404 Not Found"); + + Logging::log(print_r($this->getResponse())); return; } diff --git a/airtime_mvc/application/layouts/scripts/audio-player.phtml b/airtime_mvc/application/layouts/scripts/audio-player.phtml new file mode 100644 index 000000000..85f5a7166 --- /dev/null +++ b/airtime_mvc/application/layouts/scripts/audio-player.phtml @@ -0,0 +1,13 @@ +doctype() ?> + + + + Audio Player + headScript() ?> + headLink() ?> + google_analytics)?$this->google_analytics:"" ?> + + +
layout()->content ?>
+ + diff --git a/airtime_mvc/public/js/airtime/library/preview.js b/airtime_mvc/public/js/airtime/library/preview.js new file mode 100644 index 000000000..878214854 --- /dev/null +++ b/airtime_mvc/public/js/airtime/library/preview.js @@ -0,0 +1,72 @@ +var audio_preview_window = null; + +function playlistAudioPreviewEditor(filename, elemIndexString){ + + elemIndex =parseInt(elemIndexString)+1;//increment the index as tags start from 1 not 0 + + var cueIn = $("dd[id^=spl_cue_in_"+elemIndex+"]").find('span').html(); + console.log(cueIn); + + var cueOut = $("dd[id^=spl_cue_out_"+elemIndex+"]").find('span').html(); + console.log("The cueOut is "+cueOut); + + var fadeIn = $("dd[id^=spl_fade_in_"+elemIndex+"]").find('span').html(); + if (fadeIn == undefined){ console.log("undefined fadein"); fadeIn = $("dd[id^=spl_fade_in_main]").find('span').html();} + console.log("The fadeIn is "+fadeIn); + + var fadeInFileName = ""; + if (fadeIn != undefined && parseInt(fadeIn) > 0 ){ + //need to get the previous element in the playlist...but don't support previous playlist fading becuase thats not possible. + + } + console.log("The fadeInFileName is "+fadeInFileName); + + var fadeOut = $("dd[id^=spl_fade_out_"+elemIndex+"]").find('span').html(); + if (fadeOut == undefined){ console.log("undefined fadeout"); fadeOut = $("dd[id^=spl_fade_out_main]").find('span').html();} + console.log("The fadeOut is "+fadeOut); + + var fadeOutFileName = ""; + if (fadeOut != undefined && parseInt(fadeOut) > 0 ){ + //need to get the next element in the playlist...but don't support next playlist fading becuase thats not possible. + + } + console.log("The fadeOutFileName is "+fadeOutFileName); + + //Pop out a play list with cue in and cue out set. + open_player(); + + //Set the play button to pause. + var elemID = "spl_"+elemIndexString; + $('#'+elemID+' div.list-item-container a span').attr("class", "ui-icon ui-icon-pause"); + +} + +function open_audio_preview(filename, index) { + console.log("hello world 2 "+filename+" help?"); + url = 'Playlist/audio-preview-player/filename/'+filename+'/index/'+index; + + if (audio_preview_window == null || audio_preview_window.closed){ + console.log("opening : "+baseUrl+url); + + audio_preview_window = window.open(url, 'Audio Player', 'width=400,height=95'); + //audio_preview_window.setTitle('Audio Player'); + //$.post(baseUri+'Playlist/audio-preview-player', {fileName: fileName, cueIn: cueIn, cueOut: cueOut, fadeIn: fadeIn, fadeInFileName: fadeInFileName, fadeOut: fadeOut, fadeOutFileName: fadeOutFileName}) +/** + $.post(url, + {format: "json", elementFilename: filename, elementIndex: elemIndexString}, + function(json){ + audio_preview_window.document.open(); + audio_preview_window.document.write(json); + audio_preview_window.document.close(); + }); +**/ + } else if (!audio_preview_window.closed) { + console.log("refreshing : "+baseUrl+url); + audio_preview_window.play(filename); + } else { + console.log("something else : "+baseUrl+url); + } + + audio_preview_window.focus(); + return false; +} diff --git a/airtime_mvc/public/js/airtime/library/preview_jplayer.js b/airtime_mvc/public/js/airtime/library/preview_jplayer.js new file mode 100644 index 000000000..14ae81486 --- /dev/null +++ b/airtime_mvc/public/js/airtime/library/preview_jplayer.js @@ -0,0 +1,124 @@ + + +function audioPreview(filename, elemID){ + console.log("in the audio preview"); + var elems = $('.ui-icon.ui-icon-pause'); + elems.attr("class", "ui-icon ui-icon-play"); + + if ($("#jquery_jplayer_1").data("jPlayer") && $("#jquery_jplayer_1").data("jPlayer").status.paused != true){ + $('#jquery_jplayer_1').jPlayer('stop'); + return; + } + + var ext = getFileExt(filename); + var uri = "/api/get-media/file/" + filename; + + var media; + var supplied; + if (ext == "ogg"){ + media = {oga:uri}; + supplied = "oga"; + } else { + media = {mp3:uri}; + supplied = "mp3"; + } + + $("#jquery_jplayer_1").jPlayer("destroy"); + $("#jquery_jplayer_1").jPlayer({ + ready: function () { + $(this).jPlayer("setMedia", media).jPlayer("play"); + }, + swfPath: "/js/jplayer", + supplied: supplied + }); + + $('#'+elemID+' div.list-item-container a span').attr("class", "ui-icon ui-icon-pause"); +} + +$(document).ready(function(){ + var filename = $(".filename").text(); + //var filename = $(".jp_audio_0").attr("src"); + play(filename); + + +}); + +function play(filename){ + console.log("in the play function! "+filename); + + var uri = "/api/get-media/file/" + filename+"/api_key/H7CSH1RH1YH2W3KFAKCZ"; + var ext = getFileExt(filename); + + + var media; + var supplied; + if (ext == "ogg"){ + media = {oga:uri}; + supplied = "oga"; + } else { + media = {mp3:uri}; + supplied = "mp3"; + } + + $("#jquery_jplayer_1").jPlayer("destroy"); + $.jPlayer.timeFormat.showHour = true; + $("#jquery_jplayer_1").jPlayer({ + ready: function () { + + $(this).jPlayer("setMedia", media).jPlayer("play"); + + }, + swfPath: "/js/jplayer", + cssSelectorAncestor: '#jp_container_1', + wmode: "window" + }); + /** + $("#jquery_jplayer_1").jPlayer().bind($.jPlayer.event.play, function(event){ + console.log("playing xxx"); + //console.log(this.htmlElement.media.currentTime) + //$("#jquery_jplayer_1").jPlayer("playHead", event.jPlayer.status.seekPercent); + }); + $("#jquery_jplayer_1").jPlayer().bind($.jPlayer.event.seeking, function(event){ + console.log("hello 123"); + //console.log(this.htmlElement.media.currentTime) + //$("#jquery_jplayer_1").jPlayer("playHead", event.jPlayer.status.seekPercent); + }); + $("#jquery_jplayer_1").jPlayer().bind($.jPlayer.event.seeked, function(event){ + console.log("hello 456"); + //console.log(this.htmlElement.media.currentTime) + //$("#jquery_jplayer_1").jPlayer("playHead", event.jPlayer.status.seekPercent); + }); + $("#jquery_jplayer_1").jPlayer().bind($.jPlayer.event.volumechange, function(event){ + console.log("hello 666"); + //console.log(this.htmlElement.media.currentTime) + //$("#jquery_jplayer_1").jPlayer("playHead", event.jPlayer.status.seekPercent); + }); + $(".jp-seek-bar").click(function(){ + console.log("seek bar clicked"); + console.log($("#currentTime")); + //console.log(this.htmlElement.media.seekable) + //console.log($(".jp-play-bar").attr("style")); + //$("#jquery_jplayer_1").jPlayer("play", 40); + }); + + $(".jp-seek-bar").click(function(){ + console.log("hi"); + //console.log(this.htmlElement.media.seekable) + //console.log($(".jp-play-bar").attr("style")); + //$("#jquery_jplayer_1").jPlayer("playHead", "50%"); + }); + $(".jp-play-bar").click(function(){ + console.log("bye"); + }); + $(".jp-progres").click(function(){ + console.log("no"); + }); + $("#combo-box").change(function(eventObject){ + var elem = $("#combo-box option:selected"); + setjPlayer(elem.attr("data-url"), elem.attr("data-type"), elem.attr("server-type")); + }); + **/ + + +} + diff --git a/airtime_mvc/public/js/jplayer/skin/jplayer.blue.monday.seeking.gif b/airtime_mvc/public/js/jplayer/skin/jplayer.blue.monday.seeking.gif new file mode 100644 index 0000000000000000000000000000000000000000..dbd2105ab933f0336e1f732e32a54c6d6a8e1441 GIT binary patch literal 3284 zcmcK6c~nzp8V2y#26KZf5`~fqX8=J|kRd=R2q;pnKv;@{t&V~sI24OoP}Y!@vVdZIdfX`XHHJe?>yi0z3=B2 zu-nc3h$G4b)u@O1xI%UE;+_j%@YZ zjSjzZ@^D_@lKIF_3x$z2w`Ui~#TK)g@kCMviA-bDnYQ*go0y-IDM0k!_NK9`i@uo(Ht^li;Sr*PFcjxV#S1>=k~x0YJ3bTh_WOcnlwcaI%f9+-TLn+a;|j<)Uo z($``>J>`8WX+@HxmH1P+fov%VOYC1G32@(?=Qh2i2U#LiebP4E|Ev%#Shqo%5WZCs zJQ1rL*u(3MeJSyVGkGNm35F$G|GQ+cdto)uv-7X zB}@Fk=zacRLNT04=f6vgzt&0|x~U*iCi|XeVu2`Oik0pheV1wb?IUBCgx;}E;DM6c zt!K~Xn8e#lo2wos%{*-@e#=xd>EvUjN-eT3#BG|#%3W)Nr;Q3JyKL@^cX=;38Qh;6 z@^&pZ{B-l}v5>;4N8=u&LDmbdpT*#)bOOL->OqIO0F#Qvh zA!&o7PjV*ldMumqcwpnz7;E!#rVz*)Acm2>ezb}p7K=4=$EMYLI30Mxq_NQbdi@+?N7*U~(W7_NuD0`OwXWlA%BVp5+>c0~uA)^=2NP}|XRc%D4J#o(0TV)k5(=d^yhvnilZs!_X1Dg|LN#lU%B zre_gjs2Wb1@Dh5%d7Oj~g-nGR91@QWfmjjTke$eiP;O^khg;UJ#%DS|iG~`u*7&Ll zUPI(6+RVc(U&ZZvLRGg%+}yVcmsTB3s5Zli{HhI!vYDD4_4=1#1@XEXwS%PUBYdA? zP~XjKnms4Htc?HJfI+u4I6|hW28F}&BMWz6xe$=$jHpNy6D+k;-jzLU@$q_i z%B%kJV#?<`-O3flJuP|grNGDNMlD~e*2maymGqA_nm!3;4h|3I_MS*t{q`!Qo7weV z$M)Dmnt=&dclA@HWPTy-(5U6w(^$+=xS{?~Y6gqW=YX`V9asSukRlKH1aZJ7UwFv7 zU;j@?UfGR#>#2P02L3U3jjl~gc}S)2)&jlpzYocDYl(J-=>zv#eV7cCmzjb{IIyz# zoL$r=%~MGu9RVCGErd!ZXRsK|U>c9b_rr1oK$b0H9PowR^1l=#J+?jCcL1?ccBeqN zaV|Go_e7}Opa1&*DZmwleKc}T zsknDMoXO~XnZ=sHN$2-pW-;}fES@ViASxK}ZH3?!;|Z^rz1kHM2(Os^@QQJW_uP_t zBCzq~xbElYTFOxnA!^U5@DQ1*YF%XkvG|+2N%_Mk1jEB>?>r~H`*VqBlgspfw7LC{ z%y;@Q&Ko5c1brkj)isqti2-;qWNca(4-k+uL&Q=MmmemS1&WJ3it>R{9HL4)%&OPI z3#JcVFvdC-C90^G3uYx7Ioy*M*_2KE>ZKN1dDP5+<v3LS z1Vq7;oyLe@LJ{-~7F)z8(j`7TwoDHZavFxz|51>L7Po8nl$R3;KK9C#XK-OjbRt&U zSQ-R!1VjK3`(&|@r~8Uyz14U9eejO?y@9-N%saegnKL0zr@(`^ hP|OA(#5}aa-Ol*UIY=)YP^yrgNn}dFbR(3