author | Dan |
Fri, 25 Apr 2008 12:42:26 -0400 | |
changeset 18 | 69af47034212 |
parent 14 | 7a1573676cc4 |
child 21 | 74edc873234f |
permissions | -rw-r--r-- |
/** * AJAX functions * * Greyhound - real web management for Amarok * Copyright (C) 2008 Dan Fuhry * * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. */ var ajax; var is_playing = false, current_track = -1, current_track_length, current_track_pos, ct_advance_timeout = false, ct_counter = false, playlist_md5 = false, first_load = true; var onload_hooks = new Array(); function addOnloadHook(func) { if ( typeof ( func ) == 'function' ) { if ( typeof(onload_hooks.push) == 'function' ) { onload_hooks.push(func); } else { onload_hooks[onload_hooks.length] = func; } } } function runOnloadHooks(e) { var _errorTrapper = 0; for ( var _oLc = 0; _oLc < onload_hooks.length; _oLc++ ) { _errorTrapper++; if ( _errorTrapper >= 1000 ) break; var _f = onload_hooks[_oLc]; if ( typeof(_f) == 'function' ) { _f(e); } } } function ajaxGet(uri, f) { if (window.XMLHttpRequest) { ajax = new XMLHttpRequest(); } else { if (window.ActiveXObject) { ajax = new ActiveXObject("Microsoft.XMLHTTP"); } else { alert('AmaroK client-side runtime error: No AJAX support, unable to continue'); return; } } ajax.onreadystatechange = f; ajax.open('GET', uri, true); ajax.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" ); ajax.send(null); } function ajaxPost(uri, parms, f) { if (window.XMLHttpRequest) { ajax = new XMLHttpRequest(); } else { if (window.ActiveXObject) { ajax = new ActiveXObject("Microsoft.XMLHTTP"); } else { alert('AmaroK client-side runtime error: No AJAX support, unable to continue'); return; } } ajax.onreadystatechange = f; ajax.open('POST', uri, true); ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); // Setting Content-length in Safari triggers a warning if ( !is_Safari ) { ajax.setRequestHeader("Content-length", parms.length); } ajax.setRequestHeader("Connection", "close"); ajax.send(parms); } function setAjaxLoading() { $('ajax_status').object.src = img_ajax; $('ajax_status').object.style.display = 'block'; } function unsetAjaxLoading() { $('ajax_status').object.src = 'about:blank'; $('ajax_status').object.style.display = 'none'; } var refresh_playlist = function() { setAjaxLoading(); ajaxGet('/action.json/refresh', function() { if ( ajax.readyState == 4 && ajax.status == 200 ) { unsetAjaxLoading(); var response = (' ' + ajax.responseText).substr(1); // quickie JSON parser :) response = eval('(' + response + ')'); // has the playlist been modified? if ( playlist_md5 ) { if ( response.playlist_hash != playlist_md5 ) { // playlist has changed, reload window.location.reload(); return false; } } playlist_md5 = response.playlist_hash; // update track number if ( response.current_track != current_track ) { var ot_id = 'track_' + current_track; var nt_id = 'track_' + response.current_track; current_track = response.current_track; if ( $(ot_id).hasClass('current') ) { $(ot_id).rmClass('current'); } if ( ! $(nt_id).hasClass('current') ) { $(nt_id).addClass('current'); } pulsar_reset(); } // update playing status is_playing = response.is_playing; if ( allow_control ) { var img = $('btn_playpause').object.getElementsByTagName('img')[0]; if ( is_playing ) { img.src = img_pause; } else { img.src = img_play; } } // update volume if ( response.volume != current_volume ) { set_volume_fill(response.volume); current_volume = response.volume; } // auto-refresh on track advance if ( ct_advance_timeout ) { clearTimeout(ct_advance_timeout); } // countdown/up timer var time_remaining = response.current_track_length - response.current_track_pos; current_track_length = response.current_track_length; current_track_pos = response.current_track_pos; if ( ct_counter ) clearInterval(ct_counter); update_clock(); // set page title updateTitle(response.current_track_artist, response.current_track_album, response.current_track_title); // if not playing, set the position slider to zero if ( !is_playing ) { posslide_set_position(0); } // set advance timer if ( is_playing && time_remaining > 0 ) { ct_advance_timeout = setTimeout(refresh_playlist, ( 1000 * time_remaining )); ct_counter = setInterval(update_clock, 1000); } if ( first_load ) { first_load = false; jump_current_track(); } } }); } function player_action(action) { var act2 = action; setAjaxLoading(); ajaxGet('/action.json/' + action, function() { if ( ajax.readyState == 4 && ajax.status == 200 ) { unsetAjaxLoading(); refresh_playlist(); } }); } function jump_to_song(tid) { setAjaxLoading(); if ( tid == current_track ) return false; if ( !allow_control ) return false; ajaxGet('/action.json/jump/' + tid, function() { if ( ajax.readyState == 4 && ajax.status == 200 ) { unsetAjaxLoading(); var response = (' ' + ajax.responseText).substr(1); // quickie JSON parser :) response = eval('(' + response + ')'); // update track number var ot_id = 'track_' + current_track; var nt_id = 'track_' + tid; current_track = tid; if ( $(ot_id).hasClass('current') ) { $(ot_id).rmClass('current'); } if ( ! $(nt_id).hasClass('current') ) { $(nt_id).addClass('current'); } // update pulsar pulsar_reset(); // update playing status var img = $('btn_playpause').object.getElementsByTagName('img')[0]; is_playing = true; img.src = img_play; // auto-refresh on track advance if ( ct_advance_timeout ) { clearTimeout(ct_advance_timeout); } if ( ct_counter ) clearInterval(ct_counter); var time_remaining = response.current_track_length - response.current_track_pos; current_track_length = response.current_track_length; current_track_pos = response.current_track_pos; if ( is_playing ) { ct_advance_timeout = setTimeout(refresh_playlist, ( 1000 * time_remaining )); update_clock(); ct_counter = setInterval(update_clock, 1000); } updateTitle(response.current_track_artist, response.current_track_album, response.current_track_title); } }); } function set_playback_position(pos) { pos = Math.round(( pos / 100 ) * current_track_length); setAjaxLoading(); if ( !allow_control ) return false; ajaxGet('/action.json/seek/' + pos, function() { if ( ajax.readyState == 4 && ajax.status == 200 ) { unsetAjaxLoading(); current_track_pos = pos; update_clock(); } }); } function update_clock() { posslide_set_position((100 * (current_track_pos / current_track_length))); var str = secs_to_string(current_track_pos) + '/' + secs_to_string(current_track_length); $('playmeter').object.innerHTML = str; current_track_pos++; } function secs_to_string(time) { var count_seconds = time % 60; var count_minutes = ( time - count_seconds ) / 60; if ( isNaN(count_seconds) ) count_seconds = 0; if ( isNaN(count_minutes) ) count_minutes = 0; return fill_zeroes(count_minutes) + ':' + fill_zeroes(count_seconds); } function fill_zeroes(str, len) { if ( !len ) len = 2; if ( typeof(str) == 'number' && str == 0 ) str = '0'; str = String(str); while ( str.length < len ) { str = '0' + str; } return str; } setInterval(refresh_playlist, 10000); window.onload = function(e) { runOnloadHooks(e); } addOnloadHook(refresh_playlist); // scroll to the current track function jump_current_track() { var top = $('track_' + current_track).Top() - 138; window.scroll(0, top); if ( typeof(fix_scroll) == 'function' ) { fix_scroll(); } } // pulse the current track var pulsar_current = 0, pulsar_tdlist = [], pulsar_direction = 1; var pulsar_reset = function() { // remove any pulsar classes from items that aren't "current" var boobylist = document.getElementsByTagName('tr'); for ( var i = 0; i < boobylist.length; i++ ) { var booby = boobylist[i]; var match = booby.className.match(/(^| )(pulsar[0-9])( |$)/); if ( match && !$(booby).hasClass('current') ) { $(booby).rmClass(match[2]); } } // recalculate list of rows that should pulse var tdlist_new = document.getElementsByClassName('current', 'tr'); if ( pulsar_current == 0 && tdlist_new == pulsar_tdlist ) { return true; } // reset everything to 0 pulsar_tdlist = tdlist_new; pulsar_current = 0; pulsar_direction = 1; for ( var i = 0; i < pulsar_tdlist.length; i++ ) { var td = pulsar_reset[i]; for ( var i = 1; i < 10; i++ ) { if ( $(td).hasClass('pulsar' + i) ) { $(td).rmClass('pulsar' + i); } } if ( ! $(td).hasClass('pulsar0') ) { $(td).addClass('pulsar0'); } } } var pulsar_advance = function() { // this should be as optimized as possible, it should use a precalculated // list of elements to pulse and whatnot... heck even right now it's not // really as optimized as it should be due to the logic, but a lot of it's // kinda more or less necessary. if ( !is_playing ) return true; if ( pulsar_current + pulsar_direction == 10 ) { pulsar_direction = -1; } else if ( pulsar_current + pulsar_direction == -1 ) { pulsar_direction = 1; } var nc = pulsar_current + pulsar_direction; for ( var i = 0; i < pulsar_tdlist.length; i++ ) { $(pulsar_tdlist[i]).rmClass('pulsar' + pulsar_current).addClass('pulsar' + nc); } pulsar_current = nc; } addOnloadHook(pulsar_reset); setInterval(pulsar_advance, 50); function updateTitle(artist, album, track) { var sep = ''; var str = ''; if ( track ) { str += sep + track; sep = ' - '; } if ( artist ) { str += sep + artist; sep = ' - '; } if ( album ) { str += sep + album; sep = ' - '; } str += sep + 'AmaroK Playlist'; document.title = str; }