3  *  mpd.class.php - PHP Object Interface to the MPD Music Player Daemon
\r 
   4  *  Version 1.2, Released 05/05/2004
\r 
   5  *  Copyright (C) 2003-2004  Benjamin Carlisle (bcarlisle@24oz.com)
\r 
   6  *  http://mpd.24oz.com/ | http://www.musicpd.org/
\r 
   8  *  This program is free software; you can redistribute it and/or modify
\r 
   9  *  it under the terms of the GNU General Public License as published by
\r 
  10  *  the Free Software Foundation; either version 2 of the License, or
\r 
  11  *  (at your option) any later version.
\r 
  13  *  This program is distributed in the hope that it will be useful,
\r 
  14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
\r 
  15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
\r 
  16  *  GNU General Public License for more details.
\r 
  18  *  You should have received a copy of the GNU General Public License
\r 
  19  *  along with this program; if not, write to the Free Software
\r 
  20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
\r 
  23 // Create common command definitions for MPD to use
\r 
  24 define("MPD_CMD_STATUS",      "status");
\r 
  25 define("MPD_CMD_STATISTICS",  "stats");
\r 
  26 define("MPD_CMD_VOLUME",      "volume");
\r 
  27 define("MPD_CMD_SETVOL",      "setvol");
\r 
  28 define("MPD_CMD_PLAY",        "play");
\r 
  29 define("MPD_CMD_STOP",        "stop");
\r 
  30 define("MPD_CMD_PAUSE",       "pause");
\r 
  31 define("MPD_CMD_NEXT",        "next");
\r 
  32 define("MPD_CMD_PREV",        "previous");
\r 
  33 define("MPD_CMD_PLLIST",      "playlistinfo");
\r 
  34 define("MPD_CMD_PLADD",       "add");
\r 
  35 define("MPD_CMD_PLREMOVE",    "delete");
\r 
  36 define("MPD_CMD_PLCLEAR",     "clear");
\r 
  37 define("MPD_CMD_PLSHUFFLE",   "shuffle");
\r 
  38 define("MPD_CMD_PLLOAD",      "load");
\r 
  39 define("MPD_CMD_PLSAVE",      "save");
\r 
  40 define("MPD_CMD_KILL",        "kill");
\r 
  41 define("MPD_CMD_REFRESH",     "update");
\r 
  42 define("MPD_CMD_REPEAT",      "repeat");
\r 
  43 define("MPD_CMD_LSDIR",       "lsinfo");
\r 
  44 define("MPD_CMD_SEARCH",      "search");
\r 
  45 define("MPD_CMD_START_BULK",  "command_list_begin");
\r 
  46 define("MPD_CMD_END_BULK",    "command_list_end");
\r 
  47 define("MPD_CMD_FIND",        "find");
\r 
  48 define("MPD_CMD_RANDOM",      "random");
\r 
  49 define("MPD_CMD_SEEK",        "seek");
\r 
  50 define("MPD_CMD_PLSWAPTRACK", "swap");
\r 
  51 define("MPD_CMD_PLMOVETRACK", "move");
\r 
  52 define("MPD_CMD_PASSWORD",    "password");
\r 
  53 define("MPD_CMD_TABLE",       "list");
\r 
  55 // Predefined MPD Response messages
\r 
  56 define("MPD_RESPONSE_ERR", "ACK");
\r 
  57 define("MPD_RESPONSE_OK",  "OK");
\r 
  59 // MPD State Constants
\r 
  60 define("MPD_STATE_PLAYING", "play");
\r 
  61 define("MPD_STATE_STOPPED", "stop");
\r 
  62 define("MPD_STATE_PAUSED",  "pause");
\r 
  64 // MPD Searching Constants
\r 
  65 define("MPD_SEARCH_ARTIST", "artist");
\r 
  66 define("MPD_SEARCH_TITLE",  "title");
\r 
  67 define("MPD_SEARCH_ALBUM",  "album");
\r 
  70 define("MPD_TBL_ARTIST","artist");
\r 
  71 define("MPD_TBL_ALBUM","album");
\r 
  74         // TCP/Connection variables
\r 
  79         var $mpd_sock   = NULL;
\r 
  80         var $connected  = FALSE;
\r 
  82         // MPD Status variables
\r 
  83         var $mpd_version    = "(unknown)";
\r 
  86         var $current_track_position;
\r 
  87         var $current_track_length;
\r 
  88         var $current_track_id;
\r 
  95         var $db_last_refreshed;
\r 
  96         var $num_songs_played;
\r 
  97         var $playlist_count;
\r 
 103         var $playlist           = array();
\r 
 105         // Misc Other Vars      
\r 
 106         var $mpd_class_version = "1.2";
\r 
 108         var $debugging   = FALSE;    // Set to TRUE to turn extended debugging on.
\r 
 109         var $errStr      = "";       // Used for maintaining information about the last error message
\r 
 111         var $command_queue;          // The list of commands for bulk command sending
\r 
 113     // =================== BEGIN OBJECT METHODS ================
\r 
 115         /* mpd() : Constructor
\r 
 117          * Builds the MPD object, connects to the server, and refreshes all local object properties.
\r 
 119         function mpd($srv,$port,$pwd = NULL) {
\r 
 120                 $this->host = $srv;
\r 
 121                 $this->port = $port;
\r 
 122         $this->password = $pwd;
\r 
 124                 $resp = $this->Connect();
\r 
 125                 if ( is_null($resp) ) {
\r 
 126             $this->errStr = "Could not connect";
\r 
 129                         list ( $this->mpd_version ) = sscanf($resp, MPD_RESPONSE_OK . " MPD %s\n");
\r 
 130             if ( ! is_null($pwd) ) {
\r 
 131                 if ( is_null($this->SendCommand(MPD_CMD_PASSWORD,$pwd)) ) {
\r 
 132                     $this->connected = FALSE;
\r 
 133                     return;  // bad password or command
\r 
 135                         if ( is_null($this->RefreshInfo()) ) { // no read access -- might as well be disconnected!
\r 
 136                     $this->connected = FALSE;
\r 
 137                     $this->errStr = "Password supplied does not have read access";
\r 
 141                         if ( is_null($this->RefreshInfo()) ) { // no read access -- might as well be disconnected!
\r 
 142                     $this->connected = FALSE;
\r 
 143                     $this->errStr = "Password required to access server";
\r 
 152          * Connects to the MPD server. 
\r 
 154          * NOTE: This is called automatically upon object instantiation; you should not need to call this directly.
\r 
 156         function Connect() {
\r 
 157                 if ( $this->debugging ) echo "mpd->Connect() / host: ".$this->host.", port: ".$this->port."\n";
\r 
 158                 $this->mpd_sock = fsockopen($this->host,$this->port,$errNo,$errStr,10);
\r 
 159                 if (!$this->mpd_sock) {
\r 
 160                         $this->errStr = "Socket Error: $errStr ($errNo)";
\r 
 163                         while(!feof($this->mpd_sock)) {
\r 
 164                                 $response =  fgets($this->mpd_sock,1024);
\r 
 165                                 if (strncmp(MPD_RESPONSE_OK,$response,strlen(MPD_RESPONSE_OK)) == 0) {
\r 
 166                                         $this->connected = TRUE;
\r 
 170                                 if (strncmp(MPD_RESPONSE_ERR,$response,strlen(MPD_RESPONSE_ERR)) == 0) {
\r 
 171                                         $this->errStr = "Server responded with: $response";
\r 
 175                         // Generic response
\r 
 176                         $this->errStr = "Connection not available";
\r 
 183          * Sends a generic command to the MPD server. Several command constants are pre-defined for 
\r 
 184          * use (see MPD_CMD_* constant definitions above). 
\r 
 186         function SendCommand($cmdStr,$arg1 = "",$arg2 = "") {
\r 
 187                 if ( $this->debugging ) echo "mpd->SendCommand() / cmd: ".$cmdStr.", args: ".$arg1." ".$arg2."\n";
\r 
 189                 if ( ! $this->connected ) {
\r 
 190                         echo "mpd->SendCommand() / Error: Not connected\n";
\r 
 192                         // Clear out the error String
\r 
 193                         $this->errStr = "";
\r 
 196                         // Check the command compatibility:
\r 
 197                         if ( ! $this->_checkCompatibility($cmdStr) ) {
\r 
 198                                 echo "Not compatible command!";
\r 
 202                         if (strlen($arg1) > 0) $cmdStr .= " \"$arg1\"";
\r 
 204                         if (strlen($arg2) > 0) $cmdStr .= " \"$arg2\"";
\r 
 205                         if ( $this->debugging ) echo "mpd-> ".$cmdStr."\n";
\r 
 206                         fputs($this->mpd_sock,"$cmdStr\n");
\r 
 207                         while(!feof($this->mpd_sock)) {
\r 
 208                                 $response = fgets($this->mpd_sock,1024);
\r 
 209                                 if ( $this->debugging ) echo "mpd.response-> ".$response."\n";
\r 
 211                                 // An OK signals the end of transmission -- we'll ignore it
\r 
 212                                 if (strncmp(MPD_RESPONSE_OK,$response,strlen(MPD_RESPONSE_OK)) == 0) {
\r 
 216                                 // An ERR signals the end of transmission with an error! Let's grab the single-line message.
\r 
 217                                 if (strncmp(MPD_RESPONSE_ERR,$response,strlen(MPD_RESPONSE_ERR)) == 0) {
\r 
 218                                         list ( $junk, $errTmp ) = explode(MPD_RESPONSE_ERR . " ",$response );
\r 
 219                                         $this->errStr = strtok($errTmp,"\n");
\r 
 222                                 if ( strlen($this->errStr) > 0 ) {
\r 
 226                                 // Build the response string
\r 
 227                                 $respStr .= $response;
\r 
 229                         if ( $this->debugging ) echo "mpd->SendCommand() / response: '".$respStr."'\n";
\r 
 236          * Queues a generic command for later sending to the MPD server. The CommandQueue can hold 
\r 
 237          * as many commands as needed, and are sent all at once, in the order they are queued, using 
\r 
 238          * the SendCommandQueue() method. The syntax for queueing commands is identical to SendCommand(). 
\r 
 240         function QueueCommand($cmdStr,$arg1 = "",$arg2 = "") {
\r 
 241                 if ( $this->debugging ) echo "mpd->QueueCommand() / cmd: ".$cmdStr.", args: ".$arg1." ".$arg2."\n";
\r 
 242                 if ( ! $this->connected ) {
\r 
 243                         echo "mpd->QueueCommand() / Error: Not connected\n";
\r 
 246                         if ( strlen($this->command_queue) == 0 ) {
\r 
 247                                 $this->command_queue = MPD_CMD_START_BULK . "\n";
\r 
 249                         if (strlen($arg1) > 0) $cmdStr .= " \"$arg1\"";
\r 
 250                         if (strlen($arg2) > 0) $cmdStr .= " \"$arg2\"";
\r 
 252                         $this->command_queue .= $cmdStr ."\n";
\r 
 254                         if ( $this->debugging ) echo "mpd->QueueCommand() / return\n";
\r 
 259         /* SendCommandQueue() 
\r 
 261          * Sends all commands in the Command Queue to the MPD server. See also QueueCommand().
\r 
 263         function SendCommandQueue() {
\r 
 264                 if ( $this->debugging ) echo "mpd->SendCommandQueue()\n";
\r 
 265                 if ( ! $this->connected ) {
\r 
 266                         echo "mpd->SendCommandQueue() / Error: Not connected\n";
\r 
 269                         $this->command_queue .= MPD_CMD_END_BULK . "\n";
\r 
 270                         if ( is_null($respStr = $this->SendCommand($this->command_queue)) ) {
\r 
 273                                 $this->command_queue = NULL;
\r 
 274                                 if ( $this->debugging ) echo "mpd->SendCommandQueue() / response: '".$respStr."'\n";
\r 
 282          * Adjusts the mixer volume on the MPD by <modifier>, which can be a positive (volume increase),
\r 
 283          * or negative (volume decrease) value. 
\r 
 285         function AdjustVolume($modifier) {
\r 
 286                 if ( $this->debugging ) echo "mpd->AdjustVolume()\n";
\r 
 287                 if ( ! is_numeric($modifier) ) {
\r 
 288                         $this->errStr = "AdjustVolume() : argument 1 must be a numeric value";
\r 
 292         $this->RefreshInfo();
\r 
 293         $newVol = $this->volume + $modifier;
\r 
 294         $ret = $this->SetVolume($newVol);
\r 
 296                 if ( $this->debugging ) echo "mpd->AdjustVolume() / return\n";
\r 
 302          * Sets the mixer volume to <newVol>, which should be between 1 - 100.
\r 
 304         function SetVolume($newVol) {
\r 
 305                 if ( $this->debugging ) echo "mpd->SetVolume()\n";
\r 
 306                 if ( ! is_numeric($newVol) ) {
\r 
 307                         $this->errStr = "SetVolume() : argument 1 must be a numeric value";
\r 
 311         // Forcibly prevent out of range errors
\r 
 312                 if ( $newVol < 0 )   $newVol = 0;
\r 
 313                 if ( $newVol > 100 ) $newVol = 100;
\r 
 315         // If we're not compatible with SETVOL, we'll try adjusting using VOLUME
\r 
 316         if ( $this->_checkCompatibility(MPD_CMD_SETVOL) ) {
\r 
 317             if ( ! is_null($ret = $this->SendCommand(MPD_CMD_SETVOL,$newVol))) $this->volume = $newVol;
\r 
 319                 $this->RefreshInfo();     // Get the latest volume
\r 
 320                 if ( is_null($this->volume) ) {
\r 
 323                         $modifier = ( $newVol - $this->volume );
\r 
 324                 if ( ! is_null($ret = $this->SendCommand(MPD_CMD_VOLUME,$modifier))) $this->volume = $newVol;
\r 
 328                 if ( $this->debugging ) echo "mpd->SetVolume() / return\n";
\r 
 334      * Retrieves a database directory listing of the <dir> directory and places the results into
\r 
 335          * a multidimensional array. If no directory is specified, the directory listing is at the 
\r 
 336          * base of the MPD music path. 
\r 
 338         function GetDir($dir = "") {
\r 
 339                 if ( $this->debugging ) echo "mpd->GetDir()\n";
\r 
 340                 $resp = $this->SendCommand(MPD_CMD_LSDIR,$dir);
\r 
 341                 $dirlist = $this->_parseFileListResponse($resp);
\r 
 342                 if ( $this->debugging ) echo "mpd->GetDir() / return ".print_r($dirlist)."\n";
\r 
 348      * Adds each track listed in a single-dimensional <trackArray>, which contains filenames 
\r 
 349          * of tracks to add, to the end of the playlist. This is used to add many, many tracks to 
\r 
 350          * the playlist in one swoop.
\r 
 352         function PLAddBulk($trackArray) {
\r 
 353                 if ( $this->debugging ) echo "mpd->PLAddBulk()\n";
\r 
 354                 $num_files = count($trackArray);
\r 
 355                 for ( $i = 0; $i < $num_files; $i++ ) {
\r 
 356                         $this->QueueCommand(MPD_CMD_PLADD,$trackArray[$i]);
\r 
 358                 $resp = $this->SendCommandQueue();
\r 
 359                 $this->RefreshInfo();
\r 
 360                 if ( $this->debugging ) echo "mpd->PLAddBulk() / return\n";
\r 
 366          * Adds the file <file> to the end of the playlist. <file> must be a track in the MPD database. 
\r 
 368         function PLAdd($fileName) {
\r 
 369                 if ( $this->debugging ) echo "mpd->PLAdd()\n";
\r 
 370                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLADD,$fileName))) $this->RefreshInfo();
\r 
 371                 if ( $this->debugging ) echo "mpd->PLAdd() / return\n";
\r 
 377          * Moves track number <origPos> to position <newPos> in the playlist. This is used to reorder 
\r 
 378          * the songs in the playlist.
\r 
 380         function PLMoveTrack($origPos, $newPos) {
\r 
 381                 if ( $this->debugging ) echo "mpd->PLMoveTrack()\n";
\r 
 382                 if ( ! is_numeric($origPos) ) {
\r 
 383                         $this->errStr = "PLMoveTrack(): argument 1 must be numeric";
\r 
 386                 if ( $origPos < 0 or $origPos > $this->playlist_count ) {
\r 
 387                         $this->errStr = "PLMoveTrack(): argument 1 out of range";
\r 
 390                 if ( $newPos < 0 ) $newPos = 0;
\r 
 391                 if ( $newPos > $this->playlist_count ) $newPos = $this->playlist_count;
\r 
 393                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLMOVETRACK,$origPos,$newPos))) $this->RefreshInfo();
\r 
 394                 if ( $this->debugging ) echo "mpd->PLMoveTrack() / return\n";
\r 
 400          * Randomly reorders the songs in the playlist.
\r 
 402         function PLShuffle() {
\r 
 403                 if ( $this->debugging ) echo "mpd->PLShuffle()\n";
\r 
 404                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLSHUFFLE))) $this->RefreshInfo();
\r 
 405                 if ( $this->debugging ) echo "mpd->PLShuffle() / return\n";
\r 
 411          * Retrieves the playlist from <file>.m3u and loads it into the current playlist. 
\r 
 413         function PLLoad($file) {
\r 
 414                 if ( $this->debugging ) echo "mpd->PLLoad()\n";
\r 
 415                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLLOAD,$file))) $this->RefreshInfo();
\r 
 416                 if ( $this->debugging ) echo "mpd->PLLoad() / return\n";
\r 
 422          * Saves the playlist to <file>.m3u for later retrieval. The file is saved in the MPD playlist
\r 
 425         function PLSave($file) {
\r 
 426                 if ( $this->debugging ) echo "mpd->PLSave()\n";
\r 
 427                 $resp = $this->SendCommand(MPD_CMD_PLSAVE,$file);
\r 
 428                 if ( $this->debugging ) echo "mpd->PLSave() / return\n";
\r 
 434          * Empties the playlist.
\r 
 436         function PLClear() {
\r 
 437                 if ( $this->debugging ) echo "mpd->PLClear()\n";
\r 
 438                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLCLEAR))) $this->RefreshInfo();
\r 
 439                 if ( $this->debugging ) echo "mpd->PLClear() / return\n";
\r 
 446         * Move song from pos to the other
\r 
 448         function Move ($from,$to) {
\r 
 449                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLMOVETRACK,$from,$to))) $this->RefreshInfo();
\r 
 450                 //die(print_r($resp));
\r 
 457          * Removes track <id> from the playlist.
\r 
 459         function PLRemove($id) {
\r 
 460                 if ( $this->debugging ) echo "mpd->PLRemove()\n";
\r 
 461                 if ( ! is_numeric($id) ) {
\r 
 462                         $this->errStr = "PLRemove() : argument 1 must be a numeric value";
\r 
 465                 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLREMOVE,$id))) $this->RefreshInfo();
\r 
 466                 if ( $this->debugging ) echo "mpd->PLRemove() / return\n";
\r 
 472          * Enables 'loop' mode -- tells MPD continually loop the playlist. The <repVal> parameter 
\r 
 473          * is either 1 (on) or 0 (off).
\r 
 475         function SetRepeat($repVal) {
\r 
 476                 if ( $this->debugging ) echo "mpd->SetRepeat()\n";
\r 
 477                 $rpt = $this->SendCommand(MPD_CMD_REPEAT,$repVal);
\r 
 478                 $this->repeat = $repVal;
\r 
 479                 if ( $this->debugging ) echo "mpd->SetRepeat() / return\n";
\r 
 485          * Enables 'randomize' mode -- tells MPD to play songs in the playlist in random order. The
\r 
 486          * <rndVal> parameter is either 1 (on) or 0 (off).
\r 
 488         function SetRandom($rndVal) {
\r 
 489                 if ( $this->debugging ) echo "mpd->SetRandom()\n";
\r 
 490                 $resp = $this->SendCommand(MPD_CMD_RANDOM,$rndVal);
\r 
 491                 $this->random = $rndVal;
\r 
 492                 if ( $this->debugging ) echo "mpd->SetRandom() / return\n";
\r 
 498          * Shuts down the MPD server (aka sends the KILL command). This closes the current connection, 
\r 
 499          * and prevents future communication with the server. 
\r 
 501         function Shutdown() {
\r 
 502                 if ( $this->debugging ) echo "mpd->Shutdown()\n";
\r 
 503                 $resp = $this->SendCommand(MPD_CMD_SHUTDOWN);
\r 
 505                 $this->connected = FALSE;
\r 
 506                 unset($this->mpd_version);
\r 
 507                 unset($this->errStr);
\r 
 508                 unset($this->mpd_sock);
\r 
 510                 if ( $this->debugging ) echo "mpd->Shutdown() / return\n";
\r 
 516          * Tells MPD to rescan the music directory for new tracks, and to refresh the Database. Tracks 
\r 
 517          * cannot be played unless they are in the MPD database.
\r 
 519         function DBRefresh() {
\r 
 520                 if ( $this->debugging ) echo "mpd->DBRefresh()\n";
\r 
 521                 $resp = $this->SendCommand(MPD_CMD_REFRESH);
\r 
 523                 // Update local variables
\r 
 524                 $this->RefreshInfo();
\r 
 526                 if ( $this->debugging ) echo "mpd->DBRefresh() / return\n";
\r 
 532          * Begins playing the songs in the MPD playlist. 
\r 
 535                 if ( $this->debugging ) echo "mpd->Play()\n";
\r 
 536                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PLAY) )) $this->RefreshInfo();
\r 
 537                 if ( $this->debugging ) echo "mpd->Play() / return\n";
\r 
 543          * Stops playing the MPD. 
\r 
 546                 if ( $this->debugging ) echo "mpd->Stop()\n";
\r 
 547                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_STOP) )) $this->RefreshInfo();
\r 
 548                 if ( $this->debugging ) echo "mpd->Stop() / return\n";
\r 
 554          * Toggles pausing on the MPD. Calling it once will pause the player, calling it again
\r 
 558                 if ( $this->debugging ) echo "mpd->Pause()\n";
\r 
 559                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PAUSE) )) $this->RefreshInfo();
\r 
 560                 if ( $this->debugging ) echo "mpd->Pause() / return\n";
\r 
 566          * Skips directly to the <idx> song in the MPD playlist. 
\r 
 568         function SkipTo($idx) { 
\r 
 569                 if ( $this->debugging ) echo "mpd->SkipTo()\n";
\r 
 570                 if ( ! is_numeric($idx) ) {
\r 
 571                         $this->errStr = "SkipTo() : argument 1 must be a numeric value";
\r 
 574                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PLAY,$idx))) $this->RefreshInfo();
\r 
 575                 if ( $this->debugging ) echo "mpd->SkipTo() / return\n";
\r 
 581          * Skips directly to a given position within a track in the MPD playlist. The <pos> argument,
\r 
 582          * given in seconds, is the track position to locate. The <track> argument, if supplied is
\r 
 583          * the track number in the playlist. If <track> is not specified, the current track is assumed.
\r 
 585         function SeekTo($pos, $track = -1) { 
\r 
 586                 if ( $this->debugging ) echo "mpd->SeekTo()\n";
\r 
 587                 if ( ! is_numeric($pos) ) {
\r 
 588                         $this->errStr = "SeekTo() : argument 1 must be a numeric value";
\r 
 591                 if ( ! is_numeric($track) ) {
\r 
 592                         $this->errStr = "SeekTo() : argument 2 must be a numeric value";
\r 
 595                 if ( $track == -1 ) { 
\r 
 596                         $track = $this->current_track_id;
\r 
 599                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_SEEK,$track,$pos))) $this->RefreshInfo();
\r 
 600                 if ( $this->debugging ) echo "mpd->SeekTo() / return\n";
\r 
 606          * Skips to the next song in the MPD playlist. If not playing, returns an error. 
\r 
 609                 if ( $this->debugging ) echo "mpd->Next()\n";
\r 
 610                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_NEXT))) $this->RefreshInfo();
\r 
 611                 if ( $this->debugging ) echo "mpd->Next() / return\n";
\r 
 617          * Skips to the previous song in the MPD playlist. If not playing, returns an error. 
\r 
 619         function Previous() {
\r 
 620                 if ( $this->debugging ) echo "mpd->Previous()\n";
\r 
 621                 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PREV))) $this->RefreshInfo();
\r 
 622                 if ( $this->debugging ) echo "mpd->Previous() / return\n";
\r 
 628      * Searches the MPD database. The search <type> should be one of the following: 
\r 
 629      *        MPD_SEARCH_ARTIST, MPD_SEARCH_TITLE, MPD_SEARCH_ALBUM
\r 
 630      * The search <string> is a case-insensitive locator string. Anything that contains 
\r 
 631          * <string> will be returned in the results. 
\r 
 633         function Search($type,$string) {
\r 
 634                 if ( $this->debugging ) echo "mpd->Search()\n";
\r 
 635                 if ( $type != MPD_SEARCH_ARTIST and
\r 
 636                  $type != MPD_SEARCH_ALBUM and
\r 
 637                          $type != MPD_SEARCH_TITLE ) {
\r 
 638                         $this->errStr = "mpd->Search(): invalid search type";
\r 
 641                         if ( is_null($resp = $this->SendCommand(MPD_CMD_SEARCH,$type,$string))) return NULL;
\r 
 642                         $searchlist = $this->_parseFileListResponse($resp);
\r 
 644                 if ( $this->debugging ) echo "mpd->Search() / return ".print_r($searchlist)."\n";
\r 
 645                 return $searchlist;
\r 
 650          * Find() looks for exact matches in the MPD database. The find <type> should be one of 
\r 
 652      *         MPD_SEARCH_ARTIST, MPD_SEARCH_TITLE, MPD_SEARCH_ALBUM
\r 
 653      * The find <string> is a case-insensitive locator string. Anything that exactly matches 
\r 
 654          * <string> will be returned in the results. 
\r 
 656         function Find($type,$string) {
\r 
 657                 if ( $this->debugging ) echo "mpd->Find()\n";
\r 
 658                 if ( $type != MPD_SEARCH_ARTIST and
\r 
 659                  $type != MPD_SEARCH_ALBUM and
\r 
 660                          $type != MPD_SEARCH_TITLE ) {
\r 
 661                         $this->errStr = "mpd->Find(): invalid find type";
\r 
 664                         if ( is_null($resp = $this->SendCommand(MPD_CMD_FIND,$type,$string)))   return NULL;
\r 
 665                         $searchlist = $this->_parseFileListResponse($resp);
\r 
 667                 if ( $this->debugging ) echo "mpd->Find() / return ".print_r($searchlist)."\n";
\r 
 668                 return $searchlist;
\r 
 673          * Closes the connection to the MPD server.
\r 
 675         function Disconnect() {
\r 
 676                 if ( $this->debugging ) echo "mpd->Disconnect()\n";
\r 
 677                 fclose($this->mpd_sock);
\r 
 679                 $this->connected = FALSE;
\r 
 680                 unset($this->mpd_version);
\r 
 681                 unset($this->errStr);
\r 
 682                 unset($this->mpd_sock);
\r 
 687          * Returns the list of artists in the database in an associative array.
\r 
 689         function GetArtists() {
\r 
 690                 if ( $this->debugging ) echo "mpd->GetArtists()\n";
\r 
 691                 if ( is_null($resp = $this->SendCommand(MPD_CMD_TABLE, MPD_TBL_ARTIST)))        return NULL;
\r 
 692         $arArray = array();
\r 
 694         $arLine = strtok($resp,"\n");
\r 
 697         while ( $arLine ) {
\r 
 698             list ( $element, $value ) = explode(": ",$arLine);
\r 
 699             if ( $element == "Artist" ) {
\r 
 702                 $arArray[$arCounter] = $arName;
\r 
 705             $arLine = strtok("\n");
\r 
 707                 if ( $this->debugging ) echo "mpd->GetArtists()\n";
\r 
 713          * Returns the list of albums in the database in an associative array. Optional parameter
\r 
 714      * is an artist Name which will list all albums by a particular artist.
\r 
 716         function GetAlbums( $ar = NULL) {
\r 
 717                 if ( $this->debugging ) echo "mpd->GetAlbums()\n";
\r 
 718                 if ( is_null($resp = $this->SendCommand(MPD_CMD_TABLE, MPD_TBL_ALBUM, $ar )))   return NULL;
\r 
 719         $alArray = array();
\r 
 721         $alLine = strtok($resp,"\n");
\r 
 724         while ( $alLine ) {
\r 
 725             list ( $element, $value ) = explode(": ",$alLine);
\r 
 726             if ( $element == "Album" ) {
\r 
 729                 $alArray[$alCounter] = $alName;
\r 
 732             $alLine = strtok("\n");
\r 
 734                 if ( $this->debugging ) echo "mpd->GetAlbums()\n";
\r 
 738         //*******************************************************************************//
\r 
 739         //***************************** INTERNAL FUNCTIONS ******************************//
\r 
 740         //*******************************************************************************//
\r 
 742     /* _computeVersionValue()
\r 
 744      * Computes a compatibility value from a version string
\r 
 747     function _computeVersionValue($verStr) {
\r 
 748                 list ($ver_maj, $ver_min, $ver_rel ) = explode("\.",$verStr);
\r 
 749                 return ( 100 * $ver_maj ) + ( 10 * $ver_min ) + ( $ver_rel );
\r 
 752         /* _checkCompatibility() 
\r 
 754          * Check MPD command compatibility against our internal table. If there is no version 
\r 
 755          * listed in the table, allow it by default.
\r 
 757         function _checkCompatibility($cmd) {
\r 
 758         // Check minimum compatibility
\r 
 759                 $req_ver_low = $this->COMPATIBILITY_MIN_TBL[$cmd];
\r 
 760                 $req_ver_hi = $this->COMPATIBILITY_MAX_TBL[$cmd];
\r 
 762                 $mpd_ver = $this->_computeVersionValue($this->mpd_version);
\r 
 764                 if ( $req_ver_low ) {
\r 
 765                         $req_ver = $this->_computeVersionValue($req_ver_low);
\r 
 767                         if ( $mpd_ver < $req_ver ) {
\r 
 768                                 $this->errStr = "Command '$cmd' is not compatible with this version of MPD, version ".$req_ver_low." required";
\r 
 773         // Check maxmum compatibility -- this will check for deprecations
\r 
 774                 if ( $req_ver_hi ) {
\r 
 775             $req_ver = $this->_computeVersionValue($req_ver_hi);
\r 
 777                         if ( $mpd_ver > $req_ver ) {
\r 
 778                                 $this->errStr = "Command '$cmd' has been deprecated in this version of MPD.";
\r 
 786         /* _parseFileListResponse() 
\r 
 788          * Builds a multidimensional array with MPD response lists.
\r 
 790          * NOTE: This function is used internally within the class. It should not be used.
\r 
 792         function _parseFileListResponse($resp) {
\r 
 793                 if ( is_null($resp) ) {
\r 
 796                         $plistArray = array();
\r 
 797                         $plistLine = strtok($resp,"\n");
\r 
 800                         while ( $plistLine ) {
\r 
 801                                 list ( $element, $value ) = explode(": ",$plistLine);
\r 
 802                                 if($element == "file" || $element=="directory") {
\r 
 804                                   $plistArray[$plCounter]['name']=$value;
\r 
 805                                   $plistArray[$plCounter]['type']=$element; 
\r 
 806                                   $plistArray[$plCounter]['title']=$value;
\r 
 808                                 if($element == "Name") {
\r 
 809                                   $plistArray[$plCounter]['title']=$value;
\r 
 811                                 $plistLine = strtok("\n");
\r 
 814                 return $plistArray;
\r 
 819          * Updates all class properties with the values from the MPD server.
\r 
 821          * NOTE: This function is automatically called upon Connect() as of v1.1.
\r 
 823         function RefreshInfo() {
\r 
 824         // Get the Server Statistics
\r 
 825                 $statStr = $this->SendCommand(MPD_CMD_STATISTICS);
\r 
 830                         $statLine = strtok($statStr,"\n");
\r 
 831                         while ( $statLine ) {
\r 
 832                                 list ( $element, $value ) = explode(": ",$statLine);
\r 
 833                                 $stats[$element] = $value;
\r 
 834                                 $statLine = strtok("\n");
\r 
 838         // Get the Server Status
\r 
 839                 $statusStr = $this->SendCommand(MPD_CMD_STATUS);
\r 
 840                 if ( ! $statusStr ) {
\r 
 844                         $statusLine = strtok($statusStr,"\n");
\r 
 845                         while ( $statusLine ) {
\r 
 846                                 list ( $element, $value ) = explode(": ",$statusLine);
\r 
 847                                 $status[$element] = $value;
\r 
 848                                 $statusLine = strtok("\n");
\r 
 852         // Get the Playlist
\r 
 853                 $plStr = $this->SendCommand(MPD_CMD_PLLIST);
\r 
 854                 $this->playlist = $this->_parseFileListResponse($plStr);
\r 
 855         $this->playlist_count = count($this->playlist);
\r 
 857         // Set Misc Other Variables
\r 
 858                 $this->state = $status['state'];
\r 
 859                 if ( ($this->state == MPD_STATE_PLAYING) || ($this->state == MPD_STATE_PAUSED) ) {
\r 
 860                         $this->current_track_id = $status['song'];
\r 
 861                         list ($this->current_track_position, $this->current_track_length ) = explode(":",$status['time']);
\r 
 863                         $this->current_track_id = -1;
\r 
 864                         $this->current_track_position = -1;
\r 
 865                         $this->current_track_length = -1;
\r 
 868                 $this->repeat = $status['repeat'];
\r 
 869                 $this->random = $status['random'];
\r 
 871                 $this->db_last_refreshed = $stats['db_update'];
\r 
 873                 $this->volume = $status['volume'];
\r 
 874                 $this->uptime = $stats['uptime'];
\r 
 875                 $this->playtime = $stats['playtime'];
\r 
 876                 $this->num_songs_played = $stats['songs_played'];
\r 
 877                 $this->num_artists = $stats['num_artists'];
\r 
 878                 $this->num_songs = $stats['num_songs'];
\r 
 879                 $this->num_albums = $stats['num_albums'];
\r 
 883     /* ------------------ DEPRECATED METHODS -------------------*/
\r 
 884         /* GetStatistics() 
\r 
 886          * Retrieves the 'statistics' variables from the server and tosses them into an array.
\r 
 888          * NOTE: This function really should not be used. Instead, use $this->[variable]. The function
\r 
 889          *   will most likely be deprecated in future releases.
\r 
 891         function GetStatistics() {
\r 
 892                 if ( $this->debugging ) echo "mpd->GetStatistics()\n";
\r 
 893                 $stats = $this->SendCommand(MPD_CMD_STATISTICS);
\r 
 897                         $statsArray = array();
\r 
 898                         $statsLine = strtok($stats,"\n");
\r 
 899                         while ( $statsLine ) {
\r 
 900                                 list ( $element, $value ) = explode(": ",$statsLine);
\r 
 901                                 $statsArray[$element] = $value;
\r 
 902                                 $statsLine = strtok("\n");
\r 
 905                 if ( $this->debugging ) echo "mpd->GetStatistics() / return: " . print_r($statsArray) ."\n";
\r 
 906                 return $statsArray;
\r 
 911          * Retrieves the 'status' variables from the server and tosses them into an array.
\r 
 913          * NOTE: This function really should not be used. Instead, use $this->[variable]. The function
\r 
 914          *   will most likely be deprecated in future releases.
\r 
 916         function GetStatus() {
\r 
 917                 if ( $this->debugging ) echo "mpd->GetStatus()\n";
\r 
 918                 $status = $this->SendCommand(MPD_CMD_STATUS);
\r 
 922                         $statusArray = array();
\r 
 923                         $statusLine = strtok($status,"\n");
\r 
 924                         while ( $statusLine ) {
\r 
 925                                 list ( $element, $value ) = explode(": ",$statusLine);
\r 
 926                                 $statusArray[$element] = $value;
\r 
 927                                 $statusLine = strtok("\n");
\r 
 930                 if ( $this->debugging ) echo "mpd->GetStatus() / return: " . print_r($statusArray) ."\n";
\r 
 931                 return $statusArray;
\r 
 936          * Retrieves the mixer volume from the server.
\r 
 938          * NOTE: This function really should not be used. Instead, use $this->volume. The function
\r 
 939          *   will most likely be deprecated in future releases.
\r 
 941         function GetVolume() {
\r 
 942                 if ( $this->debugging ) echo "mpd->GetVolume()\n";
\r 
 943                 $volLine = $this->SendCommand(MPD_CMD_STATUS);
\r 
 944                 if ( ! $volLine ) {
\r 
 947                         list ($vol) = sscanf($volLine,"volume: %d");
\r 
 949                 if ( $this->debugging ) echo "mpd->GetVolume() / return: $vol\n";
\r 
 955          * Retrieves the playlist from the server and tosses it into a multidimensional array.
\r 
 957          * NOTE: This function really should not be used. Instead, use $this->playlist. The function
\r 
 958          *   will most likely be deprecated in future releases.
\r 
 960         function GetPlaylist() {
\r 
 961                 if ( $this->debugging ) echo "mpd->GetPlaylist()\n";
\r 
 962                 $resp = $this->SendCommand(MPD_CMD_PLLIST);
\r 
 963                 $playlist = $this->_parseFileListResponse($resp);
\r 
 964                 if ( $this->debugging ) echo "mpd->GetPlaylist() / return ".print_r($playlist)."\n";
\r 
 968     /* ----------------- Command compatibility tables --------------------- */
\r 
 969         var $COMPATIBILITY_MIN_TBL = array(
\r 
 972     var $COMPATIBILITY_MAX_TBL = array(
\r 
 975 }   // ---------------------------- end of class ------------------------------
\r