/*
var e = document.createElement("script");
e.type = "text/javascript";
// e.src = '<?= $host ?>/js/swfobject.js';
e.src = 'http://ajax.googleapis.com/ajax/libs/swfobject/2.1/swfobject.js';
document.getElementsByTagName("head")[0].appendChild(e);
*/


/* creates an object with play/stop functions */
/*
At the very minimum requires the following in options:
  - element : the DOM element
  - player : a string to indicate the player used. The following can be used:
    - youtube
    - soundcloud
    - soundcloudsite (only on soundcloud.com)
    - vimeo
    - jwplayer
    - yahoo
    - streampad
    - wordpress
    - mp3
*/

TwonesToolbarTrackFactory = function(options) {
  this.state = 0; // 0=stopped, 1=playing, 2=pause
  
  for (var option in options) {
    this[option] = options[option];
  }
  
  this.play = function() {
    this['_do_' + this.player]('play');
  };
  
  this.stop = function() {
    this['_do_' + this.player]('stop');    
  };
  
  this.pause = function() {
    this['_do_' + this.player]('pause');    
  };
  
  this.position = function() {
    return this['_do_' + this.player]('position');
  };
  
  this.isTrack = function(track) {
    if ('player' in track) {
      if (this.player != track.player) {
        return false;
      }
    }
    if (this.player == 'mp3') {
      return (this.element.href == track.location);  
    } else if (this.player == 'youtube') {
      var isYoutube = track.location.match(/(youtube)\.com/);
      if (isYoutube) {
        TwonesToolbar.debugMsg('Youtube url is : ' + this.element.getVideoUrl());
        var track_id = TwonesToolbarGadget.YoutubePlayer.getVideoIdByPlayURL(this.element.getVideoUrl());
        var video_id = TwonesToolbarGadget.YoutubePlayer.getVideoIdByPlayURL(track.location);
        video_id = (video_id) ? video_id : TwonesToolbarGadget.YoutubePlayer.getVideoIdByURL(track.location);
        TwonesToolbar.debugMsg('track id : ' + track_id + ' <=> video id : ' + video_id);
        return (track_id == video_id);
      } else {
        return false;
      }
    } else if (this.player == 'vimeo') {
      var isVimeo = track.location.match(/vimeo\.com\/moogaloop/);
      if (isVimeo) {
        var track_id = TwonesToolbarGadget.VimeoPlayer.getVideoIdByURL(track.location);
        var video_id = TwonesToolbarGadget.VimeoPlayer.getVideoId(this.element);
        return (track_id == video_id);
      } else {
        return false;
      }
    } else if ((this.player == 'soundcloud') || (this.player == 'soundcloudsite')) {
      var isSoundCloud = track.location.match(/soundcloud\.com/);
      if (isSoundCloud) {
        var permaLink = (this.player == 'soundcloud') ? this.element.api_getCurrentTrack().streamUrl : this.element.playerProperties.streamUrl;
        var SCStreamRegex = /^http:\/\/media\.soundcloud\.com\/stream\/([^\?]+)/i;
        var permaStream = permaLink.match(SCStreamRegex)[1];
        var locStream = track.location.match(SCStreamRegex)[1];
        TwonesToolbar.debugMsg('soundcloud track : ' + permaLink + ' <=> ' + track.location);
        TwonesToolbar.debugMsg('soundcloud streams : ' + permaStream + ' <=> ' + locStream);
        return (locStream == permaStream);
      } else {
        return false;
      }
    } else if (this.player == 'yahoo') {
      return (this.element.token == track.location);
    } else if (this.player == 'streampad') {
      return (this.element.href == track.location);
    } else if (this.player == 'wordpress') {
      var elemMatch = TwonesToolbarGadget.getObjectParam(this.element, 'flashvars').match(/soundFile\=([^\&]+)&?/i);
      var elemEncoding = (elemMatch != null) ? unescape(elemMatch[1]) : ""; //
      var trackLocation = unescape(track.location);
      var elemLocation = "";
      if (elemEncoding != "") {
        // var codekey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
        if (elemEncoding.match(/^([A-Za-z0-9_-]+)$/)) {
          // we have six bit encoding turned on
          elemLocation = TwonesToolbarGadget.WPPlayer.sixBitDecode(elemEncoding).substr(0, trackLocation.length);
        } else {
          // we do not have six bit encoding, assume it's a url
          elemLocation = elemEncoding;
        }
        // now we can still have a full or relative url
        // hack to get the absolute path
        var image = new Image();
        image.src = elemLocation;
        var absolute_location = image.src;
        elemLocation = absolute_location;
      }
      TwonesToolbar.debugMsg('wordpress : ' + trackLocation + ' <=> ' + elemLocation);
      return (trackLocation == elemLocation);
    } else if (this.player == "jwplayer") {
      var conf = this.element.getConfig();
  		var playlist = this.element.getPlaylist();
  		
  		if (playlist == null) {
  		  //TwonesToolbar.debugMsg('playlist null!');
  		  return false;
		  }

  		var item = playlist[this.trackIndex];
  		TwonesToolbar.debugMsg('item file : ' + item.file + ' <=> ' + track.location);
      return (item.file == track.location);
    }
    
    return false;
  };
  
  this._do_youtube = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('Youtube play!');
      this.element.playVideo();
    } else if (cmd == 'pause') {
      this.element.pauseVideo();
    } else if (cmd == 'stop') {
      this.element.stopVideo();
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf('id="' + this.element.getAttribute('id') + '"');      
    }
  };

  this._do_mp3 = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('mp3 play!');
      TwonesToolbar.twonesInlinePlayer.handleClick({'target':this.element});      
    } else if (cmd == 'stop') {
      TwonesToolbar.twonesInlinePlayer.handleClick({'target':this.element});      
    } else if (cmd == 'pause') {
      TwonesToolbar.twonesInlinePlayer.handleClick({'target':this.element});
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf(this.element + '');      
    }
  };
  
  this._do_soundcloud = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('soundcloud play!');
      this.element.api_play();
    } else if (cmd == 'stop') {
      this.element.api_stop();
    } else if (cmd == 'pause') {
      this.element.api_pause();
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf('id="' + this.element.getAttribute('id') + '"');      
    }    
  };
  
  this._do_soundcloudsite = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('soundcloud play!');
      this.element.play();
    } else if (cmd == 'stop') {
      this.element.stop();
    } else if (cmd == 'pause') {
      this.element.pause();
    } else if (cmd == 'position') {
      return this.trackIndex;      
    }        
  };
  
  this._do_yahoo = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('Yahoo! play!');
      YAHOO.MediaPlayer.play(this.element);
    } else if (cmd == 'stop') {
      YAHOO.MediaPlayer.stop();
    } else if (cmd == 'pause') {
      YAHOO.MediaPlayer.pause();
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf(this.element.anchor + '');      
    }        
  };
  
  this._do_vimeo = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('vimeo play!');
      this.element.api_play();
    } else if (cmd == 'stop') {
      this.element.api_pause();
    } else if (cmd == 'pause') {
      this.element.api_pause();
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf('id="' + this.element.getAttribute('id') + '"');      
    }        
  };
  
  this._do_streampad = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('streampad play!');
      if (!streampadPlayer.vars.built) {
        TwonesToolbarGadget.Streampad.queueSongByIndex(this.index);
      } else {
        SPAPI.skip(this.index);
      }      
    } else if (cmd == 'stop') {
      SPAPI.pause();
    } else if (cmd == 'pause') {
      SPAPI.pause();
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf(this.element + '');
    }            
  };

  this._do_wordpress = function(cmd) {
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('wordpress play!');
      this.element.open();
    } else if (cmd == 'stop') {
      this.element.close();
    } else if (cmd == 'pause') {
      this.element.close();
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf('id="' + this.element.getAttribute('id') + '"');      
    }        
  };

  this._do_jwplayer = function(cmd) {
    var config = this.element.getConfig();
    if (cmd == 'play') {
      TwonesToolbar.debugMsg('jw player play!');
      if (config.item != this.trackIndex) {
        this.element.sendEvent("ITEM", this.trackIndex);
      }
      this.element.sendEvent("PLAY", "true");
    } else if (cmd == 'stop') {
      this.element.sendEvent("STOP");
    } else if (cmd == 'pause') {
      this.element.sendEvent("PLAY", "false");
    } else if (cmd == 'position') {
      TwonesToolbarGadget.get_html();
      return TwonesToolbarGadget.doc_html.indexOf('id="' + this.element.getAttribute('id') + '"') + this.trackIndex;      
    }        
  };

  return this;
};

var TwonesToolbarGadget = {
  postTimerId: null,
  postTime: 50000, // wait 50 secs to post
  api_url: "http://api.twones.com/v2",
  host: "twones.com",
  service: null,
  host2api: {
    "development" : "http://api.localhost.twones.com:8888/v2",
    "preproduction" : "http://api.trunk.twones.com/v2",
    "production" : "http://api.twones.com/v2"
  },
  currentTrack: null,
  metadata: null,
  playdata: null,
  tracks: [ // list of (candidate) tracks on the page
  ],
  actions: { // pending actions that are still running.
  },
  doc_html: null,
  get_html: function() {
    if (this.doc_html == null) {
      this.doc_html = document.body.innerHTML;
    }
  },
  embed: function(s) {
    document.write(s);
  },
  init: function(twones_host, activate_now, environment) {
    TwonesToolbarGadget.actions['TwonesToolbarGadget.init'] = false;
    
    this.host = twones_host;
    this.api_url = this.host2api[environment];
    TwonesToolbar.debugMsg('TwonesToolbarGadget api url : ' + this.api_url);
    TwonesToolbar.debugMsg(activate_now ? "Should activate now" : "Activate on window load");
    this.Streampad.init(activate_now);
    this.YahooMediaPlayer.init(activate_now);
    this.JWPlayer.init(activate_now);
    this.YoutubePlayer.init(activate_now);
    this.WPPlayer.init(activate_now);
    this.SoundCloudPlayer.init(activate_now);
    this.SoundCloudSitePlayer.init(activate_now);
    this.VimeoPlayer.init(activate_now);
    this.FlashWModeFixer.init(activate_now);
    this.TwonesAddon.init(activate_now);
    
    var br_tags = document.getElementsByTagName("br");
    var p_tags = document.getElementsByTagName("p");

    for ( var i = 0; i < br_tags.length + p_tags.length; i++ ) {
      var my_tag = ( i < br_tags.length ) ? br_tags[i] : p_tags[i-br_tags.length];
      my_tag.parentNode.insertBefore(document.createTextNode("\n"), my_tag);
      if (null !== my_tag.nextSibling) {
        my_tag.parentNode.insertBefore(document.createTextNode("\n"), my_tag.nextSibling);
      }
    }

    TwonesToolbarGadget.actions['TwonesToolbarGadget.init'] = true;
  },
  allActionsPerformed: function() {
    var allPerformed = true;
    for(var act_idx in this.actions) {
      allPerformed = allPerformed && this.actions[act_idx];
    }
    return allPerformed;
  },
  countAllActions: function() {
    var allCount = 0;
    for(var act_idx in this.actions) {
      allCount++;
    }
    return allCount;    
  },
  favorite: function(favdata) {
    metadata = ('metadata' in this) ? this.metadata : {};
    if (!('artist' in metadata)) {
	    metadata['artist'] = ('artist' in favdata) ? favdata.artist : null;
	  }
	  if (!('title' in metadata)) {
	    metadata['title'] = ('title' in favdata) ? favdata.title : null;	
    }
    metadata['action'] = 'favorite';
    metadata['service'] = ('service' in metadata) ? metadata.service : this.service;
    metadata['annotation'] = favdata.message;
    metadata['playlists'] = favdata.playlists;
    if ('callback' in favdata) {
      metadata['callback'] = favdata['callback'];
    }
    request_params = this.build_request_params(metadata);
    TwonesToolbarGadget.post('favorite', request_params);
  },
  updateToolbarPlayButtons: function(cmd) {
    if (cmd == 'play') {
      tjq('#twones-toolbar-playbutton img').attr('src', 'http://' + this.host + '/img/toolbar/tb-play.png');
    } else if (cmd == 'pause') {
      tjq('#twones-toolbar-playbutton img').attr('src', 'http://' + this.host + '/img/toolbar/tb-pause.png');      
    }
  },
  updateMessage: function(msg) {
    tjq('#current_playing').html(msg);
  },
  updateCurrentPlaying: function(metadata) {
    TwonesToolbar.debugMsg('update current playing data according to :');
    TwonesToolbar.debugDir(metadata);
    if ((metadata['artist'] != null) && (metadata['artist'] != '')) {
      tjq('#current_playing').html(metadata['artist'] + ' - ' + metadata['title']);
    } else {
      tjq('#current_playing').html(metadata['title']);
    }
    TwonesToolbarGadget.updateToolbarPlayButtons('pause');
    TwonesToolbar.showToolbar();
    TwonesToolbar.updateSideBar();    
  },
  setPlayData: function(data) {
    //TwonesToolbar.debugMsg('getting playdata :');
    //TwonesToolbar.debugDir(data);
    TwonesToolbarGadget.playdata = data;
    //TwonesToolbar.updateShareLinks(data.id);
  },
  playNow: function(pndata) {
    if (this.metadata == null) return;
    
    if (this.playdata != null) return;
    
    TwonesToolbar.debugMsg('getting a play id now!');
    metadata2 = this.metadata;
    metadata2['callback'] = 'TwonesToolbar.loadShareDialog';
    
    if (pndata != undefined) {
      for(prop in pndata) {
        metadata2[prop] = pndata[prop];
      }
    }
    
    this.play(metadata2);
    
    if(this.postTimerId) {
      clearTimeout(this.postTimerId);
      this.postTimerId = null;
    }
    
    TwonesToolbar.debugMsg('really posting now!');
    TwonesToolbarGadget.post();
  },
  play: function(metadata) {
    TwonesToolbar.debugMsg('TwonesToolbarGadget.play');
    var track_found = false;
    for (var track_index = 0; track_index <  TwonesToolbarGadget.tracks.length; track_index++) {
      //TwonesToolbar.debugMsg('Checking track #' + track_index);
      var track = TwonesToolbarGadget.tracks[track_index];
      if (!track_found && track.isTrack(metadata)) {
        track_found = true;
        this.currentTrack = track;
        this.currentTrack.state = 1; //playing
      }
    }
    TwonesToolbar.debugMsg(track_found ? "track found:" : "track not found:");
    TwonesToolbar.debugMsg(metadata.location);
    metadata['action'] = 'play';
    metadata['service'] = this.service;
    if (!('callback' in metadata)) {
      metadata['callback'] = 'TwonesToolbarGadget.setPlayData';
    }
    this.metadata = metadata;
    request_params = this.build_request_params(metadata);

    TwonesToolbar.initTrackerPlayerBar(function(){TwonesToolbarGadget.updateCurrentPlaying(metadata);});
    
    if(this.postTimerId) {
      clearTimeout(this.postTimerId);
      this.postTimerId = null;
    }
    this.request_params = request_params;
    this.postTimerId = setTimeout("TwonesToolbarGadget.post()", TwonesToolbarGadget.postTime);
  },
  stop: function(display_msg) {
    if (this.currentTrack != null) {
      this.currentTrack.state = 0; //stopped      
    }
    request_params = this.build_request_params({action: 'stop'});
    TwonesToolbar.debugMsg('display msg : ' + display_msg);
    tjq('#current_playing').html((display_msg != undefined) ? display_msg : 'nothing');
    TwonesToolbarGadget.updateToolbarPlayButtons('play');    
    this.metadata = null;
    this.playdata = null;
    this.currentTrack = null; // clear the current track, finished playing :)
    //TwonesToolbar.updateShareLinks(undefined);
    if(this.postTimerId) {
      clearTimeout(this.postTimerId);
      this.postTimerId = null;
    }
  },
  pause: function() {
    if (this.currentTrack != null) {
      this.currentTrack.state = 2; //paused      
    }
    request_params = this.build_request_params({action: 'stop'});
    /*
    tjq('#current_playing').html('nothing');
    */
    TwonesToolbarGadget.updateToolbarPlayButtons('play');    
    
    this.metadata = null;
    this.playdata = null;
    //TwonesToolbar.updateShareLinks(undefined);
    if(this.postTimerId) {
      clearTimeout(this.postTimerId);
      this.postTimerId = null;
    }
  },
  post: function(method_call, request_params) {  
    // post to the api        
    var e = document.createElement("script");
    var m = (method_call != undefined) ? method_call : 'add';
    var r = (request_params != undefined) ? request_params : this.request_params;
    
    var noCacheIE = '&_=' + (new Date()).getTime();    
    var src = this.api_url + "/" + m + "?" + r + noCacheIE;
    
    e.setAttribute("type", "text/javascript");
    e.setAttribute("charset", "utf-8");
    e.setAttribute("src", src);
    TwonesToolbar.debugMsg('getting json url ' + src);
    document.getElementsByTagName("head").item(0).appendChild(e);
  },
  build_request_params: function(data) {
    // build request params
    var pairs = [];
    for(key in data) {
      if (data[key] != null)
        pairs.push(key + '=' + encodeURIComponent(data[key]));
    }
    return pairs.join('&');
  },
  getObjectUrl: function(object) {
    TwonesToolbar.debugMsg('Getting object url for ' + object);
    var url = object.data;
    if(!url || (url.length == 0) ) {
      var params = object.getElementsByTagName('param');
      TwonesToolbar.debugMsg('No data on object, sifting through ' + params + ' parameters...');
      for(var j = 0; j <  params.length; j++) {
        var p = params[j];
        TwonesToolbar.debugMsg('object : ' + object.id + ' param ' + p.getAttribute('name') + ' = ' + p.getAttribute('value'));
        if(p.getAttribute("name").toLowerCase() == 'movie') {
          // alert('movie');
          url = p.getAttribute('value');
          TwonesToolbar.debugMsg('For object ' + object.id + ' we have movie : ' + url);
          break;
        }
      }
    }
    return url; //.toLowerCase();
  },
  getObjectParam: function(object, param_name) {
    var params = object.getElementsByTagName('param');
    var url = undefined;
    
    for(var j = 0; j <  params.length; j++) {
      var p = params[j];
      if(p.getAttribute("name") == param_name) {
        // alert('movie');
        url = p.getAttribute('value');
        break;
      }
    }
    return url; //.toLowerCase();
  },
  TwonesAddon: {		
    init: function (activate_now) {
		  var _init = function() {
        TwonesToolbarGadget.actions['TwonesAddOn'] = true;
      }
      
      TwonesToolbarGadget.actions['TwonesAddOn'] = false;
      if(!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
		},
		
		add_to_blacklist: function(pageUrl) {
		  // Adds page URL to tracker blacklist
			if ("createEvent" in document) {
				var element = document.createElement("TwonesTrackerBlackList");
				element.setAttribute("pageUrl", pageUrl);
				element.setAttribute("addRemoveFlag", true);
				document.documentElement.appendChild(element);

				var evt = document.createEvent("Events");
				evt.initEvent("TwonesTrackerBlackListEvent", true, false);
				element.dispatchEvent(evt);
			}
		},
		
		remove_from_blacklist: function(pageUrl) {
		  // Removes page URL from tracker blacklist
			if ("createEvent" in document) {
				var element = document.createElement("TwonesTrackerBlackList");
				element.setAttribute("pageUrl", pageUrl);
				element.setAttribute("addRemoveFlag", false);
				document.documentElement.appendChild(element);

				var evt = document.createEvent("Events");
				evt.initEvent("TwonesTrackerBlackListEvent", true, false);
				element.dispatchEvent(evt);
			}
		},
		close: function() {
			if(navigator.userAgent.indexOf('MSIE') > -1) {
				var tracker = window.document.body.getAttribute("TwonesTracker");
				if (tracker != null)
					tracker.removeFromBlackList(document.location);
			}
			else{
					TwonesToolbarGadget.TwonesAddon.remove_from_blacklist(document.location);
			}		
		}
  },
  JWPlayer: {
    isInited: {},
    cachedMetadata: {},
    playlistAdded: false,
    init: function(activate_now) {
      var _init = function() {
        //TwonesToolbar.debugMsg(playerReady);
        if (typeof(playerReady) != "undefined") {

          // the playerReady function is already defined. 

          // ala alias_method_chain? 

          // This trick only works if the user defined 'playerReady' function is before the gadget 

          // change the name of the function to oldPlayerReady
          var code = playerReady.toString();
          code = code.replace(/playerReady/,"oldPlayerReady"); // danger! danger!

          // add oldPlayerReady to the dom 
          var e = document.createElement("script");
          e.type = "text/javascript";
          e.text = code;
          document.getElementsByTagName("body")[0].appendChild(e);        

          // add the new playerReady that calls the oldPlayerReady
          var e = document.createElement("script");
          e.type = "text/javascript";
          e.text = "playerReady = function(thePlayer){ TwonesToolbarGadget.JWPlayer.playerReady(window.document[thePlayer.id]); oldPlayerReady(thePlayer);}";
          document.getElementsByTagName("body")[0].appendChild(e);
        }
        else {
          var e = document.createElement("script");
          e.type = "text/javascript";
          e.text = "playerReady = function(thePlayer){ TwonesToolbarGadget.JWPlayer.playerReady(window.document[thePlayer.id]); } ";
          document.getElementsByTagName("body")[0].appendChild(e);

        }
        TwonesToolbarGadget.actions['JWPlayer.findPlayer'] = false;
        setTimeout('TwonesToolbarGadget.JWPlayer.findPlayer()', 3000);
        TwonesToolbarGadget.actions['JWPlayer'] = true;
      };
      
      // disable jw player catching on hypem.com
      if (document.location.href.match(/\/\/hypem\.com/i)) {
        TwonesToolbar.debugMsg('We are on hypem and do not do jw therefore.');
        return;
      }
      
      TwonesToolbarGadget.actions['JWPlayer'] = false;
      if (!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
    },
    reEmbedPlayer: function(el, tag, index) {
      var embedEl = document.createElement(tag);
      for(var i=0;i<el.attributes.length;i++) {
        embedEl.setAttribute(el.attributes[i].nodeName, el.attributes[i].nodeValue);
      }
      embedEl.id = el.id ? el.id : 'twones-embed-' + index;
      embedEl.name = embedEl.id;
      el.parentNode.insertBefore(embedEl, el);
      el.parentNode.removeChild(el);      
    },
    findPlayer: function() {
      //TwonesToolbar.debugMsg('finding players ' + document.URL);
      var objects = document.getElementsByTagName('object');
      for (var index = 0; index < objects.length; index++) {
        var element = objects[index];
        if ((element.sendEvent != undefined) && (element.addModelListener != undefined) && (element.addViewListener != undefined)) {
          TwonesToolbarGadget.JWPlayer.playerReady(element);
        }
      }
      var embeds = document.getElementsByTagName('embed');
      for (index = 0; index < embeds.length; index++) {
        var element = embeds[index];
        if (element.name && (element.name != '')) {
          if ((element.sendEvent != undefined) && (element.addModelListener != undefined) && (element.addViewListener != undefined)) {
            TwonesToolbarGadget.JWPlayer.playerReady(element);
          }
        } else {
          // potentially dangerous!
          /*
          if (embed.src && (embed.src != '')) {
            var url = embed.src;
            TwonesToolbar.debugMsg(url);
            // avoid re-embedding youtube urls -- this happens later (or earlier)
            var isYoutube = url.match(/(youtube)\.com/);
            if (!isYoutube) {
              TwonesToolbar.debugMsg('almost re-embedded youtube element');
              TwonesToolbarGadget.JWPlayer.reEmbedPlayer(element, 'embed', index);
            }
          }*/
        }
      }
      TwonesToolbarGadget.actions['JWPlayer.findPlayer'] = true;
    },
    playerReady: function(thePlayer) {
      if (!(thePlayer in TwonesToolbarGadget.JWPlayer.isInited)) {
        TwonesToolbar.debugMsg('player ready for ' + thePlayer.id);
        TwonesToolbarGadget.JWPlayer.isInited[thePlayer.id] = true;
        TwonesToolbarGadget.JWPlayer.addListeners(thePlayer);
        // TwonesToolbar.initTrackerPlayerBar(function(){TwonesToolbarGadget.JWPlayer.checkAutoPlay(thePlayer.id);});
        TwonesToolbarGadget.JWPlayer.scanPlaylist(thePlayer);
        TwonesToolbarGadget.JWPlayer.checkAutoPlay(thePlayer.id);
      }
    },
    checkAutoPlay: function(player_id) {
      thePlayer = window.document[player_id];
      var conf = thePlayer.getConfig();
      TwonesToolbar.debugMsg('checking jw autoplay');
      if (conf.autostart) {
        TwonesToolbar.debugMsg('jw autoplay on!');
        TwonesToolbarGadget.JWPlayer.stateListener({
          newstate: "PLAYING",
          oldstate: undefined,
          id: thePlayer.id
        });
      }
    },
    addListeners: function(thePlayer) {
      // this.player.addControllerListener("PLAY", "JWTracker.playListener"); //{state,id,client,version}. 
      thePlayer.addModelListener("STATE", "TwonesToolbarGadget.JWPlayer.stateListener"); //{variable1,variable2,variable3,...,id,client,version}. 
      thePlayer.addModelListener("META", "TwonesToolbarGadget.JWPlayer.metaListener"); //{variable1,variable2,variable3,...,id,client,version}. 
      thePlayer.addViewListener("STOP", "TwonesToolbarGadget.JWPlayer.stopListener"); //{id,client,version}.
      thePlayer.addViewListener("PLAY", "TwonesToolbarGadget.JWPlayer.playListener"); //{id,client,version}.
      thePlayer.addViewListener("ITEM", "TwonesToolbarGadget.JWPlayer.itemListener"); //{id,client,version}.
      thePlayer.addControllerListener("PLAYLIST", "TwonesToolbarGadget.JWPlayer.playlistListener"); //{id,client,version}.
    },
    playlistListener: function(obj) {
      TwonesToolbar.debugMsg('got jw playlist :');
      //TwonesToolbar.debugDir(obj);
      TwonesToolbarGadget.JWPlayer.scanPlaylist(window.document[obj.id]);
    },
    stateListener: function(obj) { //IDLE, BUFFERING, PLAYING, PAUSED, COMPLETED
    	var currentState = obj.newstate; 
    	var previousState = obj.oldstate;
      switch (currentState){
        case "PLAYING":

          var player = window.document[obj.id];
      		// get metadata from playlist
      		var conf = player.getConfig();
      		var playlist = player.getPlaylist();
      		
      		if (playlist == null) {
//      		  TwonesToolbar.debugMsg('playlist null!');
      		  return;
    		  }

          var itemIndex = ('index' in obj ) ? obj.index : conf.item;
      		var item = playlist[itemIndex];

          TwonesToolbarGadget.JWPlayer._data = {};
          
      	  if((item.title != null) && (item.title != '')) {
            TwonesToolbarGadget.JWPlayer._data = {
        		  title: item.title,
        		  artist: item.author,
        		  album: item.album,
        		  duration: item.duration,
        		  location: item.file,
              player: "jwplayer"
        		};
          } else {
            try {
              var cachedMedatada = TwonesToolbarGadget.JWPlayer.cachedMetadata[obj.id][temIndex];
              if((cachedMedatada.title != null) && (cachedMedatada.title != '')) 
                TwonesToolbarGadget.JWPlayer._data = cachedMedatada;
            } catch(err) {
              // Breaks when there's no "medatada". Doesn't matter. Just find the damn permalink. (S.J. Meurkens)
            }
          } 

          TwonesToolbar.getPermalinkByBoss(player, false, "jwplayer");

          break;
        case "PAUSED":
    		  TwonesToolbarGadget.pause();
          break;
        case "COMPLETED":
    		  TwonesToolbarGadget.stop();
          break;
      }
      
    },

    setToolbarPlay: function() {
      TwonesToolbar.debugMsg('permalink for jwplayer: ' + TwonesToolbarGadget.JWPlayer._data.permaLink);
      TwonesToolbarGadget.play({
        title: TwonesToolbarGadget.JWPlayer._data.title, 
        artist: TwonesToolbarGadget.JWPlayer._data.creator,
        location: TwonesToolbarGadget.JWPlayer._data.location,
        pageLink: TwonesToolbarGadget.JWPlayer._data.permaLink,
        duration: TwonesToolbarGadget.JWPlayer._data.duration,
        player: "JWPlayer"
      });
    },

    playListener: function(obj) {
      if (obj != undefined) {
        if ('state' in obj) {
          if (obj.state) {
            TwonesToolbar.debugMsg('jw player ' + obj.id + 'got a play event!');
            obj.newstate = "PLAYING";
            obj.oldstate = undefined;
            TwonesToolbarGadget.JWPlayer.stateListener(obj);
          }
        }
      }
    },
    itemListener: function(obj) {
      TwonesToolbar.debugMsg('jw player ' + obj.id + 'got an item view event!');
      obj.newstate = "PLAYING";
      obj.oldstate = undefined;
      TwonesToolbarGadget.stop();
      TwonesToolbarGadget.JWPlayer.stateListener(obj);      
    },
    stopListener: function() {
      // stop, end of track or stop button
      TwonesToolbarGadget.stop();
    },
    metaListener: function(obj) {
      var player = window.document[obj.id];
      
      // playlists are nicer, but if we dont have a title for this item...
      var playlist = player.getPlaylist();
      var conf = player.getConfig();
      var item = playlist[conf.item];
  	  if((item.title == null) || (item.title == '')) {  	    
        
        // hack to get the absolute path
        var image = new Image();
        image.src = item['file'];
        var location = image.src;
  		
    		// then we save this for when the guy starts and stops
    		if (TwonesToolbarGadget.JWPlayer.cachedMetadata[obj.id] == null) 
    		  TwonesToolbarGadget.JWPlayer.cachedMetadata[obj.id] = {};
  		  
  		  // then we use the id3 tags

        currentPermaLink = TwonesToolbarGadget.JWPlayer._data.permaLink;

  		  TwonesToolbarGadget.JWPlayer._data = {
    		  title: obj['name'],
    		  artist: obj['artist'],
    		  album: obj['album'],
    		  location: location,
          player: "jwplayer",
          permaLink: currentPermaLink
    		};

    		TwonesToolbarGadget.JWPlayer.cachedMetadata[obj.id][conf.item] = TwonesToolbarGadget.JWPlayer._data;
        TwonesToolbarGadget.JWPlayer.setToolbarPlay();

		  }
    },
    scanPlaylist: function(thePlayer) {
      var playlist = thePlayer.getPlaylist();
      
      if (playlist == null) {
        TwonesToolbarGadget.JWPlayer.playlistAdded = true;
        return;        
      }
      
      if ((playlist.length == 0) || TwonesToolbarGadget.JWPlayer.playlistAdded) {
        return; // got the playlist already
      }
      
      for(var i=0; i < playlist.length; i++) {
        TwonesToolbarGadget.tracks.push(new TwonesToolbarTrackFactory({
          player: "jwplayer",
          element: thePlayer,
          trackIndex: i
        }));
      }
      
      TwonesToolbarGadget.JWPlayer.playlistAdded = true;
    }
  },
  YahooMediaPlayer : {
    init: function(activate_now) {
        var _init = function() {
          if ((typeof(YAHOO) != "undefined") && ('MediaPlayer' in YAHOO))
            YAHOO.MediaPlayer.onAPIReady.subscribe(TwonesToolbarGadget.YahooMediaPlayer.apiReady);
          TwonesToolbarGadget.actions['YahooMediaPlayer'] = true;
        };
        
        TwonesToolbarGadget.actions['YahooMediaPlayer'] = false;
        if(!activate_now) {
          if (window.addEventListener) 
            window.addEventListener("load", _init, false);
          else if (window.attachEvent)
            window.attachEvent("onload", _init);
        } else {
          _init();
          // TODO : check for DOM readiness?
          if ((typeof(YAHOO) != "undefined") && ('MediaPlayer' in YAHOO)) {
            TwonesToolbar.debugMsg('Yahoo mediaplayer defined!');
            TwonesToolbarGadget.YahooMediaPlayer.apiReadyInterval = setInterval(TwonesToolbarGadget.YahooMediaPlayer.apiReady, 1000);
          }
        }
    },
    apiReady: function() {
      if (this.isApiReady) {
        return;
      }
      TwonesToolbar.debugMsg('Check if Yahoo! API is ready ...');
      if ((typeof(YAHOO) != "undefined") && ('MediaPlayer' in YAHOO)) {
        if ('onTrackStart' in YAHOO.MediaPlayer) {
          this.isApiReady = true;
          TwonesToolbar.debugMsg("Initializing yahoo api callbacks ...");
          YAHOO.MediaPlayer.onTrackStart.subscribe(TwonesToolbarGadget.YahooMediaPlayer.play);
          YAHOO.MediaPlayer.onTrackPause.subscribe(TwonesToolbarGadget.YahooMediaPlayer.pause);  
          YAHOO.MediaPlayer.onTrackComplete.subscribe(TwonesToolbarGadget.YahooMediaPlayer.stop);
          TwonesToolbarGadget.actions['YahooMediaPlayerPlaylist'] = false;
          YAHOO.MediaPlayer.onPlaylistUpdate.subscribe(TwonesToolbarGadget.YahooMediaPlayer.updateTracks);
          clearInterval(TwonesToolbarGadget.YahooMediaPlayer.apiReadyInterval);
          TwonesToolbar.debugMsg("Initialized yahoo api callbacks ...");
          //TwonesToolbarGadget.YahooMediaPlayer.getTracks();
        }
      }  
    },
    updateTracks: function(playlist) {
      var plCount = YAHOO.MediaPlayer.getPlaylistCount();
      TwonesToolbar.debugMsg('Yahoo! playlist count : ' + plCount);
      //TwonesToolbar.debugDir(playlist);
      for(var i=0; i < plCount; i++) {
        var plMetaData = playlist[i];
        var track = new TwonesToolbarTrackFactory({
          element: plMetaData,
          player: 'yahoo'
        });
        TwonesToolbarGadget.tracks.push(track);       
      }
      TwonesToolbarGadget.actions['YahooMediaPlayerPlaylist'] = true;
      TwonesToolbar.debugMsg('Yahoo! playlist updated.');
    },
    play: function(mediaObject) {
      //TwonesToolbar.debugMsg(TwonesToolbar.findContextByElement(mediaObject.mediaObject.anchor));
      TwonesToolbar.debugMsg('playing something on Yahoo player!');
      TwonesToolbarGadget.YahooMediaPlayer._data = {};
      TwonesToolbarGadget.YahooMediaPlayer._data.title = mediaObject.mediaObject.title;
      TwonesToolbarGadget.YahooMediaPlayer._data.creator = mediaObject.mediaObject.artistName;
      TwonesToolbarGadget.YahooMediaPlayer._data._location = mediaObject.mediaObject.url;
      
      var permaLink = TwonesToolbarGadget.YahooMediaPlayer.findPermaLink(mediaObject.mediaObject.url);
      if (permaLink) {
        TwonesToolbarGadget.YahooMediaPlayer._data.permaLink = permaLink;
        TwonesToolbarGadget.YahooMediaPlayer.setToolbarPlay();
      } else {
        TwonesToolbar.getPermalinkByBoss(mediaObject.mediaObject.anchor, false, "yahoo");
      }
      //TwonesToolbar.debugMsg('Got permalink : ' + permaLink);
      /*
      TwonesToolbarGadget.play({
        title:  mediaObject.mediaObject.title,
        artist: mediaObject.mediaObject.artistName,
        location: mediaObject.mediaObject.url,
        pageLink: permaLink
      });
      */

    },

    setToolbarPlay: function() {
      TwonesToolbar.debugMsg('permalink for yahoo: ' + TwonesToolbarGadget.YahooMediaPlayer._data.permaLink);
      TwonesToolbarGadget.play({
        title: TwonesToolbarGadget.YahooMediaPlayer._data.title, 
        artist: TwonesToolbarGadget.YahooMediaPlayer._data.creator,
        location: TwonesToolbarGadget.YahooMediaPlayer._data._location,
        pageLink: TwonesToolbarGadget.YahooMediaPlayer._data.permaLink,
        player: "yahoo"
      });
    },
          
    stop: function(mediaObject) {
      TwonesToolbar.debugMsg('stopping playing on Yahoo player!');
      TwonesToolbarGadget.stop();
    },
    pause: function(mediaObject) {
      TwonesToolbar.debugMsg('pausing playing on Yahoo player!');
      TwonesToolbarGadget.pause();
    },
    findPermaLink: function(enclosure) {
      TwonesToolbar.debugMsg('Search string : ' + enclosure);
      var permaLink = TwonesToolbar.findStringInFeedEntries(enclosure);
      return (permaLink) ? permaLink : false;       
    }
  },
  Streampad : {
    init: function(activate_now) {
      
        var _init = function() {
          TwonesToolbar.debugMsg('Streampad _init called!');
          if (typeof(streampadPlayer) != "undefined") {
            streampadPlayer.Event.add(window, 'setCurrent', TwonesToolbarGadget.Streampad.play);
            streampadPlayer.Event.add(window, 'pause', TwonesToolbarGadget.Streampad.pause);
            streampadPlayer.Event.add(window, 'play', TwonesToolbarGadget.Streampad.play);
            streampadPlayer.Event.add(window, 'handleMore', TwonesToolbarGadget.Streampad.stop); 
            streampadPlayer.Event.add(window, 'gotPlaylist', TwonesToolbarGadget.Streampad.gotPlaylist);
            TwonesToolbarGadget.actions['StreampadPlaylist'] = false;
            TwonesToolbarGadget.Streampad.scrape();
          }
          TwonesToolbarGadget.actions['Streampad'] = true;
        }
        
        TwonesToolbarGadget.actions['Streampad'] = false;
        if(!activate_now) {
          if (window.addEventListener) {
            TwonesToolbar.debugMsg('Adding load event listener for streampad');
            window.addEventListener("load", _init, false);
          } else if (window.attachEvent) {
            TwonesToolbar.debugMsg('Attaching onload event listener for streampad');
            window.attachEvent("onload", _init);
          }
        } else {
          _init();
        }
    },
    play: function() {
      if (TwonesToolbarGadget.currentTrack != null) {
        TwonesToolbarGadget.currentTrack.state = (TwonesToolbarGadget.currentTrack.state == 1) ? 0 : TwonesToolbarGadget.currentTrack.state;
        // streampad dos not appear to have a specific stop event
        // so when this function is called it means we have switched tracks if the previous
        // state was playing, so mark that song as stopped
      }
      currentSongVO = streampadPlayer.vars.currentSongVO;
      var permaLink = TwonesToolbarGadget.Streampad.findPermaLink(currentSongVO.enclosure);
      TwonesToolbar.debugMsg('Got permalink : ' + permaLink);
      TwonesToolbarGadget.play({
        title: currentSongVO.text, // we could use currentSongVO.songTitle
        artist: currentSongVO.artist,
        location: currentSongVO.enclosure,
        pageLink: permaLink,
        player: "streampad"
      });
    },
    stop: function() {
      TwonesToolbar.debugMsg('Streampad player queue ended playing!');
      TwonesToolbarGadget.stop();
      // TODO: find out about stop event?
    },
    pause: function() {
      TwonesToolbar.debugMsg('Streampad player paused!');
      TwonesToolbarGadget.pause();
      // TODO: find out about stop event?
    },
    scrape: function() {
      TwonesToolbar.debugMsg('Scraping a la Streampad');
      /* Sadly streampad does not provide a way to get the playlist
        before the user actually clicks the bar. They have a scrape function
        but it relies on the UI being available. So here we copy/paste the important
        bits of their scraping routine. Sorry Streampad! */
    	var as = document.getElementsByTagName('a');
  		var mp3s = 0;
  		for(j=0; j<as.length; j++){
  			var a = as[j];
  			if (a.href.indexOf('.mp3') != -1){
  				mp3s ++;
  				/*
  				var songVO = new streampadPlayer.SongVO();
  				songVO.text = a.innerHTML;
  				songVO.enclosure = a.href;
  				songVO.sourceUrl = location.href;
  				//streampadPlayer.Playlist.push(songVO);*/
  				var track = new TwonesToolbarTrackFactory({
            element: a,
            index: (mp3s - 1),
            player: 'streampad'
          });
          TwonesToolbarGadget.tracks.push(track);       
  			}
  		}
  		TwonesToolbarGadget.actions['StreampadPlaylist'] = true;
      TwonesToolbar.debugMsg('playlist ended streampad scraping ...');
    },
    findPermaLink: function(enclosure) {
      TwonesToolbar.debugMsg('Search string : ' + enclosure);
      var permaLink = TwonesToolbar.findStringInFeedEntries(enclosure);
      return (permaLink) ? permaLink : document.location.href;       
    },
    queueSongByIndex : function(song_index) {
      this.playlistIndex = song_index;
      streampadPlayer.Event.add(window, 'gotPlaylist', TwonesToolbarGadget.Streampad.playSong);
      SPAPI.start();
    },
    playSong : function(playlist) {
      TwonesToolbar.debugMsg('Got streampad playlist!');
      streampadPlayer.Event.remove(window, 'gotPlaylist', TwonesToolbarGadget.Streampad.playSong);
      TwonesToolbar.debugMsg('queing song nr ' + TwonesToolbarGadget.Streampad.playlistIndex);
      SPAPI.skip(TwonesToolbarGadget.Streampad.playlistIndex);
      TwonesToolbarGadget.Streampad.playlistIndex = null;
      //SPAPI.play();
    },
    gotPlaylist: function(playlist) {
      TwonesToolbar.debugMsg('=====> Got streampad playlist !');
      TwonesToolbar.debugDir(playlist);
    }
  },
  YoutubePlayer : {
    init: function(activate_now) {
      TwonesToolbarGadget.actions['YoutubePlayer'] = false;      
    
      TwonesToolbarGadget.YoutubePlayer.definePlayerReadyCallback();
      
      var _init = function() {
    
        /*
        <object width="480" height="385">
          <param name="movie" value="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&color1=0x234900&color2=0x4e9e00"></param>
          <param name="allowFullScreen" value="true"></param>
          <param name="allowscriptaccess" value="always"></param>
          <embed src="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&color1=0x234900&color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed>
        </object>
        */ 

        // look for youtube players
        var objects = document.getElementsByTagName('object'); 
        var len = objects.length;
        var  num_objects = objects.length;
        TwonesToolbar.debugMsg('found ' + len + ' objects');
        for(var index = 0; index < len; index++) {
          var object = objects[index];
          TwonesToolbar.debugMsg("object id : " + index);

          var url;
          try{
            url = TwonesToolbarGadget.getObjectUrl(object);
          } catch(e) {
            //
          }
          TwonesToolbar.debugMsg("object url : " + url);
          var isYoutube = (url != undefined) && url.match(/(youtube)\.com/);

          if(isYoutube) {
            try {
              TwonesToolbarGadget.YoutubePlayer.reembedElement(object, url, index);
            } catch(e) {
              //
            }
          }            
        }
        
        // now look form embeds. :-(
        var embeds = document.getElementsByTagName('embed'); 
        var len = embeds.length;
        TwonesToolbar.debugMsg('found ' + len + ' embeds');
        for(var index = 0; index < len; index++) {
          var embed = embeds[0]; // on IE when I remove the element from the dom it also get removed from the array
          if(embed) {
            var url = embed.src;
            TwonesToolbar.debugMsg(url);
            isYoutube = (url != undefined) && url.match(/(youtube)\.com/);

            if(isYoutube) {
              TwonesToolbarGadget.YoutubePlayer.reembedElement(embed, url, num_objects + index); 
            }         
          }
        }
        
        TwonesToolbarGadget.actions['YoutubePlayer'] = true;
      };

      if(!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
    },
    reembedElement : function(element, url, index) {
      TwonesToolbar.debugMsg('re-embedding Youtube player (' + url + ') ' + index);
      // clear original api params. one day we should turn this evil bit off
      url = url.replace(/enablejsapi=\w&/, ''); 
      url = url.replace(/playerapiid=\w&/, '');
      url += '&enablejsapi=1&playerapiid=' + index;
      
      var w = element.width;
      var h = element.height;
      
      
      // insert a container span for the new object
      var container = document.createElement("span");
      container.id = 'ytplayer_container_' + index;
      var insertedElement = element.parentNode.insertBefore(container, element);
      
      // remove old object
      element.parentNode.removeChild(element);
      
      var params = { allowScriptAccess: "always", bgcolor: "#cccccc", allowfullscreen: 'true', wmode: 'transparent'};
      var atts = { 
        id: "ytplayer_" +  index
      };
      
      // swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes, callbackFn)
      TwonesToolbar.debugMsg('actually trying to replace now ..');
      TwonesToolbarGadget.actions[atts.id] = false;
      try {
        swfobject.embedSWF(url, container.id, w, h, "8", null, null, params, atts, function(e) {
          TwonesToolbar.debugMsg('swfembed done:');
          var yt_track = new TwonesToolbarTrackFactory({
            element: document.getElementById(atts.id),
            player: 'youtube'
          });
          TwonesToolbarGadget.tracks.push(yt_track);
        });
        //swfobject.embedSWF(url, fakeytembed, w, h, "8", null, null, params, atts);
        //swfobject.embedSWF(url, container.id, w, h, "8", null, null, params, atts, function(e){TwonesToolbar.debugMsg('swfembed done:'); TwonesToolbar.debugDir(e);});
        //swfobject.embedSWF(url, 'fakeytembed', w, h, "8", null, null, params, atts, function(e){TwonesToolbar.debugMsg('swfembed done:'); TwonesToolbar.debugDir(e);});
      } catch (err) {
        TwonesToolbar.debugDir(err);
      }
    },
    definePlayerReadyCallback: function() {
      
      if (typeof(onYouTubePlayerReady) != "undefined") {

        // the onYouTubePlayerReady function is already defined. 
        // ala alias_method_chain? 
        // This trick only works if the user defined 'onYouTubePlayerReady' function is before the gadget 
        // change the name of the function to oldOnYouTubePlayerReady
        var code = onYouTubePlayerReady.toString();
        code = code.replace(/onYouTubePlayerReady/,"oldOnYouTubePlayerReady"); // danger! danger!

        // add oldOnYouTubePlayerReady to the dom 
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.text = code;
        document.getElementsByTagName("head")[0].appendChild(e);        

        // add the new playerReady that calls the oldPlayerReady
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.text = "onYouTubePlayerReady = function(playerId){ oldOnYouTubePlayerReady(playerId); TwonesToolbarGadget.YoutubePlayer.playerReady(playerId); }";
        document.getElementsByTagName("head")[0].appendChild(e);
      }
      else {
        
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.text = "onYouTubePlayerReady = function(playerId){ TwonesToolbarGadget.YoutubePlayer.playerReady(playerId); } ";
        document.getElementsByTagName("head")[0].appendChild(e);

      }      
    },
    playerReady: function(playerId) {
      // subscribe to events
      TwonesToolbar.debugMsg('player ready for ' + playerId);
      // <object id="ytplayer_756">
      //   <param name="movie" value="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&enablejsapi=1&playerapiid=756"></param> ...
      
      var object = TwonesToolbarGadget.YoutubePlayer.getObjectByPlayerId(playerId);
      // alert(object.id);
      // alert(object.width);
      TwonesToolbarGadget.actions[object.id] = true;
      
      TwonesToolbarGadget.YoutubePlayer.stateChangeHandlers[playerId] = function(state) { TwonesToolbarGadget.YoutubePlayer.stateChange(state, playerId); }
      var onStateChangeName = 'TwonesToolbarGadget.YoutubePlayer.stateChangeHandlers[' + playerId + ']';
      
      // the youtube js api only accepts function names. not function 'pointers'. 
      object.addEventListener("onStateChange", onStateChangeName);
      object.addEventListener("onError", "TwonesToolbarGadget.YoutubePlayer.playerError");
        
    },
    stateChangeHandlers: {},
    playerError : function() {
      // alert('player error');
    },
    stateChange: function(state, playerId) {
      TwonesToolbar.debugMsg('state change for ' + playerId + ' ' + state);      
      // unstarted (-1), ended (0), playing (1), paused (2), buffering (3), video cued (5)
      switch(state) {
        case 1:
          if (TwonesToolbarGadget.YoutubePlayer._state != 1) {
            TwonesToolbarGadget.YoutubePlayer.play(playerId);
          }
          break;
        case 0:
          TwonesToolbarGadget.stop();
          break;
        case 2:
          TwonesToolbarGadget.pause();
          break;
      }
      if (state != 3) {
        TwonesToolbarGadget.YoutubePlayer._state = state;
      }
      return true;
    },
    play: function(playerId) {
      TwonesToolbar.debugMsg('playing youtube!');
      // scrape video id      
      var videoid = TwonesToolbarGadget.YoutubePlayer.getVideoIdByPlayerId(playerId);
      
      // get video info 
      TwonesToolbarGadget.YoutubePlayer.getVideoData(videoid, function(video_info) {
        
        var title = "";
    		var creator = "";
    		// try to split title on a dash character
    		var m = video_info.title.match(/\s*(.+)\s+[\-\-]+\s+(.+)\s*/);
    		if (!m) 
    		  m = video_info.title.match(/\s*(.+)\s*[\-\-]+\s*(.+)\s*/);
    		if (m && m[1] && m[2]) {
    			title = m[2];
    			creator = m[1];
    		} else
    			title = video_info.title;

        TwonesToolbarGadget.YoutubePlayer._data = {};
        TwonesToolbarGadget.YoutubePlayer._data.title = title;
        TwonesToolbarGadget.YoutubePlayer._data.creator = creator;
        TwonesToolbarGadget.YoutubePlayer._data._location = TwonesToolbarGadget.getObjectUrl(TwonesToolbarGadget.YoutubePlayer.getObjectByPlayerId(playerId));

        var permaLink = TwonesToolbarGadget.YoutubePlayer.findPermaLink(videoid);
        if (permaLink) {
          TwonesToolbarGadget.YoutubePlayer._data.permaLink = permaLink;
          TwonesToolbarGadget.YoutubePlayer.setToolbarPlay();
        } else {
          TwonesToolbar.getPermalinkByBoss(TwonesToolbarGadget.YoutubePlayer.getObjectByPlayerId(playerId), false, "youtube");
        }
      });
    },
      
    setToolbarPlay: function() {
      TwonesToolbar.debugMsg('permalink for youtube: ' + TwonesToolbarGadget.YoutubePlayer._data.permaLink);
      TwonesToolbarGadget.play({
        title: TwonesToolbarGadget.YoutubePlayer._data.title, 
        artist: TwonesToolbarGadget.YoutubePlayer._data.creator,
        location: TwonesToolbarGadget.YoutubePlayer._data._location,
        pageLink: TwonesToolbarGadget.YoutubePlayer._data.permaLink,
        player: "youtube"
      });
    },

    getVideoData: function(video_id, callback) {
      // jsonp to the twones server
      // alert('getVideoData');
      var callback_name = 'getVideoDataCallback' + Math.floor(Math.random() * 100000) ;
      TwonesToolbarGadget.YoutubePlayer[callback_name] = callback;
      // alert(callback_name);
      
      var e = document.createElement("script");
      e.src = 'http://' + TwonesToolbarGadget.host + "/music/youtube_video_data?videoid=" + video_id + '&jsonp=TwonesToolbarGadget.YoutubePlayer.' + callback_name;
      e.type = "text/javascript";
      document.getElementsByTagName("head")[0].appendChild(e);
    },
    getObjectByPlayerId: function(playerId) {
      return document.getElementById("ytplayer_" +  playerId);
    },
    getVideoIdByPlayerId: function(playerId) {
      var url = TwonesToolbarGadget.getObjectUrl(TwonesToolbarGadget.YoutubePlayer.getObjectByPlayerId(playerId));
      // url  is like http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&enablejsapi=1&playerapiid=756
      var result = /youtube.com\/v\/([^&]*)/i.exec(url); 
      var videoId = result[1];
      return videoId; 
    },
    getVideoIdByURL: function(url) {
      var result = /youtube.com\/v\/([^&]*)/i.exec(url); 
      if (result) {
        var videoId = result[1];
        return videoId;
      }
    },
    getVideoIdByPlayURL: function(url) {
      var result = /youtube.com\/watch\?v=([^&]*)/i.exec(url); 
      if (result) {
        var videoId = result[1];
        return videoId;
      }
    },
    findPermaLink: function(videoid) {
      // url  is like http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&enablejsapi=1&playerapiid=756
      TwonesToolbar.debugMsg('Search string : ' + 'http://www.youtube.com/v/' + videoid + '&');
      var permaLink = TwonesToolbar.findStringInFeedEntries('http://www.youtube.com/v/' + videoid + '&');
      return (permaLink) ? permaLink : false;       
    }
  },
  WPPlayer : {
    init: function(activate_now) {
      var _init = function() {       
         
        if (typeof(onWPPlayerReady) != "undefined") {

          // the onYouTubePlayerReady function is already defined. 
          // ala alias_method_chain? 
          // This trick only works if the user defined 'onYouTubePlayerReady' function is before the gadget 
          // change the name of the function to oldOnYouTubePlayerReady
          var code = onWPPlayerReady.toString();
          code = code.replace(/onWPPlayerReady/,"oldOnWPPlayerReady"); // danger! danger!

          // add oldOnYouTubePlayerReady to the dom 
          var e = document.createElement("script");
          e.type = "text/javascript";
          e.text = code;
          document.getElementsByTagName("head")[0].appendChild(e);        

          // add the new playerReady that calls the oldPlayerReady
          var e = document.createElement("script");
          e.type = "text/javascript";
          e.text = "onWPPlayerReady = function(playerId){ oldOnWPPlayerReady(playerId); TwonesToolbarGadget.WPPlayer.playerReady(playerId); }";
          document.getElementsByTagName("head")[0].appendChild(e);
        }
        else {

          var e = document.createElement("script");
          e.type = "text/javascript";
          e.text = "onWPPlayerReady = function(playerId){ TwonesToolbarGadget.WPPlayer.playerReady(playerId); } ";
          document.getElementsByTagName("head")[0].appendChild(e);

        }
        
        // look for WP players 
        TwonesToolbar.debugMsg('settimeout for look for WP players ');
        window.setTimeout(function() {
          TwonesToolbar.debugMsg('look for WP players ');
          
          var ps = document.getElementsByTagName("p");
          TwonesToolbar.debugMsg('ps: ' + ps.length);
          for(var tw_wp_i = 0; tw_wp_i < ps.length; tw_wp_i++) {
            var tw_wp_p = ps[tw_wp_i];
            if (tw_wp_p.className == "audioplayer_container") {
              var tw_wp_o = tw_wp_p.getElementsByTagName('object')[0];
              if(tw_wp_o != null) 
                onWPPlayerReady(tw_wp_o.id);    // force call onWPPlayerReady for every one
            }              
          }
          TwonesToolbarGadget.actions['WPPlayer'] = true;
        }, 1000, true);
        
        
      }
      
      TwonesToolbarGadget.actions['WPPlayer'] = false;
      
      if(!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
    },
    playerReady: function(playerId) {
      TwonesToolbar.debugMsg('TwonesToolbarGadget.WPPlayer.playerReady ' + playerId);
      
      var o = document.getElementById(playerId);
      if ('addListener' in o) {
        o.addListener('play', 'TwonesToolbarGadget.WPPlayer.play');  
  			o.addListener('stop', 'TwonesToolbarGadget.WPPlayer.stop');  
  			o.addListener('pause', 'TwonesToolbarGadget.WPPlayer.pause');
  			o.addListener('metadata', 'TwonesToolbarGadget.WPPlayer.metadata');
			
  			var track = new TwonesToolbarTrackFactory({
          element: o,
          player: 'wordpress'
        });
        TwonesToolbarGadget.tracks.push(track);
      }       	
    },
    play: function(data) {
      TwonesToolbar.debugMsg('TwonesToolbarGadget.WPPlayer.play');
      TwonesToolbar.debugDir(data);
      var track_title = "";
      if (typeof(data.title) != 'undefined') {
        track_title = data.title;
      } else {
        // no title and no artist
        track_title = "unknown";
      }
      // hack to get the absolute path
      var image = new Image();
      image.src = data.location;
      var absolute_location = image.src;

      TwonesToolbarGadget.WPPlayer._data = {};
      TwonesToolbarGadget.WPPlayer._data.title = track_title;
      TwonesToolbarGadget.WPPlayer._data.creator = data.artist;
      TwonesToolbarGadget.WPPlayer._data.album = data.album;
      TwonesToolbarGadget.WPPlayer._data.location = absolute_location;

      var permaLink = TwonesToolbarGadget.WPPlayer.findPermaLink(data.location);
      if (permaLink) {
        TwonesToolbarGadget.WPPlayer._data.permaLink = permaLink;
        TwonesToolbarGadget.WPPlayer.setToolbarPlay();
      } else {
        TwonesToolbar.getPermalinkByBoss(document.getElementById(data.playerID), false, "wpplayer");
      }
    },

    setToolbarPlay: function() {
      TwonesToolbar.debugMsg('TwonesToolbarGadget.WPPlayer.play calling play routine ...');
      TwonesToolbarGadget.play({
        title: TwonesToolbarGadget.WPPlayer._data.title,
        artist: TwonesToolbarGadget.WPPlayer._data.creator,
        album: TwonesToolbarGadget.WPPlayer._data.album,
        location: TwonesToolbarGadget.WPPlayer._data.location,
        pageLink: TwonesToolbarGadget.WPPlayer._data.permaLink,
        player: "wordpress"
      });
    },

    stop: function(data) {
      TwonesToolbarGadget.stop();
    },
    pause: function(data) {
      TwonesToolbarGadget.pause();
    },
    metadata: function(data) {
      TwonesToolbar.debugMsg('TwonesToolbarGadget.WPPlayer.metadata:');
      TwonesToolbar.debugDir(data);
      if (typeof(data.title) != 'undefined') {
        // hack to get the absolute path
        var image = new Image();
        image.src = data.location;
        var absolute_location = image.src;
        var permaLink = TwonesToolbarGadget.WPPlayer.findPermaLink(data.location);
               
        TwonesToolbarGadget.play({
          title: data.title, 
          artist: data.artist,
          album: data.album,
          location: absolute_location,
          pageLink: permaLink,
          player: "wordpress"
        });
      }
    },
    findPermaLink: function(enclosure) {
      TwonesToolbar.debugMsg('Search string : ' + enclosure);
      var permaLink = TwonesToolbar.findStringInFeedEntries(enclosure);
      return (permaLink) ? permaLink : document.location.href;       
    },
    ord: function (string) {
        // phpjs
        // http://kevin.vanzonneveld.net
        // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
        // +   bugfixed by: Onno Marsman
        // +   improved by: Brett Zamir (http://brett-zamir.me)
        // *     example 1: ord('K');
        // *     returns 1: 75
        // *     example 2: ord('\uD800\uDC00'); // surrogate pair to create a single Unicode character
        // *     returns 2: 65536

        var str = string + '';

        var code = str.charCodeAt(0);
        if (0xD800 <= code && code <= 0xDBFF) { // High surrogate (could change last hex to 0xDB7F to treat high private surrogates as single characters)
            var hi = code;
            if (str.length === 1) {
                return code; // This is just a high surrogate with no following low surrogate, so we return its value;
                                        // we could also throw an error as it is not a complete character, but someone may want to know
            }
            var low = str.charCodeAt(1);
            if (!low) {

            }
            return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;
        }
        if (0xDC00 <= code && code <= 0xDFFF) { // Low surrogate
            return code; // This is just a low surrogate with no preceding high surrogate, so we return its value;
                                    // we could also throw an error as it is not a complete character, but someone may want to know
        }
        return code;
    },
    base_convert: function(number, frombase, tobase) {
      // phpjs
        // http://kevin.vanzonneveld.net
        // +   original by: Philippe Baumann
        // *     example 1: base_convert('A37334', 16, 2);
        // *     returns 1: '101000110111001100110100'

        return parseInt(number+'', frombase+0).toString(tobase+0);
    },
    intval: function(mixed_var, base) {
        // http://kevin.vanzonneveld.net
        // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
        // +   improved by: stensi
        // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
        // +   input by: Matteo
        // +   bugfixed by: Brett Zamir (http://brett-zamir.me)
        // *     example 1: intval('Kevin van Zonneveld');
        // *     returns 1: 0
        // *     example 2: intval(4.2);
        // *     returns 2: 4
        // *     example 3: intval(42, 8);
        // *     returns 3: 42
        // *     example 4: intval('09');
        // *     returns 4: 9
        // *     example 5: intval('1e', 16);
        // *     returns 5: 30

        var tmp;

        var type = typeof( mixed_var );

        if (type === 'boolean') {
            return (mixed_var) ? 1 : 0;
        } else if (type === 'string') {
            tmp = parseInt(mixed_var, base || 10);
            return (isNaN(tmp) || !isFinite(tmp)) ? 0 : tmp;
        } else if (type === 'number' && isFinite(mixed_var) ) {
            return Math.floor(mixed_var);
        } else {
            return 0;
        }
    },
    encodeSource: function(mp3_url) {
      // ported from wp audio player -- nasty :)
      var ntextto = "";
      var codekey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
      for(var i=0; i<mp3_url.length; i++) {
        var binchar = "0000" + TwonesToolbarGadget.WPPlayer.base_convert(TwonesToolbarGadget.WPPlayer.ord(mp3_url[i]), 10, 2);
        ntextto = ntextto + binchar.substr(-8);
      }
      //TwonesToolbar.debugMsg('ntextto : ' + ntextto);
      ntextto = ntextto + "00000".substr(0, 6 - (mp3_url.length % 6));
      var mp3_res = "";
      for(var i=0; i < (ntextto.length-1); i = i + 6) {
        mp3_res = mp3_res + codekey[TwonesToolbarGadget.WPPlayer.intval(ntextto.substr(i, 6), 2)];
      }
      return mp3_res;
    },
    /**
    	* Decodes a 6-bit encoded string
    	* Thanks to mattiasdh (mattias_d@excite.com) for this
    	* http://modxcms.com/forums/index.php/topic,9340.0.html
    	* @param	source the string to decode
    	* @return	the decoded string
    	*/
  	sixBitDecode : function(sourceStr) {
  		var ntexto = "";
  		var nntexto = "";
  		var codeKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-"
  		var charCode, charChar, charCodeBin, i;
  		for(i=0; i<sourceStr.length; i++)
  		{
  			charCode = codeKey.indexOf(sourceStr.substr(i,1)); // char index
  			charCodeBin = ("000000" + charCode.toString(2)).substr(-6,6); // char index in binary, 6 bits
  			ntexto += charCodeBin;
  		}
  		for (i=0; i< ntexto.length; i+=8) {
  			charCodeBin = ntexto.substr(i, 8); // char code in binary
  			charCode = parseInt(charCodeBin, 2);
  			charChar = String.fromCharCode(charCode);
  			nntexto += charChar;
  		}
  		return (nntexto);
  	}
  },
  SoundCloudPlayer : {
    init: function(activate_now) {
      
      /*
      *   JavaScript interface for the SoundCloud Player widget
      *   Author: Matas Petrikas, matas@soundcloud.com
      *   Copyright (c) 2009  SoundCloud Ltd.
      *   Licensed under the MIT license:
      *   http://www.opensource.org/licenses/mit-license.php
      */
      /*
      *   docs
      *   http://wiki.github.com/soundcloud/Widget-JS-API 
      *
      *   last version
      *   http://github.com/soundcloud/Widget-JS-API/blob/master/soundcloud.player.js
      *   
      *   this is version
      *   75234b07fc90eabd4a07fdee25969f6329bff3dc
      */
      (function(){
        var isIE = (/msie/i).test(navigator.userAgent) && !(/opera/i).test(navigator.userAgent);

        var soundcloud = window.soundcloud = {
          version: "0.1",
          debug: false,
          _listeners: [],
          // re-dispatches widget events in the DOM, using JS library support, the events also should bubble up the DOM
          _redispatch: function(eventType, flashId, data) {
            try{
              // find the flash player
              var playerNode = this.getPlayer(flashId),
                  listeners  = this._listeners[eventType] || [];
                  // construct the custom eventType  e.g. 'soundcloud:onPlayerReady'
                  customEventType = 'soundcloud:' + eventType;
            }catch(e){
              if(window.console){
                console.error('unable to dispatch widget event ' + eventType + ' for the widget id ' + flashId, data, e);
              }
              return;
            }
            // re-dispatch SoundCloud events up in the DOM
            if(window.jQuery){
              // if jQuery is available, trigger the custom event
              jQuery(playerNode).trigger(customEventType, [data]);
            }else if(window.Prototype){
              // if Prototype.js is available, fire the custom event
              $(playerNode).fire(customEventType, data);
            }else{
              // TODO add more JS libraries that support custom DOM events
            }
            // if there are any listeners registered to this event, trigger them all
            for(i in listeners){
              listeners[i].apply(playerNode, [playerNode, data]);
            }
            // log the events in debug mode
            if(this.debug && window.console){
              console.log(customEventType, eventType, flashId, data);
            }

          },
          // you can add multiple listeners to a certain event
          // e.g. soundcloud.addEventListener('onPlayerReady', myFunctionOne);
          //      soundcloud.addEventListener('onPlayerReady', myFunctionTwo);
          addEventListener: function(eventType, callback) {
            if(!this._listeners[eventType]){
              this._listeners[eventType] = [];
            }
            this._listeners[eventType].push(callback);
          },
          // you can also remove the function listener if e.g you want to trigger it only once
          // soundcloud.removeEventListener('onMediaPlay', myFunctionOne);
          removeEventListener: function(eventType, callback) {
            var listeners = this._listeners[eventType];
            if(listeners){
              for(i in listeners){
                if(listeners[i] === callback){
                  listeners.splice(i, 1);
                }
              }
            }
          },
          // get widget node based on its id (if object tag) or name (if embed tag)
          // if you're using SWFObject or other dynamic Flash generators, please make sure that you set the id parameter
          //  only if the DOM has an id/name it's possible to call player's methods.
          // Important!: because of the bug in Opera browser, the Flash can't get its own id
          // so the generator should set it additionally through flashvars parameter 'object_id'
          getPlayer: function(id){
            try{
              if(!id){
                throw "The SoundCloud Widget DOM object needs an id atribute, please refer to SoundCloud Widget API documentation.";
              }
              var flash = isIE ? window[id] : document[id];
              if(flash){
                if(flash.api_getFlashId){
                  return flash;
                }else{
                  throw "The SoundCloud Widget External Interface is not accessible. Check that allowscriptaccess is set to 'always' in embed code";
                }
              }else{
                throw "The SoundCloud Widget with an id " + id + " couldn't be found";
              }
            }catch(e){
              if (console && console.error) {
               console.error(e);
              }
              throw e;
            }
          },
          // fired when widget has loaded its data and is ready to accept calls from outside
          // the widget will call these functions only if in it's flashvars there's a parameter enable_api=true
          // @flashId: the widget id, basically the Flash node should be accessible to JS with soundcloud.getPlayer(flashId)
          // @data: an object containing .mediaUri (eg. 'http://api.soundcloud.com/tracks/49931') .mediaId (e.g. '4532')
          // in buffering events data contains also .percent = (e.g. '99')
          onPlayerReady: function(flashId, data) {
            this._redispatch('onPlayerReady', flashId, data);
          },
          // fired on player error
          onPlayerError: function(flashId, data) {
            this._redispatch('onPlayerError', flashId, data);            
          },
          // fired when widget starts playing current track (fired only once per track)
          onMediaStart : function(flashId, data) {
            this._redispatch('onMediaStart', flashId, data);
          },
          // fired when the track/playlist has finished playing
          onMediaEnd : function(flashId, data) {
            this._redispatch('onMediaEnd', flashId, data);
          },
          // fired when widget starts playing current track (fired on every play, seek)
          onMediaPlay : function(flashId, data) {
            this._redispatch('onMediaPlay', flashId, data);
          },
          // fired when track was paused
          onMediaPause : function(flashId, data) {
            this._redispatch('onMediaPause', flashId, data);
          },
          // fired when the widget is still buffering, means you can't seek in the track fully yet
          onMediaBuffering : function(flashId, data) {
            this._redispatch('onMediaBuffering', flashId, data);
          },
          // fired when the widget is done buffering and the whole track length is seekable
          onMediaDoneBuffering : function(flashId, data) {
            this._redispatch('onMediaDoneBuffering', flashId, data);
          }
        };

      })();
      
      TwonesToolbarGadget.actions['SoundCloud'] = false;
      
      // now use it!!
      soundcloud.addEventListener('onPlayerReady', TwonesToolbarGadget.SoundCloudPlayer.onPlayerReady);
      soundcloud.addEventListener('onPlayerError', TwonesToolbarGadget.SoundCloudPlayer.onPlayerError);
      
      // // find other soundcloud players that are not API ready and reembed them
      /*
      if (!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
      */

      TwonesToolbarGadget.actions['SoundCloudReEmbed'] = false;      
      TwonesToolbarGadget.actions['SoundCloud'] = true;
      
      if (!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", TwonesToolbarGadget.SoundCloudPlayer.reembed, false);
        else if (window.attachEvent)
          window.attachEvent("onload", TwonesToolbarGadget.SoundCloudPlayer.reembed);
      } else {
        TwonesToolbarGadget.SoundCloudPlayer.reembed();
      }
      
    },
    reembed: function() {      
      var objects = document.getElementsByTagName('object'); 
      var len = objects.length;
      var num_objects = objects.length;
      TwonesToolbar.debugMsg('found ' + len + ' objects');
      for(var index = 0; index < len; index++) {
        var object = objects[index];
        TwonesToolbar.debugMsg("object id : " + index);

        var url;
        try{
          url = TwonesToolbarGadget.getObjectUrl(object);
          url = url.toLowerCase();
        } catch(e) {
          //
        }
        TwonesToolbar.debugMsg("object url : " + url);
        isSoundCloud = (url != undefined) && url.match(/player\.soundcloud\.com/);

        if(isSoundCloud) {
          shouldReembed = false;
          shouldReembed = shouldReembed || (typeof(object.id) == 'undefined');
          shouldReembed = shouldReembed || (!url.match(/enable_api=true/));
          shouldReembed = shouldReembed || (!url.match(/object_id=/));
          // TODO the object.id should be the same as the player_id ?
          
          if (shouldReembed) {
            try {
              TwonesToolbarGadget.SoundCloudPlayer.reembedElement(object, url, index);
            } catch(e) {
              //
            }
          }
        }            
      }
      
      // now look form embeds. :-(
      var embeds = document.getElementsByTagName('embed'); 
      var len = embeds.length;
      TwonesToolbar.debugMsg('found ' + len + ' embeds');
      var smartIndex = 0;
      for(var index = 0; index < len; index++) {
        // on IE when I remove the element from the dom it also get removed from the array. So we use an alternative index
        var embed = embeds[smartIndex]; 
        if(embed) {
          var url = embed.src;
          TwonesToolbar.debugMsg(url);
          isSoundCloud = url.match(/player\.soundcloud\.com/);

          if(isSoundCloud) {
            shouldReembed = false;
            shouldReembed = shouldReembed || (typeof(embed.name) == 'undefined');
            shouldReembed = shouldReembed || (!url.match(/enable_api=true/));
            shouldReembed = shouldReembed || (!url.match(/player_id=/));
            
            if (shouldReembed) {
              try {
                TwonesToolbarGadget.SoundCloudPlayer.reembedElement(embed, url, num_objects + index); 
              }
              catch(e) {}
            }else {
              smartIndex++;
            }
          }         
        }
      }
      TwonesToolbarGadget.actions['SoundCloudReEmbed'] = true;
    },
    reembedElement : function(element, url, index) {
      TwonesToolbar.debugMsg('re-embedding SoundCloud player (' + url + ') ' + index);
      
      var future_id = "sound_cloud_player_" +  index;
      
      // clear original api params. one day we should turn this evil bit off
      url = url.replace(/enable_api=\w&/, ''); 
      url = url.replace(/object_id=\w&/, '');
      url += '&enable_api=true&object_id=' + future_id;
      
      var w = element.width;
      var h = element.height;
      
      
      // insert a container span for the new object
      var container = document.createElement("span");
      container.id = 'scplayer_container_' + index;
      var insertedElement = element.parentNode.insertBefore(container, element);
      
      // remove old object
      element.parentNode.removeChild(element);
      
      var params = { allowScriptAccess: "always", bgcolor: "#cccccc", wmode: 'transparent'};
      var atts = { 
        id: future_id
      };
      
      // swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes, callbackFn)
      TwonesToolbar.debugMsg('actually trying to replace now ..');
      TwonesToolbarGadget.actions[atts.id] = false;
      try {
        swfobject.embedSWF(url, container.id, w, h, "8", null, null, params, atts, function (e) {
          var track = new TwonesToolbarTrackFactory({
            element: document.getElementById(atts.id),
            player: 'soundcloud'
          });
          TwonesToolbarGadget.tracks.push(track);       
        });
        //swfobject.embedSWF(url, fakeytembed, w, h, "8", null, null, params, atts);
        //swfobject.embedSWF(url, container.id, w, h, "8", null, null, params, atts, function(e){TwonesToolbar.debugMsg('swfembed done:'); TwonesToolbar.debugDir(e);});
        //swfobject.embedSWF(url, 'fakeytembed', w, h, "8", null, null, params, atts, function(e){TwonesToolbar.debugMsg('swfembed done:'); TwonesToolbar.debugDir(e);});
      } catch (err) {
        TwonesToolbar.debugDir(err);
      }
    },
    onPlayerReady: function(player, data) {
      TwonesToolbarGadget.actions[player.id] = true;
      soundcloud.addEventListener('onMediaPlay', TwonesToolbarGadget.SoundCloudPlayer.onMediaPlay);
      soundcloud.addEventListener('onMediaPause', TwonesToolbarGadget.SoundCloudPlayer.onMediaPause);
      soundcloud.addEventListener('onMediaEnd', TwonesToolbarGadget.SoundCloudPlayer.onMediaStop);
    },
    onPlayerError: function(player, data) {
      TwonesToolbar.debugMsg('Soundcloud player ' + player.id + 'was not able to load!');
      TwonesToolbarGadget.actions[player.id] = true;
    },
    onMediaPlay: function(player, data) {
      TwonesToolbar.debugMsg('SoundCloud.onMediaPlay');    
      var track = player.api_getCurrentTrack();

      TwonesToolbarGadget.SoundCloudPlayer._data = {};
      TwonesToolbarGadget.SoundCloudPlayer._data.title = track.title;
      TwonesToolbarGadget.SoundCloudPlayer._data.creator = track.user.name;
      TwonesToolbarGadget.SoundCloudPlayer._data.annotation = track.description;
      TwonesToolbarGadget.SoundCloudPlayer._data._location = track.streamUrl;

      var permaLink = TwonesToolbarGadget.SoundCloudPlayer.findPermaLink(track);

      if (permaLink) {
        TwonesToolbarGadget.SoundCloudPlayer._data.permaLink = permaLink;
        TwonesToolbarGadget.SoundCloudPlayer.setToolbarPlay();
      } else {
        TwonesToolbar.getPermalinkByBoss(player, false, "soundcloud");
      }
    },

    setToolbarPlay: function() {
      TwonesToolbar.debugMsg('permalink for soundcloud: ' + TwonesToolbarGadget.SoundCloudPlayer._data.permaLink);
      TwonesToolbarGadget.play({
        title: TwonesToolbarGadget.SoundCloudPlayer._data.title, 
        artist: TwonesToolbarGadget.SoundCloudPlayer._data.creator,
        annotation: TwonesToolbarGadget.SoundCloudPlayer._data.annotation,
        location: TwonesToolbarGadget.SoundCloudPlayer._data._location,
        pageLink: TwonesToolbarGadget.SoundCloudPlayer._data.permaLink,
        player: "soundcloud"
      });
    },

    onMediaPause: function(player, data) {
      TwonesToolbar.debugMsg('SoundCloud.onMediaPause');
      TwonesToolbarGadget.pause();
    },

    onMediaStop: function(player, data) {
      TwonesToolbar.debugMsg('SoundCloud.onMediaStop');
      TwonesToolbarGadget.stop();
    },

    findPermaLink: function(track) {
        TwonesToolbar.debugDir(track);
        var scPlayerStr = '"http://player.soundcloud.com/player.swf?url=' + encodeURIComponent(track.permalinkUrl) + '"';
        TwonesToolbar.debugMsg('search string : ' + scPlayerStr);
        var permaLink = TwonesToolbar.findStringInFeedEntries(scPlayerStr);
        return (permaLink) ? permaLink : false;
    }
  },
  SoundCloudSitePlayer: {
    metadataCache: {},    
    init: function(activate_now) {
      TwonesToolbarGadget.actions['SoundCloudSitePlayer'] = false;
      var _init = function() {
        TwonesToolbar.debugMsg('soundcloud site player init!');
        //TwonesToolbarGadget.actions['SoundCloudSitePlayer'] = true;      
        if (document.location.href.match(/soundcloud\.com\//i)) {
          TwonesToolbar.debugMsg('|===============> on soundcloud.com!');
          // soundcloud uses jQuery :)
          $(document).ready(function() {
            TwonesToolbarGadget.SoundCloudSitePlayer.playerReady();
          });
        } else {
          TwonesToolbar.debugMsg('|===============> not on soundcloud.com!');
          TwonesToolbarGadget.actions['SoundCloudSitePlayer'] = true;      
        }
      };
      if(!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
    },
    playerReady: function() {
      TwonesToolbar.debugMsg('soundcloud site player!');
      // sadly, the thing below does not work
      //$(document).bind('soundcloud:onPlayerReady', function(event, data) {TwonesToolbar.debugMsg('soundcloud:onPlayerReady!');});
      
      // bind to the play, pause and stop events
      $('div.player').bind('onPlay', function() {TwonesToolbarGadget.SoundCloudSitePlayer.onPlay(this);})
      .bind('onPause', function() {TwonesToolbarGadget.SoundCloudSitePlayer.onPause(this);})
      .bind('onStop', function() {TwonesToolbarGadget.SoundCloudSitePlayer.onStop(this);});
      
      // add tracks
      for (var track_index = 0; track_index < SC.playerManager.players.length; track_index++) {
        var player = SC.playerManager.players[track_index];
        var track = new TwonesToolbarTrackFactory({
          element: player,
          trackIndex: track_index,
          player: 'soundcloudsite'
        });
        TwonesToolbarGadget.tracks.push(track);       
      }
      TwonesToolbarGadget.actions['SoundCloudSitePlayer'] = true;      
    },
    onPlay: function(obj) {
      TwonesToolbar.debugMsg('Playing soundcloud ' + $(obj).attr('id'));
      var sc_id = SC.playerManager.activePlayer.playerProperties.id;
      if (sc_id in TwonesToolbarGadget.SoundCloudSitePlayer.metadataCache) {
        TwonesToolbarGadget.SoundCloudSitePlayer.doPlay(obj, TwonesToolbarGadget.SoundCloudSitePlayer.metadataCache[sc_id]);
      } else {
        $.getJSON('http://api.soundcloud.com/tracks/' + sc_id + '.js?callback=?', function(data) {
          TwonesToolbarGadget.SoundCloudSitePlayer.metadataCache[sc_id] = data;
          TwonesToolbarGadget.SoundCloudSitePlayer.doPlay(obj, TwonesToolbarGadget.SoundCloudSitePlayer.metadataCache[sc_id]);
        });
      }
    },
    onPause: function(obj) {
      TwonesToolbar.debugMsg('Pausing soundcloud ' + $(obj).attr('id'));
      if (tjq !== undefined) {
        TwonesToolbarGadget.pause();
      }
    },
    onStop: function(obj) {
      TwonesToolbar.debugMsg('Stopping soundcloud ' + $(obj).attr('id'));
      if (tjq !== undefined) {
        TwonesToolbarGadget.stop();
      }
    },
    doPlay: function(obj, track) {
      TwonesToolbar.debugMsg('got soundcloud site track data!:');
      TwonesToolbar.debugDir(track);
      TwonesToolbarGadget.play({
        title: track.title, 
        artist: track.user.username,
        annotation: track.description,
        location: track.stream_url,
        pageLink: track.permalink_url,
        player: "soundcloudsite"
      });
    }
  },
  VimeoPlayer : {
    init: function(activate_now) {
      TwonesToolbarGadget.actions['VimeoPlayer'] = false;
      TwonesToolbar.debugMsg('Initializing Vimeo player ...');
      
      TwonesToolbarGadget.VimeoPlayer.definePlayerReadyCallback();
      
      var _init = function() {
    
        /*
        <object width="480" height="385">
          <param name="movie" value="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&color1=0x234900&color2=0x4e9e00"></param>
          <param name="allowFullScreen" value="true"></param>
          <param name="allowscriptaccess" value="always"></param>
          <embed src="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&color1=0x234900&color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed>
        </object>
        */ 

        // look for youtube players
        var objects = document.getElementsByTagName('object'); 
        var len = objects.length;
        var  num_objects = objects.length;
        TwonesToolbar.debugMsg('found ' + len + ' objects');
        for(var index = 0; index < len; index++) {
          var object = objects[index];
          TwonesToolbar.debugMsg("object id : " + index);

          var url;
          try{
            url = TwonesToolbarGadget.getObjectUrl(object);
          } catch(e) {
            TwonesToolbar.debugMsg('exception : ' + e);
          }
          TwonesToolbar.debugMsg("object url : " + url);
          isVimeo = (url != undefined) && url.match(/(vimeo)\.com\/moogaloop\.swf/);

          if(isVimeo) {
            try {
              //TwonesToolbarGadget.VimeoPlayer.reembedElement(object, url, index);
            } catch(e) {
              //
            }
          }            
        }
        
        // now look form embeds. :-(
        var embeds = document.getElementsByTagName('embed'); 
        var len = embeds.length;
        TwonesToolbar.debugMsg('found ' + len + ' embeds');
        for(var index = 0; index < len; index++) {
          var embed = embeds[0]; // on IE when I remove the element from the dom it also get removed from the array
          if(embed) {
            var url = embed.src;
            TwonesToolbar.debugMsg(url);
            isVimeo = url.match(/(vimeo)\.com\/moogaloop(_local)?\.swf/);

            if(isVimeo) {
              TwonesToolbarGadget.VimeoPlayer.reembedElement(embed, url, num_objects + index); 
            }         
          }
        }
        
        TwonesToolbarGadget.actions['VimeoPlayer'] = true;
      };
      
      if(!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
    },
    reembedElement : function(element, url, index) {
      TwonesToolbar.debugMsg('re-embedding Vimeo player (' + url + ') ' + index);
      // clear original api params. one day we should turn this evil bit off
      url = url.replace(/js_api=\w&/, '');
      url = url.replace('moogaloop_local', 'moogaloop');
      //url = 'htp://vimeo.com/megaloop.swf';
      TwonesToolbar.debugMsg(element.getAttribute('flashvars'));
      var flash_vars = element.getAttribute('flashvars');
      if (('element' == 'embed') && url.match(/moogaloop\.swf$/i)) {
        url += '?js_api=1';
      } else {
        url += '&js_api=1';
      }
      if (flash_vars != '') {
        url += '&' + flash_vars;
      }
      TwonesToolbar.debugMsg('final re-embed url : ' + url);
      var w = element.width;
      var h = element.height;
      
      
      // insert a container span for the new object
      var container = document.createElement("span");
      container.id = 'vmplayer_container_' + index;
      var insertedElement = element.parentNode.insertBefore(container, element);
      
      
      var params = { allowScriptAccess: "always", bgcolor: "#cccccc" };
      var atts = { 
        id: "vmplayer_" +  index,
        allowFullScreen: "true",
        wmode: 'transparent'
      };
      var flashParams = {
        js_api: 1,
        js_onLoad: 'vimeo_player_loaded',
        js_swf_id: atts.id
      };
      
      if (element == 'object') {
        var params = element.getElementsByTagName('param');

        for(j in params) {
          var p = params[j];
          var k = p.getAttribute('name');
          var v = p.getAttribute('value');
          flashParams[k] = v;
        }
      }
      // remove old object
      element.parentNode.removeChild(element);
      
      // swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes, callbackFn)
      TwonesToolbar.debugMsg('actually trying to replace now ..');
      TwonesToolbarGadget.actions[atts.id] = false;
      try {
        swfobject.embedSWF(url, container.id, w, h, "9", null, flashParams, params, atts, function (e) {
          var track = new TwonesToolbarTrackFactory({
            element: document.getElementById(atts.id),
            player: 'vimeo'
          });
          TwonesToolbarGadget.tracks.push(track);       
        });
        //swfobject.embedSWF(url, fakeytembed, w, h, "8", null, null, params, atts);
        //swfobject.embedSWF(url, container.id, w, h, "8", null, null, params, atts, function(e){TwonesToolbar.debugMsg('swfembed done:'); TwonesToolbar.debugDir(e);});
        //swfobject.embedSWF(url, 'fakeytembed', w, h, "8", null, null, params, atts, function(e){TwonesToolbar.debugMsg('swfembed done:'); TwonesToolbar.debugDir(e);});
      } catch (err) {
        TwonesToolbar.debugDir(err);
      }
    },
    definePlayerReadyCallback: function() {
      
      if (typeof(vimeo_player_loaded) != "undefined") {

        // the onVimeoPlayerReady function is already defined. 
        // ala alias_method_chain? 
        // This trick only works if the user defined 'onVimeoPlayerReady' function is before the gadget 
        // change the name of the function to oldOnVimeoPlayerReady
        var code = vimeo_player_loaded.toString();
        code = code.replace(/vimeo_player_loaded/,"old_vimeo_player_loaded"); // danger! danger!

        // add oldOnVimeoPlayerReady to the dom 
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.text = code;
        document.getElementsByTagName("head")[0].appendChild(e);        

        // add the new playerReady that calls the oldPlayerReady
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.text = "vimeo_player_loaded = function(playerId){ old_vimeo_player_loaded(playerId); TwonesToolbarGadget.VimeoPlayer.playerReady(playerId); }";
        document.getElementsByTagName("head")[0].appendChild(e);
      }
      else {
        
        var e = document.createElement("script");
        e.type = "text/javascript";
        e.text = "vimeo_player_loaded = function(playerId){ TwonesToolbarGadget.VimeoPlayer.playerReady(playerId); } ";
        document.getElementsByTagName("head")[0].appendChild(e);

      }      
    },
    playerReady: function(playerId) {
      // subscribe to events
      TwonesToolbar.debugMsg('player ready for ' + playerId);
      var object = TwonesToolbarGadget.VimeoPlayer.getObjectByPlayerId(playerId);
      // alert(object.id);
      // alert(object.width);

      object.api_addEventListener('onFinish', 'TwonesToolbarGadget.VimeoPlayer.onFinish');
      object.api_addEventListener('onPlay', 'TwonesToolbarGadget.VimeoPlayer.play');
      object.api_addEventListener('onPause', 'TwonesToolbarGadget.VimeoPlayer.onPause');

      TwonesToolbarGadget.actions[object.id] = true;
    },
    onFinish : function(playerId) {
      TwonesToolbar.debugMsg('Stopped playing on ' + playerId);
      TwonesToolbarGadget.stop();
    },
    onPause : function(playerId) {
      TwonesToolbar.debugMsg('Paused playing on ' + playerId);
      TwonesToolbarGadget.pause();
    },
    playerError : function() {
      // alert('player error');
    },
    play: function(playerId) {
      TwonesToolbar.debugMsg('playing vimeo on ' + playerId);
      // scrape video id      
      TwonesToolbar.debugMsg('getting clip id on ' + playerId);
      var videoid = TwonesToolbarGadget.VimeoPlayer.getVideoIdByPlayerId(playerId);
      TwonesToolbar.debugMsg('clip id : ' + videoid);
      // get video info 
      TwonesToolbarGadget.VimeoPlayer.getVideoData(videoid, function(video_info) {
        TwonesToolbar.debugDir(video_info);
        var title = "";
    		var creator = "";
    		// try to split title on a dash character
    		var m = video_info[0].title.match(/\s*(.+)\s+[\-\-]+\s+(.+)\s*/);
    		if (!m) 
    		  m = video_info[0].title.match(/\s*(.+)\s*[\-\-]+\s*(.+)\s*/);
    		if (m && m[1] && m[2]) {
    			title = m[2];
    			creator = m[1];
    		} else
    			title = video_info[0].title;
        
        if (video_info[0].tags.match(/(musicvideo|acoustic|ambient|blues|classical|country|electronic|emo|folk|hardcore|hip|hop|indie|jazz|latin|metal|pop|punk|reggae|rnb|rock|soul|world|50s|60s|70s|80s|90s|music|concert|gig|live),?/)) {
          TwonesToolbarGadget.VimeoPlayer._data = {};
          TwonesToolbarGadget.VimeoPlayer._data.title = title;
          TwonesToolbarGadget.VimeoPlayer._data.creator = creator;
          TwonesToolbarGadget.VimeoPlayer._data._location = TwonesToolbarGadget.getObjectUrl(TwonesToolbarGadget.VimeoPlayer.getObjectByPlayerId(playerId));

          var permaLink = TwonesToolbarGadget.VimeoPlayer.findPermaLink(videoid, playerId);
          if (permaLink) {
            TwonesToolbarGadget.VimeoPlayer._data.permaLink = permaLink;
            TwonesToolbarGadget.VimeoPlayer.setToolbarPlay();
          } else {
            TwonesToolbar.getPermalinkByBoss(TwonesToolbarGadget.VimeoPlayer.getObjectByPlayerId(playerId), false, "vimeo");
          }
        }
      });
      
    },

    setToolbarPlay: function() {
      TwonesToolbar.debugMsg('permalink for vimeo: ' + TwonesToolbarGadget.VimeoPlayer._data.permaLink);
      TwonesToolbarGadget.play({
        title: TwonesToolbarGadget.VimeoPlayer._data.title, 
        artist: TwonesToolbarGadget.VimeoPlayer._data.creator,
        location: TwonesToolbarGadget.VimeoPlayer._data._location,
        pageLink: TwonesToolbarGadget.VimeoPlayer._data.permaLink,
        player: "vimeo"
      });
    },

    getVideoData: function(video_id, callback) {
      // jsonp to the twones server
      // alert('getVideoData');
      var callback_name = 'getVideoDataCallback' + Math.floor(Math.random() * 100000) ;
      TwonesToolbarGadget.VimeoPlayer[callback_name] = callback;
      // alert(callback_name);
      
      var e = document.createElement("script");
      e.src = 'http://vimeo.com/api/v2/video/' + video_id + '.json?callback=TwonesToolbarGadget.VimeoPlayer.' + callback_name;
      e.type = "text/javascript";
      document.getElementsByTagName("head")[0].appendChild(e);
    },
    getObjectByPlayerId: function(playerId) {
      //var result = /_(\d+)$/i.exec(playerId);
      //TwonesToolbar.debugDir(result);
      //var videoId = result[1];
      //return document.getElementById("vmplayer_" +  videoId);
      return document.getElementById(playerId);
    },
    getVideoIdByPlayerId: function(playerId) {
      TwonesToolbar.debugMsg('getting data url : ');
      var player = TwonesToolbarGadget.VimeoPlayer.getObjectByPlayerId(playerId);
      return TwonesToolbarGadget.VimeoPlayer.getVideoId(player);
    },
    getVideoId: function(player) {
      TwonesToolbar.debugMsg('got player' + player);
      var url = player.data;
      TwonesToolbar.debugMsg('got url');
      TwonesToolbar.debugMsg('data url : ' + url);
      var clip_id_regex = /clip_id=([^&]*)/i;
      var result = clip_id_regex.exec(url);
      TwonesToolbar.debugDir(result);
      if (result == null) {  
        url = TwonesToolbarGadget.getObjectParam(player, 'flashvars');
        TwonesToolbar.debugMsg('flashvars ul : ' + url);
        result = clip_id_regex.exec(url);
      }
      if (result == null) {  
        url = TwonesToolbarGadget.getObjectParam(player, 'movie');
        TwonesToolbar.debugMsg('flashvars ul : ' + url);
        result = clip_id_regex.exec(url);
      }
      // url  is like http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&enablejsapi=1&playerapiid=756
      if (result != null) {
        var videoId = result[1];
        return videoId;
      }
    },
    getVideoIdByURL : function(url) {
      var clip_id_regex = /clip_id=([^&]*)/i;
      var result = clip_id_regex.exec(url);
      // url  is like http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&enablejsapi=1&playerapiid=756
      if (result != null) {
        var videoId = result[1];
        return videoId;
      }      
    },
    findPermaLink: function(videoId, playerId) {
      /*
      <object width="400" height="300">
        <param name="allowfullscreen" value="true" />
        <param name="allowscriptaccess" value="always" />
        <param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=1186736&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" />
        <embed src="http://vimeo.com/moogaloop.swf?clip_id=1186736&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300">
        </embed>
      </object>
      <p><a href="http://vimeo.com/1186736">Yun - No One Knows</a> from <a href="http://vimeo.com/breyten">Breyten Ernsting</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
      */
      var permaLink = TwonesToolbar.findStringInFeedEntries('http://vimeo.com/moogaloop.swf?clip_id=' + videoId + '&');
      return (permaLink) ? permaLink : false;

    }
  },
  FlashWModeFixer : {
    init: function(activate_now) {
      TwonesToolbarGadget.actions['FlashWModeFixer'] = false;
      TwonesToolbar.debugMsg('Initializing wmode fixer ...');
      
      var _init = function() {
        TwonesToolbarGadget.FlashWModeFixer.fix_flash();
        TwonesToolbarGadget.actions['FlashWModeFixer'] = true;
      }
      
      if(!activate_now) {
        if (window.addEventListener) 
          window.addEventListener("load", _init, false);
        else if (window.attachEvent)
          window.attachEvent("onload", _init);
      } else {
        _init();
      }
    },
    fix_flash: function() {
        // basically took the code of http://www.onlineaspect.com/2009/08/13/javascript_to_fix_wmode_parameters/
        // except it does not reembed when the wmode is already transparent or opaque
        
        // loop through every embed tag on the site
        var embeds = document.getElementsByTagName('embed');
        for(var i=0; i<embeds.length; i++)  {
            var embed = embeds[i];
            // do not re-embed sound manager 2 things
            if ((embed.id !== "sm2movie") && (embed.id !== "sm2movie_twones")) {
              var new_embed;
              
              if(embed.getAttribute('wmode') && (embed.getAttribute('wmode').toLowerCase()!='window')) {
                TwonesToolbar.debugMsg('embed ' + embed + ' has no wmode with window!');
                continue;
              } else {
                TwonesToolbar.debugMsg('Re-embedding for flash wmode fix : '+ embed);
              }
              
              // everything but Firefox & Konqueror
              if(embed.outerHTML) {
                  var html = embed.outerHTML;
                  // replace an existing wmode parameter
                  if(html.match(/wmode\s*=\s*('|")[a-zA-Z]+('|")/i))
                      new_embed = html.replace(/wmode\s*=\s*('|")window('|")/i,"wmode='transparent'");
                  // add a new wmode parameter
                  else
                      new_embed = html.replace(/<embed\s/i,"<embed wmode='transparent' ");
                  // replace the old embed object with the fixed version
                  embed.insertAdjacentHTML('beforeBegin',new_embed);
                  embed.parentNode.removeChild(embed);
              } else {
                  // cloneNode is buggy in some versions of Safari & Opera, but works fine in FF
                  new_embed = embed.cloneNode(true);
                  if(!new_embed.getAttribute('wmode') || new_embed.getAttribute('wmode').toLowerCase()=='window')
                      new_embed.setAttribute('wmode','transparent');
                  embed.parentNode.replaceChild(new_embed,embed);
              }
            }
        }
        // loop through every object tag on the site
        var objects = document.getElementsByTagName('object');
        for(var i=0; i<objects.length; i++) {
            var object = objects[i];
            if (object.id !== "sm2movie_twones") {
              var new_object;
              var obj_wmode = TwonesToolbarGadget.getObjectParam(object, 'wmode');
              
              if(obj_wmode && (obj_wmode.toLowerCase()!='window')) {
                TwonesToolbar.debugMsg('object ' + object + ' has no wmode with window!');
                continue;
              } else {
                TwonesToolbar.debugMsg('Re-embedding object for flash wmode fix : '+ object.id);
              }
              
              // object is an IE specific tag so we can use outerHTML here
              if(object.outerHTML) {
                  var html = object.outerHTML;
                  // replace an existing wmode parameter
                  if(html.match(/<param\s+name\s*=\s*('|")wmode('|")\s+value\s*=\s*('|")[a-zA-Z]+('|")\s*\/?\>/i))
                      new_object = html.replace(/<param\s+name\s*=\s*('|")wmode('|")\s+value\s*=\s*('|")window('|")\s*\/?\>/i,"<param name='wmode' value='transparent' />");
                  // add a new wmode parameter
                  else
                      new_object = html.replace(/<\/object\>/i,"<param name='wmode' value='transparent' />\n</object>");
                  // loop through each of the param tags
                  var children = object.childNodes;
                  for(var j=0; j<children.length; j++) {
                      var child_name = children[j].getAttribute('name');
                      if((child_name != undefined) && child_name.match(/flashvars/i)) {
                          new_object = html.replace(/<param\s+name\s*=\s*('|")flashvars('|")\s+value\s*=\s*('|")[^'"]*('|")\s*\/?\>/i,"<param name='flashvars' value='"+children[j].getAttribute('value')+"' />");
                      }
                  }
                  // replace the old embed object with the fixed versiony
                  object.insertAdjacentHTML('beforeBegin',new_object);
                  object.parentNode.removeChild(object);
              }
            }
        }
    }
  }
};

/*

  SoundManager 2 Demo: Play MP3 links "in-place"
  ----------------------------------------------

  http://schillmania.com/projects/soundmanager2/

  A simple demo making MP3s playable "inline"
  and easily styled/customizable via CSS.

  Requires SoundManager 2 Javascript API.

*/

function TwonesInlinePlayerFactory() {
  var self = this;
  var pl = this;
  var sm = soundManager; // soundManager instance
  this.excludeClass = 'twones-toolbar-inline-exclude'; // CSS class for ignoring MP3 links
  this.includeClass = 'twones-toolbar-inline-include'; // CSS class for explicitly including MP3 links
  this.anchors = [];
  this.buttons = [];
  this.links = [];
  this.context = [];
  this.sounds = [];
  this.soundsByURL = [];
  this.indexByURL = [];
  this.lastSound = null;
  this.soundCount = 0;
  var isIE = (navigator.userAgent.match(/msie/i));

  this.config = {
    playNext: false, // stop after one sound, or play through list until end
	  autoPlay: false  // start playing the first sound right away
  }

  this.css = {
    // CSS class names appended to link during various states
    sDefault: 'twones_toolbar_sm2_link', // default state
    sLoading: 'twones_toolbar_sm2_loading',
    sPlaying: 'twones_toolbar_sm2_playing',
    sPaused: 'twones_toolbar_sm2_paused'
  }

  this.addEventHandler = function(o,evtName,evtHandler) {
    typeof(attachEvent)=='undefined'?o.addEventListener(evtName,evtHandler,false):o.attachEvent('on'+evtName,evtHandler);
  }

  this.removeEventHandler = function(o,evtName,evtHandler) {
    typeof(attachEvent)=='undefined'?o.removeEventListener(evtName,evtHandler,false):o.detachEvent('on'+evtName,evtHandler);
  }

  this.classContains = function(o,cStr) {
	  return (typeof(o.className)!='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false);
  }

  this.addClass = function(o,cStr) {
    if (!o || !cStr || self.classContains(o,cStr)) return false;
    o.className = (o.className?o.className+' ':'')+cStr;
  }

  this.removeClass = function(o,cStr) {
    if (!o || !cStr || !self.classContains(o,cStr)) return false;
    o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');
  }

  this.getSoundByURL = function(sURL) {
    return (typeof self.soundsByURL[sURL] != 'undefined'?self.soundsByURL[sURL]:null);
  }

  this.isChildOfNode = function(o,sNodeName) {
    if (!o || !o.parentNode) {
      return false;
    }
    sNodeName = sNodeName.toLowerCase();
    do {
      o = o.parentNode;
    } while (o && o.parentNode && o.nodeName.toLowerCase() != sNodeName);
    return (o.nodeName.toLowerCase() == sNodeName?o:null);
  }

  this.parseAnchor = function(sAnchor) {
    var re_at = /[\s_]*(\-|\:\:?|_\-_)[\s_]*/i;
    matches = re_at.exec(sAnchor);
    if (matches) {
      anchor_info = sAnchor.split(re_at);
      anchor_info[2] = anchor_info[2].replace(/^["']*/g, '');
      anchor_info[2] = anchor_info[2].replace(/["']*$/g, '');
      return [
        anchor_info[0],
        anchor_info[2]
      ];
    } else {
      return [
        sAnchor
      ];
    }
  }
  
  this.updatePlaying = function(url, permaLink) {
      sm._writeDebug('url : ' + url);
      sm._writeDebug('url index : ' + pl.indexByURL[url]);
      //TwonesToolbar.debugDir(pl.anchors);
      sm._writeDebug('anchor : ' + pl.anchors[pl.indexByURL[url]]);
      this._anchor = pl.parseAnchor(pl.anchors[pl.indexByURL[url]]);
      TwonesToolbar.debugDir(this._anchor);
      if (typeof(this._anchor) == "object") {
        this._artist = (this._anchor.length == 1) ? null : this._anchor[0];
        this._title = (this._anchor.length == 1) ? this._anchor[0] : this._anchor[1];
        TwonesToolbar.debugMsg('Playing ' + this._title + ' from ' + this._artist);
        TwonesToolbarGadget.play({
          title:  this._title,
          artist: this._artist,
          location: url,
          pageLink: (permaLink) ? permaLink : document.location.href,
          player: "mp3"
        });
      } else {
        TwonesToolbarGadget.play({
          title:  (this._anchor != undefined) ? this._anchor : "unknown",
          artist: null,
          location: url,
          pageLink: (permaLink) ? permaLink : document.location.href,
          player: "mp3"
        });
        TwonesToolbar.debugMsg('Playing ' + this._anchor);        
      }
  }

  this.events = {

    // handlers for sound events as they're started/stopped/played

    play: function() {
      pl.removeClass(this._data.oLink,this._data.className);
      this._data.className = pl.css.sPlaying;
      pl.addClass(this._data.oLink,this._data.className);
      //TwonesToolbar.debugDir(pl.indexByURL[this.url]);
      //TwonesToolbar.debugDir(pl.indexByURL);
      //TwonesToolbar.debugMsg('playing or stopping : ' + url);
      var permaLink = TwonesToolbar.findStringInFeedEntries(this.url);
      if (permaLink) {
        pl.updatePlaying(this.url, permaLink);
      } else {
        TwonesToolbar.getPermalinkByBoss(this._data.link, this.url, "mp3");
      }
    },

    stop: function() {
      TwonesToolbarGadget.stop();
      pl.removeClass(this._data.oLink,this._data.className);
      this._data.className = '';
    },

    pause: function() {
      TwonesToolbarGadget.pause();
      pl.removeClass(this._data.oLink,this._data.className);
      this._data.className = pl.css.sPaused;
      pl.addClass(this._data.oLink,this._data.className);
    },

    resume: function() {
      pl.removeClass(this._data.oLink,this._data.className);
      this._data.className = pl.css.sPlaying;
      pl.addClass(this._data.oLink,this._data.className);      
      var permaLink = TwonesToolbar.findStringInFeedEntries(this.url);
      pl.updatePlaying(this.url, permaLink);
    },

    finish: function() {
      TwonesToolbarGadget.stop();
      pl.removeClass(this._data.oLink,this._data.className);
      this._data.className = '';
      if (pl.config.playNext) {
        var nextLink = (pl.indexByURL[this._data.oLink.href]+1);
        if (nextLink<pl.links.length) {
          pl.handleClick({'target':pl.links[nextLink]});
        }
      }
    },

    id3: function() {
      sm._writeDebug('id3 ready!');
    },
    
    load: function(success) {
      // success is a boolean, but if mp3 loaded for cache it is false
      // hence, we also need to look at readyState
      if (!success && (this.readyState == 2)) {
        sm._writeDebug('mp3 load not successful! readyState : ' + this.readyState);
        this.stop();
        TwonesToolbarGadget.stop("Could not load sound.");        
      } else {
        sm._writeDebug('mp3 load successful!');
      }
    }
  }

  this.stopEvent = function(e) {
   if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
      e.preventDefault();
    } else if (typeof event != 'undefined' && typeof event.returnValue != 'undefined') {
      event.returnValue = false;
    }
    return false;
  }

  this.getTheDamnLink = (isIE)?function(e) {
    // I really didn't want to have to do this.
    return (e && e.target?e.target:window.event.srcElement);
  }:function(e) {
    return e.target;
  }

  this.handleClick = function(e) {
    var _preventBubblingOfClick = function() {
      if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
        e.preventDefault();
      } else {
        event.returnValue = false;
      }      
    };
    sm._writeDebug('handleClick()');
    // a sound link was clicked
    if (typeof e.button != 'undefined' && e.button>1) {
	    // ignore right-click
	    return true;
    }
    var o = self.getTheDamnLink(e);
    TwonesToolbar.debugMsg('link element: ' + o);
    if (o.nodeName.toLowerCase() != 'a') {
      o = self.isChildOfNode(o,'a');
      if (!o) return true;
    }
    TwonesToolbar.debugMsg('is link element !');
    if (!self.classContains(o, self.includeClass)) {
      TwonesToolbar.debugMsg('not specifically included!' + o.className);
      var sURL = o.getAttribute('href');
      if (!o.href || !o.href.match(/\.mp3(\\?.*)$/i) || self.classContains(o,self.excludeClass)) {
        if (isIE && o.onclick) {
          return false; // IE will run this handler before .onclick(), everyone else is cool?
        }
        return true; // pass-thru for non-MP3/non-links
      }
    }
    
    TwonesToolbar.debugMsg('is even a mp3 link! ' + o.getAttribute('class'));
    if (!self.classContains(o, self.css.sDefault) && !self.classContains(o, self.css.sLoading) && 
    !self.classContains(o, self.css.sPlaying) && !self.classContains(o, self.css.sPaused)) {
      if (isIE && o.onclick) {
        return false; // IE will run this handler before .onclick(), everyone else is cool?
      }
      return true; // pass-thru for non-MP3/non-links      
    }
    TwonesToolbar.debugMsg('and is not excluded/css correct!');    
    var soundURL = (o.href);
    TwonesToolbar.debugMsg('MP3 link : ' + soundURL);
    var thisSound = self.getSoundByURL(soundURL);
    if (thisSound) {
      sm._writeDebug('sound exists!');
      if (thisSound.readyState == 2) {
        TwonesToolbarGadget.stop("Could not load sound.");                  
      } else if (thisSound == self.lastSound) {
        // already exists
        // and was playing (or paused)
        thisSound.togglePause();
      } else {
        // different sound
        thisSound.togglePause(); // start playing current
        sm._writeDebug('sound different than last sound: '+self.lastSound.sID);
        if (self.lastSound) self.stopSound(self.lastSound);
      }
    } else {
      sm._writeDebug('sound needs to be created!');
      // create sound
      if (!sm.canPlayURL(soundURL)) {
        sm._writeDebug('sm2 Can not play url ' + soundURL);
      }
      try {
        thisSound = sm.createSound({
         id:'TwonesToolbarinlineMP3Sound'+(self.soundCount++),
         url:soundURL,
         onplay:self.events.play,
         onstop:self.events.stop,
         onpause:self.events.pause,
         onresume:self.events.resume,
         onfinish:self.events.finish,
         onid3:self.events.id3,
         onload:self.events.load
        });
        
        // tack on some custom data
        thisSound._data = {
          oLink: o, // DOM node for reference within SM2 object event handlers
          link: self.links[self.indexByURL[o.href]],
          className: self.css.sPlaying
        };
        self.soundsByURL[soundURL] = thisSound;
        self.sounds.push(thisSound);
        if (self.lastSound) self.stopSound(self.lastSound);
        thisSound.play();
        TwonesToolbar.debugMsg('started playing sound ...');
        // stop last sound

      } catch(err) {
        TwonesToolbar.debugMsg('err: ' + err);
        TwonesToolbar.debugMsg('typeof(sm): ' + typeof(sm));
//        TwonesToolbar.debugMsg('typeof(_s): ' + typeof(_s));
//        TwonesToolbar.debugMsg('typeof(_s.o): ' + typeof(_s.o));
        TwonesToolbar.debugMsg('soundURL: ' + soundURL);
      }
    }
    self.lastSound = thisSound; // reference for next call

    sm._writeDebug('cencelling buubling event!');
    if (typeof e != 'undefined' && typeof e.preventDefault != 'undefined') {
      e.preventDefault();
    }
    if ((typeof(event) != 'undefined') && (typeof(event.returnValue) != 'undefined')) {
      sm._writeDebug('returnvalue!');
      event.returnValue = false;
    }
    return false;
  }

  this.stopSound = function(oSound) {
    soundManager.stop(oSound.sID);
    soundManager.unload(oSound.sID);
  }

  this.init = function() {
    TwonesToolbarGadget.actions['NakedMP3s'] = false;      
    sm._writeDebug('inlinePlayer.init()');
    var oLinks = document.getElementsByTagName('a');
    // grab all links, look for .mp3
    var foundItems = 0;
    for (var i=0; i<oLinks.length; i++) {
      if (self.classContains(oLinks[i],self.includeClass) || (oLinks[i].href.match(/\.mp3$/i) && !self.classContains(oLinks[i],self.excludeClass))) {
        //self.addClass(oLinks[i],self.css.sDefault); // add default CSS decoration
        if (oLinks[i].href in self.indexByURL) {
          var alt_olink_cnt = 1;
          var alt_olink_url = oLinks[i].href + '#' + alt_olink_cnt;
          while (alt_olink_url in self.indexByURL) {
            alt_olink_cnt++;
            alt_olink_url = oLinks[i].href + '#' + alt_olink_cnt;
          }
          oLinks[i].href = alt_olink_url;
        }
        self.links[foundItems] = (oLinks[i]);
        self.indexByURL[oLinks[i].href] = foundItems; // hack for indexing
        foundItems++;
      }
    }
    if (foundItems>0) {
      for (var i=0; i<self.links.length; i++) {
        self.buttons[i] = self.addPlayButtonToNakedMP3(i, self.links[i].href);
        self.anchors[i] = self.links[i].textContent || self.links[i].innerText;
        self.addClass(self.buttons[i], self.css.sDefault);
        self.addClass(self.buttons[i], self.includeClass);
        self.links[i].parentNode.insertBefore(self.buttons[i], self.links[i]);       
        var track = new TwonesToolbarTrackFactory({
          element: self.buttons[i],
          player: 'mp3'
        });
        TwonesToolbarGadget.tracks.push(track);       
      }
      self.addEventHandler(document,'click',self.handleClick);
	    if (self.config.autoPlay) {
	      self.handleClick({target:self.links[0],preventDefault:function(){}});
	    }
    }
    sm._writeDebug('inlinePlayer.init(): Found '+foundItems+' relevant items.');
    TwonesToolbarGadget.actions['NakedMP3s'] = true;      
  }

  this.addPlayButtonToNakedMP3 = function(index, mp3) {
    // TwonesToolbar.debugMsg('adding button for ' + mp3);
    var playClickEl = document.createElement('a');
    playClickEl.setAttribute('class', 'naked-play-button');
    playClickEl.setAttribute('id', 'twones-naked-player-' + index);   
    //playClickEl.href = 'javascript:TwonesToolbar.playNakedMP3(' + index + ',"' + mp3 + '")';
    playClickEl.href = mp3;
    playClickEl.innerHTML = '';
    return playClickEl;
    //el.parentNode.insertBefore(playEl, el);
  };

  this.playURL = function(mp3_href) {
    var playLink = pl.indexByURL[mp3_href];
    TwonesToolbar.debugMsg('index of url : ' + playLink + ' / ' + pl.links[playLink]);
    if ((playLink != undefined) && (playLink >= 0)) {
      TwonesToolbar.debugMsg('Previous sibling : ' + pl.links[playLink].previousSibling);
      pl.handleClick({'target':pl.links[playLink].previousSibling}); // use previous sibling because that is the actual url
    }    
  };
  
  this.init();

}

/*
var inlinePlayer = null;

soundManager.debugMode = true; // disable or enable debug output

soundManager.url = '../../swf/'; // path to directory containing SM2 SWF

soundManager.onready(function() {
  if (soundManager.supported()) {
    // soundManager.createSound() etc. may now be called
    inlinePlayer = new InlinePlayer();
  }
});
*/

var tjq;

function TwonesToolbarFactory(options) {
  this.twonesHost = options.twonesHost || 'trunk.twones.com';
  this.twonesInlinePlayer = null;
  this.loadNow = options.loadNow || false;
  
  this.init = function(options) {
    TwonesToolbar.findHostName();
    this.interceptXHRcalls();
    this.findFeedUrl();
    this.append_css_to_head('http://' + TwonesToolbar.twonesHost + '/css/tracker_player.css', function() {
      TwonesToolbar.debugMsg('inserted CSS for naked mp3s');
    });
    this.append_script_to_head('http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js', function() {
      TwonesToolbar.debugMsg('initing TwonesToolbarGadget ...');
      // TODO: activate_now (2nd arg) should be false?
      //TwonesToolbarGadget.init(TwonesToolbar.twonesHost, true, TwonesToolbar.environment);
      var loadGadgetNow = TwonesToolbar.loadNow;
      if (TwonesToolbar.isDeadToolbar()) {
        TwonesToolbar.debugMsg('loaded on dead toolbar!');
        loadGadgetNow = true;
      }
      // FIXME: temp fix for IE?
      if(navigator.userAgent.indexOf('MSIE') > -1) {
        //loadGadgetNow = true;
      }
      TwonesToolbarGadget.init(TwonesToolbar.twonesHost, loadGadgetNow, TwonesToolbar.environment);
      TwonesToolbar.debugMsg('inited TwonesToolbarGadget ...');
    });
    TwonesToolbar.debugMsg('adding event target ...');
    // create communication div for use with tracker.
    var e = document.createElement('div');
    e.id = 'twones-toolbar-event-target';
    e.style.display = 'none';
    document.body.appendChild(e);
    TwonesToolbar.debugMsg('added event target ...');
  	// Add listeners
  	// Add a listener to the main "window" object
  	this.addListener("Event", showToolbarListener);

  	// Add a listener to the main "window" object
  	this.addListener("updateTrackInfoEvent", updateTrackInfoListener);
	
    this.append_script_to_head('http://' + TwonesToolbar.twonesHost + '/js/json.js', function() {
	
      });    
    if (!this.checkForYahoo()) {
      this.initNakedMP3s();
    }

    var track_sorting = false;
    var track_sorting_id = setInterval(function() {
      // TwonesToolbar.debugMsg('Checking if all actions performed ...');
      var actionsCount = TwonesToolbarGadget.countAllActions();
      if (!TwonesToolbarGadget.allActionsPerformed() || (actionsCount == 0) || track_sorting) {
        return;
      }
      track_sorting = true;
      clearInterval(track_sorting_id);
      
      // now calling the TwonesToolbar api ready thing
      TwonesToolbar.doTwonesToolbarReady();
      
      if (TwonesToolbarGadget.tracks.length > 0) {
        TwonesToolbar.debugMsg('All actions performed, sorting tracks.');
        // TODO: make action to prevent autoplay
        TwonesToolbarGadget.tracks.sort(function (a, b) {
          return a.position() - b.position();
        });
      }
      
      /* the idea is to redirecto to the actual page if user is logged in.
  	     however, need to figure out what to show exactly. Can show 'now playing'
  	     but should be something like 'looking at $user's {favorite|paly} */
      if (TwonesToolbar.checkForTwonesReferrer()) {
        TwonesToolbar.showToolbar();
      }
    }, 20);
    
  };
  
	//////////////////////////////////////////////////////
	// Cross browser addEventListener implementation
	//////////////////////////////////////////////////////
	this.addListener = function (aEvent, aListener) {
		if (window.addEventListener) {
			window.addEventListener(aEvent, aListener, false);
			if (typeof(console) != 'undefined') {
		      console.log("Listener ADDED");
		    }
		}
		else if (window.attachEvent) {
			window.attachEvent(aEvent, aListener);
			if (typeof(console) != 'undefined') {
			  console.log("Event ATTACHED");
		  }
		}
		else if (document.addEventListener) {
			document.addEventListener(aEvent, aListener, false);
		}
	};

  this.getPermalinkByBoss = function(elem, linkelem, type) {
    this._linkelem = linkelem;
    var data = this.findContextByElement(elem);
    this.append_script_to_head('http://' + this.twonesHost + '/tracker_player/getPermalinkByBoss?site=' + location.hostname + '&context=' + data + '&type=' + type);
  }

  this.foundPermalinkByBoss = function(data, type, searchurl) {
    TwonesToolbar.debugMsg("found using query: " + searchurl);
    TwonesToolbar.debugMsg(data);
    data = (data !== "") ? data : false;
    if (type == "mp3") {
      TwonesToolbar.twonesInlinePlayer.updatePlaying(this._linkelem, data);
    } else if (type == "vimeo") {
      if (data) {
        TwonesToolbarGadget.VimeoPlayer._data.permaLink = data;
      } else {
        TwonesToolbarGadget.VimeoPlayer._data.permaLink = document.location.href;
      }
      TwonesToolbarGadget.VimeoPlayer.setToolbarPlay();
    } else if (type == "youtube") {
      if (data) {
        TwonesToolbarGadget.YoutubePlayer._data.permaLink = data;
      } else {
        TwonesToolbarGadget.YoutubePlayer._data.permaLink = document.location.href;
      }
      TwonesToolbarGadget.YoutubePlayer.setToolbarPlay();
    } else if (type == "soundcloud") {
      if (data) {
        TwonesToolbarGadget.SoundCloudPlayer._data.permaLink = data;
      } else {
        TwonesToolbarGadget.SoundCloudPlayer._data.permaLink = document.location.href;
      }
      TwonesToolbarGadget.SoundCloudPlayer.setToolbarPlay();
    } else if (type == "yahoo") {
      TwonesToolbarGadget.YahooMediaPlayer._data.permaLink = (data) ? data : document.location.href;
      TwonesToolbarGadget.YahooMediaPlayer.setToolbarPlay();
    } else if (type == "wpplayer") {
      TwonesToolbarGadget.WPPlayer._data.permaLink = (data) ? data : document.location.href;
      TwonesToolbar.debugMsg(TwonesToolbarGadget.WPPlayer._data.permaLink);
      TwonesToolbarGadget.WPPlayer.setToolbarPlay();
    } else if (type == "jwplayer") {
      TwonesToolbarGadget.JWPlayer._data.permaLink = (data) ? data : document.location.href;
      TwonesToolbar.debugMsg("JWPLAYER PERMALINK" + TwonesToolbarGadget.JWPlayer._data.permaLink);
      TwonesToolbarGadget.JWPlayer.setToolbarPlay();
    }
  }

  this.findFeedUrl = function() {
    TwonesToolbar.debugMsg('Finding feed urls ...');
    var headID = document.getElementsByTagName("head")[0];         
    var headLinks = headID.getElementsByTagName('link');
    var feedRegex = /^application\/(rss|atom)\+xml$/i;
    var pageFeeds = [];
    for(var i=0; i < headLinks.length; i++) {
      var headLink = headLinks[i];
      if ((headLink.getAttribute('rel') != null) && 
          (headLink.getAttribute('type') != null) && 
          (headLink.getAttribute('href') != null) && 
          (headLink.getAttribute('rel') == 'alternate') && 
           feedRegex.test(headLink.getAttribute('type'))) {
        TwonesToolbar.debugMsg('link ' + headLink.getAttribute('href') + ' -> rel = ' + headLink.getAttribute('rel') + ', type = ' + headLink.getAttribute('type'));
        pageFeeds.push(headLink.getAttribute('href'));
      }
    }
    if (pageFeeds.length > 0) {
      TwonesToolbar.debugMsg('Final feed url : ' + pageFeeds[0]);
      this.feedUrl = pageFeeds[0];
      this.append_script_to_head('http://' + this.twonesHost + '/rss2json?feed=' + escape(pageFeeds[0]) + '&callback=TwonesToolbar.feedUrlLoaded');
    }    
  };
  
  this.feedUrlLoaded = function(data) {
    TwonesToolbar.debugMsg('got feed data!');
    //TwonesToolbar.debugDir(data);
    this.feedData = data; // save for later use
  }
  
  this.findStringInFeedEntries = function(search_string) {
    if (!('feedData' in this) || (typeof(this.feedData) == "undefined")) {
      return false;
    }
    for(var i=0; i < this.feedData.length; i++) {
      TwonesToolbar.debugDir(this.feedData[i]);
      if (this.feedData[i].description.indexOf(search_string) >= 0) {
        return this.feedData[i].link;
      }
    }  
    return false;
  };

  this.findRegexInFeedEntries = function(search_regex) {
      if (!('feedData' in this) || (typeof(this.feedData) == "undefined")) {
        return false;
      }
      for(var i=0; i < this.feedData.length; i++) {
        if (search_regex.test(this.feedData[i].description)) {
          return this.feedData[i].link;
        }
      }        
      return false;
  };
    
  this.interceptXHRcalls = function() {
    TwonesToolbar.debugMsg('Setting XHR calls interception ...');
    // TODO: Uncomment when needed for use
    // NOTE: XMLHttpRequest.prototype.open is undefined under IE
    
    /*
    (function(open) {

        XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {

            this.addEventListener("readystatechange", function() {
                TwonesToolbar.debugMsg(url + ' is : ' +this.readyState);
            }, false);

            open.call(this, method, url, async, user, pass);
        };

    })(XMLHttpRequest.prototype.open);   
    */
    
    return; 
  };
  
  this.checkForTwonesReferrer = function() {
    this.debugMsg('referer : ' + document.referrer);
    return document.referrer.match(/twones\.com\/[f|p]\/\d+$/) || document.location.href.match(/twones\.com\/[f|p]\/\d+$/);  
  };
  
  this.initTrackerPlayerBar = function(callback) {
    if (!tjq) {
      this.append_script_to_head('http://' + TwonesToolbar.twonesHost + '/js/jquery.min.js', function() {
        tjq = jQuery.noConflict();
        TwonesToolbar.createTrackerPlayerBar(callback);
        //callback();
      });
    } else {
      callback();
    }
  };
  
  this.findHostName = function() {
    var dev2host = {
      'development' : 'localhost.twones.com',
      'preproduction' : 'trunk.twones.com',
      'production' : 'twones.com'
    };
    TwonesToolbar.debugMsg('finding hostname ...');
    var docScript = document.getElementById("TwonesInjectedJS");
    this.environment = docScript.getAttribute('environment');
    TwonesToolbar.debugMsg('Environment is : ' + this.environment);
    this.twonesHost = dev2host[this.environment];
    TwonesToolbar.debugMsg('Hostname set to ' + this.twonesHost);
  };
  
  this.isDeadToolbar = function() {
    var docScript = document.getElementById("TwonesInjectedJS");
    this.deadToolbar = docScript.getAttribute('dead');
    TwonesToolbar.debugMsg('injected elemtn is ' + docScript + ' ==> ' + this.deadToolbar);
    return (this.deadToolbar && (this.deadToolbar.toLowerCase() == 'true'));
  };
  
  this.append_script_to_body = function(script_source, onload_fn) {
    var e=document.createElement('script');
    e.setAttribute('type','text/javascript');
    e.setAttribute('src',script_source);
    e.onload = onload_fn;
    document.body.appendChild(e);
  };
  
  this.append_script_to_head = function(script_source, onload_fn) {
    var headID = document.getElementsByTagName("head")[0];         
    var newScript = document.createElement('script');
    newScript.setAttribute('type', 'text/javascript');
    newScript.setAttribute('src', script_source);
    headID.appendChild(newScript);  
    newScript.onload = onload_fn;
    newScript._script_loaded = false;
    newScript.onreadystatechange = function () {
      TwonesToolbar.debugMsg('onreadystatechange! ' + this.readyState + ' : ' + this.src);
      if ((this.readyState == 'loaded') || (this.readyState == 'complete')) {
        TwonesToolbar.debugMsg('script ' + this.src + ' loaded!');
        if (!this._script_loaded) {
          this._script_loaded = true;
          if(this.onload != null)
            this.onload();
        }
      }
    };
    
  };

  this.append_css_to_head = function(css_source, onload_fn) {
    var headID = document.getElementsByTagName("head")[0];         
    var newScript = document.createElement('link');
    newScript.href = css_source;
    newScript.rel = 'stylesheet';
    newScript.type = 'text/css';
    newScript.onload = onload_fn;
    headID.appendChild(newScript);  
  };
  
  this.streampad_loaded = function() {
    streampadPlayer.init();
    sBB = document.getElementById('streampadBottomBar');
    if (sBB) {
      sBB.style.height=0;
    }
    TwonesToolbar.createTrackerPlayerBar();
  };
  
  this.createTrackerPlayerBar = function(callback) {
    TwonesToolbar.debugMsg('creating tracker player bar ...');
    var el = tjq('<div />');
    el.attr({
      id: 'twones-tracker-player-bar' //,
      //onShowPanel: "alert('Triggerred ShowPanel event with additional data: ' + params);"
    });
    tjq('body').append(el);
    TwonesToolbar.debugMsg('created tracker player bar ...');
    this.loadTrackerPlayerBar(callback);
  };
  
  this.showSidebar = function(tgt, show){
  	if ("createEvent" in document) {
		var element = document.getElementById("TwonesTrackerSidebarDataContainer");
		if (!element) {
			element = document.createElement("TwonesTrackerSidebarDataContainer");
			document.documentElement.appendChild(element);
		}

  		// Set the event data 
		try {
			
			if (typeof(tgt) == 'undefined') tgt = null;
			if (typeof(show) == 'undefined') show = null;
			
			var data = {Target: tgt, Show: show};
			data = JSON.stringify(data);
			element.setAttribute('data', data);
			
			var evt = document.createEvent("Events");
			evt.initEvent("TwonesTrackerSidebarEvent", true, false);
			element.dispatchEvent(evt);
		}
		catch(e){
			alert(e);
		}
  	}
  };
  
  this.loadTrackerPlayerBar = function(callback) {
    TwonesToolbar.debugMsg('loading tracker player bar from - ' + 'http://' + TwonesToolbar.twonesHost + '/tracker_player/?callback=?');
    tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/tracker_player/?callback=?', function(data) {
      TwonesToolbar.debugMsg('loaded tracker player bar ...');
      TwonesToolbar.debugMsg(data);
      //TwonesToolbar.debugDir(tjq(data));
      //tjq('#twones-tracker-player-bar').html(data);
      tjq('#twones-tracker-player-bar').empty();
      TwonesToolbar.debugMsg('appending bar html and stuff ...');
      tjq('#twones-tracker-player-bar').html(data);
      if (tjq('#twones-tracker-player-bar').html() == '') {
        TwonesToolbar.debugMsg('setting inner html for bar ...');
        document.getElementById('twones-tracker-player-bar').innerHTML = data;
      }


      // set sharing links correctly
      sharing_services = ['facebook', 'twitter'];
      for(var sharing_idx = 0; sharing_idx < sharing_services.length; sharing_idx++) {
        var sharing_service = sharing_services[sharing_idx];
        TwonesToolbar.debugMsg('========> changing sharing links for ' + sharing_service);
        if (tjq('#twones-toolbar-share-button-' + sharing_service).hasClass('loggedin')) {
          tjq('#twones-toolbar-share-button-' + sharing_service).click(function () {
            var share_service = tjq(this).find('img').attr('alt').toLowerCase();
            TwonesToolbar.showShareDialog(share_service);
            return false;
          });
        } else {
          tjq('#twones-toolbar-share-button-' + sharing_service).click(function () {
            var share_service = tjq(this).find('img').attr('alt').toLowerCase();
            TwonesToolbar.showShareWindow(share_service);
            return false;
          });          
        }
      }
      
      // set the hiding of the bar
	    tjq('#twones-toolbar-bar').mouseenter(function(){TwonesToolbar.stopHideTimer();});
	    tjq('#twones-toolbar-bar').mouseleave(function(){TwonesToolbar.startHideTimer();});
	    tjq('#twones-toolbar-background').mouseenter(function(){TwonesToolbar.showToolbar();});
	    TwonesToolbar.startHideTimer();
      TwonesToolbar.getServiceInfo();

      var num_tracks_check = false;
      var num_tracks_id = setInterval(function() {
        TwonesToolbar.debugMsg('Checking if all actions performed for checking number of tracks...');
        if (!TwonesToolbarGadget.allActionsPerformed() || num_tracks_check) {
          return;
        }
        num_tracks_check = true;
        clearInterval(num_tracks_id);
        TwonesToolbar.debugMsg('All actions performed, now checking number of tracks.');
      
        TwonesToolbar.debugMsg('checking the number of tracks ...' + TwonesToolbarGadget.tracks.length);
        if (TwonesToolbarGadget.tracks.length > 0) {
          TwonesToolbar.debugMsg('=====> Found tracks on the page, enabling play button ...');
          // attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/tb-play.png')
          tjq('#twones-toolbar-playbutton img').click(function() {
            TwonesToolbar.clickPlayButton();
          });
        }
      }, 500);
      
      if (TwonesToolbar.checkForTwonesReferrer()) {
        TwonesToolbar.debugMsg('checkForTwonesReferrer: true' + document.referrer + ' / ' + document.location);
        // if we have the tiny url as a referrer we should get back to the song and start playing it.
        var referrer_url = document.referrer || document.location.href;
        var referrer_info = referrer_url.match(/twones\.com\/([f|p])\/(\d+)$/);
        var referrer2path = {
          'f': 'favorite',
          'p': 'play'
        };
        var referrer_what = referrer2path[referrer_info[1]];
        var referrer_id = referrer_info[2];
        tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/' + referrer_what + '/' + referrer_id + '?callback=?', function(data) {
          TwonesToolbar.gotShortUrlData(data);
        });
      }
      callback();
    });
  };
  
  this.gotShortUrlData = function(data) {
    TwonesToolbar.debugMsg('getShortUrlData');
    TwonesToolbar.debugDir(data);
    var auto_play_busy = false;
    var auto_play_id = setInterval(function() {
      TwonesToolbar.debugMsg('Checking if all actions performed ...');
      if (!TwonesToolbarGadget.allActionsPerformed() || auto_play_busy) {
        return;
      }
      auto_play_busy = true;
      clearInterval(auto_play_id);
      TwonesToolbar.debugMsg('All actions performed, now starting autoplay.');
      var track_title = (data.artist_name == null) ? data.track_name : data.artist_name + ' - ' + data.track_name
      var track_info = {
        artist: data.artist_name,
        title: data.track_name,
        location: data.link,
        pageLink: data.web_link
      };
      /*
      TwonesToolbarGadget.updateCurrentPlaying(track_info);
      */
      // loop through all the found "tracks" and
      // see if it's a match for the location of the favorite|play
      // if so, start playing :)
      TwonesToolbar.debugMsg('==> Trying to find tracks ...');
      var started_playing = false;
      for (track_index in TwonesToolbarGadget.tracks) {
        var track = TwonesToolbarGadget.tracks[track_index];
        if (!started_playing && track.isTrack(track_info)) {
          track.play();
          started_playing = true;
        }
      }
      TwonesToolbar.debugMsg('==> Tried to find tracks ...');
      if (!started_playing) {
        TwonesToolbarGadget.updateMessage('track not loaded... <a href="http://' + TwonesToolbar.twonesHost + '/pages/faq" target="_new">?</a>');
      }
      auto_play_busy = false;
    }, 500);
  };
  
  // public API functions

  this.play = function(obj) {
  	// we should do some validation here
    obj.artist = ('creator' in obj) ? obj.creator : null;
    obj.location = ('location' in obj) ? obj.location : document.URL;

    TwonesToolbarGadget.play(obj);
  }

  this.pause = function() {
    TwonesToolbarGadget.pause();
  }

  this.stop = function() {
	  TwonesToolbarGadget.stop();
  }

  this.getServiceInfo = function() {
    var e = document.createElement("script");
    
    var noCacheIE = '&_=' + (new Date()).getTime();    
    var src = 'http://' + TwonesToolbar.twonesHost + '/tracker_player/service?site=' + escape(document.URL) + "&callback=TwonesToolbar.setServiceInfo" + noCacheIE;
    
    e.setAttribute("type", "text/javascript");
    e.setAttribute("charset", "utf-8");
    e.setAttribute("src", src);
    
    document.getElementsByTagName("head").item(0).appendChild(e);
    
  };
  
  this.apiPlayerName = 'api custom player';
  
  this.lastTrackIndex = 0;
  
  this.addTrack = function(track) {
    TwonesToolbar.debugMsg('addTrack');
    TwonesToolbar.debugDir(track);
    if('trackIndex' in track)
      this.lastTrackIndex = track['trackIndex'];
    else
      track['trackIndex'] = this.lastTrackIndex++;
    
    track['player'] = this.apiPlayerName;
    track['position'] = function() { return(track['trackIndex']); };
    track['isTrack'] = function(metadata) { 
      return(metadata['location'] == track['location'] &&
            metadata['artist'] == track['creator'] &&
            metadata['title'] == track['title']); 
    }
    TwonesToolbarGadget.tracks.push(track);
  };
  
  this.setServiceInfo = function(data) {
    if (data != null) {
      TwonesToolbarGadget.service = data.name;
      TwonesToolbar.updateJoinButton(data.user_joined_service);
    } 
  };
  
  this.ajax = function(url, callback, postData) {
    req = new XMLHttpRequest();
    if (!req) return;
  	var method = (postData) ? "POST" : "GET";
  	req.open(method,url,true);
  	//req.setRequestHeader('User-Agent','XMLHTTP/1.0');
  	if (postData)
  		req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	  req.onreadystatechange = function () {
  		if (req.readyState != 4) return;
  		if (req.status != 200 && req.status != 304) {
        //			alert('HTTP error ' + req.status);
  			return;
  		}
  		callback(req);
  	}
  	if (req.readyState == 4) return;
  	req.send(postData);    
  };
  
  this.makeButton = function(btn_id, btn_name, btn_fn) {
    var e=document.createElement('div');
    e.setAttribute('id', btn_id);
    e.setAttribute('class', 'button');
    e.setAttribute('style', 'width: 40px; float: left;')
    var f=document.createElement('a');
    f.setAttribute('href', '#');
    f.onclick = btn_fn;
    f.innerHTML = btn_name;
    e.appendChild(f);
    return e;
  };
  
  this.togglePlayButton = function() {
    var e=document.getElementById('twones-tracker-player-playbtn');
    var l=e.getElementsByTagName('a')[0];
    if (streampadPlayer.vars.isPlaying == true) {
      SPAPI.pause();
      l.innerHTML = '>';
    } else {
      l.innerHTML = '||';
      if (streampadPlayer.vars.built == false) {
        streampadPlayer.UI.build(); 
      }
      SPAPI.play();
    }
  };

  this.clearSidebarResize = function() {
    if (typeof(sidebarResizeTimer) != "undefined") {
      window.clearTimeout(sidebarResizeTimer);
    }
  }

  this.sidebarResize = function() {
    var windowHeight = tjq(window).height();
    SideBar = tjq("#twones-tracker-player-sidebar-frame")
    if (Math.abs(parseInt(SideBar.css('height')) + 80 - windowHeight) > 5) {
      SideBar.animate({height: windowHeight - 80}, 500);
    }
  }
  
  this.toggleSideBar = function() {
    var windowHeight = tjq(window).height();
    sideBarWindow = tjq('#twones-tracker-player-sidebar');
    if (sideBarWindow.length == 0) {
      sideBarWindow = TwonesToolbar.createWindow('twones-tracker-player-sidebar', 'band buzz');
      sideBar = tjq('<iframe frameborder="0" id="twones-tracker-player-sidebar-frame"></iframe>');
      sideBar.attr('width', '340');
      sideBar.attr('height', windowHeight - 80);
      sideBar.attr('marginwidth', '0');
      sideBar.attr('marginheight', '0');
      sideBar.attr('border', '0');
      sideBar.attr('scrolling', 'no');      
      sideBar.css({'background' : 'white', 'border' : 0});
      tjq('#twones-tracker-player-sidebar .window').append(sideBar);
      sideBarWindow.hide();
    }
    this.updateSideBar();
    //sideBarWindow.attr('height', windowHeight - 80);
    var windowResizeHandler = function(){
      TwonesToolbar.clearSidebarResize();
      sidebarResizeTimer = window.setTimeout(TwonesToolbar.sidebarResize, 500);
    }
    window.onresize = windowResizeHandler;
    if (sideBarWindow.is(':visible')) {
      sideBarWindow.hide();
    } else {
      sideBarWindow.show();
      TwonesToolbar.sidebarResize();
    }
  };
  
  this.updateSideBar = function() {
    sideBar = tjq('#twones-tracker-player-sidebar-frame');
    if (sideBar.length > 0) {
	  TwonesToolbar.debugMsg('metadata: ');
	  TwonesToolbar.debugDir(TwonesToolbarGadget.metadata);
	  if (TwonesToolbarGadget.metadata != null) {
 	    tjq('#twones-tracker-player-sidebar .content').html('');
 	    tjq('#twones-tracker-player-sidebar .content').hide();
    	searchInfoBarFor = (TwonesToolbarGadget.metadata['artist'] != null) ? TwonesToolbarGadget.metadata['artist'] : TwonesToolbarGadget.metadata['title'];
    	tjq('#twones-tracker-player-sidebar h3').empty().html(searchInfoBarFor);
      searchInfoBarFor = searchInfoBarFor.replace(/[\u0100-\uFFFF]+/g, "");
      sideBar.attr('src', 'http://' + TwonesToolbar.twonesHost + '/infobar/' + escape(tjq.trim(searchInfoBarFor)));
      sideBar.show();
    } else {
	    sideBarWindow = tjq('#twones-tracker-player-sidebar');
	    if (sideBarWindow.length == 0) {
		    return;
	    }
    	sideBar.attr('src', 'about:blank');
//	    sideBar.hide();
    	tjq('#twones-tracker-player-sidebar h3').html('band buzz');
	    tjq('#twones-tracker-player-sidebar .content').html('You are not playing anything right now.');
      tjq('#twones-tracker-player-sidebar .content').css({"position": "absolute", "top" : 37, "left" : 5});
	    tjq('#twones-tracker-player-sidebar .content').show();
      }
    }    
  };
  
  this.showToolbar = function(callback) {
    
	  // Init toolbar if not already present
    if (!tjq) {
			TwonesToolbar.debugMsg('tjq undefined...');		
			TwonesToolbar.initTrackerPlayerBar(function(){
        tjq('#twones-tracker-player-bar').show();
        if(typeof(callback) != 'undefined')
          callback(); 
      });
			TwonesToolbar.debugMsg('tjq initialized...');		
	  } else {
		  if (!tjq('#twones-tracker-player-bar')){
			TwonesToolbar.debugMsg('tjq : tracker-player bar undefined...');		
			TwonesToolbar.createTrackerPlayerBar(function(){
        tjq('#twones-tracker-player-bar').show();
        if(typeof(callback) != 'undefined')
          callback();
      });
			TwonesToolbar.debugMsg('tjq : tracker-player bar initialized...');		
		  } else {
          // show the toolbar
        TwonesToolbar.debugMsg('tjq : ready  - show it');		
        tjq('#twones-tracker-player-bar').show();
        if (!tjq('#twones-toolbar-bar').is(':visible')) {
          tjq('#twones-toolbar-background').animate({height:'32px'}, 1000);
          tjq('#twones-toolbar-bar').show();
          tjq('#twones-toolbar-bar').animate({height:'32px'}, 1000);
          TwonesToolbar.startHideTimer();
        }
        if(typeof(callback) != 'undefined')
          callback();
	    }
    }
  };
  
  this.createWindow = function(window_id, window_title, bulge_color) {
    window_bulge_color = (bulge_color != undefined) ? bulge_color : 'gray';
    var createDiv = function(class_name) {
      var div_el = tjq('<div />');
      div_el.addClass(class_name);
      return div_el;
    }
    window_el = tjq('<div />');
    window_el.attr({
      id: window_id
    });
    window_el.addClass('window-outer');
    var top2_el = createDiv('window-bulge');
    var img_el = tjq('<img />');
    img_el.attr({
      'src' : 'http://' + this.twonesHost + '/img/toolbar/window-bulge-' + window_bulge_color + '.png'
    })
    top2_el.append(img_el);
    window_el.append(top2_el);
    var window_contents = createDiv('window');
    window_el.append(window_contents);
    header_el = tjq('<h3 />');
    header_el.html(window_title);
    header_el.css('float', 'left');
    window_contents.append(header_el);
    close_el = tjq('<div />');
    close_el.attr('class', 'closebtn')
    close_el.html('<a href="javascript:TwonesToolbar.hideWindow(\'#' + window_id + '\')"><img src="http://' + this.twonesHost + '/img/toolbar/delete.png" width="12" height="12" alt="close window" title="close window" /></a>');
    close_el.css('float', 'right');
    window_contents.append(close_el);
    content_el = tjq('<div />');
    content_el.attr({
      id: window_id + '-contents'
    });
    content_el.addClass('content');
    content_el.css('clear', 'both');
    window_contents.append(content_el);
    tjq('#twones-tracker-player-bar').append(window_el);
    return window_el;
  };
  
  this.hideWindow = function(window_id) {
    
    if (this.shouldRefreshToolbarAndJoinService) {
      this.loadTrackerPlayerBar(function(){
                                  TwonesToolbarGadget.updateCurrentPlaying(TwonesToolbarGadget.metadata);
                                });
      this.join();
      this.shouldRefreshToolbarAndJoinService = false;
    }
    tjq(window_id).hide();
  };
  
  this._getValue = function(list, key) {
		for (var i = 0; i < list.length; i++) {
			if (typeof(list[i][key]) !== "undefined") {
				return list[i][key];
			}
		}
		return null;
  };
  
  this.updateTrackInfo = function(track){
    // this function gets called when the tracker detects something is played
    // Ie. social music sites, youtube on-site etc.
    try{
		var trackObj = JSON.parse(track);
		if (trackObj.data != null) {
			trackObj = trackObj.data;
		}

		var track_info = {
          artist: trackObj.creator,
          title: trackObj.title
        }
		
		track_info.location = this._getValue(trackObj.link, 'http://twones.com/ns/jspf#playLink'),
        track_info.pageLink = this._getValue(trackObj.link, 'http://twones.com/ns/jspf#pageLink'),
        track_info.service = this._getValue(trackObj.link, 'http://twones.com/ns/jspf#metaService')
    }
    catch(e){
      if (console && console.error) {
       console.error(e);
      }
      else{
        alert("ERROR\n" + e);
      }
    }
    
    TwonesToolbarGadget.metadata = track_info;
    
    if (!tjq) {
  		TwonesToolbar.initTrackerPlayerBar(function(){
  			tjq('#twones-tracker-player-bar').show(); 
  			TwonesToolbarGadget.updateCurrentPlaying(track_info);
  		});
	  }
	  else
		  if (tjq('#current_playing').length > 0) {
			  TwonesToolbarGadget.updateCurrentPlaying(track_info);
		  }
  };
  
  this.showFavoriteDialog = function() {
    if (TwonesToolbar.favoriteDialogCloseCounterID != null) {
      clearTimeout(TwonesToolbar.favoriteDialogCloseCounterID);
      TwonesToolbar.favoriteDialogCloseCounterID = null;
    }
    if (tjq('#twones-tracker-player-favorite-dialog').length > 0) {
      if (tjq('#twones-tracker-player-favorite-dialog').is(':visible')) {
        tjq('#twones-tracker-player-favorite-dialog').hide();        
      } else {
	    tjq('#twones-tracker-player-favorite-dialog div.content').html('');	
        tjq('#twones-tracker-player-favorite-dialog').show();
      }
    } else { 
      var el = TwonesToolbar.createWindow('twones-tracker-player-favorite-dialog', 'bookmark this track');
    }
    tjq('#twones-tracker-player-favorite-dialog').css('left', tjq('.favbtn').offset().left - 40);
    if (TwonesToolbarGadget.metadata == null) {
      tjq('#twones-tracker-player-favorite-dialog div.content').html('You are not playing anything right now.');
      return;	    
    } else {
      tjq('#twones-tracker-player-favorite-dialog div.content').html('');	
    }
    tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/tracker_player/favorite_form?site=' + escape(document.URL) + '&link=' + escape(TwonesToolbarGadget.metadata['location']) + '&callback=?', function(data) {
      tjq('#twones-tracker-player-favorite-dialog div.content').html(data);
      tjq('#twones-toolbar-favorite-url').html(document.URL);
      tjq('#twones-toolbar-favorite-track').html((TwonesToolbarGadget.metadata['artist'] != null) ? TwonesToolbarGadget.metadata['artist'] + " - " + TwonesToolbarGadget.metadata['title'] : TwonesToolbarGadget.metadata['title']);
      if (tjq('#FavoriteAddForm #FavoritePlaylists').val() != "type a new label") {
        tjq('#FavoriteAddForm #FavoritePlaylists').css('color', 'black');
      }
      if (tjq('#FavoriteAddForm #FavoriteMessage').val() != "my comment") {
        tjq('#FavoriteAddForm #FavoriteMessage').css('color', 'black');
      }
      tjq('#FavoriteAddForm #FavoritePlaylists').focus(function() {
	    if (tjq(this).val() == 'type a new label') {
	      tjq(this).val('');
	      tjq(this).css('color', 'black');
        }
      });
      tjq('#FavoriteAddForm #FavoriteMessage').focus(function() {
	    if (tjq(this).val() == 'my comment') {
	      tjq(this).val('');
	      tjq(this).css('color', 'black');
        }
      });
      tjq('#twones-tracker-player-favorite-dialog form').submit(function() {
        return TwonesToolbar.submitFavoriteDialog();
      });
      tjq('#twones-toolbar-favorite-dialog-cancel-button').click(function() {
        return TwonesToolbar.hideWindow('#twones-tracker-player-favorite-dialog');
      });
      tjq('#twones-toolbar-favorite-dialog-send-button').click(function() {
        tjq('#FavoriteAddForm').submit();
        return false;
      });
      tjq('#FavoriteAddForm #FavoriteMessage').keydown(function() {
        TwonesToolbar.countFavoriteCharactersLeft('#twones-toolbar-favorite-dialog-charcount', '#twones-tracker-player-favorite-dialog #FavoriteMessage');
      });
      tjq('#FavoriteAddForm #FavoriteMessage').keyup(function() {
        TwonesToolbar.countFavoriteCharactersLeft('#twones-toolbar-favorite-dialog-charcount', '#twones-tracker-player-favorite-dialog #FavoriteMessage');
      });
      tjq('#FavoriteAddForm #FavoriteMessage').keypress(function() {
        TwonesToolbar.countFavoriteCharactersLeft('#twones-toolbar-favorite-dialog-charcount', '#twones-tracker-player-favorite-dialog #FavoriteMessage');
      });
      tjq('#FavoriteAddForm #FavoritePlaylists').keydown(function(event) {
        return TwonesToolbar.favoritesKeyDownCheck(event);
      });
      tjq('#FavoriteAddForm #FavoritePlaylists').keyup(function(event) {
        return TwonesToolbar.favoritesAutofill(this, event);
      });
    });    
  };
  
  this.submitFavoriteDialog = function() {
    //tjq('#twones-favorite-dialog-spinner').show();
    tjq('#twones-toolbar-favorite-dialog-send-button img').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/button-send-ani.gif');
    TwonesToolbar.debugMsg('favoriting track ...');
    TwonesToolbarGadget.favorite({
      message: tjq('#twones-tracker-player-favorite-dialog #FavoriteMessage').val(),
      playlists: tjq('#twones-tracker-player-favorite-dialog #FavoritePlaylists').val(),
      callback: 'TwonesToolbar.favoriteDialogSubmitted'
    });
    tjq('#twones-tracker-player-favorite-dialog #FavoriteMessage').val('');
    tjq('#twones-tracker-player-favorite-dialog #FavoritePlaylists').val('');
    //tjq('#twones-tracker-player-favorite-dialog').hide();
    return false;    
  };

  this.closeFavoriteDialog = function() {
    TwonesToolbar.favoriteDialogCloseCounterID = null;
    tjq('#twones-tracker-player-favorite-dialog').hide('slow');
  };
  
  this.favoriteDialogSubmitted = function(data) {
    TwonesToolbar.debugMsg('Favorite submitted  ....');
    tjq('#twones-toolbar-favorite-dialog-send-button img').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/button-send.png');
    tjq('#twones-tracker-player-favorite-dialog div.content').html('The song was succesfully added to your favorites!');
    TwonesToolbar.favoriteDialogCloseCounterID = setTimeout('TwonesToolbar.closeFavoriteDialog()', 5000);   
  };
  
  this.createService = function(site_url, callback) {
    tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/tracker_player/service_add?site=' + escape(site_url) + '&callback=?', function(data) {
      callback(data);
    });
  };
  
  this.closebar = function() {
    tjq('#twones-tracker-player-bar').hide();
  };
  
  this._join = function(action) {
    var url = 'http://' + TwonesToolbar.twonesHost + '/services/' + TwonesToolbarGadget.service + '/' + action + '?callback=?';
    tjq('#join_image').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/join_ani.gif');     
    tjq.getJSON(url, function(data) {
      TwonesToolbar.debugMsg(data);
      TwonesToolbar.updateJoinButton(!data.match(/unjoined/));
    });    
  };

  this.updateJoinButton = function(joined) {
    if (joined) {
      tjq('#join_link span').html('stop tracking');
      tjq('#join_link').attr('href', "javascript:TwonesToolbar.unjoin()");
      tjq('#join_image').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/follow_stop.png');     
    } else {
      tjq('#join_link span').html('start tracking');
      tjq('#join_link').attr('href', "javascript:TwonesToolbar.join()");      
      tjq('#join_image').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/follow_start.png');     
    }
  };
  
  this.joinAction = function(joined) {
    TwonesToolbar._join(joined ? 'join' : 'unjoin');
    //TwonesToolbar.updateJoinButton(joined);
  };
  
  this.possiblyDeferredJoinAction = function(joined) {
    if (TwonesToolbarGadget.service == null) {
      TwonesToolbar.createService(document.URL, function (data) {
        TwonesToolbar.setServiceInfo(data);
        TwonesToolbar.joinAction(joined);
      });
    } else {
      TwonesToolbar.joinAction(joined);
    }
  };
  
  this.unjoin = function() {
    TwonesToolbar.possiblyDeferredJoinAction(false);
  };

  this.join = function() {
    TwonesToolbar.possiblyDeferredJoinAction(true);
  };

  this.shouldRefreshToolbarAndJoinService = false;

  this.signup = function() {
    if (TwonesToolbarGadget.service === null) {
      TwonesToolbar.createService(document.URL, function(data) {
        TwonesToolbar.setServiceInfo(data)
        TwonesToolbar._signup();        
      });
    } else {
      TwonesToolbar._signup();
    }
  };
    
  this._signup = function() {
    
    if (tjq('#twones-toolbar-login-dialog').length > 0) {
      var el = tjq('#twones-toolbar-login-dialog');
      if (tjq('#twones-toolbar-login-dialog').is(':visible'))
        el.hide();        
      else 
        el.show();
    } else {
      var el = TwonesToolbar.createWindow('twones-toolbar-login-dialog', 'login');
    }
    tjq('#twones-toolbar-login-dialog').css('left', tjq('.favbtn').offset().left - 40);
    
    tjq('#twones-toolbar-login-dialog .content').html('You need to login to do that <br/> <a href="http://' + this.twonesHost + '/login?site=' + escape(document.location.href) + '"> login </a>');    
    //this.shouldRefreshToolbarAndJoinService = true;
    
  };

  this.checkForYouTubeVideo = function() {

    /*
    <object width="480" height="385">
      <param name="movie" value="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&color1=0x234900&color2=0x4e9e00"></param>
      <param name="allowFullScreen" value="true"></param>
      <param name="allowscriptaccess" value="always"></param>
      <embed src="http://www.youtube.com/v/MB2f6-U72Zk&hl=en&fs=1&color1=0x234900&color2=0x4e9e00" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"></embed>
    </object>
    */ 

    // look for youtube players
    var objects = document.getElementsByTagName('object'); 
    var len = objects.length;
    for(var index = 0; index < len; index++) {
      var object = objects[index];

      var url = TwonesToolbarGadget.getObjectUrl(object);
      isYoutube = url.match(/(youtube)\.com/);
      if(isYoutube) 
        return true;             
    }
    
    // now look form embeds. :-(
    var embeds = document.getElementsByTagName('embed'); 
    var len = embeds.length;
    for(var index = 0; index < len; index++) {
      var embed = embeds[index]; // on IE when I remove the element from the dom it also get removed from the array
      if(embed) {
        var url = embed.src;
        
        isYoutube = url.match(/(youtube)\.com/);

        if(isYoutube) 
          return true;          
      }
    }
    
    return false;
  };

  this.checkForYahoo = function() {
    // we check for Yahoo Player or Streampad here
    return (((typeof(YAHOO) != "undefined") && ('MediaPlayer' in YAHOO)) || (typeof(streampadPlayer) != "undefined"));
  };
    
  this.checkForMusic = function() {
    // we check for Yahoo Player, Streampad and YouTube here
    // check for JW player is done in onReady function
    // || this.checkForYouTubeVideo()
    return ((typeof(YAHOO) != "undefined") || this.checkForYouTubeVideo() || (typeof(streampadPlayer) != "undefined"));
  };

  this.classContains = function(o,cStr) {
	  return (typeof(o.className)!='undefined'?o.className.match(new RegExp('(\\s|^)'+cStr+'(\\s|$)')):false);
  }
  
  this.initNakedMP3s = function() {
    TwonesToolbar.debugMsg('determining if there are naked mp3s for ' + document.URL);
    doclinks = document.getElementsByTagName('a');
    hasMP3s = false;
    len = doclinks.length;
    TwonesToolbar.hasNakedMP3s = false;
    for(docIndex=0; docIndex < len; docIndex++) {
      docLink = doclinks[docIndex];
      if (docLink.href && (docLink.href != '')) {
        //TwonesToolbar.debugMsg('href : ' + docLink.href);
        TwonesToolbar.hasNakedMP3s = TwonesToolbar.hasNakedMP3s || docLink.href.match(/\.mp3$/) || TwonesToolbar.classContains(docLink, 'twones-toolbar-inline-include');
      }
    }
    if (TwonesToolbar.hasNakedMP3s) {
      TwonesToolbar.debugMsg('there were naked mp3s for ' + document.URL);
      TwonesToolbar.append_script_to_head('http://' + TwonesToolbar.twonesHost + '/js/player/soundmanager2.js', function() {
        TwonesToolbar.debugMsg('sound manager 2 javascript loaded!');
        TwonesToolbar.debugMsg('polling : ' + soundManager.allowPolling);
        TwonesToolbar.debugMsg('flash version : ' + soundManager.flashVersion);
        soundManager.debugMode = true;
        soundManager.flashVersion = 9;
        soundManager.flashLoadTimeout = 2000; // longer timeout?
        //soundManager.allowPolling = false;
        soundManager.waitForWindowLoad = true;
        soundManager.consoleOnly = true;
        // the toolbar uses a different version of sm2 because it needs cross-domain flash-js communication to work        
        soundManager.url = 'http://' + TwonesToolbar.twonesHost + '/swf/toolbar/';
        //soundManager.url = '/swf/';
        soundManager.onload = function() {
          TwonesToolbar.debugMsg('sm2 loaded!');
          TwonesToolbar.soundManager2ready();
        };
        soundManager.onerror = function() {
          TwonesToolbar.debugMsg('sm2 error!');
        };
        TwonesToolbar.debugMsg('Beginning delayed init');
        //setTimeout(soundManager.beginDelayedIinit(), 25000);
        //TwonesToolbar.debugMsg(soundManager._windowLoaded);
        soundManager.beginDelayedInit();
        //TwonesToolbar.debugMsg(soundManager._windowLoaded);
        TwonesToolbar.debugMsg('Set options for soundmanager.');
     });
    }
  };

  this.soundManager2ready = function() {
    //TwonesToolbar.debugMsg('sound manager 2 ready');
    if (soundManager.supported()) {
      TwonesToolbar.twonesInlinePlayer = new TwonesInlinePlayerFactory();
    } else {
      TwonesToolbar.debugMsg('soundmanager not supported?');
    }
  };
  
  this.debugMsg = function(msg) {
    if (typeof(console) != 'undefined') {
      console.log(msg);
    }
  };
  
  this.debugDir = function(obj) {
    if ((typeof(console) != 'undefined') && ('dir' in console)) {
      console.dir(obj);
    }    
  };

  this.arrPlaylists = false;
  this.lastPlaylistsEntry = false;
  this.changingFavs = false;

  this.favoritesAutofill = function(elem, ev) {
    var oldValue = elem.value;
    if (!TwonesToolbar.arrPlaylists) {
      tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/playlists/autofill?format=jsonp&callback=?', function(returned) {
        if ((returned != undefined) && (returned != '')) {
            TwonesToolbar.arrPlaylists = returned.split(',');
            for (i=0; i<TwonesToolbar.arrPlaylists.length; i++) {
              TwonesToolbar.arrPlaylists[i] = tjq.trim(TwonesToolbar.arrPlaylists[i]);
            }
            TwonesToolbar.favoritesAutofill(elem, ev);
        }
      });
    } else {
      if (ev.keyCode == 8 || ev.keyCode == 46) {
        TwonesToolbar.lastPlaylistsEntry = elem.value;
        return;
      } 
      if (ev.keyCode == 188) {
        elem.value += ',';
      }
      if (ev.keyCode == 13) {
        if (elem.value != "" && elem.value.substr(elem.value.length-1) != "," && elem.value.substr(elem.value.length-2) != ", ") {
          elem.value += ', ';
        }
        return;
      }
      var strEntries = elem.value;
      var arrEntries = strEntries.split(',');
      var strLastEntry = arrEntries[arrEntries.length-1];
      while (strLastEntry.charAt(0) == ' ') {strLastEntry = strLastEntry.substr(1);}
      var strSuggestion = false;
      var i = 0;
      while (!strSuggestion && i < TwonesToolbar.arrPlaylists.length) {
        if (TwonesToolbar.arrPlaylists[i].substr(0, strLastEntry.length) == strLastEntry) {
          strSuggestion = TwonesToolbar.arrPlaylists[i];
        }
        i++;
      }
      TwonesToolbar.changingFavs = true;
      if (strLastEntry.length > 0 && strSuggestion && elem.value == oldValue) {
        elem.value += strSuggestion.substr(strLastEntry.length);
        elem.setSelectionRange(strEntries.length, elem.value.length);
        elem.focus();
      }
      TwonesToolbar.lastPlaylistsEntry = elem.value;
      TwonesToolbar.changingFavs = false;
      return;
    }
  };

  this.animateClosebar = function() {
    tjq('#twones-toolbar-background').animate({height:'8px'}, 1000);
    tjq('#twones-toolbar-bar').animate({height:'0px'}, 1000, function(){tjq('#twones-toolbar-bar').hide();});
    //tjq('#twones-toolbar-bar').slideUp('slow');
    //tjq('#twones-toolbar-background').slideUp('slow');
    //tjq('#twones-tracker-player-bar').show(); 
  };
  
  this.favoritesKeyDownCheck = function(event) {
    if ((event.keyCode == 13) || (event.keyCode == 188) || TwonesToolbar.changingFavs) {
      return false;
    }
    return true;
  };
  
  this.startHideTimer = function() {
    TwonesToolbar.stopHideTimer(); // for safety
    TwonesToolbar.debugMsg('starting timeout ...');
	  //TwonesToolbar.hideTimeoutID = setTimeout('TwonesToolbar.animateClosebar()', 20000);
  };

  this.stopHideTimer = function() {
  	if ('hideTimeoutID' in TwonesToolbar) {
  		if (TwonesToolbar.hideTimeoutID != null) {
        TwonesToolbar.debugMsg('stopping timeout ...');
  			clearTimeout(TwonesToolbar.hideTimeoutID);
  			TwonesToolbar.hideTimeoutID = null;
  		}
  	}
  };

  this.countFavoriteCharactersLeft = function(el_result, el_text) {
    tjq(el_result).html(140 - tjq(el_text).val().length);
  };

  this.showShareWindow = function(share_service) {
    TwonesToolbar._share_service = share_service;
    TwonesToolbarGadget.playNow({
      callback: 'TwonesToolbar.openShareWindow'
    });
    if (TwonesToolbarGadget.playdata != null) {
      TwonesToolbar.openShareWindow(TwonesToolbarGadget.playdata);
    }
  };
  
  this.openShareWindow = function(play_data) {
    TwonesToolbar.debugMsg('got play now data for not logged in user using ' + TwonesToolbar._share_service + ' :');
    TwonesToolbarGadget.setPlayData(play_data);
    var share_text = "";
    var share_url = "";
    if (TwonesToolbar._share_service == 'twitter') {
      share_text = 'Listening to ' + tjq('#current_playing').html() + ' http://' + TwonesToolbar.twonesHost + '/p/' + play_data.id + ' @twones';
      share_url =  'http://twitter.com/timeline/home?source=twones&status=' + escape(share_text);
    } else {
      var share_short_url = 'http://' + TwonesToolbar.twonesHost + '/p/' + play_data.id;
      share_text = 'Listening to ' + tjq('#current_playing').html() + ' at Twones';  
      share_url = 'http://www.facebook.com/sharer.php?u=' + encodeURIComponent(share_short_url) + '&t=' + encodeURIComponent(share_text);     
    }
    TwonesToolbar._share_service = null;
    TwonesToolbar.debugMsg('Gonna open a tab via js!');
    window.open(share_url, '_blank');    
  };
  
  this.showShareDialog = function(share_service) {
    if (TwonesToolbar.shareDialogCloseCounterID != null) {
      clearTimeout(TwonesToolbar.shareDialogCloseCounterID);
      TwonesToolbar.shareDialogCloseCounterID = null;
    }
    if (tjq('#twones-toolbar-share-dialog').length > 0) {
      tjq('#twones-toolbar-share-dialog h3').html('share on ' + share_service);
      if (tjq('#twones-toolbar-share-dialog').is(':visible')) {
        tjq('#twones-toolbar-share-dialog').hide();        
      } else {
	      tjq('#twones-toolbar-share-dialog div.content').html('');	
        tjq('#twones-toolbar-share-dialog').show();
      }
    } else { 
      var el = TwonesToolbar.createWindow('twones-toolbar-share-dialog', 'share on ' + share_service);
    }
    tjq('#twones-toolbar-share-dialog').css('left', tjq('#twones-toolbar-share-button-' + share_service).offset().left - 40);
    if (TwonesToolbarGadget.metadata == null) {
      tjq('#twones-toolbar-share-dialog div.content').html('You are not playing anything right now.');
      return;	    
    } else {
      tjq('#twones-toolbar-share-dialog div.content').html('');	
    }
    tjq('#twones-toolbar-share-dialog div.content').html('<img src="http://' + TwonesToolbar.twonesHost + '/img/spinner.gif" width="16" height="16" />');
    TwonesToolbarGadget.playNow();
    if (TwonesToolbarGadget.playdata != null) {
      TwonesToolbar.loadShareDialog(TwonesToolbarGadget.playdata);
    }
  };
  
  this.loadShareDialog = function(play_data) {
    TwonesToolbar.debugMsg('got play data :');
    TwonesToolbar.debugDir(play_data);
    TwonesToolbarGadget.setPlayData(play_data);
    TwonesToolbar.debugMsg('getting service name :');
    if (tjq('#twones-toolbar-share-dialog h3').html().match(/twitter/)) {
      share_service = 'twitter';
    } else {
      share_service = 'facebook';
    }
    TwonesToolbar.debugMsg('share service : ' + share_service);
    tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/tracker_player/share_form?service=' + share_service + '&callback=?', function(data) {
      TwonesToolbar.debugMsg(data);
      tjq('#twones-toolbar-share-dialog div.content').html(data);
      
      if (tjq('#twones-toolbar-share-dialog h3').html().match(/twitter/)) {
        share_text = 'Listening to ' + tjq('#current_playing').text() + ' http://' + TwonesToolbar.twonesHost + '/p/' + play_data.id + ' @twones';
      } else {
        share_text = 'Listening to ' + tjq('#current_playing').text() + ' http://' + TwonesToolbar.twonesHost + '/p/' + play_data.id + ' at Twones';        
      }
      tjq('#twones-toolbar-share-dialog #ShareMessage').val(share_text);
      tjq('#twones-toolbar-share-dialog-charcount').val(140 - share_text.length);
      
      tjq('#twones-toolbar-share-dialog form').submit(function() {
        return TwonesToolbar.submitShareDialog();
      });
      tjq('#twones-toolbar-share-dialog-cancel-button').click(function() {
        return TwonesToolbar.hideWindow('#twones-toolbar-share-dialog');
      });
      tjq('#twones-toolbar-share-dialog-send-button').click(function() {
        tjq('#ShareForm').submit();
        return false;
      });
    });        
  };
  
  this.submitShareDialog = function() {
    //tjq('#twones-share-dialog-spinner').show();
    tjq('#twones-toolbar-share-dialog-send-button img').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/button-send-ani.gif');
    TwonesToolbar.debugMsg('sharing play ...');
    tjq.getJSON('http://' + TwonesToolbar.twonesHost + '/tracker_player/share?message=' + escape(tjq('#twones-toolbar-share-dialog #ShareMessage').val())  + '&play=' + TwonesToolbarGadget.playdata.id +  '&service=' + escape(tjq('#twones-toolbar-share-dialog #ShareService').val()) + '&callback=?', function (data) {
      TwonesToolbar.shareDialogSubmitted(data);
    });
    tjq('#twones-toolbar-share-dialog #ShareMessage').val('');
    return false;    
  };
  
  this.shareDialogSubmitted = function(data) {
    TwonesToolbar.debugMsg('play successfully shared! ' + data);
    //tjq('#twones-share-dialog-spinner').hide();
    tjq('#twones-toolbar-share-dialog-send-button img').attr('src', 'http://' + TwonesToolbar.twonesHost + '/img/toolbar/button-send.png');
    tjq('#twones-toolbar-share-dialog div.content').html(data);
    TwonesToolbar.favoriteDialogCloseCounterID = setTimeout('TwonesToolbar.closeShareDialog()', 5000);
  };
  
  this.closeShareDialog = function() {
    TwonesToolbar.shareDialogCloseCounterID = null;
    tjq('#twones-toolbar-share-dialog').hide('slow');
  };

  this.findContextByElement = function(elem) {
    /* Context for Permalink finder BOSS */
    var my_text = (elem.textContent || elem.innerText) || "";
    var anchorLength = my_text.length;
    var context = "";
    var newContextNode;
    var oldContextNode;
    var contextNode = null;  
    do {
      newContextNode = (contextNode != null) ? contextNode.parentNode : elem;
      oldContextNode = (contextNode != null) ? contextNode : null;
      contextNode = newContextNode;
      context = (contextNode.textContent || contextNode.innerText) || "";
    } while ((context.length - anchorLength) < 40 && contextNode != document) 

    var siblingContext = "";
    var contextNodeSibling = null;
    do {
      if (oldContextNode.previousSibling) {
              contextNodeSibling = (contextNodeSibling != null) ? contextNodeSibling.previousSibling : oldContextNode.previousSibling;
      } else {
        contextNodeSibling = contextNode;
      }
      // TwonesToolbar.debugMsg(oldContextNode);
      siblingContext = (contextNodeSibling.textContent || contextNodeSibling.innerText) || "";
      siblingContext = siblingContext.replace(/\s/, " ")
    } while (!(contextNodeSibling.tagName != undefined) && ((siblingContext == "") || (siblingContext == " ")))

    if (siblingContext.length > 30) {
      context = siblingContext;
    }

    context = context.split(/\s+/, 40);
    for (i = 0; i < context.length; i++) {
      context[i] = context[i].replace(/([^ \w])/g, " ").replace(/\b(\d+)\b/g, " ");
      // 'favorite' and 'site' are not allowed.
      if (context[i] == "favorite" || context[i] == "site") {
        context[i] = "";
      }
    }

    context = context.join(" ").split(/\s+/, 15).join(" ");
    context = context.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    TwonesToolbar.debugMsg('context found: ' + context);
    return context;
  }
  
  this.clickPlayButton = function() {
    if (TwonesToolbarGadget.currentTrack == null) {
      // nothing played before, what to do?
      if (TwonesToolbarGadget.tracks.length > 0) {
        TwonesToolbarGadget.tracks[0].play(); //play the first track
      }
    } else {
      if (TwonesToolbarGadget.currentTrack.state == 0) {
        // stopped playing?
        TwonesToolbarGadget.currentTrack.play();
      } else if (TwonesToolbarGadget.currentTrack.state == 1) {
        TwonesToolbarGadget.currentTrack.pause();
      } else {
        TwonesToolbarGadget.currentTrack.play();
      }
    }
  };
  
  this.random = function() {
    // nothing right now :)
    tjq.getJSON('http://' + this.twonesHost + '/favorites/random?callback=?', function (random_id) {
      TwonesToolbar.debugMsg('Got random number ! : ' + random_id);
      var random_link = 'http://' + TwonesToolbar.twonesHost + '/f/' + random_id;
      document.location.href = random_link;
    });
  };
  
  this.doTwonesToolbarReady = function() {
    if (typeof(twonesToolbarReady) != "undefined") {
      TwonesToolbar.debugMsg('Calling twonesToolbarRady API function ...');
      twonesToolbarReady();
    }
  };
};

TwonesToolbar = new TwonesToolbarFactory({});
TwonesToolbar.debugMsg('instantiated toolbar ...');
TwonesToolbar.init();

//////////////////////////////////////////////////////
// Show panel event listener sent from the XUL
//////////////////////////////////////////////////////
function showToolbarListener(event){
	try {
		//TwonesToolbar.debugMsg('panel!');
		var elm = event.target;
		//var att = elm.getAttribute("onShowPanel");
		
		if (elm /* && att*/) {
			// Trigger showToolbar action
			window.TwonesToolbar.showToolbar();
		}
	}
	catch(e) {
		alert("Show Toolbar event error\n" + e);
	}
};


//////////////////////////////////////////////////////
// Update Track information event listener sent from the XUL
//////////////////////////////////////////////////////
function updateTrackInfoListener(event){
	// TwonesToolbar.debugMsg("new track");
	try {
		var elm = event.target;
		//var att = elm.getAttribute("onUpdateTrackInfo");
		
		if (elm /*&& att*/) {
			// Additional parameter(s) is set in extension code
			// track is a JSON represented JSPF track
			// var track = JSON.parse(elm.getAttribute("track"));
			var track = elm.getAttribute('track');
			//window.TwonesToolbar.debugMsg('Got track ! :');
			//window.TwonesToolbar.debugDir(track);
			window.TwonesToolbar.updateTrackInfo(track);
		}
		// Clean up
		if (elm.hasAttribute("track")) 
			elm.removeAttribute("track");
	} 
	catch (e) {
		alert("Update Track info event error\n" + e);
	}
};
