diff options
author | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2005-08-13 04:30:26 +0000 |
---|---|---|
committer | Karl 'vollmerk' Vollmer <vollmer@ampache.org> | 2005-08-13 04:30:26 +0000 |
commit | e7fea90327419214531371543662056c1398470d (patch) | |
tree | 8b7642b5cac62994ff55f80e733dedbff22105bf | |
parent | 3836a33d1c210a806c13f9bb172724394fb3fd80 (diff) | |
download | ampache-e7fea90327419214531371543662056c1398470d.tar.gz ampache-e7fea90327419214531371543662056c1398470d.tar.bz2 ampache-e7fea90327419214531371543662056c1398470d.zip |
new mpd mojo from rosensama and rperkins
-rw-r--r-- | amp-mpd.php | 276 | ||||
-rw-r--r-- | config/ampache.cfg.php.dist | 4 | ||||
-rw-r--r-- | index.php | 31 | ||||
-rw-r--r-- | lib/class/playlist.class.php | 12 | ||||
-rw-r--r-- | lib/mpd.php | 14 | ||||
-rwxr-xr-x | modules/xmlrpc/xmlrpc.inc | 390 | ||||
-rwxr-xr-x | modules/xmlrpc/xmlrpcs.inc | 49 | ||||
-rw-r--r-- | mpd.php | 1 | ||||
-rw-r--r-- | templates/header.inc | 6 | ||||
-rw-r--r-- | templates/show_mpd_pl_box.inc.php | 29 | ||||
-rw-r--r-- | templates/show_mpdpl.inc | 270 | ||||
-rw-r--r-- | templates/show_mpdplay.inc | 2 |
12 files changed, 701 insertions, 383 deletions
diff --git a/amp-mpd.php b/amp-mpd.php index 6dcb19a6..fa83ef6b 100644 --- a/amp-mpd.php +++ b/amp-mpd.php @@ -30,147 +30,175 @@ require_once("modules/init.php"); $myMpd = init_mpd(); if (is_object($myMpd)) { - switch ($_REQUEST['action']) { - case "add": - if (!$user->has_access(25)) { break; } - $song_ids = array(); - $song_ids[0] = $_REQUEST[song_id]; - addToPlaylist( $myMpd, $song_ids ); - break; - case "rem": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->PLRemove($_REQUEST[id])) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case ' > ': - case "play": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->Play()) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "stop": - case ' X ': - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->Stop()) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case ' = ': - case "pause": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->Pause()) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case '|< ': - case "Prev": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->Previous()) ) echo "ERROR: " . $myMpd->errStr."\n"; - mpd_redirect(); - break; - case ' >|'; - case "Next": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->Next()) ) echo "ERROR: " . $myMpd->errStr."\n"; - mpd_redirect(); - break; - case "shuffle": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->PLShuffle()) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "clear": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->PLClear()) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "loop": - if (!$user->has_access(25)) { break; } - if ($_REQUEST['val'] == "On") { $_REQUEST['val'] = '1'; } - else { $_REQUEST['val'] = '0'; } - if ( is_null($myMpd->SetRepeat($_REQUEST['val'])) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "random": - if (!$user->has_access(25)) { break; } + switch ($_REQUEST['action']) { + case "add": + if (!$user->has_access(25)) { break; } + $song_ids = array(); + $song_ids[0] = $_REQUEST[song_id]; + addToPlaylist( $myMpd, $song_ids ); + break; + case "rem": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->PLRemove($_REQUEST[id])) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case ' > ': + case "play": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->Play()) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "stop": + case ' X ': + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->Stop()) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case ' | | ': + case ' = ': + case "pause": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->Pause()) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case '|< ': + case "Prev": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->Previous()) ) echo "ERROR: " . $myMpd->errStr."\n"; + mpd_redirect(); + break; + case ' >|'; + case "Next": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->Next()) ) echo "ERROR: " . $myMpd->errStr."\n"; + mpd_redirect(); + break; + case "shuffle": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->PLShuffle()) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "clear": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->PLClear()) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "loop": + if (!$user->has_access(25)) { break; } + if ($_REQUEST['val'] == "On") { $_REQUEST['val'] = '1'; } + else { $_REQUEST['val'] = '0'; } + if ( is_null($myMpd->SetRepeat($_REQUEST['val'])) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "random": + if (!$user->has_access(25)) { break; } if ($_REQUEST['val'] == "On") { $_REQUEST['val'] = '1'; } else { $_REQUEST['val'] = '0'; } - if ( is_null($myMpd->SetRandom($_REQUEST['val']))) echo "ERROR: " .$myMpd->errStr."\n"; + if ( is_null($myMpd->SetRandom($_REQUEST['val']))) echo "ERROR: " .$myMpd->errStr."\n"; mpd_redirect(); break; - case "adjvol": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->AdjustVolume($_REQUEST[val])) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "setvol": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->SetVolume($_REQUEST[val])) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "skipto": - if (!$user->has_access(25)) { break; } - if ( is_null($myMpd->SkipTo($_REQUEST[val])) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); - break; - case "pladd": - if (!$user->has_access(25)) { break; } - $plist = new Playlist( $_REQUEST[pl_id] ); - $song_ids = $plist->get_songs(); - addToPlaylist( $myMpd, $song_ids ); - break; - case "albadd": - if (!$user->has_access(25)) { break; } - $album = new Album( $_REQUEST[alb_id] ); - $song_ids = $album->get_song_ids( ); - addToPlaylist( $myMpd, $song_ids ); - break; - case "show_control": - require (conf('prefix') . "/templates/show_mpdplay.inc"); - break; + case "adjvol": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->AdjustVolume($_REQUEST[val])) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "setvol": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->SetVolume($_REQUEST[val])) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "skipto": + if (!$user->has_access(25)) { break; } + if ( is_null($myMpd->SkipTo($_REQUEST[val])) ) echo "ERROR: " .$myMpd->errStr."\n"; + mpd_redirect(); + break; + case "pladd": + if (!$user->has_access(25)) { break; } + $plist = new Playlist( $_REQUEST[pl_id] ); + $song_ids = $plist->get_songs(); + addToPlaylist( $myMpd, $song_ids ); + break; + case "albadd": + if (!$user->has_access(25)) { break; } + $album = new Album( $_REQUEST[alb_id] ); + $song_ids = $album->get_song_ids( ); + addToPlaylist( $myMpd, $song_ids ); + break; + case "show_control": + require (conf('prefix') . "/templates/show_mpdplay.inc"); + break; case "mute": if (!$user->has_access(25)) { break; } if ( is_null($myMpd->SetVolume(0)) ) echo "ERROR: " .$myMpd->errStr."\n"; - mpd_redirect(); + mpd_redirect(); break; case "condPL": if (!$user->has_access(25)) { break; } $condPL = (conf('condPL')==1 ? 0 : 1); conf(array('condPL' => $condPL),1); - $pref_id = get_preference_id('condPL'); - $user->update_preference($pref_id,$condPL); - mpd_redirect(); + $pref_id = get_preference_id('condPL'); + $user->update_preference($pref_id,$condPL); + mpd_redirect(); break; case "crop": if (!$user->has_access(25)) { break; } $pl = $myMpd->playlist; $cur = $myMpd->current_track_id; - foreach ($pl as $id => $entry) - { - if ($id != $cur) + foreach ($pl as $id => $entry ) { + if ($id != $cur) { { if ( is_null($myMpd->PLRemove($id < $cur ? 0 : 1))) {echo "ERROR: " .$myMpd->errStr."\n"; } } } - mpd_redirect(); + } + mpd_redirect(); break; case "plact": if (!$user->has_access(25)) { break; } switch ($_REQUEST['todo']) - { + { + case "Add to Playlist": + if( isset( $_REQUEST['song'] ) ) { + $pl = $myMpd->playlist; + if( is_null($pl) ) { + echo "ERROR: ".$myMpd->errStr."\n"; + } else { + $mpd_dir = conf('mpd_dir') . '/'; + $pl_ids = scrub_in( $_REQUEST['song'] ); + foreach( $pl as $id => $entry ) { + // remember in_array( needle, haystack ) + if( in_array( $id, $pl_ids ) ) { + $song_files[] = $mpd_dir . $entry['file']; + } + } + // basically copied from playlist.php Add to case + $pl_id = scrub_in( $_REQUEST['playlist_id'] ); + $playlist = new Playlist($pl_id); + if( $pl_id == 0 ) { // new playlist + $playlist_name = _("New Playlist") . " - " . date("m/j/y, g:i a"); + $playlist->create_playlist($playlist_name, $user->username, 'private'); + $pl_id = $playlist->id; + } + foreach( $song_files as $song_file ) { + $song_file = sql_escape( $song_file ); + $sql = "SELECT id FROM song WHERE `file` = '$song_file'"; + $db_results = mysql_query( $sql, dbh() ); + $results = mysql_fetch_object( $db_results ); + $song_ids[] = $results->id; + } + if (isset($song_ids) && is_array($song_ids)) { + $playlist->add_songs($song_ids, true); // $is_ordered = true + } + } + } + // would be nice to redirect to the playlist page for the new $pl_id, but header( "Location: " ) doesn't seem to do it + $page = 'playlist.php?playlist_id=' . $pl_id . '&action=view_list'; + break; case "Delete": $shrunkby =0; - foreach ($_REQUEST[song] as $id => $entry) { + foreach ($_REQUEST['song'] as $id ) { if ( is_null($myMpd->PLRemove($id-$shrunkby)) ) echo "ERROR: " .$myMpd->errStr."\n"; $shrunkby++; } break; - case "Crop": - $skipped=0; - $upto = $myMpd->playlist_count-1; - for ($count=0; $count <= $upto; $count++) { - if (!isset($_REQUEST[song][$count])) { - if ( is_null($myMpd->PLRemove($skipped)) ) echo "ERROR: " .$myMpd->errStr."\n"; - } - else {$skipped++;} - } - break; case "move Next": /* This does not work yet */ $fromabovenp = 0; @@ -197,19 +225,25 @@ if (is_object($myMpd)) { echo "id=".$id." entry=".$entry."_REQUEST[song][id]=".$_REQUEST[song][$id]."<br>"; } } - mpd_redirect(); + if( $page ) { + mpd_redirect( $page ); + } else { + mpd_redirect(); + } break; case "movenext": if (!$user->has_access(25)) { break; } - if (is_null($myMpd->PLMoveTrack($_REQUEST[val],$myMpd->current_track_id+1))) echo "ERROR: ".$myMpd->errStr."\n"; - mpd_redirect(); + if ($_REQUEST[val] < $myMpd->current_track_id) $offset=-1; + if (is_null($myMpd->PLMoveTrack($_REQUEST[val],$myMpd->current_track_id+1+$offset))) + echo "ERROR: ".$myMpd->errStr."\n"; + mpd_redirect(); break; - default: - mpd_redirect(); - break; - } // end switch + default: + mpd_redirect(); + break; + } // end switch - // We're done let's disconnect - $myMpd->Disconnect(); + // We're done let's disconnect + $myMpd->Disconnect(); } // end else ?> diff --git a/config/ampache.cfg.php.dist b/config/ampache.cfg.php.dist index 7bf9ff36..bfee16ed 100644 --- a/config/ampache.cfg.php.dist +++ b/config/ampache.cfg.php.dist @@ -470,6 +470,10 @@ rss_song_description = <![CDATA[$song->f_title @ $album played by $user->fullna # DEFAULT: "" #mpd_pass = "" +# MPD base directory +# this is the directory mpd.conf's music_directory points to, but +# it's the path on your Ampache server, not the mpd server +#mpd_dir = "" # MPD Method # This is the method you want to use to pass your @@ -63,11 +63,15 @@ $action = scrub_in($_REQUEST['action']); <?php show_local_catalog_info(); ?> </td> <td valign="top" align="left"> - <?php + <?php + if ($user->prefs['play_type'] == 'mpd' && !conf('localplay_menu')) { + show_mpd_control(); + } else { if ( $items = get_global_popular('album') ) { show_info_box(_("Most Popular Albums"), 'album',$items); } - ?> + } + ?> </td> </tr> <tr><td colspan="2"> </td></tr> @@ -77,16 +81,16 @@ $action = scrub_in($_REQUEST['action']); </td> </tr> <tr><td colspan="2"> </td></tr> - <tr> - <?php - if ($user->prefs['play_type'] == 'mpd') { - show_mpd_pl(); - } else { - echo "<td> </td>"; - } - ?> - </tr> - <tr><td colspan="2"> </td></tr> + <tr> + <?php + if ($user->prefs['play_type'] == 'mpd' && !conf('localplay_menu')) { + show_mpd_pl(); + } else { + echo "<td> </td>"; + } + ?> + </tr> + <tr><td colspan="2"> </td></tr> <tr> <td valign="top" align="right"> <?php @@ -137,9 +141,6 @@ $action = scrub_in($_REQUEST['action']); if($user->prefs['play_type'] == 'local_play') { show_local_control(); echo "<br />"; - } elseif ($user->prefs['play_type'] == 'mpd' && !conf('localplay_menu')) { - show_mpd_control(); - echo "<br />"; } else { echo " "; } diff --git a/lib/class/playlist.class.php b/lib/class/playlist.class.php index b17eadc6..7fa55492 100644 --- a/lib/class/playlist.class.php +++ b/lib/class/playlist.class.php @@ -186,18 +186,26 @@ class Playlist { /*! @function add_songs @discussion Reads an array of song_ids to add to the playlist + @param $song_ids the array of song_ids + @param $is_ordered boolean, if true insert in order submitted, not by track number */ - function add_songs($song_ids) { + function add_songs($song_ids, $is_ordered = false) { $dbh = dbh(); if ($this->id && isset($song_ids) && is_array($song_ids)) { + $count = 0; foreach ($song_ids as $song_id) { + if( $is_ordered ) { + $track_num = $count++; + } else { + $track_num = $song->track; + } $song = new Song($song_id); if (isset($song->id)) { $sql = "INSERT INTO playlist_data" . " (playlist, song, track)" . - " VALUES ('$this->id', '$song->id', '$song->track')"; + " VALUES ('$this->id', '$song->id', '$track_num')"; $db_results = mysql_query($sql, $dbh); } } diff --git a/lib/mpd.php b/lib/mpd.php index 5eacddad..efbbda6e 100644 --- a/lib/mpd.php +++ b/lib/mpd.php @@ -90,10 +90,11 @@ function show_mpd_pl() { * Redriect mojo * @package Local Play * @catagory MPD + * @param $page is the URL after conf('web_path') . '/' */ -function mpd_redirect() { +function mpd_redirect( $page = 'mpd.php' ) { if (conf('localplay_menu')) { - header ("Location: " . conf('web_path') . "/mpd.php"); + header ("Location: " . conf('web_path') . '/' . $page); } else { header ("Location: " . conf('web_path')); @@ -119,8 +120,15 @@ function init_mpd() { $myMpd = new mpd(conf('mpd_host'),conf('mpd_port')); } + if (!$myMpd->connected AND is_object($myMpd)) { + // Attempt to reconnect + $myMpd->Connect(); + } + if (!$myMpd->connected) { - if (conf('debug')) { log_event ($_SESSION['userdata']['username'],' connection_failed ',"Error: unable to connect to MPD, ".$myMpd->errStr); } + if (conf('debug')) { + log_event ($_SESSION['userdata']['username'],' connection_failed ',"Error: unable to connect to ". conf('mpd_host') . " on port " . conf('mpd_port') . " ".$myMpd->errStr); + } return false; } diff --git a/modules/xmlrpc/xmlrpc.inc b/modules/xmlrpc/xmlrpc.inc index bdb818e2..e8b6aedd 100755 --- a/modules/xmlrpc/xmlrpc.inc +++ b/modules/xmlrpc/xmlrpc.inc @@ -58,6 +58,7 @@ global $xmlrpcI4; global $xmlrpcInt; global $xmlrpcDouble; + global $xmlrpcBoolean; global $xmlrpcString; global $xmlrpcDateTime; global $xmlrpcBase64; @@ -99,6 +100,26 @@ $xmlrpcStruct => 3 ); + $xmlrpc_valid_parents = array( + 'BOOLEAN' => array('VALUE'), + 'I4' => array('VALUE'), + 'INT' => array('VALUE'), + 'STRING' => array('VALUE'), + 'DOUBLE' => array('VALUE'), + 'DATETIME.ISO8601' => array('VALUE'), + 'BASE64' => array('VALUE'), + 'ARRAY' => array('VALUE'), + 'STRUCT' => array('VALUE'), + 'PARAM' => array('PARAMS'), + 'METHODNAME' => array('METHODCALL'), + 'PARAMS' => array('METHODCALL', 'METHODRESPONSE'), + 'MEMBER' => array('STRUCT'), + 'NAME' => array('MEMBER'), + 'DATA' => array('ARRAY'), + 'FAULT' => array('METHODRESPONSE'), + 'VALUE' => array('MEMBER', 'DATA', 'PARAM', 'FAULT'), + ); + $xmlEntities=array( 'amp' => '&', 'quot' => '"', @@ -123,8 +144,9 @@ $xmlrpcstr['no_ssl']='No SSL support compiled in.'; $xmlrpcerr['curl_fail']=8; $xmlrpcstr['curl_fail']='CURL error'; - - + $xmlrpcerr['invalid_request']=15; + $xmlrpcstr['invalid_request']='Invalid request payload'; + $xmlrpcerr['multicall_notstruct'] = 9; $xmlrpcstr['multicall_notstruct'] = 'system.multicall expected struct'; $xmlrpcerr['multicall_nomethod'] = 10; @@ -146,7 +168,7 @@ $xmlrpc_internalencoding='ISO-8859-1'; $xmlrpcName='XML-RPC for PHP'; - $xmlrpcVersion='1.1.1'; + $xmlrpcVersion='1.2'; // let user errors start at 800 $xmlrpcerruser=800; @@ -158,15 +180,14 @@ // used to store state during parsing // quick explanation of components: - // st - used to build up a string for evaluation // ac - used to accumulate values - // qt - used to decide if quotes are needed for evaluation - // cm - used to denote struct or array (comma needed) // isf - used to indicate a fault // lv - used to indicate "looking for a value": implements // the logic to allow values with no types to be strings // params - used to store parameters in method calls // method - used to store method name + // stack - array with genealogy of xml elements names: + // used to validate nesting of xmlrpc elements $_xh=array(); @@ -517,38 +538,73 @@ function xmlrpc_se($parser, $name, $attrs) { - global $_xh, $xmlrpcDateTime, $xmlrpcString; + global $_xh, $xmlrpcDateTime, $xmlrpcString, $xmlrpc_valid_parents; + + // if invalid xmlrpc already detected, skip all processing + if ($_xh[$parser]['isf'] < 2) + { + + // check for correct element nesting + // top level element can only be of 2 types + if (count($_xh[$parser]['stack']) == 0) + { + if ($name != 'METHODRESPONSE' && $name != 'METHODCALL') + { + $_xh[$parser]['isf'] = 2; + $_xh[$parser]['isf_reason'] = 'missing top level xmlrpc element'; + return; + } + } + else + { + // not top level element: see if parent is OK + if (!in_array($_xh[$parser]['stack'][0], $xmlrpc_valid_parents[$name])) + { + $_xh[$parser]['isf'] = 2; + $_xh[$parser]['isf_reason'] = "xmlrpc element $name cannot be child of {$_xh[$parser]['stack'][0]}"; + return; + } + } switch($name) { case 'STRUCT': case 'ARRAY': - $_xh[$parser]['st'].='array('; - $_xh[$parser]['cm']++; + //$_xh[$parser]['st'].='array('; + //$_xh[$parser]['cm']++; // this last line turns quoting off // this means if we get an empty array we'll // simply get a bit of whitespace in the eval - $_xh[$parser]['qt']=0; + //$_xh[$parser]['qt']=0; + + // create an empty array to hold child values, and push it onto appropriate stack + $cur_val = array(); + $cur_val['values'] = array(); + $cur_val['type'] = $name; + array_unshift($_xh[$parser]['valuestack'], $cur_val); break; + case 'METHODNAME': case 'NAME': - $_xh[$parser]['st'].='"'; + //$_xh[$parser]['st'].='"'; $_xh[$parser]['ac']=''; break; case 'FAULT': $_xh[$parser]['isf']=1; break; case 'PARAM': - $_xh[$parser]['st']=''; - break; + //$_xh[$parser]['st']=''; + // clear value, so we can check later if no value will passed for this param/member + $_xh[$parser]['value']=null; + break; case 'VALUE': - $_xh[$parser]['st'].='new xmlrpcval('; - $_xh[$parser]['vt']=$xmlrpcString; + //$_xh[$parser]['st'].='new xmlrpcval('; + // look for a value: if this is still true by the + // time we reach the end tag for value then the type is string + // by implication + $_xh[$parser]['vt']='value'; $_xh[$parser]['ac']=''; - $_xh[$parser]['qt']=0; + //$_xh[$parser]['qt']=0; $_xh[$parser]['lv']=1; - // look for a value: if this is still 1 by the - // time we reach the first data segment then the type is string - // by implication and we need to add in a quote break; case 'I4': case 'INT': @@ -557,9 +613,18 @@ case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': - $_xh[$parser]['ac']=''; // reset the accumulator + if ($_xh[$parser]['vt']!='value') + { + //two data elements inside a value: an error occurred! + $_xh[$parser]['isf'] = 2; + $_xh[$parser]['isf_reason'] = "$name element following a {$_xh[$parser]['vt']} element inside a single value"; + return; + } - if ($name=='DATETIME.ISO8601' || $name=='STRING') + // reset the accumulator + $_xh[$parser]['ac']=''; + + /*if ($name=='DATETIME.ISO8601' || $name=='STRING') { $_xh[$parser]['qt']=1; if ($name=='DATETIME.ISO8601') @@ -577,73 +642,120 @@ // at the end of the element we must check // for data format errors. $_xh[$parser]['qt']=0; - } + }*/ break; case 'MEMBER': - $_xh[$parser]['ac']=''; + //$_xh[$parser]['ac']=''; + // avoid warnings later on if no NAME is found before VALUE inside + // a struct member predefining member name as NULL + $_xh[$parser]['valuestack'][0]['name'] = ''; + // clear value, so we can check later if no value will passed for this param/member + $_xh[$parser]['value']=null; break; + case 'DATA': + case 'METHODCALL': + case 'METHODRESPONSE': + case 'PARAMS': + // valid elements that add little to processing + break; default: + /// INVALID ELEMENT: RAISE ISF so that it is later recognized!!! + $_xh[$parser]['isf'] = 2; + $_xh[$parser]['isf_reason'] = "found not-xmlrpc xml element $name"; break; } + // Save current element name to stack, to validate nesting + array_unshift($_xh[$parser]['stack'], $name); + if ($name!='VALUE') { $_xh[$parser]['lv']=0; } + } } function xmlrpc_ee($parser, $name) { - global $_xh,$xmlrpcTypes,$xmlrpcString; + global $_xh,$xmlrpcTypes,$xmlrpcString,$xmlrpcDateTime; + + if ($_xh[$parser]['isf'] < 2) + { + + // push this element name from stack + // NB: if XML validates, correct opening/closing is guaranteed and + // we do not have to check for $name == $curr_elem. + // we also checked for proper nesting at start of elements... + $curr_elem = array_shift($_xh[$parser]['stack']); switch($name) { case 'STRUCT': case 'ARRAY': - if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',') - { - $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1); - } - $_xh[$parser]['st'].=')'; + //if ($_xh[$parser]['cm'] && substr($_xh[$parser]['st'], -1) ==',') + //{ + // $_xh[$parser]['st']=substr($_xh[$parser]['st'],0,-1); + //} + //$_xh[$parser]['st'].=')'; + + // fetch out of stack array of values, and promote it to current value + $cur_val = array_shift($_xh[$parser]['valuestack']); + $_xh[$parser]['value'] = $cur_val['values']; + $_xh[$parser]['vt']=strtolower($name); - $_xh[$parser]['cm']--; + //$_xh[$parser]['cm']--; break; case 'NAME': - $_xh[$parser]['st'].= $_xh[$parser]['ac'] . '" => '; + //$_xh[$parser]['st'].= $_xh[$parser]['ac'] . '" => '; + $_xh[$parser]['valuestack'][0]['name'] = $_xh[$parser]['ac']; break; case 'BOOLEAN': - // special case here: we translate boolean 1 or 0 into PHP - // constants true or false - // NB: this simple checks helps a lot sanitizing input, ie no - // security problems around here - if ($_xh[$parser]['ac']=='1') - { - $_xh[$parser]['ac']='true'; - } - else - { - $_xh[$parser]['ac']='false'; - } - $_xh[$parser]['vt']=strtolower($name); - // Drop through intentionally. case 'I4': case 'INT': case 'STRING': case 'DOUBLE': case 'DATETIME.ISO8601': case 'BASE64': - if ($_xh[$parser]['qt']==1) + $_xh[$parser]['vt']=strtolower($name); + //if ($_xh[$parser]['qt']==1) + if ($name=='STRING') { // we use double quotes rather than single so backslashification works OK - $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; + //$_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; + $_xh[$parser]['value']=$_xh[$parser]['ac']; + } + elseif ($name=='DATETIME.ISO8601') + { + $_xh[$parser]['vt']=$xmlrpcDateTime; + $_xh[$parser]['value']=$_xh[$parser]['ac']; } - elseif ($_xh[$parser]['qt']==2) + elseif ($name=='BASE64') { - $_xh[$parser]['st'].='base64_decode("'. $_xh[$parser]['ac'] . '")'; + //$_xh[$parser]['st'].='base64_decode("'. $_xh[$parser]['ac'] . '")'; + + ///@todo check for failure of base64 decoding / catch warnings + $_xh[$parser]['value']=base64_decode($_xh[$parser]['ac']); } elseif ($name=='BOOLEAN') { - $_xh[$parser]['st'].=$_xh[$parser]['ac']; + // special case here: we translate boolean 1 or 0 into PHP + // constants true or false + // NB: this simple checks helps a lot sanitizing input, ie no + // security problems around here + if ($_xh[$parser]['ac']=='1') + { + //$_xh[$parser]['ac']='true'; + $_xh[$parser]['value']=true; + } + else + { + //$_xh[$parser]['ac']='false'; + // log if receiveing something strange, even though we set the value to false anyway + if ($_xh[$parser]['ac']!='0') + error_log('XML-RPC: invalid value received in BOOLEAN: '.$_xh[$parser]['ac']); + $_xh[$parser]['value']=false; + } + //$_xh[$parser]['st'].=$_xh[$parser]['ac']; } elseif ($name=='DOUBLE') { @@ -654,12 +766,14 @@ // TODO: find a better way of throwing an error // than this! error_log('XML-RPC: non numeric value received in DOUBLE: '.$_xh[$parser]['ac']); - $_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; + //$_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; + $_xh[$parser]['value']='ERROR_NON_NUMERIC_FOUND'; } else { // it's ok, add it on - $_xh[$parser]['st'].=(double)$_xh[$parser]['ac']; + //$_xh[$parser]['st'].=(double)$_xh[$parser]['ac']; + $_xh[$parser]['value']=(double)$_xh[$parser]['ac']; } } else @@ -671,21 +785,28 @@ // TODO: find a better way of throwing an error // than this! error_log('XML-RPC: non numeric value received in INT: '.$_xh[$parser]['ac']); - $_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; + //$_xh[$parser]['st'].="'ERROR_NON_NUMERIC_FOUND'"; + $_xh[$parser]['value']='ERROR_NON_NUMERIC_FOUND'; } else { // it's ok, add it on - $_xh[$parser]['st'].=(int)$_xh[$parser]['ac']; + //$_xh[$parser]['st'].=(int)$_xh[$parser]['ac']; + $_xh[$parser]['value']=(int)$_xh[$parser]['ac']; } } $_xh[$parser]['ac']=''; - $_xh[$parser]['qt']=0; + //$_xh[$parser]['qt']=0; $_xh[$parser]['lv']=3; // indicate we've found a value break; case 'VALUE': - // deal with a string value - if (strlen($_xh[$parser]['ac'])>0 && + // This if() detects if no scalar was inside <VALUE></VALUE> + if ($_xh[$parser]['vt']=='value') + { + $_xh[$parser]['value']=$_xh[$parser]['ac']; + $_xh[$parser]['vt']=$xmlrpcString; + } + /*if (strlen($_xh[$parser]['ac'])>0 && $_xh[$parser]['vt']==$xmlrpcString) { $_xh[$parser]['st'].='"'. $_xh[$parser]['ac'] . '"'; @@ -704,44 +825,62 @@ if ($_xh[$parser]['cm']) { $_xh[$parser]['st'].=','; - } + }*/ + + // build the xmlrpc val out of the data received, and substitute it + $temp = new xmlrpcval($_xh[$parser]['value'], $_xh[$parser]['vt']); + // check if we are inside an array or struct: + // if value just built is inside an array, let's move it into array on the stack + if (count($_xh[$parser]['valuestack']) && $_xh[$parser]['valuestack'][0]['type']=='ARRAY') + { + $_xh[$parser]['valuestack'][0]['values'][] = $temp; + } else { + $_xh[$parser]['value'] = $temp; + } break; case 'MEMBER': $_xh[$parser]['ac']=''; - $_xh[$parser]['qt']=0; + //$_xh[$parser]['qt']=0; + // add to array in the stack the last element built + // unless no VALUE was found + if ($_xh[$parser]['value']) + $_xh[$parser]['valuestack'][0]['values'][$_xh[$parser]['valuestack'][0]['name']] = $_xh[$parser]['value']; + else + error_log('XML-RPC: missing VALUE inside STRUCT in received xml'); break; case 'DATA': $_xh[$parser]['ac']=''; - $_xh[$parser]['qt']=0; + //$_xh[$parser]['qt']=0; break; case 'PARAM': - $_xh[$parser]['params'][]=$_xh[$parser]['st']; + //$_xh[$parser]['params'][]=$_xh[$parser]['st']; + if ($_xh[$parser]['value']) + $_xh[$parser]['params'][]=$_xh[$parser]['value']; + else + error_log('XML-RPC: missing VALUE inside PARAM in received xml'); break; case 'METHODNAME': $_xh[$parser]['method']=ereg_replace("^[\n\r\t ]+", '', $_xh[$parser]['ac']); break; - // BOOLEAN HAS BEEN ENUMERATED ABOVE! - /*case 'BOOLEAN': - // special case here: we translate boolean 1 or 0 into PHP - // constants true or false - if ($_xh[$parser]['ac']=='1') - { - $_xh[$parser]['ac']='true'; - } - else - { - $_xh[$parser]['ac']='false'; - $_xh[$parser]['vt']=strtolower($name); - } - break;*/ + case 'PARAMS': + case 'FAULT': + case 'METHODCALL': + case 'METHORESPONSE': + break; default: + // End of INVALID ELEMENT! + // shall we add an assert here for unreachable code??? break; } + // if it's a valid type name, set the type - if (isset($xmlrpcTypes[strtolower($name)])) + /*if (isset($xmlrpcTypes[strtolower($name)])) { $_xh[$parser]['vt']=strtolower($name); + }*/ + } + } function xmlrpc_cd($parser, $data) @@ -751,37 +890,48 @@ //if (ereg("^[\n\r \t]+$", $data)) return; // print "adding [${data}]\n"; - if ($_xh[$parser]['lv']!=3) + // skip processing if xml fault already detected + if ($_xh[$parser]['isf'] < 2) { - // "lookforvalue==3" means that we've found an entire value - // and should discard any further character data - if ($_xh[$parser]['lv']==1) + if ($_xh[$parser]['lv']!=3) { - // if we've found text and we're just in a <value> then - // turn quoting on, as this will be a string - $_xh[$parser]['qt']=1; - // and say we've found a value - $_xh[$parser]['lv']=2; - } - if(!@isset($_xh[$parser]['ac'])) - { - $_xh[$parser]['ac'] = ''; + // "lookforvalue==3" means that we've found an entire value + // and should discard any further character data + if ($_xh[$parser]['lv']==1) + { + // if we've found text and we're just in a <value> then + // turn quoting on, as this will be a string + //$_xh[$parser]['qt']=1; + // and say we've found a value + $_xh[$parser]['lv']=2; + } + if(!@isset($_xh[$parser]['ac'])) + { + $_xh[$parser]['ac'] = ''; + } + //$_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); + $_xh[$parser]['ac'].=$data; } - $_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); } } function xmlrpc_dh($parser, $data) { global $_xh, $xmlrpc_backslash; - if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') + + // skip processing if xml fault already detected + if ($parser[$_xh]['isf'] < 2) { - if ($_xh[$parser]['lv']==1) + if (substr($data, 0, 1) == '&' && substr($data, -1, 1) == ';') { - $_xh[$parser]['qt']=1; - $_xh[$parser]['lv']=2; + if ($_xh[$parser]['lv']==1) + { + //$_xh[$parser]['qt']=1; + $_xh[$parser]['lv']=2; + } + //$_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); + $_xh[$parser]['ac'].=$data; } - $_xh[$parser]['ac'].=str_replace('$', '\$', str_replace('"', '\"', str_replace(chr(92),$xmlrpc_backslash, $data))); } } @@ -1327,6 +1477,8 @@ $_xh=array(); $_xh[$parser]=array(); $_xh[$parser]['headers'] = array(); + $_xh[$parser]['stack'] = array(); + $_xh[$parser]['valuestack'] = array(); // separate HTTP headers from data if (ereg("^HTTP", $data)) @@ -1401,11 +1553,12 @@ if ($bd) $data = substr($data, 0, $bd); - $_xh[$parser]['st']=''; - $_xh[$parser]['cm']=0; + //$_xh[$parser]['st']=''; + //$_xh[$parser]['cm']=0; $_xh[$parser]['isf']=0; + $_xh[$parser]['isf_reason']=0; $_xh[$parser]['ac']=''; - $_xh[$parser]['qt']=''; + //$_xh[$parser]['qt']=''; xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); // G. Giunta 2005/02/13: PHP internally uses ISO-8859-1, so we have to tell @@ -1439,13 +1592,19 @@ return $r; } xml_parser_free($parser); - if ($this->debug) + + if ($_xh[$parser]['isf'] > 1) { - print "<PRE>---EVALING---[" . - strlen($_xh[$parser]['st']) . " chars]---\n" . - htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>"; + if ($this->debug) + { + ///@todo echo something for user? + } + + $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], + $xmlrpcstr['invalid_return'] . ' ' . $_xh[$parser]['isf_reason']); } - if (strlen($_xh[$parser]['st'])==0) + //else if (strlen($_xh[$parser]['st'])==0) + else if (!is_object($_xh[$parser]['value'])) { // then something odd has happened // and it's time to generate a client side error @@ -1455,13 +1614,25 @@ } else { - $allOK=0; - @eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;'); - if (!$allOK) + + if ($this->debug) { - $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']); + //print "<PRE>---EVALING---[" . + //strlen($_xh[$parser]['st']) . " chars]---\n" . + //htmlspecialchars($_xh[$parser]['st']) . ";\n---END---</PRE>"; + print "<PRE>---PARSED---\n" ; + var_dump($_xh[$parser]['value']); + print "\n---END---</PRE>"; } - else + + //$allOK=0; + //@eval('$v=' . $_xh[$parser]['st'] . '; $allOK=1;'); + //if (!$allOK) + //{ + // $r = new xmlrpcresp(0, $xmlrpcerr['invalid_return'], $xmlrpcstr['invalid_return']); + //} + //else + $v = $_xh[$parser]['value']; if ($_xh[$parser]['isf']) { $errno_v = $v->structmem('faultCode'); @@ -1742,7 +1913,8 @@ @reset($t); while(list($id,$cont) = @each($t)) { - eval('$b->'.$id.' = $cont;'); + //eval('$b->'.$id.' = $cont;'); + @$b->$id = $cont; } } // end contrib diff --git a/modules/xmlrpc/xmlrpcs.inc b/modules/xmlrpc/xmlrpcs.inc index c361fe39..080fcd3e 100755 --- a/modules/xmlrpc/xmlrpcs.inc +++ b/modules/xmlrpc/xmlrpcs.inc @@ -374,10 +374,13 @@ $parser = xml_parser_create($xmlrpc_defencoding); $_xh[$parser]=array(); - $_xh[$parser]['st']=''; - $_xh[$parser]['cm']=0; + //$_xh[$parser]['st']=''; + //$_xh[$parser]['cm']=0; $_xh[$parser]['isf']=0; + $_xh[$parser]['isf_reason']=''; $_xh[$parser]['params']=array(); + $_xh[$parser]['stack']=array(); + $_xh[$parser]['valuestack'] = array(); $_xh[$parser]['method']=''; // decompose incoming XML into request structure @@ -401,35 +404,45 @@ xml_parser_free($parser); } else + if ($_xh[$parser]['isf']) { xml_parser_free($parser); + $r=new xmlrpcresp(0, + $xmlrpcerr['invalid_request'], + $xmlrpcstr['invalid_request'] . ' ' . $_xh[$parser]['isf_reason']); + } + else + { + xml_parser_free($parser); + $m=new xmlrpcmsg($_xh[$parser]['method']); // now add parameters in $plist=''; - $allOK = 1; + //$allOK = 1; for($i=0; $i<sizeof($_xh[$parser]['params']); $i++) { //print "<!-- " . $_xh[$parser]['params'][$i]. "-->\n"; $plist.="$i - " . $_xh[$parser]['params'][$i]. ";\n"; - $allOK = 0; - @eval('$m->addParam(' . $_xh[$parser]['params'][$i]. '); $allOK=1;'); - if (!$allOK) - { - break; - } + //$allOK = 0; + //@eval('$m->addParam(' . $_xh[$parser]['params'][$i]. '); $allOK=1;'); + @$m->addParam($_xh[$parser]['params'][$i]); + //if (!$allOK) + //{ + // break; + //} } // uncomment this to really see what the server's getting! // xmlrpc_debugmsg($plist); - if (!$allOK) - { - $r = new xmlrpcresp(0, - $xmlrpcerr['incorrect_params'], - $xmlrpcstr['incorrect_params'] . ": xml error in param " . $i); - } - else - { + //if (!$allOK) + //{ + // $r = new xmlrpcresp(0, + // $xmlrpcerr['incorrect_params'], + // $xmlrpcstr['incorrect_params'] . ": xml error in param " . $i); + //} + //else + //{ $r = $this->execute($m); - } + //} } return $r; } @@ -33,6 +33,7 @@ show_clear(); if ($user->prefs['play_type'] == 'mpd') { show_mpd_control(); + show_mpd_pl(); } show_clear(); diff --git a/templates/header.inc b/templates/header.inc index 31708101..996a17f9 100644 --- a/templates/header.inc +++ b/templates/header.inc @@ -84,6 +84,12 @@ function flipField(element) { } } + function invert_songs() { + for( i = 0; i < document.forms.songs.elements["song[]"].length; ++i ) { + document.forms.songs.elements["song[]"][i].checked = !document.forms.songs.elements["song[]"][i].checked + } + } + var checkflag_results = "false"; function check_results() { diff --git a/templates/show_mpd_pl_box.inc.php b/templates/show_mpd_pl_box.inc.php new file mode 100644 index 00000000..429a2866 --- /dev/null +++ b/templates/show_mpd_pl_box.inc.php @@ -0,0 +1,29 @@ +<?php +/* + + Copyright (c) 2001 - 2005 Ampache.org + All rights reserved. + + This program is free software; you can redistribute it 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 more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +?> +<table border="0" cellpadding="0" cellspacing="1" class="text-box"> +<tr align="center"> + <td > + <?php show_playlist_dropdown($GLOBALS['playlist_id']); ?> + </td> +</tr> +</table> diff --git a/templates/show_mpdpl.inc b/templates/show_mpdpl.inc index 8d8bc222..777053d3 100644 --- a/templates/show_mpdpl.inc +++ b/templates/show_mpdpl.inc @@ -34,128 +34,170 @@ TTD: $nopad = "style='padding: 0px 0px 0px 0px'"; $minpad = "style='padding: 0px 2px 0px 2px'"; +$myMpd = init_mpd(); ?> -<td colspan="2" valign="top"> - -<form action="<?php echo conf('web_path')."/amp-mpd.php"; ?>" method="post" enctype="multipart/form-data"> +<td colspan="2" valign="top"> +<form name="songs" action="<?php echo conf('web_path')."/amp-mpd.php"; ?>" method="post" enctype="multipart/form-data"> <table border="0" cellpadding="0" cellspacing="1" width="100%" class="tabledata"> -<tr><td align="center" class="table-header"><b>MPD Server Playlist</b><br /> - <i>[<a title="<?php echo _("Refresh the Playlist Window"); ?>" href="<?php echo conf('web_path'); ?>">refresh</a>] -<?php if ( $myMpd->playlist_count > 0 ) { - $un = (conf('condPL')) ? "un" : ""; ?> - [<a title="<?php echo _("Click to shuffle (randomize) the playlist");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=shuffle"><?php echo _("shuffle")?></a>] - [<a title="<?php echo _("Click to the clear the playlist");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=clear">clear</a>] - [<a title="<?php echo 'Click to '.$un.'condense playlist';?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=condPL"><?php echo $un?>condense</a>] - [<a title="<?php echo _("Click to the remove all except the Now Playing");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=crop">crop</a>] -<?php } ?> </i></td></tr> -<tr><td <?php echo $nopad ?>> -<table cellspacing="0" cellpadding="0" border="0" width="100%"><tr class="table-header"> - <th <?php echo $minpad ?>><a href="#" onclick="check_songs(); return false;">Flip</a></th> - <th align="left"><?php echo _("Song title"); ?></th> - <th align="left"><?php echo _("Artist"); ?></th> - <th align="left"><?php echo _("Album"); ?></th> - <th align="right" <?php echo $minpad ?>><?php echo _("Track"); ?></th> - <th align="right" <?php echo $minpad ?>><?php echo _("Time"); ?></th> - <th <?php echo $minpad ?>><?php echo _("Genre"); ?></th> - <th><?php echo _("Action"); ?></th> - </tr> - <?php - $pl = $myMpd->playlist; - if (is_null($pl)) echo "ERROR: ".$myMpd->errStr."\n"; - else { - $maxlen = strlen (count($pl)); - $condPL = conf('condPL'); - if ($condPL) - { - echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>"; - } - else - { - echo "<tr><td> </td></tr>"; - } - foreach ($pl as $id=>$entry) { - - if ( ($condPL) and (($id < $myMpd->current_track_id-1) or ($id > $myMpd->current_track_id + 10)) ) - { continue; } - - unset($text_class); - - $track = $id+1; - $len=strlen($track); - while ($len < $maxlen) - { - $track = "0".$track; - $len++; - } - - // Still needed crap - $totalsize += $song->size; - $totaltime += $entry['Time']; - ?> - - <tr class="<?php echo flip_class(); ?>"> - <?php if ($id==$myMpd->current_track_id) - {$tdstyle = "style='padding: 0px 2px 0px 2px; font-weight: bold'";} - else {$tdstyle = $minpad;} ?> -<?php -$mpddir = conf('mpd_dir')."/"; -if ($entry['Title']) { - $sql = "SELECT genre.name, song.genre, song.id, song.album, song.artist FROM song, genre WHERE file = \"".$mpddir.$entry['file']."\" AND song.genre=genre.id"; - $db_results = @mysql_query($sql,dbh()); - $r = @mysql_fetch_object ($db_results); -} else { - list($tmp, $id, $tmp) = preg_split("/(song=|&)/", $entry['file']); - $r = new Song($id); - $entry['Title'] = $r->title; - $entry['Artist'] = $r->get_artist_name(); - $entry['Album'] = $r->get_album_name(); -} -$count=0; // Didn't move this because I wasn't sure what it was for... -?> - <td align="center" <?php echo $minpad ?>> <input type="checkbox" name="song[<?php echo $entry['Pos']?>]" value="1" id="song_<?php echo $entry['Pos']; ?>"></input></td> - <td align="left" <?php echo $tdstyle ?>> <?php echo $track.". ";?><a href="<?php echo $web_path; ?>/amp-mpd.php?action=skipto&val=<?php echo $entry['Pos']; ?>" title=" <?php echo htmlspecialchars($entry['Title']); ?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Title']); ?> </a></td> - <td align="left" <?php echo $tdstyle ?>> <a href="<?php echo $web_path; ?>/artists.php?action=show&artist=<?php echo htmlspecialchars($r->artist); ?>" title="More from <?php echo htmlspecialchars($entry['Artist']);?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Artist']);?> </a></td> - <td align="left" <?php echo $tdstyle ?>> <a href="<?php echo $web_path; ?>/albums.php?action=show&album=<?php echo htmlspecialchars($r->album); ?>" title="More on <?php echo htmlspecialchars($entry['Album']); ?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Album']); ?> </a></td> - <td align="right" <?php echo $tdstyle ?>> <?php echo $entry['Track']; ?></td> - <td align="right" <?php echo $tdstyle ?>> <?php echo sprintf ("%d:%02d",$entry['Time']/60,$entry['Time']%60) ?></td> - <td align="center" <?php echo $tdstyle ?>> <?php echo $r->name ?></td> - - <td <?php echo $tdstyle ?>> +<tr> + <td align="center" class="table-header"> + <b><?php echo _("MPD Server Playlist"); ?></b><br /> + <i>[<a title="<?php echo _("Refresh the Playlist Window"); ?>" href="<?php echo $_SERVER['PHP_SELF']; ?>">refresh</a>] + <?php if ( $myMpd->playlist_count > 0 ) { $un = (conf('condPL')) ? "un" : ""; ?> + [<a title="<?php echo _("Click to shuffle (randomize) the playlist");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=shuffle"><?php echo _("shuffle")?></a>] + [<a title="<?php echo _("Click to the clear the playlist");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=clear">clear</a>] + <?php if( $myMpd->playlist_count > 10 ) { ?> + [<a title="<?php echo 'Click to '.$un.'condense playlist';?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=condPL"><?php echo $un?>condense</a>] + <?php } ?> + [<a title="<?php echo _("Click to the remove all except the Now Playing");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=crop">crop</a>] + <?php } ?> </i> + </td> +</tr> +<tr> + <td <?php echo $nopad ?>> + <table cellspacing="0" cellpadding="0" border="0" width="100%"> + <tr class="table-header"> + <th <?php echo $minpad ?>><a href="#" onclick="check_songs(); return false;">Select</a> - <a href="#" onclick="invert_songs(); return false;">Invert</a></th> + <th align="left"><?php echo _("Song title"); ?></th> + <th align="left"><?php echo _("Artist"); ?></th> + <th align="left"><?php echo _("Album"); ?></th> + <th align="right" <?php echo $minpad ?>><?php echo _("Track"); ?></th> + <th align="right" <?php echo $minpad ?>><?php echo _("Time"); ?></th> + <th <?php echo $minpad ?>><?php echo _("Genre"); ?></th> + <th><?php echo _("Action"); ?></th> + </tr> + <?php + $pl = $myMpd->playlist; + if (is_null($pl)) echo "ERROR: ".$myMpd->errStr."\n"; + else { + $maxlen = strlen (count($pl)); + $condPL = conf('condPL'); + if ($condPL) { + echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>"; + } + else { + echo "<tr><td> </td></tr>"; + } + + foreach ($pl as $id=>$entry) { + + if ( ($condPL) and (($id < $myMpd->current_track_id-1) or ($id > $myMpd->current_track_id + 10)) ) { + continue; + } + + unset($text_class); + + $track = $id+1; + $len=strlen($track); + while ($len < $maxlen) { + $track = "0".$track; + $len++; + } + + ?> +<tr class="<?php echo flip_class(); ?>"> + <?php + if ($id==$myMpd->current_track_id) { + $tdstyle = "style='padding: 0px 2px 0px 2px; font-weight: bold;' class='error'"; + $linkstyle = "class='error'"; + } + else { + $tdstyle = $minpad; + $linkstyle = ""; + } + ?> + <?php + $mpddir = conf('mpd_dir')."/"; + if (strtolower(conf('mpd_method')) == 'file') { + $sql = "SELECT genre.name, song.genre, song.id, song.album, song.artist FROM song, genre WHERE file = \"".$mpddir.$entry['file']."\" AND song.genre=genre.id"; + $db_results = @mysql_query($sql,dbh()); + $r = @mysql_fetch_object ($db_results); + $entry['genre'] = $r->name; + } + else { + list($tmp, $id, $tmp) = preg_split("/(song=|&)/", $entry['file']); + $r = new Song($id); + $entry['Title'] = $r->title; + $entry['Artist'] = $r->get_artist_name(); + $entry['Album'] = $r->get_album_name(); + $entry['genre'] = $r->get_genre_name(); + $entry['Time'] = $r->time; + $entry['Track'] = $r->track; + } + + $totaltime += $entry['Time']; + $count=0; // Didn't move this because I wasn't sure what it was for... + ?> + <td align="center" <?php echo $minpad ?>> <input type="checkbox" name="song[]" value="<?php echo $entry['Pos']?>" id="song_<?php echo $entry['Pos']; ?>"></input></td> + <td align="left" <?php echo $tdstyle ?>> <?php echo $track.". ";?><a <?php echo $linkstyle ?> href="<?php echo $web_path; ?>/amp-mpd.php?action=skipto&val=<?php echo $entry['Pos']; ?>" title=" <?php echo htmlspecialchars($entry['Title']); ?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Title']); ?> </a></td> + <td align="left" <?php echo $tdstyle ?>> <a <?php echo $linkstyle ?> href="<?php echo $web_path; ?>/artists.php?action=show&artist=<?php echo htmlspecialchars($r->artist); ?>" title="More from <?php echo htmlspecialchars($entry['Artist']);?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Artist']);?> </a></td> + <td align="left" <?php echo $tdstyle ?>> <a <?php echo $linkstyle ?> href="<?php echo $web_path; ?>/albums.php?action=show&album=<?php echo htmlspecialchars($r->album); ?>" title="More on <?php echo htmlspecialchars($entry['Album']); ?>"<?php echo $text_class; ?>><?php echo htmlspecialchars($entry['Album']); ?> </a></td> + <td align="right" <?php echo $tdstyle ?>> <?php echo $entry['Track']; ?></td> + <td align="right" <?php echo $tdstyle ?>> <?php echo sprintf ("%d:%02d",$entry['Time']/60,$entry['Time']%60) ?> </td> + <td align="left" <?php echo $tdstyle ?>> <?php echo $entry['genre'] ?></td> + + <td <?php echo $tdstyle ?>> <a href="<?php echo $web_path;?>/flag.php?song=<?php echo $r->id;?>&action=flag" title="Flag '<?php echo htmlspecialchars($entry['file']);?>' by <?php echo htmlspecialchars($entry['Artist']);?>"<?php echo $text_class;?>>f</a> <a href="<?php echo $web_path;?>/amp-mpd.php?action=movenext&val=<?php echo $entry['Pos'];?>" title="Move '<?php echo htmlspecialchars($entry['Title']);?>' to play next "<?php echo $text_class;?>>n</a> <a href="<?php echo $web_path;?>/amp-mpd.php?action=rem&id=<?php echo $entry['Pos'];?>" title="Remove '<?php echo htmlspecialchars($entry['Title']);?>' from playlist "<?php echo $text_class;?>>x</a> - </td> - </tr> + </td> +</tr> <?php - }// foreach loop - if (($condPL) && ($myMpd->current_track_id+10 <= $myMpd->playlistcount)) - { - echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>"; - } - } //else - - $time = floor($totaltime/60) . ":" . sprintf("%02d", ($totaltime%60) ); - $num = count($pl); + }// foreach loop + if (($condPL) && ($myMpd->current_track_id+10 <= $myMpd->playlistcount)) { + echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>"; + } + + } //else + + $time = floor($totaltime/60) . ":" . sprintf("%02d", ($totaltime%60) ); + $num = count($pl); + if ($condPL) { + echo "<tr class=\"".flip_class()."\"><td colspan=\"8\" align=\"center\" style=\"padding: 3px 0px 3px 0px\">... Condensed Playlist ...</td></tr>"; + } + else { + echo "<tr><td> </td></tr>"; + } ?> - <tr><td> </td></tr> - <tr class="table-header" valign="middle"> - <td><input type="hidden" name="action" value="plact" /> <button name="submit" value="submit" type="submit" style = "font-family: <?php echo conf('font')?>; font-size: <?php echo conf('font_size')?>px" title="Take Action on the checked songs">Do</button></td> - <td valign="middle"> - <select name="todo" style = "font-family: <?php echo conf('font')?>; font-size: <?php echo conf('font_size')?>px" size="1"> - <option>Delete</option> - <!-- <option>move Next This isn't working yet --> - <option>Crop</option> - </select> - </td> - <td valign="middle"><?php echo _("Total"); ?>:</td> - <td valign="middle"><?php echo $num; ?> song(s)</td> - <td></td> - <td valign="middle" align="right" <?php echo $minpad; ?> nowrap="nowrap"><?php echo $time; ?></td> - <td> </td> - <td> </td> - </tr> - </table></td></tr> +<tr class="table-header" valign="middle"> + <td> + <input type="hidden" name="action" value="plact" /> <button name="submit" value="submit" type="submit" style = "font-family: <?php echo conf('font')?>; font-size: <?php echo conf('font_size')?>px" title="Take Action on the checked songs">Do</button> + </td> + <td valign="middle"> + <select name="todo" style = "font-family: <?php echo conf('font')?>; font-size: <?php echo conf('font_size')?>px" size="1"> + <option>Add to Playlist</option> + <option>Delete</option> + <!-- <option>move Next This isn't working yet --> + </select> + </td> + <td valign="middle"><?php show_playlist_dropdown($GLOBALS['playlist_id']); ?></td> + <td valign="middle"><?php echo $num; ?> song(s)</td> + <td></td> + <td valign="middle" align="right" <?php echo $minpad; ?> nowrap="nowrap"><?php echo $time; ?></td> + <td> </td> + <td> </td> +</tr> +</table> +<tr> + <td align="center" valign="bottom" class="table-header"> + <i>[<a title="<?php echo _("Refresh the Playlist Window"); ?>" href="<?php echo $_SERVER['PHP_SELF']; ?>">refresh</a>] + <?php + if ( $myMpd->playlist_count > 0 ) { + $un = (conf('condPL')) ? "un" : ""; + ?> + [<a title="<?php echo _("Click to shuffle (randomize) the playlist");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=shuffle"><?php echo _("shuffle")?></a>] + [<a title="<?php echo _("Click to the clear the playlist");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=clear">clear</a>] + <?php if($myMpd->playlist_count > 10) { ?> + [<a title="<?php echo 'Click to '.$un.'condense playlist';?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=condPL"><?php echo $un?>condense</a>] + <?php } ?> + [<a title="<?php echo _("Click to the remove all except the Now Playing");?>" href="<?php echo conf('web_path'); ?>/amp-mpd.php?action=crop">crop</a>] + <?php } ?> + </i> + </td> +</tr> +</td> +</tr> </table> <br /> </form> diff --git a/templates/show_mpdplay.inc b/templates/show_mpdplay.inc index ca1a1f4f..c12f8f91 100644 --- a/templates/show_mpdplay.inc +++ b/templates/show_mpdplay.inc @@ -48,7 +48,7 @@ global $condPL; <input class="button" type="submit" title="<?php echo _("Prev"); ?>" name="action" value="|< " /> <input class="button" type="submit" title="<?php echo _("Stop"); ?>" name="action" value=" X " <?php echo $stop; ?> /> <input class="button" type="submit" title="<?php echo _("Play"); ?>" name="action" value=" > " <?php echo $play; ?> /> - <input class="button" type="submit" title="<?php echo _("Pause"); ?>" name="action" value=" = " <?php echo $pause; ?> /> + <input class="button" type="submit" title="<?php echo _("Pause"); ?>" name="action" value=" | | " <?php echo $pause; ?> /> <input class="button" type="submit" title="<?php echo _("Next"); ?>" name="action" value= " >|" /> </form> </td> |