﻿// dependency: jQuery

LivecastMediaPlayer = function(playerDivID, width, height, resetPageFlagsCallback) {
  this.playerDivID = playerDivID;
  this.width = width;
  this.height = height;
  this.resetPageFlagsFunc = resetPageFlagsCallback;
  
  var pThis = this; // closure hack
  this.play = function(mediaURL, flashURL) { LivecastMediaPlayer.prototype.play(pThis, mediaURL, flashURL); }
  this.changePlayer = function(whichPlayer) { LivecastMediaPlayer.prototype.changePlayer(pThis, whichPlayer); }
  this.showMediaPlayer = function(whichPlayer, mediaURL) { LivecastMediaPlayer.prototype.showMediaPlayer(pThis, whichPlayer, mediaURL); }  
  this.CurrentItemChange = function() { LivecastMediaPlayer.prototype.CurrentItemChange(pThis); }
  this.PlayerScriptCommand = function(scType, scParam) { LivecastMediaPlayer.prototype.PlayerScriptCommand(pThis, scType, scParam); }
  
  // cleanup WMP vs. IE7,8
  $(window).bind('beforeunload', LivecastMediaPlayer.prototype.disposeWMP);
};

LivecastMediaPlayer.prototype = {
  mediaURL : '_',
  flashURL : '_',
  currentPlayer : '_',
  playerDivID : '_',
  rmtpServer : '_',  // streaming flash
  width : 0,
  height : 0,
  rootPath : '/ajax_controls/MediaPlayer/',  // root path of THIS file
  
  disposeFunc : null,  // func to dispose the currently displayed player
  isSafeToDisposeTheActivePlayer : true,
  resetPageFlagsFunc : null, // callback to script on the host page
  
  // external event handlers attach HERE
  onGPSEvent : function(){}, // fired when GPS data occurs in a media stream
  onCurrentItemChanged : function(){},  // fired when the media changes in WMPlayer
  onNewPlayerSpawned : function(){},
  onBufferEmpty : function(flowplayer){}, // fired when a livestream ends, or stream chokes
  onBufferFull : function(flowplayer){},  // evidence that a livestream is streaming properly
  
  embed_WM_IE : ' \
      <object id="wmplayer" height=<%=height%> width=<%=width%> border=2 classid=clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6 borderColor="#cccccc" VIEWASTEXT> \
        <param name="URL" value="<%=url%>"> \
        <param name="invokeURLs" value="false"> \
        <param name="StretchToFit" value="true"> \
        <embed type="application/x-mplayer2" src="<%=url%>" width="<%=width%>" height="<%=height%>" showcontrols="1" stretchtofit="1" autostart="1"></embed> \
      </object>',

  embed_WM_FF : ' \
      <object ID="wmplayer" name="wmplayer" type="application/x-ms-wmp" width="<%=width%>" height="<%=height%>" codebase="http://port25.technet.com/videos/downloads/wmpfirefoxplugin.exe" data="<%=url%>"> \
        <param name="URL" value="<%=url%>"> \
        <param name="autoStart" value="-1"> \
        <param name="stretchToFit" value="1"> \
        <param name="invokeURLs" value="false"> \
        <embed type="application/x-mplayer2" src="<%=url%>" width="<%=width%>" height="<%=height%>" showcontrols="1" autostart="true" stretchToFit="1"></embed> \
      </object>',

  embed_QT : ' \
      <object id="qtplayer" CLASSID="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" WIDTH="320" HEIGHT="256" CODEBASE="http://www.apple.com/qtactivex/qtplugin.cab" VIEWASTEXT> \
        <param name="SRC" value="<%=url%>"> \
        <param name="QTSRC" value="<%=url%>"> \
        <param name="AUTOPLAY" value="true"> \
        <param name="CONTROLLER" value="true"> \
        <param name="SCALE" value="tofit"> \
        <param name="BGCOLOR" value="BLACK"> \
        <embed SRC="<%=url%>" QTSRC="<%=url%>" WIDTH="320" HEIGHT="256" bgcolor="000000" SCALE="tofit" AUTOPLAY="true" CONTROLLER="true" PLUGINSPAGE="http://www.apple.com/quicktime/download/"/> \
      </object>',

  // event forwarding from Windows Media Player
  PlayerScriptCommand: function(pThis, scType, scParam) {  // ONLY FIRES ONCE in FFOX
    if(scType == 'GPS') {
      var p = scParam.split(',');  //flags, latitude, longitude, altitude, velocity, direction, UTC
      var eventParams = {
        flags : p[0],
        latitude : p[1],
        longitude : p[2]
//        altitude : p[3],
//        velocity : p[4],
//        direction : p[5],
//        UTC : p[6],
//        sender : pThis
      };
      if(!(eventParams.flags & 256)) return;
      setTimeout( function() { pThis.onGPSEvent(eventParams); }, 1);
    }
  },
  
  CurrentItemChange : function(pThis) {
    setTimeout(function() { pThis.onCurrentItemChanged( {sender: pThis} ); }, 1);
  },

  changePlayer : function(pThis, whichPlayer) {
    pThis.currentPlayer = whichPlayer;
    pThis.play(pThis.mediaURL);
  },  
  
  play : function(pThis, mediaURL, flashURL) {
    pThis.flashURL = flashURL;
    var streamType;
    if(pThis.currentPlayer == 'WM') {
      streamType = "pt=wm";
    } else if(pThis.currentPlayer == 'QT') {
      streamType = "pt=qt";
    } else if(pThis.currentPlayer == 'Flash'
           || pThis.currentPlayer == 'Flowplayer') {      
      pThis.mediaURL = mediaURL;
      pThis.showMediaPlayer(pThis.currentPlayer, flashURL); 
      return;
    } else throw("Unsupported player: " + pThis.currentPlayer);
    
    pThis.mediaURL = mediaURL;
    mediaURL = mediaURL.replace(/<%=streamType%>/, streamType);
    pThis.showMediaPlayer(pThis.currentPlayer, mediaURL);
  },
  
  //
  // main - the whole of this class exists to support this function
  //  
  showMediaPlayer : function(pThis, whichPlayer, mediaURL) {

    if(!pThis.isSafeToDisposeTheActivePlayer) {
      var retry = function() { pThis.showMediaPlayer(whichPlayer, mediaURL) };
      setTimeout(retry, 1000);  // queue execution of this request for 1 sec
      return;
    }    

    pThis.currentPlayer = whichPlayer;
    var WRAPPER_ID = 'playerWrapper';

    var createFunc;  // this function (& closure) which will write the HTML for the player.
                     // invoked via setTimeout so that the browser graphics will refresh properly
                     // when switching between players

    if(pThis.disposeFunc) pThis.disposeFunc(); // dispose previous player resources

    $('#'+WRAPPER_ID).remove();
    $('#placeholder').show();
    $('#'+pThis.playerDivID).append('<div id="'+WRAPPER_ID+'"></div>');
    
    if(whichPlayer == 'QT') {    
      var rawHtml = pThis.embed_QT;
      rawHtml = pThis.xformPlayerParams(pThis, rawHtml, mediaURL);      
      createFunc = pThis.createPlayer(pThis, rawHtml, WRAPPER_ID);      
      pThis.disposeFunc = null;
      setTimeout(pThis.safeToDispose(pThis), 5000); // allow 5 sec for init
    }
    else if(whichPlayer == 'WM') {     
      var rawHtml = ($.browser.msie) ? pThis.embed_WM_IE : pThis.embed_WM_FF;
      rawHtml = pThis.xformPlayerParams(pThis, rawHtml, mediaURL);
      var init = function() {
        if(p.object) p.object.StretchToFit = true;        
      };
      createFunc = pThis.createPlayer(pThis, rawHtml, WRAPPER_ID, pThis.resetPageFlagsFunc);
      pThis.disposeFunc = function() {
//        var p = document.getElementById("wmplayer");
//        if(p && p.object) p.object.Close();
      }      
      setTimeout(pThis.safeToDispose(pThis), 2000); // allow 2 sec for init            
    }
    else if(whichPlayer == 'Flash') {
      createFunc = pThis.createFlashPlayer(pThis, WRAPPER_ID, mediaURL);
      pThis.disposeFunc = function() {
        var flow = flowplayer();
        flow.stopBuffering();
        flow.unload();
      };
      setTimeout(pThis.safeToDispose(pThis), 2000); // 2 sec for init
    }
    else if(whichPlayer == 'Flowplayer') {      
      // flowplayer livestream  
      createFunc = pThis.createFlowplayer(pThis, WRAPPER_ID, mediaURL);
      pThis.disposeFunc = function() {
        var flow = flowplayer();
        flow.stopBuffering();
        flow.unload();
      };
      setTimeout(pThis.safeToDispose(pThis), 2000); // allow 2 sec for init
    }
    else throw "Unsupported player: " + whichPlayer;
    
    // delay is induced so that two players
    // are never simultaneously present on the page
    setTimeout(createFunc, 100);
    pThis.isSafeToDisposeTheActivePlayer = false;
  },  

  disposeWMP : function() {  
    if($.browser.msie) {
      var wmp = $('#wmplayer');
      if(wmp.size() > 0 && wmp[0].object) {
        wmp[0].object.uiMode = "invisible";
        wmp[0].object.close();
      }
    }
    else {
      try {
          var wmp=document.getElementById('wmplayer');
          wmp.uiMode = "invisible";
          wmp.Close();
      } catch(e) {}
    }
  },

  xformPlayerParams : function(pThis, raw, mediaURL) {
    return raw.replace(/<%=root%>/g, pThis.rootPath)
              .replace(/<%=url%>/g, mediaURL)
              .replace(/<%=width%>/g, pThis.width)
              .replace(/<%=height%>/g, pThis.height);
  },
    
  createPlayer : function(pThis, rawHtml, WRAPPER_ID, resetPageFlagsFunc) {
    // for Windows Media & QuickTime players
    return function() {
      if(resetPageFlagsFunc) resetPageFlagsFunc(); // so the page script event-forwarding will work as intended, for Firefox/WMPlayer
      if($.browser.msie) {
        $('#'+WRAPPER_ID)[0].innerHTML = rawHtml; // prevents resize to size of video for IE/WMP plug-in
      } else {
        $('#'+WRAPPER_ID).html(rawHtml);
      }
      $('#placeholder').hide();
      pThis.onNewPlayerSpawned({sender: pThis, player: pThis.currentPlayer});
    };
  },
  
  createFlashPlayer : function(pThis, WRAPPER_ID, mediaURL) {		
    return function() {
      $('#'+WRAPPER_ID).remove(); // remove b/c need to explicitly supply (height,width)
      var h = pThis.width / 4 * 3 + 24;  // aspect ratio + control bar size
      $('#'+pThis.playerDivID).append('<div id="'+WRAPPER_ID+'" style="height:'+h+'px; width:'+pThis.width+'px" style="background-color=#000"></div>');      
      
      flowplayer(WRAPPER_ID, "flash/play.swf", {
//TODO: from Global.FlowplayerLicenseKey
        key: '#@44b72e38e3e2aeb904f'
        ,clip: {
          url: mediaURL,
          autoPlay: true,
          scaling: 'scale',
          onBegin: function() { pThis.isSafeToDisposeTheActivePlayer = true; }
        }
      });
     
      $('#placeholder').hide();
      pThis.onNewPlayerSpawned({sender: pThis, player: pThis.currentPlayer});
    };
  },
  
  createFlowplayer : function(pThis, WRAPPER_ID, mediaURL) {
    return function() {
      $('#'+WRAPPER_ID).remove(); // remove b/c need to explicitly supply (height,width)
//      $('#'+pThis.playerDivID).append('<div id="'+WRAPPER_ID+'" style="height:'+pThis.height+'px; width:'+pThis.width+'px"></div>');
      var h = pThis.width / 4 * 3 + 24;  // aspect ratio + control bar size
      $('#'+pThis.playerDivID).append('<div id="'+WRAPPER_ID+'" style="height:'+h+'px; width:'+pThis.width+'px" style="background-color=#000"></div>');
      
//      flowplayer(WRAPPER_ID, "/flash/flowplayer-3.1.1.swf", { 
      flowplayer(WRAPPER_ID, "/flash/play.swf", { 
        //onError
//TODO: from Global.FlowplayerLicenseKey        
        key: '#@44b72e38e3e2aeb904f'
        ,clip: {
          url: mediaURL,
          live: true,
          provider: 'rtmp',
          scaling: 'scale',
          //onStart
          onBegin: function() { pThis.isSafeToDisposeTheActivePlayer = true; }
        }
        ,plugins: {
          rtmp: { 
            url: '/flash/flowplayer.rtmp-3.1.0.swf', 
            netConnectionUrl: pThis.rmtpServer
          }        
        }
        ,onBufferEmpty: function() { // when stream is interrupted
          pThis.onBufferEmpty(this); // this = flowplayer
        }  
        ,onBufferFull: function() {
          pThis.onBufferFull(this); // this = flowplayer
        }  
      });
     
      $('#placeholder').hide();
      pThis.onNewPlayerSpawned({sender: pThis, player: pThis.currentPlayer});
    }
  },
  
  safeToDispose : function(pThis) {
    return function() {
      pThis.isSafeToDisposeTheActivePlayer = true;
    }
  }

};