var playlist        = new Array();
var playlist_index  = 0;
var player = null;
function load_new(video_name) {
    new Ajax.Request(
        '/!site.get_available_videos/'+encodeURIComponent(video_name), {
            method: 'get',
            onSuccess: function(response){
                eval(response.responseText);
                
                playlist = new Array();
               
                if( play_before[0] )
                    playlist.push(play_before[0]);
                
                playlist.push(video_name);

                if( play_after[0] )
                    playlist.push(play_after[0]);

                start_play_list();
            }
        });
}

function start_play_list() {
    playlist_index = 0;

    if( player != null ) {
        player.play(playlist[playlist_index]);
    } else {
        var my_config = { 'VIDEOS_PATH': 'http://static.green.tv/static/videos', 'SWF_PATHS': {'h264': '/static/swf/largeblue.player.h264.n.swf','vp6': '/static/swf/largeblue.player.vp6.swf','xi': '/static/swf/expressInstall.swf'}, 'FLASH_PLAYER_9_SKIN': {'normal_skin': '/static/swf/greentv.swf','normal_skin_height': 18}, 'URL_FORMAT': '#{path}/#{videoid}/#{videoid}.#{ext}', 'SUPPORTED_FORMATS': { 'flash': { 'h264': { 'version': { 'major': 9, 'minor': 0, 'version': 124 }, 'ext': 'h264.flv' }, 'vp6': { 'version': { 'major': 8, 'minor': 0, 'version': 0 }, 'ext': 'flv' }, 'xi': { 'version': { 'major': 6, 'minor': 0, 'version': 65 }, 'ext': 'flv' } }, 'windows': { 'series9': { 'version': 7, 'ext': '9.wmv' } }, 'quicktime': { 'h264': { 'version': 7, 'ext': 'mp4', 'mimetype': 'video/mp4' }, 'mov': { 'version': 6, 'ext': 'mov', 'mimetype': 'video/quicktime' } } } };
//            var my_config = { 'VIDEOS_PATH': 'http://static.green.tv/static/videos', 'SWF_PATHS': {'h264': '/static/swf/largeblue.player.h264.swf','vp6': '/static/swf/largeblue.player.vp6.swf','xi': '/static/swf/expressInstall.swf'}, 'FLASH_PLAYER_9_SKIN': {'normal_skin': '/static/swf/greentv.swf', 'normal_skin_height': 18}, 'URL_FORMAT': '#{path}/#{videoid}/#{videoid}.#{ext}', 'SUPPORTED_FORMATS': { 'windows': { 'series9': { 'version': 7, 'ext': '9.wmv' } }, 'quicktime': { 'h264': { 'version': 7, 'ext': 'mp4', 'mimetype': 'video/mp4' }, 'mov': { 'version': 6, 'ext': 'mov', 'mimetype': 'video/quicktime' } } } };
        largeblue.player.Config.addMethods(my_config);
        player = new largeblue.player.MultiFormatPlayer(playlist[playlist_index]);
    }    
}

function play_next_item_in_the_playlist() {
    playlist_index++;
    player.play(playlist[playlist_index]);
}

var largeblue = window.largeblue || {};
largeblue.player = largeblue.player || {};
largeblue.player.Config = Class.create({ /*
    
      This Config is meant to be overridden using::
      
        largeblue.player.Config.addMethods();
      
      This allows you to control:
      
      - the formats you *don't* want to provide
      - the url / file naming convention
      - which bandwidth flags to support
      - player element & container element ids
      - player dimensions
      
    
    */
    
    'SUPPORTED_FORMATS': { /*
        
        Two things to note:
        
          a. if you don't want to support a format, i.e.: you
          don't want to publish files in that format, comment
          it out ala::
          
            ...
            'flash': {
              //'h264': : {
              //  'version': {
              //    'major': 9,
              //    'minor': 0, 
              //    'version': 124
              //  },
              //'ext': 'h264.flv'
              'vp6': : {
                'version': {
                  'major': 9,
                  'minor': 0, 
                  'version': 124
                },
                'ext': 'vp6.flv'
              }
              ...
            },
            ...
          
          b. if you *do* support a format, name your files
          according to the value in this mapping, e.g.: if
          you're supporting quicktime 6, export files with
          a .mov extension.  See URL_FORMAT below for more
          on naming files.
        
        N.b.: you can remove whole items (e.g.: remove quicktime)
        and you can edit the values (e.g.: '.mp4') but *do not*
        edit the keys (e.g.: '7andabove') as that will break the
        detection logic!
        
        Also, rather obviously, the 'ext' must be unique if the
        file it references is unique.
        
        
      */
      'flash': {
        'h264': {
          'version': {
            'major': 9,
            'minor': 0, 
            'version': 124
          },
          'ext': 'h264.flv' // might be .mp4 or .fl4
        },
        'vp6': {
          'version': {
            'major': 8,
            'minor': 0, 
            'version': 0
          },
          'ext': 'vp6.flv'
        },
        'xi': {
          'version': {
            'major': 6,
            'minor': 0, 
            'version': 65
          },
          'ext': 'vp6.flv'
        }
      },
      'windows': {
        'series9': {
          'version': 7,
          'ext': 'wmv'
        }
      },
      'quicktime': {
        'h264': {
          'version': 7,
          'ext': 'h264.mp4',
          'mimetype': 'video/mp4'
        },
        'mov': {
          'version': 6,
          'ext': '.mov',
          'mimetype': 'video/quicktime'
        }
      }
    }, /*
      
      Bandwidth names - these only affect which file the player
      looks for, see #{bandwidth} in example above.  The keys are
      the valid arguments to the::
      
          player.setBandwidth(flag) // flag must be a key of 
      
      i.e.: ``flag`` must be a key of SUPPORTED_BANDWIDTHS
      
      
    */
    'SUPPORTED_BANDWIDTHS': {
      'high': true, // set the default to true
      'med': null, // set the alternatives to null
      'low': null
    },
    // Player dimensions in pixels
    'PLAYER_DIMENSIONS': {
      'width': 514,
      'height': 288
    }, 
    'FULLSCREEN_DIMENSIONS': {
      'width': 768,
      'height': 432
    }, /*
      
      Template to match video files, for example if::
          
          path = VIDEOS_PATH
          videoid = 'myvid1'
          bandwidth = 'high'
          ext = 'h264.flv'
      
      Then we get::
          
          '/static/videos/myvid1/myvid1.high.h264.flv'
      
      If the URL_FORMAT was::
          
          '#{path}/#{videoid}.#{bandwidth}.#{ext}'
      
      And the VIDEOS_PATH was::
          
          '/videos'
      
      We'd get::
          
          '/videos/myvid1.high.h264.flv'
      
      
    */
    'URL_FORMAT': '#{path}/#{videoid}/#{videoid}.#{bandwidth}.#{ext}', 
    'VIDEOS_PATH': '/static/videos',
    // Paths to the .swf files 
    'SWF_PATHS': {
      'h264': '/static/flash/largeblue.player.h264.swf',
      'vp6': '/static/flash/largeblue.player.vp6.swf',
      'xi': '/static/flash/expressInstall.swf'
    }, 
    // names of the target DOM elements
    'PLAYER_CONTAINER_ELEMENT_ID': 'video-content',
    'PLAYER_ELEMENT_ID': 'video',
    // controls
    'CONTROLS_CONTAINER_ELEMENT_ID': 'largeblue-player-controls',
    'CONTROLS_CLASS_NAMES': {
      'play': 'play-button',
      'pause': 'pause-button',
      'stop': 'stop-button',
      'seek_btn': 'seek-button',
      'seek_bar': 'seek-bar',
      'progress_bar': 'progress-bar',
      'time_display': 'time-display',
      'volume_btn': 'volume-button',
      'volume_bar': 'volume-bar',
      'mute_on': 'mute-on-button',
      'mute_off': 'mute-off-button',
      'fullscreen_on': 'fullscreen-on-button',
      'fullscreen_off': 'fullscreen-off-button'
    },
    'FLASH_PLAYER_9_SKIN': {
      'normal_skin': '/static/flash/SkinUnderPlayStopSeekFullVol.swf',
      // leave as null to stick with the normal skin when entering fullscren, 
      // or change to a value like '/static/flash/SkinUnderPlayStopSeekFullVol.swf',
      'fullscreen_skin': '/static/flash/SkinOverPlayStopSeekFullVol.swf', // null, 
      'normal_skin_height': 39 // height of the normal skin in px
    },
    'FLASH_BACKGROUND_COLOUR': '#000000'
  }
);
largeblue.player.AbstractController = Class.create(
  largeblue.player.Config, {
    'WAIT_DELAY': 0.67, // seconds, the update loop frequency
    'RETRY_DELAY': 0.2, // seconds, pause before retrying do_foo
    'MAX_ATTEMPTS': 6, // n times to retry do_foo if unresponsive
    'format': null,
    'ready': false,
    'READY_ATTEMPTS': 30,
    'active': false,
    'listening': false,
    'is_playing': false,
    'playstate': null,
    'position': 0,
    'progress': 0,
    'fullscreen': false,
    'mute': false,
    'attempts_delay': 200,
    'attempted_plays': 0,
    'attempted_pauses': 0,
    'attempted_stops': 0,
    'attempted_seeks': 0,
    'update_interval': null, /*
      
      misc helpers
      
      
    */
    '_fire': document.fire.bind(document),
    '_ensure_two_digits': function (i) {
      if (i < 10) {
        i = '0' + i;
      }
      return i;
    },
    '_convert_seconds_to_mmss': function (s) {
      s = parseInt(s);
      if ( isNaN(s) ) {
        s = 0;
      }
      var m = 0;
      var h = 0;
      if (s >= 60) {
        m = parseInt(s / 60);
        s -= m * 60;
        /*
        if (m >= 60) {
          h = parseInt(m / 60);
          m -= h * 60;
        }
        */
      }
      return /*this._ensure_two_digits(h) + ':' + */this._ensure_two_digits(m) + ':' + this._ensure_two_digits(s);
    },
    '_cache_seek_related_dimensions': function () {
      this.seek_button_width = this.controls.seek_btn.getWidth();
      this.seek_bar_width = this.controls.seek_bar.getWidth();
      this.seek_bar_offset = this.controls.seek_bar.cumulativeOffset().first();
      this.sbo_less_hbw = this.seek_bar_offset + (this.seek_button_width / 2);
      this._handle_progress_changed(
        this.getProgress()
      );
    },
    '_cache_volume_related_dimensions': function () {
      this.volume_button_width = this.controls.volume_btn.getWidth();
      this.volume_bar_width = this.controls.volume_bar.getWidth();
      this.volume_bar_offset = this.controls.volume_bar.cumulativeOffset().first();
      this.vbo_less_hbw = this.volume_bar_offset + (this.volume_button_width / 2);
      this.max_volume_x = this.volume_bar_width - this.volume_button_width;
    },
    '_snap_within': function (pos, min, max) {
      if (pos > max) { 
        pos = max > 0 ? max : 0; // ? : means max can't be less than 0
      }
      else if (pos < min) {
        pos = min;
      }
      return pos;
    }, /*
      
      seek
      
      
    */
    '_set_seek_button_pos': function (x) {
      this.controls.seek_btn.setStyle({
          'marginLeft': x + 'px'
        }
      );
    },
    '_handle_seek_pointer_x': function (pointerX) {
      var x = pointerX - this.sbo_less_hbw;
      var max = this.progress_area_width - this.seek_button_width;
      x = this._snap_within(x, 0, max);
      this._set_seek_button_pos(x);
      this._seek_to(x);
    },
    '_handle_seek_movement': function (event) { 
      var px = event.pointerX();
      this._handle_seek_pointer_x(px);
    },
    '_handle_end_seek': function (event) {
      var px = event.pointerX();
      this._handle_seek_pointer_x(px);
      this._stop_seeking();
    },
    '_seek_to': function (x) {
      var f = 1 - ((this.seek_bar_width - x) / this.seek_bar_width);
      this.seek(f * this.getDuration());
    }, 
    '_start_seeking': function () {
      this.dragging = true;
      this.playstate_on_start_seek = this.getPlayState();
      if (this.playstate_on_start_seek == 'playing') {
        this.pause();
      }
      $(document.body).observe('mousemove', this.drag_seek);
      $(document.body).observe('mouseup', this.end_drag_seek);
    },
    '_stop_seeking': function () {
      this.dragging = false;
      if (this.playstate_on_start_seek == 'playing') {
        this.play();
      }
      $(document.body).stopObserving('mousemove', this.drag_seek);
      $(document.body).stopObserving('mouseup', this.end_drag_seek);
    },
    '_proxy_seek': function (event) {
      var px = event.pointerX();
      this._start_seeking();
      this._handle_seek_pointer_x(px);
    }, /*
      
      volume
      
      
    */
    '_set_volume_button_pos': function (x) {
      this.controls.volume_btn.setStyle({
          'marginLeft': x + 'px'
        }
      );
    },
    '_handle_volume_pointer_x': function (pointerX) {
      var x = pointerX - this.vbo_less_hbw;
      this._set_volume_button_pos(
        this._snap_within(x, 0, this.max_volume_x)
      );
      this._volume_to(x);
    },
    '_handle_volume_movement': function (event) {
      var px = event.pointerX();
      this._handle_volume_pointer_x(px);
    },
    '_handle_end_volume': function (event) {
      var px = event.pointerX();
      this._handle_volume_pointer_x(px);
      this._stop_volume_drag();
    },
    '_volume_to': function (x) {
      var f = 1 - ((this.volume_bar_width - x) / this.volume_bar_width);
      this.setVolume(
        this._snap_within(f * 100, 0, 100)
      );
    },
    '_start_volume_drag': function () {
      $(document.body).observe('mousemove', this.drag_volume);
      $(document.body).observe('mouseup', this.end_drag_volume);
    },
    '_stop_volume_drag': function () {
      $(document.body).stopObserving('mousemove', this.drag_volume);
      $(document.body).stopObserving('mouseup', this.end_drag_volume);
    },
    '_proxy_volume': function (event) {
      var px = event.pointerX();
      this._handle_volume_pointer_x(px);
      this._start_volume_drag();
    }, /*
      
      initialisation helpers
      
      
    */
    '_finish_initialize': function () {},
    '_poll_ready': function () {
      var ready = this._test_ready();
      if (ready) {
        this.start_up();
        this._fire.defer('largeblue-player:ready');
      }
      else {
        if (this.READY_ATTEMPTS) {
          this.READY_ATTEMPTS -= 1;
          this._poll_ready.bind(this).delay(this.RETRY_DELAY);
        }
        else {
          this._fire.defer(
            'largeblue-player:never-going-to-be-ready'
          );
        }
      }
    },
    '_test_ready': function () {},
    '_listen': function () {
      if (!this.listening && this.controls) {
        this.controls.play.observe(
          'click', 
          this.play.bindAsEventListener(this)
        );
        this.controls.pause.observe(
          'click', 
          this.pause.bindAsEventListener(this)
        );
        this.controls.stop.observe(
          'click', 
          this._proxy_stop.bindAsEventListener(this)
        );
        this.controls.seek_bar.observe(
          'mousedown', 
          this._proxy_seek.bindAsEventListener(this)
        );
        this.controls.volume_bar.observe(
          'mousedown', 
          this._proxy_volume.bindAsEventListener(this)
        );
        this.controls.mute_on.observe(
          'click', 
          this._set_mute_on.bindAsEventListener(this)
        );
        this.controls.mute_off.observe(
          'click', 
          this._set_mute_off.bindAsEventListener(this)
        );
        this.controls.fullscreen_on.observe(
          'click', 
          this._set_fullscreen_on.bindAsEventListener(this)
        );
        this.controls.fullscreen_off.observe(
          'click', 
          this._set_fullscreen_off.bindAsEventListener(this)
        );
        this.listening = true;
      }
    },
    '_stop_listening': function () {
      if (this.listening) {
        this.controls.play.stopObserving('click');
        this.controls.pause.stopObserving('click');
        this.controls.stop.stopObserving('click');
        this.controls.seek_bar.stopObserving('mousedown');
        this.controls.volume_bar.stopObserving('mousedown');
        this.listening = false;
      }
    }, 
    '_proxy_stop': function (evt) {
      this._set_seek_button_pos(0);
      this.stop();
    },
    '_set_mute_on': function () {
      this.setMute(true);
    },
    '_set_mute_off': function () {
      this.setMute(false);
    },
    '_set_fullscreen_on': function () {
      this.setFullscreen(true);
    },
    '_set_fullscreen_off': function () {
      this.setFullscreen(false);
    }, /*
      
      some retry based resiliency
      
      
    */
    '_try_to': function (what) {
      // log('trying to: ' + what);
      var attempts = 'attempted_' + what + 's';
      try {
        this['_do_actual_' + what]();
        this[attempts] = 0;
      }
      catch (e) {
        this[attempts] += 1;
        if (this[attempts] < this.MAX_ATTEMPTS) {
          this[what].bind(this).delay(this.RETRY_DELAY);
        }
        else {
          // log('maxed out on attempts to ' + what);
          this[attempts] = 0;
        }
      }
    },
    '_do_actual_play': function () {},
    '_do_actual_pause': function () {},
    '_do_actual_stop': function () {},
    '_do_actual_seek': function (pos) {}, /*
      
      update loop / event handlers
      
      
    */
    '_update': function () {
      var pos = this.getPosition();  
      // log('pos: ' + pos);
      if (!isNaN(pos) && this.position != pos) {
        this.position = pos;
        this._handle_position_changed(pos);
      }
      var prog = this.getProgress();
      // log('prog: ' + prog);
      if (!isNaN(prog) && this.progress != prog) {
        this.progress = prog;  
        this._handle_progress_changed(prog);
      }
      var fullscreen = this.getFullscreen();
      // log('fullscreen: ' + fullscreen);
      if (this.fullscreen != fullscreen) {
        this.fullscreen = fullscreen;  
        this._handle_fullscreen_changed(fullscreen);
      }
      var mute = this.getMute();
      // log('mute: ' + mute);
      if (this.mute != mute) {
        this.mute = mute;  
        this._handle_mute_changed(mute);
      }
      var playstate = this.getPlayState();
      // log('playstate: ' + playstate);
      if (playstate && this.playstate != playstate) {
        this.playstate = playstate;
        // log('playstate changed: ' + playstate);
        if (playstate == 'playing') {
          this._handle_playback_started();
        }
        else if (playstate == 'paused') {
          this._handle_playback_paused();
        }
        else {
          this._handle_playback_stopped();
        }
      }
    },
    '_handle_playback_stopped': function () {
      // log('playback stopped');
      this.controls.pause.setStyle({'visibility': 'hidden'});
      this.controls.play.setStyle({'visibility': 'visible'});
    },
    '_handle_playback_started': function () {
      // log('playback started');
      this.controls.play.setStyle({'visibility': 'hidden'});
      this.controls.pause.setStyle({'visibility': 'visible'});
    },
    '_handle_playback_paused': function () {
      // log('playback paused');
      if (!this.dragging) {
        this.controls.pause.setStyle({'visibility': 'hidden'});
        this.controls.play.setStyle({'visibility': 'visible'});
      }
    },
    '_handle_position_changed': function (pos) {
      //log('position changed: ' + pos);
      if ( isNaN(pos) ) {
        if (!this.dragging) {
          var f = pos / this.getDuration();
          var x = f * this.seek_bar_width;
          var max = this.progress_area_width - this.seek_button_width;
          if (max < 0) {
            this._set_seek_button_pos(0);
          }
          else {
            this._set_seek_button_pos(
              this._snap_within(x, 0, max)
            );
          }
        }
        // convert seconds into hh:mm:ss
        var t = this._convert_seconds_to_mmss(pos);
        this.controls.time_display.update(t);
        this._fire.defer(
          'largeblue-player:position-changed', {
            'pos': pos
          }
        );
      }
    },
    '_handle_progress_changed': function (prog) {
      if ( isNaN(prog) ) {
        this.progress_area_width = this.seek_bar_width * prog / 100;
        this.controls.progress_bar.setStyle({
            'width': this.progress_area_width + 'px'
          }
        );
        this._fire.defer(
          'largeblue-player:progress-changed', {
            'prog': prog
          }
        );
      }
    }, 
    '_handle_mute_changed': function (mute) {
      if (this.controls) {
        if (mute) {
          this.controls.mute_on.hide();
          this.controls.mute_off.show();
        } 
        else {
          this.controls.mute_on.show();
          this.controls.mute_off.hide();
        }
        this._fire.defer(
          'largeblue-player:mute-changed', {
            'mute': mute
          }
        );
      }
    },
    '_handle_fullscreen_changed': function (fullscreen) {
      // log('_handle_fullscreen_changed');
      if (this.controls) {
        if (fullscreen) {
          this.controls.fullscreen_on.hide();
          this.controls.fullscreen_off.show();
        } 
        else {
          this.controls.fullscreen_on.show();
          this.controls.fullscreen_off.hide();
        }
        this._fire.defer(
          'largeblue-player:fullscreen-changed', {
            'fullscreen': fullscreen
          }
        );
      }
    }, 
    '_handle_dimensions_changed': function () {
      if (this.controls) {
        this._cache_seek_related_dimensions(true);
        this._cache_volume_related_dimensions(true);
      }
    }, /*
      
      controller api
      
      
    */
    'setVolume': function (value) {},
    'getVolume': function () {}, // integer
    'setMute': function (value) {},
    'getMute': function () {}, // boolean
    'setFullscreen': function (value) {},
    'getFullscreen': function () {},
    'setSize': function (w, h) {
      this.player.setStyle({
          width: w,
          height: h
        }
      );
    },
    'getSize': function () {
      return this.player.getDimensions();
    },
    'getPlayState': function () {},
    'getDuration': function () {},
    'getPosition': function () {},
    'getProgress': function () {},  
    'seek': function (pos) {
      this._do_actual_seek(pos);
    },  
    'stop': function () {
      this._try_to('stop');
    },
    'pause': function () {
      this._try_to('pause');
    },
    'play': function () {
      this._try_to('play');
    },
    'unload': function () {},  
    'load': function (uri) {}, /*
      
      start and stop
      
      
    */
    'shut_down': function () {
      if (this.active) {
        this.update_interval.stop();
        this.active = false;
      }
      this.stop();
      this._stop_listening();
    },
    'start_up': function () {
      if (!this.active) {
        this.update_interval = new PeriodicalExecuter(
          this._update.bind(this),
          this.WAIT_DELAY
        );
        this.active = true;
      }
      // cache some dimensions
      if (this.controls) {
        this._cache_seek_related_dimensions(true);
        this._cache_volume_related_dimensions(true);
      }
      // start listening
      this._listen();
    }, /*
      
      initialize
      
      
    */
    'initialize': function (player, controls_container, format) {
      // cache the player
      this.player = player;
      // cache the format info
      this.format = format;
      if (controls_container) {
        // cache the controls
        var controls = {};
        $H(this.CONTROLS_CLASS_NAMES).each(
          function (item) {
            var matches = controls_container.select('.' + item.value);
            var target = matches.first();
            if (typeof(target) == 'undefined') {
              throw 'control missing: ' + item.value;
            }
            // rehide as we go
            if (target.hasClassName('hide-to-begin-with')) {
              target.removeClassName('hide-to-begin-with');
              target.hide();
            }
            controls[item.key] = target;
          }
        );
        this.controls = controls;
        // cache the seek internals
        this.drag_seek = this._handle_seek_movement.bindAsEventListener(this);
        this.end_drag_seek = this._handle_end_seek.bindAsEventListener(this);
        // cache the volume internals
        this.drag_volume = this._handle_volume_movement.bindAsEventListener(this);
        this.end_drag_volume = this._handle_end_volume.bindAsEventListener(this);
        // handle resize events by re-caching
        var rs = new ResizeSnitch();
        document.observe(
          'window:resized', 
          this._handle_dimensions_changed.bindAsEventListener(this)
        );
        document.observe(
          'largeblue-player:dimensions-changed', 
          this._handle_dimensions_changed.bindAsEventListener(this)
        );
      }
      else {
        // flag stops the update loop from starting
        this.active = true;
      }
      // do any sub class initialization
      this._finish_initialize();
      this._poll_ready();
    }
  }
);
largeblue.player.WindowsController = Class.create(
  largeblue.player.AbstractController, {
    'had_live_seek_button_class_name': false,
    '_finish_initialize': function () {
      this._set_not_ready_to_seek_yet();
      document.observe(
        'largeblue-player:fullscreen-changed',
        this._handle_windows_fullscreen_changed.bindAsEventListener(this)
      );
    },
    '_set_not_ready_to_seek_yet': function () {
      this.ready_to_seek = false;
      var target = this.controls.seek_btn;
      if (target.hasClassName('live-seek-button')) {
        this.had_live_seek_button_class_name = true;
        target.removeClassName('live-seek-button');
      }
    },
    '_set_ready_to_seek_now': function () {
      this.ready_to_seek = true;
      if (this.had_live_seek_button_class_name) {
        this.controls.seek_btn.addClassName('live-seek-button');
      }
    },
    '_proxy_seek': function (event) {
      if (this.ready_to_seek) {
        var px = event.pointerX();
        this._start_seeking();
        this._handle_seek_pointer_x(px);
      }
    },
    '_test_ready': function () {
      try {
        // ff wm plugin needs a shove in the no-controls direction
        this.player.enableContextMenu = false;
        this.player.uiMode = 'none';
        if (this.player.controls.isAvailable('play')) {
          this.ready = true;
          return true;
        }
        else if (this.player.controls.isAvailable('pause')) {
          this.ready = true;
          return true;
        }
      }
      catch (e) {}
      return false;
    },
    '_handle_windows_fullscreen_changed': function (event) {
      if (!event.memo.fullscreen) {
        this.player.uiMode = 'none';
      }
    },
    'load': function (uri) {
      this.progress = 0;
      this.player.URL = uri;
    },
    'unload': function () {  
      this.player.URL = "";
      this.player.close();  
    },
    '_do_actual_play': function () {
      this.player.controls.currentPosition = this.position;
      this.player.controls.play();
    },
    '_do_actual_pause': function () {
      this.player.controls.pause();
    },
    '_do_actual_stop': function () {
      this.player.controls.stop();
    },
    '_do_actual_seek': function (pos) {  
      this.player.controls.currentPosition = pos;
      this.position = pos;
      // why the hell does WMP stop after setting the position
      // ?!?!?!?!?!?
      if (! this.is_playing) {
        // and why doed it not seem to update the image when
        // restting the position
        this.player.controls.step(1);  
      }
      else {
        this.player.controls.play();
      }
    },
    'setVolume': function (value) {  
      this.player.settings.volume = value;
    },
    'getVolume': function () {  
      return this.player.settings.volume;
    },
    'setMute': function (value) {  
      this.player.settings.mute = value;
    },
    'getMute': function () {  
      return this.player.settings.mute;
    },
    'setFullscreen': function (value) {  
      if (value) {
        this.player.uiMode = 'full';
        this.player.fullScreen = value;
      }
      else {
        this.player.fullScreen = value;
        this.player.uiMode = 'none';
      }
    },
    'getFullscreen': function () {  
      return this.player.fullScreen;
    },
    'getPlayState': function () { /*
        
        this.StateUndefined = 0;
        this.StateStopped  = 1;
        
        
      */
      var StatePaused = 2;
      var StatePlaying = 3; /*
        
        this.StateScanForward = 4;
        this.StateScanReverse = 5;
        this.StateBuffering = 6;
        this.StateWaiting = 7;
        this.StateMediaEnded = 8;
        this.StateTransitioning = 9;
        this.StateReady = 10;
        this.StateReconnecting = 11;
        
        
      */
      switch(this.player.playState) {
        case StatePlaying:
          return "playing";
        case StatePaused:
          return "paused";
        default: return "stopped"; 
      }
    },
    'getProgress': function () {  
      if (this.progress >= 100) {
        if (!this.ready_to_seek) {
          this._set_ready_to_seek_now();
        } 
        return this.progress;
      }
      else {
        try {
          this.player = $(this.PLAYER_ELEMENT_ID);
          var prog = this.player.network.downloadProgress;
          log('prog: ' + prog);
          if (typeof(prog) == 'undefined' || isNaN(prog)) {
            log('returning this.progress');
            return this.progress;
          }
          else {
            log('returning prog');
            return prog;
          }
        }  
        catch (e) {
          log('error');
          return 0;
        }
      }
    },
    'getPosition': function () {  
      var pos = this.player.controls.currentPosition;
      if (typeof(pos) == typeof(0)) {
        return pos;
      }
      return 0;
    },
    'getDuration': function () {
      var dur = this.player.currentMedia.duration;
      if (typeof(dur) == typeof(0)) {
        return dur;
      }
      return 0;
    }
  }
);
largeblue.player.QuicktimeController = Class.create(
  largeblue.player.AbstractController, { /*
      
      fullscreen config
      
      
    */
    'current_movie': '',
    'wants_to_do_fullscreen_using_qtl': false, // if so set the config below
    'qtl_url': '/playfullscreen.qtl', // n.b.: this mechanism opens the video in 
    'qtl_movie_param': 'url', // quicktime player in fullscreen; it *is* possible
    'qtl_mimetype_param': 'mimetype', //  to open at the current seek pos using
    'qtl_src_url_base': window.location.protocol + '//' + window.location.host,
    'was_playing': false, // SMIL.  This is an exercise for the reader ;)
    'actually_fullscreen': false,
    '_test_ready': function () {
      var acceptable = {
        'Loading': null, 
        'Playable': null, 
        'Complete': null
      };
      try {
        if (this.player.GetPluginStatus() in acceptable) {
          this.ready = true;
          return true;
        }
      }
      catch (e) {
        this.player = $(this.PLAYER_ELEMENT_ID);
      }
      return false;
    },
    'load': function (uri) {
      this.progress = 0;
      this.player.SetResetPropertiesOnReload(false);
      this.player.SetURL(uri);
      this.current_movie = uri;
    },
    'unload': function () {  
      this.player.Stop();  
      this.player.SetURL("");  
    },
    '_do_actual_play': function () {  
      this.player.Play();
    },
    '_do_actual_pause': function () {  
      this.player.Stop();
    },
    '_do_actual_stop': function () {  
      this.player.Stop();  
      this.player.Rewind();  
    },
    '_do_actual_seek': function(pos) {  
      this.player.SetTime(pos * this.player.GetTimeScale());  
    },
    'setVolume': function (value) {  
      this.player.SetVolume(value);
    },
    'getVolume': function () {  
      return this.player.GetVolume();
    },
    'setMute': function (value) {   
      this.player.SetMute(value);
    },
    'getMute': function () {  
      return this.player.GetMute();
    },
    'setFullscreen': function (value) {
    
      if (this.wants_to_do_fullscreen_using_qtl) {
        if (value) {
          var src = null;
          if (this.current_movie.indexOf('://') < 0) {
            if (this.current_movie.startsWith('/')) {
              src = this.qtl_src_url_base + this.current_movie;
            }
            else {
              var parts = window.location.pathname.split('/');
              parts.pop();
              var path = parts.join('/');
              src = this.src_url_base + path + '/' + this.current_movie;
            }
          }
          else {
            src = this.current_movie;
          }
          var url = this.qtl_url + '?' + this.qtl_movie_param + '=';
          url = url + encodeURI(src) + '&' + this.qtl_mimetype_param + '=';
          url = url + encodeURI(this.format.mimetype);
          window.location.assign(url);
          if (this.getPlayState() == 'playing') {
            this.was_playing = true;
          }
          this.pause();
        }
        else if (!value && this.was_playing) {
          this.play();  
        }
      }
      else {
        if (value) {
            this.player.setStyle({
                'width': '' + this.FULLSCREEN_DIMENSIONS.width + 'px',
                'height': '' + this.FULLSCREEN_DIMENSIONS.height + 'px',
                'zIndex' : 9999
            });
            
            this.player.up().setStyle({
                'width': '' + this.FULLSCREEN_DIMENSIONS.width + 'px',
                'height': '' + this.FULLSCREEN_DIMENSIONS.height + 'px',
                'marginLeft' : '84px',
                'zIndex' : 9999
            });
            
            $(this.CONTROLS_CONTAINER_ELEMENT_ID).setStyle({
                'marginLeft' : '84px',
                'borderColor' : '#fff',
                'width': '' + this.FULLSCREEN_DIMENSIONS.width + 'px',
                'zIndex' : 9999
            });

            var viewport = document.viewport.getDimensions(); // Gets the viewport as an object literal
            var width  = viewport.width; // Usable window width
            var height = webpage.scrollSize()["height"];

            if( !$('coverup') ) {
                var my_div      = document.createElement('div');
                my_div.id   = 'coverup';
                my_div.style.position = 'absolute';
                my_div.style.background = '#fff url(http://static.green.tv/static/images/greentv/logo/green_tv_logo.gif) 0 0 no-repeat';
                my_div.style.left    = '0px';
                my_div.style.top     = '0px';
                my_div.style.width   = '100%';
                my_div.style.height  = height + 'px';
                my_div.style.zIndex  = 9980;
                
                document.body.appendChild(my_div);            
            } else {
                $('coverup').setStyle({
                    'height' : height + 'px',
                    'width' : width + 'px'
                });
                
                $('coverup').show();
            }
                            
        } else {
            this.player.setStyle({
                'width': '' + this.PLAYER_DIMENSIONS.width + 'px',
                'height': '' + this.PLAYER_DIMENSIONS.height + 'px'
            });
            
            this.player.up().setStyle({
                'marginLeft' : '0',
                'width': '' + this.PLAYER_DIMENSIONS.width + 'px',
                'height': '' + this.PLAYER_DIMENSIONS.height + 'px'
            });
            
            $(this.CONTROLS_CONTAINER_ELEMENT_ID).setStyle({
                'borderColor' : '',
                'marginLeft' : '0',
                'width': '' + this.PLAYER_DIMENSIONS.width + 'px'
            });
            
            $('coverup').hide();
        }

        this.actually_fullscreen = value;
        document.fire('largeblue-player:dimensions-changed');
      }
    },
    'getFullscreen': function () {  
      return this.actually_fullscreen;
    },
    'getProgress': function () {  
      if (this.progress >= 100) {
        return this.progress;
      }
      else {
        try {
          var mtl = this.player.GetMaxTimeLoaded();
          // log('mtl: ' + mtl);
          var dur = this.player.GetDuration();
          // log('dur: ' + dur);
          var f = mtl / dur;
          var p = 100 * f;
          // log('prog: ' + p);
          if (isNaN(p)) {
            return this.progress;
          }
          else {
            return p;
          }
        }  
        catch (e) {
          return 0;
        }
      }
    },
    'getPlayState': function () {  
      try {
        var r = this.player.GetRate();
        // log('r: ' + r);
        if (isNaN(r)) {
          return null;
        }
        else if (r > 0) {
          return "playing";
        }
        else {
          return 'paused';
        }
      }
      catch (e) {
        return null;
      }
    },
    'getDuration': function () {  
      try {
        var d = this.player.GetDuration();
        var ts = this.player.GetTimeScale();
        // log('getDuration, d = ' + d + ', ts = ' + ts);
        var dur = d / ts;
        if (isNaN(dur)) {
          return 0;
        }
        else {
          return dur;
        }
      }  
      catch (e) {
        return 0;  
      }
    },
    'getPosition': function () {  
      try {
        var t = this.player.GetTime();
        //log('t: ' + t);
        var ts = this.player.GetTimeScale();
        //log('ts: ' + ts);
        var pos = t / ts;
        // log('pos: ' + pos);
        if (isNaN(pos)) {
          return this.position;
        }
        else {
          return pos;
        }
      }
      catch (e) {
        return 0;  
      }
    }  
  }
);
largeblue.player.FlashController = Class.create(
  largeblue.player.AbstractController, {
    '_finish_initialize': function () {
      document.observe(
        'largeblue-player:flash-ready',
        this._handle_flash_ready.bind(this)
      );
    },
    '_handle_flash_ready': function () {
      // log('flash ready!');
      this.ready = true;
    },
    '_handle_seek_movement': function (event) { 
      var x = event.pointerX() - this.sbo_less_hbw;
      var max = this.progress_area_width - this.seek_button_width;
      x = this._snap_within(x, 0, max);
      this._set_seek_button_pos(x);
      // don't actually seek until end - flash can't handle it
    },
    '_test_ready': function () {
      return this.ready;
    },
    'load': function (uri) {
      this.player.lb_xi_load(uri);
    },
    'unload': function (){  
      this.player.lb_xi_load('');
    },
    '_do_actual_play': function () {
      this.player.lb_xi_play();
    },
    '_do_actual_pause': function () {  
      this.player.lb_xi_pause();
    },
    '_do_actual_stop': function () {
      this.player.lb_xi_stop();
    },
    '_do_actual_seek': function (pos) {  
      this.player.lb_xi_seek(pos);
    },
    'setVolume': function (value) {  
      this.player.lb_xi_set_volume(value);
    },
    'getVolume': function () {  
      return this.player.lb_xi_get_volume();
    },
    'setMute': function (value) {  
      this.player.lb_xi_set_mute(value);
    },
    'getMute': function () {  
      return this.player.lb_xi_get_mute();
    },
    'setFullscreen': function(value) {
      if (this.controls) {
        if (value) {
            this.player.setStyle({
                'width': '' + this.FULLSCREEN_DIMENSIONS.width + 'px',
                'height': '' + this.FULLSCREEN_DIMENSIONS.height + 'px',
                'zIndex' : 10
            });
            
            this.player.up().setStyle({
                'width': '' + this.FULLSCREEN_DIMENSIONS.width + 'px',
                'height': '' + this.FULLSCREEN_DIMENSIONS.height + 'px',
                'marginLeft' : '84px',
                'zIndex' : 10
            });
            
            $(this.CONTROLS_CONTAINER_ELEMENT_ID).setStyle({
                'marginLeft' : '84px',
                'borderColor' : '#fff',
                'width': '' + this.FULLSCREEN_DIMENSIONS.width + 'px',
                'zIndex' : 10
            });

            var viewport = document.viewport.getDimensions(); // Gets the viewport as an object literal
            var width  = viewport.width; // Usable window width
            var height = webpage.scrollSize()["height"];

            if( !$('coverup') ) {
                var my_div      = document.createElement('div');
                my_div.id   = 'coverup';
                my_div.style.position = 'absolute';
                my_div.style.background = '#fff url(http://static.green.tv/static/images/greentv/logo/green_tv_logo.gif) 0 0 no-repeat';
                my_div.style.left    = '0px';
                my_div.style.top     = '0px';
                my_div.style.width   = '100%';
                my_div.style.height  = height + 'px';
                my_div.style.zIndex  = 9;
                
//                document.body.appendChild(my_div);            
            } else {
                $('coverup').setStyle({
                    'height' : height + 'px',
                    'width' : width + 'px'
                });
                
                $('coverup').show();
            }
        } else {
            this.player.setStyle({
                'width': '' + this.PLAYER_DIMENSIONS.width + 'px',
                'height': '' + this.PLAYER_DIMENSIONS.height + 'px'
            });
            
            this.player.up().setStyle({
                'marginLeft' : '0',
                'width': '' + this.PLAYER_DIMENSIONS.width + 'px',
                'height': '' + this.PLAYER_DIMENSIONS.height + 'px'
            });
            
            $(this.CONTROLS_CONTAINER_ELEMENT_ID).setStyle({
                'borderColor' : '',
                'marginLeft' : '0',
                'width': '' + this.PLAYER_DIMENSIONS.width + 'px'
            });
            
            $('coverup').hide();
        }

        this.actually_fullscreen = value;
        document.fire('largeblue-player:dimensions-changed');
      }
      this.player.lb_xi_set_fullscreen(value);
    },
    'getFullscreen': function () {
      return this.player.lb_xi_get_fullscreen();
    },
    'setSize': function (w, h) {
      this.player.setStyle({
          'width': '' + w + 'px',
          'height': '' + h + 'px'
        }
      );
      this.player.lb_xi_resize(w, h);
    },
    'getPlayState': function () {  
      return this.player.lb_xi_get_playstate();
    },
    'getDuration': function () {  
      return this.player.lb_xi_get_duration();
    },
    'getPosition': function () {  
      return this.player.lb_xi_get_position();
    },
    'getProgress': function () {   
      return this.player.lb_xi_get_progress();
    }  
  }
);
largeblue.player.MultiFormatPlayer = Class.create(
  largeblue.player.Config, {
    'choice': null,
    'videoid': null,
    'bandwidth': null,
    'ext': null,
    'url_template': null,
    'windows_embed_mode': null,
    'quicktime_embed_mode': null,
    '_get_flash_version': function () {
      return swfobject.getFlashPlayerVersion();
    },
    '_flash_is_at_least': function (detected_version, config_version) {
      if (detected_version.major >= config_version['major']) {
        return true;
      }
      if (detected_version.major == config_version['major']) {
        if (detected_version.minor >= config_version['minor'] + 1) {
          return true;
        }
        if (detected_version.minor == config_version['minor']) {
          if (detected_version.release >= config_version['release']) {
            return true;
          }
        }
      }
      return false;
    },
    '_get_windows_version': function () {
      var version = 0;
      try {
        if (window.ActiveXObject) {
          var player = new ActiveXObject("WMPlayer.OCX.7");
          this.windows_embed_mode = 'activex';
        } 
        else if (window.GeckoActiveXObject) {
          var player = new GeckoActiveXObject();
          this.windows_embed_mode = 'geckoactivex';
        }
      } 
      catch (e) {}
      if (player) {
        version = parseInt(player.versionInfo);
      }
      else { // if we're in FF

//        if (Prototype.Browser.Gecko || Prototype.Browser.Chrome) {
          try {
            var plugin = navigator.mimeTypes['video/x-ms-asf'].enabledPlugin;
            var name = plugin.name.toLowerCase();
            // we're after Microsoft® Windows Media Player Firefox Plugin
            // and not anything else that won't be scriptable
            var match_qt = name.indexOf('quickTime') > -1;
            var match_flip = name.indexOf('flip') > -1;
            var match_vlc = name.indexOf('vlc') > -1;
            var match_wmp = name.indexOf('windows media player') > -1;
            if (!match_qt && !match_flip && !match_vlc && match_wmp) {
              // we're in business
              this.windows_embed_mode = 'embed';
              version = 7;
            }
          }
          catch (e) {}
        }
  //    }
      // log('windows_version: ' + version);
      return version;
    },
    '_get_windows_html': function (version) {
      var player_uri = this._construct_url(this.videoid);
      var id = this.PLAYER_ELEMENT_ID;
      var width = this.PLAYER_DIMENSIONS['width'];
      var height = this.PLAYER_DIMENSIONS['height'];
      var markup = null;
      if (this.windows_embed_mode == 'activex') {
        markup = '<object id="' + id + '" classid="clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6" type="application/x-oleobject" width="' + width + '" height="' + height + '"><param name="enableContextMenu" value="false" /><param name="uiMode" value="none" /><param name="url" value="' + player_uri + '" /></object>';
      }
      else if (this.windows_embed_mode == 'geckoactivex') {
        markup = '<object id="' + id + '" type="application/x-oleobject" width="' + width + '" height="' + height + '"><param name="enableContextMenu" value="false" /><param name="uiMode" value="none" /><param name="url" value="' + player_uri + '" /></object>';
      }
      else if (this.windows_embed_mode == 'embed') {
        markup = '<embed id="' + id + '" type="application/x-mplayer2" src="' + player_uri + '" width="' + width + '" height="' + height + '" enableContextMenu="false" uiMode="none"></embed>';
        // you have to set them in js instead, due to ff plugin bug
      }
      else {
        throw 'embed mode ' + this.windows_embed_mode + ' not recognised';
      }
      return markup;
    },
    '_get_quicktime_version': function () {
      var version = null;
      if (navigator.plugins && navigator.mimeTypes.length) {
        for (var i = 0; i < navigator.plugins.length; i++) {
          if (navigator.plugins[i].name.indexOf("QuickTime") >= 0) {
            n = navigator.plugins[i].name;
            version = parseInt(
              n.charAt(
                n.indexOf(".") - 1
              )
            );
          }
        }
        if (version != 0) {
          this.quicktime_embed_mode = 'embed';
        }
      }
      else {
        try {
          var test = new ActiveXObject(
            'QuickTimeCheckObject.QuickTimeCheck.1'
          );
          version = parseInt(
            test.QuickTimeVersion.toString(16).substring(0,3)
          ) / 100 || 0;
          this.quicktime_embed_mode = 'object';
        } 
        catch(e) {}
      }
      if (version == 0) {
        version = null;
      }
      return version
    },
    '_get_quicktime_html': function (player_version, embed_type) {
      var player_uri = this._construct_url(this.videoid);
      var version = '6,0,2,0';
      if (parseInt(player_version) >= 7) {
        version = '7,0,0,0';
      }
      var id = this.PLAYER_ELEMENT_ID;
      var width = this.PLAYER_DIMENSIONS['width'];
      var height = this.PLAYER_DIMENSIONS['height'];
      var params = {
        'enablejavascript': "true",
        'postdomevents': "true",
        'type': "video/quicktime",
        'controller': "false",
        'kioskmode': "false",
        'autoplay': "true",
        'scale': "aspect",
        'bgcolor': "#000000"
      };
//      alert(player_uri);
      var markup = "";
      if (embed_type == "embed") {
        markup = "<embed pluginspage=\"http://www.apple.com/quicktime/download/\" src=\"" + player_uri + "\" width=\"" + width + "\" height=\"" + height + "\"";
        markup += " id=\"" + id + "\" name=\"" + id + "\" ";
        for (var key in params) {
          markup += [key] + "=\"" + params[key] + "\" ";  
        }
        markup += "/>";
      }
      else if (embed_type == "object") {
        markup = "<object id=\"" + id + "\" classid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\" codebase=\"http://www.apple.com/qtactivex/qtplugin.cab#version=" + version + "\" width=\"" + width + "\" height=\"" + height + "\">";
        markup += "<param name=\"movie\" value=\"" + player_uri + "\" />";
        for (var key in params) {
          markup += "<param name=\"" + key + "\" value=\"" + params[key] + "\" />";
        }
        markup += "</object>";
      }
      return markup;
    },
    '_get_fallback_html': function () {
      if (!this.original_markup) {
        this.original_markup = $(this.PLAYER_CONTAINER_ELEMENT_ID).innerHTML;
      }
      return this.original_markup;
    },
    '_detect_best_video_player': function () { /*
        
        if flash 9:
          flash 9
        if safari:
          quicktime 7
          quicktime 6
        if flash 8:
          flash 8
        if ie:
          windows series 9
        else:
          if quicktime:
            quicktime 7
            quicktime 6
          if windows series 9:
            windows series 9
        if flash xi:
          flash xi
        fallback
        
        
      */
      var formats = this.SUPPORTED_FORMATS;
      var format = null;
      var flash_version = this._get_flash_version();
      var quicktime_version = null;
      var windows_version = null;
      if ('flash' in formats && 'h264' in formats.flash) {
        format = formats.flash.h264;
        if (this._flash_is_at_least(flash_version, format.version)) {
          return {
            'plugin': 'flash',
            'version': 'h264'
          };
        }
      }
      if (Prototype.Browser.WebKit) {
        // let's go with QT
        if ('quicktime' in formats) {
          quicktime_version = this._get_quicktime_version();
          if ('h264' in formats.quicktime) {
            format = formats.quicktime.h264;
            if (quicktime_version >= format.version) {
              return {
                'plugin': 'quicktime',
                'version': 'h264'
              };
            }
          }
          if ('mov' in formats.quicktime) {
            format = formats.quicktime.mov;
            if (quicktime_version >= format.version) {
              return {
                'plugin': 'quicktime',
                'version': 'mov'
              };
            }
          }
        }
      }
      if ('flash' in formats && 'vp6' in formats.flash) {
        format = formats.flash.vp6;
        if (this._flash_is_at_least(flash_version, format.version)) {
          return {
            'plugin': 'flash',
            'version': 'vp6'
          };
        }
      }
      if (Prototype.Browser.IE) {
        // we can assume windows media is a fair bet
        if ('windows' in formats && 'series9' in formats.windows) {
          windows_version = this._get_windows_version();
          format = formats.windows.series9;
          if (windows_version >= format.version) {
            return {
              'plugin': 'windows',
              'version': 'series9'
            };
          }
        }
      }
      if ('quicktime' in formats) {
        quicktime_version = this._get_quicktime_version();
        if ('h264' in formats.quicktime) {
          format = formats.quicktime.h264;
          if (quicktime_version >= format.version) {
            return {
              'plugin': 'quicktime',
              'version': 'h264'
            };
          }
        }
        if ('mov' in formats.quicktime) {
          format = formats.quicktime.mov;
          if (quicktime_version >= format.version) {
            return {
              'plugin': 'quicktime',
              'version': 'mov'
            };
          }
        }
      }
      if ('windows' in formats && 'series9' in formats.windows) {
        windows_version = this._get_windows_version();
        format = formats.windows.series9;
        if (windows_version >= format.version) {
          return {
            'plugin': 'windows',
            'version': 'series9'
          };
        }
      }
      // one last try: flash via express install
      if ('flash' in formats && 'xi' in formats.flash) {
        format = formats.flash.xi;
        if (this._flash_is_at_least(flash_version, format.version)) {
          return {
            'plugin': 'flash',
            'version': 'xi'
          };
        }
      }
      // else we ran out of options
      return {
        'plugin': null,
        'version': null
      };
    },
    '_get_extension': function () {
      var plugin = this.choice.plugin;
      var options = this.EXTENSIONS[plugin];
      if (plugin == 'flash') {
        var version = 'vp6';
        if (choice.version == 'h264') {
          version = 'movistar';
        }
        return options[version];
      }
      if (plugin == 'windows') {
        return options;
      }
      if (plugin == 'quicktime') {
        var version = 'below';
        if (choice.version >= 7) {
          version = '7andabove';
        }
        return options[version];
      }
    },
    '_embed_player_markup': function () {
      // cache the original markup in case we fallback later
      this.original_markup = $(this.PLAYER_CONTAINER_ELEMENT_ID).innerHTML;
      // now...
      var choice = this.choice;
      var plugin = choice['plugin'];
      var version = choice['version'];
      var version_string = '';
      var formats = this.SUPPORTED_FORMATS;

//plugin = 'quicktime'; /* pire */

      if (plugin == 'flash') {
        var params = {
          'quality': 'autohigh',
          'swliveconnect': true,
          'menu': false,
          'salign': 'tl',
          'wmode': 'opaque',
          'bgcolor': this.FLASH_BACKGROUND_COLOUR,
          'allowscriptaccess': 'always',
          'allowfullscreen': true
        };
        // n.b. we embed the xi swf as if it were the minimum
        embed_version_id = version;
        if (version == 'xi') {
          if ('vp6' in formats.flash) {
            embed_version_id = 'vp6';
          }
          else if ('h264' in formats.flash) {
            embed_version_id = 'h264';
          }
          else {
            throw 'there must be at least one non xi flash format';
          }
        }

        var embed_version = formats.flash[embed_version_id].version;
        var url = this.SWF_PATHS[embed_version_id];
        if (Prototype.Browser.IE) {
          var d = new Date();
          url += '?ts=' + d.getTime();
        }
        version_string = version_string + embed_version['major'] + '.';
        version_string = version_string + embed_version['minor'] + '.';
        version_string += embed_version['release'];
        var express_install_swf = null;
        if (version == 'xi') {
          express_install_swf = this.SWF_PATHS['xi'];
        }
        var flashvars = this.FLASH_PLAYER_9_SKIN;
        flashvars['normal_width'] = this.PLAYER_DIMENSIONS.width;
        flashvars['normal_height'] = this.PLAYER_DIMENSIONS.height;
        flashvars['fullscreen_width'] = this.FULLSCREEN_DIMENSIONS.width;
        flashvars['fullscreen_height'] = this.FULLSCREEN_DIMENSIONS.height;

        if (version == 'h264') {
          swfobject.embedSWF(
            url,
            this.PLAYER_ELEMENT_ID,
            this.PLAYER_DIMENSIONS.width,
            this.PLAYER_DIMENSIONS.height + this.FLASH_PLAYER_9_SKIN.normal_skin_height,
            version_string, 
            express_install_swf, 
            flashvars,
            params,
            null
          );
          // hide the normal controls
          $(this.CONTROLS_CONTAINER_ELEMENT_ID).hide();
        }
        else {
          swfobject.embedSWF(
            url,
            this.PLAYER_ELEMENT_ID,
            this.PLAYER_DIMENSIONS['width'],
            this.PLAYER_DIMENSIONS['height'],
            version_string, 
            express_install_swf, 
            flashvars, 
            params,
            null
          );

        }
      }
      else if (plugin == 'windows') {
        version_string = '' + formats.windows[version].version;
        $(this.PLAYER_CONTAINER_ELEMENT_ID).update(
          this._get_windows_html(version_string)
        );
      }
      else if (plugin == 'quicktime') {
        version_string = '' + formats.quicktime[version].version;
        $(this.PLAYER_CONTAINER_ELEMENT_ID).update(
          this._get_quicktime_html(
            version_string, 
            this.quicktime_embed_mode)
        );
      }
      else {
        $(this.PLAYER_CONTAINER_ELEMENT_ID).update(
          this._get_fallback_html()
        );
      }
    },
    '_wrap_player_with_controller': function () {
      var player = $(this.PLAYER_ELEMENT_ID);
      var controls = $(this.CONTROLS_CONTAINER_ELEMENT_ID);
      var plugin = this.choice.plugin;
      var version = this.choice.version;
      var format = this.SUPPORTED_FORMATS[plugin][version];
      var Controller = largeblue.player[plugin.capitalize() + 'Controller'];
      if (plugin == 'flash' && version == 'h264') {
        this.controller = new Controller(player, null);
      }
      else {
        this.controller = new Controller(player, controls, format);
      }
    },
    '_get_player_choice': function () {
      var choice = null;
      var supports_cookies = jaaulde.utils.cookies.test();
      if (supports_cookies) { // try and read the value
        var cookie_value = jaaulde.utils.cookies.get(
          'largeblue-player-choice'
        );
        if (cookie_value) { // if it exists, great :)
          choice = cookie_value.evalJSON(true);
        }
        //else { // if not, detect and store
          choice = this._detect_best_video_player();
          jaaulde.utils.cookies.set(
            'largeblue-player-choice', 
            Object.toJSON(choice)
          );
        //}
      }
      else { // we have to detect each time :(
        choice = this._detect_best_video_player();
      }
      return choice;
    },
    '_get_bandwidth': function () {
      var bandwidth = null;
      var supports_cookies = jaaulde.utils.cookies.test();
      if (supports_cookies) { // try and read the value
        var cookie_value = jaaulde.utils.cookies.get(
          'largeblue-player-bandwidth'
        );
        if (cookie_value) { // if it exists, great :)
          bandwidth = cookie_value;
        }
        else { // if not, detect and store
          var item = $H(this.SUPPORTED_BANDWIDTHS).find(
            function (option) {
              return option.value;
            }
          );
          if (typeof(item) == 'undefined') {
            throw 'must select a default bandwidth';
          }
          bandwidth = item.key;
          jaaulde.utils.cookies.set(
            'largeblue-player-bandwidth', 
            bandwidth
          );
        }
      }
      else {
        bandwidth = $H(this.SUPPORTED_BANDWIDTHS).find(
          function (option) {
            return option.value;
          }
        ).key;
      }
      return bandwidth;
    },
    '_handle_ready': function (event) {
      if (this.videoid && this.choice.plugin == 'flash') {
        this.play(this.videoid);
      }
      if (this.callback) {
        this.callback(this);
      }
    },
    '_handle_never_going_to_be_ready': function (event) {
      $(this.PLAYER_CONTAINER_ELEMENT_ID).update(
        this._get_fallback_html()
      );
    },
    '_construct_url': function (videoid) {
      if (!this.url_template) {
        this.url_template = new Template(this.URL_FORMAT);
      }

      var formats = this.SUPPORTED_FORMATS;
      var format = formats[this.choice.plugin][this.choice.version];

      var url = this.url_template.evaluate({
          'path': this.VIDEOS_PATH,
          'videoid': videoid,
          'bandwidth': this.bandwidth,
          'ext': format.ext
        }
      );
      // log('faking url');
      // return 'http://static.green.tv/static/videos/oil_on_ice/oil_on_ice.9.wmv';
      return url;
    },
    'play': function (videoid) {
      // log('play: ' + videoid);
      this.videoid = videoid;
      var url = this._construct_url(this.videoid);
      this.controller.load(url);
    },
    'setBandwidth': function (bandwidth) {
      // log('setBandwidth: ' + bandwidth);
      if (bandwidth in this.SUPPORTED_BANDWIDTHS) {
        jaaulde.utils.cookies.set(
          'largeblue-player-bandwidth', 
          bandwidth
        );
        this.bandwidth = bandwidth;
        if (this.videoid) {
          // it's progressive download - seeking is a bad idea
          // just play from the top and let the user deal with it
          // they'll only do this once
          this.play(this.videoid);
        }
      }
      else {
        var options = this.SUPPORTED_BANDWIDTHS.join(', ');
        throw '' + bandwidth + ' not in ' + options;
      }
    },
    'initialize': function (videoid, ready_callback) {
      if (typeof(videoid) != 'undefined') {
        this.videoid = videoid;
      }
      else {
        throw 'you pass pass a videoid to the MultiFormatPlayer constructor';
      }
      if (typeof(ready_callback) != 'undefined') {
        this.callback = ready_callback;
      }
      document.observe(
        'largeblue-player:ready', 
        this._handle_ready.bindAsEventListener(this)
      );
      document.observe(
        'largeblue-player:never-going-to-be-ready',
        this._handle_never_going_to_be_ready.bindAsEventListener(this)
      );
      this.bandwidth = this._get_bandwidth();
      this.choice = this._get_player_choice();
      var plugin = this.choice.plugin;
      if (this.choice.plugin) {
        this._embed_player_markup();
        if (plugin != 'flash' || this.choice.version != 'xi') {
          this._wrap_player_with_controller.bind(this).defer();
        }
      }
      else {
        $(this.PLAYER_CONTAINER_ELEMENT_ID).update(
          this._get_fallback_html()
        );
      }
    }
  }
);


var webpage = {
  scrollSize : function(){
    if( window.innerHeight && window.scrollMaxY ){
      // Firefox
      pageWidth = window.innerWidth + window.scrollMaxX;
      pageHeight = window.innerHeight + window.scrollMaxY;
    }else if( document.body.scrollHeight > document.body.offsetHeight ){
      // all but Explorer Mac
      pageWidth = document.body.scrollWidth;
      pageHeight = document.body.scrollHeight;
    }else{
      // works in Explorer 6 Strict, Mozilla (not FF) and Safari
      pageWidth = document.body.offsetWidth + document.body.offsetLeft; pageHeight = document.body.offsetHeight + document.body.offsetTop;
    }
    return {width: pageWidth, height: pageHeight};
  },
  viewportWidth: function() {
    return self.innerWidth || (document.documentElement.clientWidth || document.body.clientWidth);
  },

  viewportHeight: function() {
    return self.innerHeight || (document.documentElement.clientHeight || document.body.clientHeight);
  },
  
  viewportSize: function() {
    return { width: this.viewportWidth(), height: this.viewportHeight() };
  }

};