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
54 define("MPD_CMD_LISTS", "listplaylists");
\r
55 define("MPD_CMD_DELLIST", "rm");
\r
57 // Predefined MPD Response messages
\r
58 define("MPD_RESPONSE_ERR", "ACK");
\r
59 define("MPD_RESPONSE_OK", "OK");
\r
61 // MPD State Constants
\r
62 define("MPD_STATE_PLAYING", "play");
\r
63 define("MPD_STATE_STOPPED", "stop");
\r
64 define("MPD_STATE_PAUSED", "pause");
\r
66 // MPD Searching Constants
\r
67 define("MPD_SEARCH_ARTIST", "artist");
\r
68 define("MPD_SEARCH_TITLE", "title");
\r
69 define("MPD_SEARCH_ALBUM", "album");
\r
72 define("MPD_TBL_ARTIST","artist");
\r
73 define("MPD_TBL_ALBUM","album");
\r
76 // TCP/Connection variables
\r
81 var $mpd_sock = NULL;
\r
82 var $connected = FALSE;
\r
84 // MPD Status variables
\r
85 var $mpd_version = "(unknown)";
\r
88 var $current_track_position;
\r
89 var $current_track_length;
\r
90 var $current_track_id;
\r
97 var $db_last_refreshed;
\r
98 var $num_songs_played;
\r
99 var $playlist_count;
\r
105 var $playlist = array();
\r
107 // Misc Other Vars
\r
108 var $mpd_class_version = "1.2";
\r
110 var $debugging = FALSE; // Set to TRUE to turn extended debugging on.
\r
111 var $errStr = ""; // Used for maintaining information about the last error message
\r
113 var $command_queue; // The list of commands for bulk command sending
\r
115 // =================== BEGIN OBJECT METHODS ================
\r
117 /* mpd() : Constructor
\r
119 * Builds the MPD object, connects to the server, and refreshes all local object properties.
\r
121 function mpd($srv,$port,$pwd = NULL) {
\r
122 $this->host = $srv;
\r
123 $this->port = $port;
\r
124 $this->password = $pwd;
\r
126 $resp = $this->Connect();
\r
127 if ( is_null($resp) ) {
\r
128 $this->errStr = "Could not connect";
\r
131 list ( $this->mpd_version ) = sscanf($resp, MPD_RESPONSE_OK . " MPD %s\n");
\r
132 if ( ! is_null($pwd) ) {
\r
133 if ( is_null($this->SendCommand(MPD_CMD_PASSWORD,$pwd)) ) {
\r
134 $this->connected = FALSE;
\r
135 return; // bad password or command
\r
137 if ( is_null($this->RefreshInfo()) ) { // no read access -- might as well be disconnected!
\r
138 $this->connected = FALSE;
\r
139 $this->errStr = "Password supplied does not have read access";
\r
143 if ( is_null($this->RefreshInfo()) ) { // no read access -- might as well be disconnected!
\r
144 $this->connected = FALSE;
\r
145 $this->errStr = "Password required to access server";
\r
154 * Connects to the MPD server.
\r
156 * NOTE: This is called automatically upon object instantiation; you should not need to call this directly.
\r
158 function Connect() {
\r
159 if ( $this->debugging ) echo "mpd->Connect() / host: ".$this->host.", port: ".$this->port."\n";
\r
160 $this->mpd_sock = fsockopen($this->host,$this->port,$errNo,$errStr,10);
\r
161 if (!$this->mpd_sock) {
\r
162 $this->errStr = "Socket Error: $errStr ($errNo)";
\r
165 while(!feof($this->mpd_sock)) {
\r
166 $response = fgets($this->mpd_sock,1024);
\r
167 if (strncmp(MPD_RESPONSE_OK,$response,strlen(MPD_RESPONSE_OK)) == 0) {
\r
168 $this->connected = TRUE;
\r
172 if (strncmp(MPD_RESPONSE_ERR,$response,strlen(MPD_RESPONSE_ERR)) == 0) {
\r
173 $this->errStr = "Server responded with: $response";
\r
177 // Generic response
\r
178 $this->errStr = "Connection not available";
\r
185 * Sends a generic command to the MPD server. Several command constants are pre-defined for
\r
186 * use (see MPD_CMD_* constant definitions above).
\r
188 function SendCommand($cmdStr,$arg1 = "",$arg2 = "") {
\r
189 if ( $this->debugging ) echo "mpd->SendCommand() / cmd: ".$cmdStr.", args: ".$arg1." ".$arg2."\n";
\r
191 if ( ! $this->connected ) {
\r
192 echo "mpd->SendCommand() / Error: Not connected\n";
\r
194 // Clear out the error String
\r
195 $this->errStr = "";
\r
198 // Check the command compatibility:
\r
199 if ( ! $this->_checkCompatibility($cmdStr) ) {
\r
200 echo "Not compatible command!";
\r
204 if (strlen($arg1) > 0) $cmdStr .= " \"$arg1\"";
\r
206 if (strlen($arg2) > 0) $cmdStr .= " \"$arg2\"";
\r
207 if ( $this->debugging ) echo "mpd-> ".$cmdStr."\n";
\r
208 fputs($this->mpd_sock,"$cmdStr\n");
\r
209 while(!feof($this->mpd_sock)) {
\r
210 $response = fgets($this->mpd_sock,1024);
\r
211 if ( $this->debugging ) echo "mpd.response-> ".$response."\n";
\r
213 // An OK signals the end of transmission -- we'll ignore it
\r
214 if (strncmp(MPD_RESPONSE_OK,$response,strlen(MPD_RESPONSE_OK)) == 0) {
\r
218 // An ERR signals the end of transmission with an error! Let's grab the single-line message.
\r
219 if (strncmp(MPD_RESPONSE_ERR,$response,strlen(MPD_RESPONSE_ERR)) == 0) {
\r
220 list ( $junk, $errTmp ) = explode(MPD_RESPONSE_ERR . " ",$response );
\r
221 $this->errStr = strtok($errTmp,"\n");
\r
224 if ( strlen($this->errStr) > 0 ) {
\r
228 // Build the response string
\r
229 $respStr .= $response;
\r
231 if ( $this->debugging ) echo "mpd->SendCommand() / response: '".$respStr."'\n";
\r
238 * Queues a generic command for later sending to the MPD server. The CommandQueue can hold
\r
239 * as many commands as needed, and are sent all at once, in the order they are queued, using
\r
240 * the SendCommandQueue() method. The syntax for queueing commands is identical to SendCommand().
\r
242 function QueueCommand($cmdStr,$arg1 = "",$arg2 = "") {
\r
243 if ( $this->debugging ) echo "mpd->QueueCommand() / cmd: ".$cmdStr.", args: ".$arg1." ".$arg2."\n";
\r
244 if ( ! $this->connected ) {
\r
245 echo "mpd->QueueCommand() / Error: Not connected\n";
\r
248 if ( strlen($this->command_queue) == 0 ) {
\r
249 $this->command_queue = MPD_CMD_START_BULK . "\n";
\r
251 if (strlen($arg1) > 0) $cmdStr .= " \"$arg1\"";
\r
252 if (strlen($arg2) > 0) $cmdStr .= " \"$arg2\"";
\r
254 $this->command_queue .= $cmdStr ."\n";
\r
256 if ( $this->debugging ) echo "mpd->QueueCommand() / return\n";
\r
261 /* SendCommandQueue()
\r
263 * Sends all commands in the Command Queue to the MPD server. See also QueueCommand().
\r
265 function SendCommandQueue() {
\r
266 if ( $this->debugging ) echo "mpd->SendCommandQueue()\n";
\r
267 if ( ! $this->connected ) {
\r
268 echo "mpd->SendCommandQueue() / Error: Not connected\n";
\r
271 $this->command_queue .= MPD_CMD_END_BULK . "\n";
\r
272 if ( is_null($respStr = $this->SendCommand($this->command_queue)) ) {
\r
275 $this->command_queue = NULL;
\r
276 if ( $this->debugging ) echo "mpd->SendCommandQueue() / response: '".$respStr."'\n";
\r
284 * Adjusts the mixer volume on the MPD by <modifier>, which can be a positive (volume increase),
\r
285 * or negative (volume decrease) value.
\r
287 function AdjustVolume($modifier) {
\r
288 if ( $this->debugging ) echo "mpd->AdjustVolume()\n";
\r
289 if ( ! is_numeric($modifier) ) {
\r
290 $this->errStr = "AdjustVolume() : argument 1 must be a numeric value";
\r
294 $this->RefreshInfo();
\r
295 $newVol = $this->volume + $modifier;
\r
296 $ret = $this->SetVolume($newVol);
\r
298 if ( $this->debugging ) echo "mpd->AdjustVolume() / return\n";
\r
304 * Sets the mixer volume to <newVol>, which should be between 1 - 100.
\r
306 function SetVolume($newVol) {
\r
307 if ( $this->debugging ) echo "mpd->SetVolume()\n";
\r
308 if ( ! is_numeric($newVol) ) {
\r
309 $this->errStr = "SetVolume() : argument 1 must be a numeric value";
\r
313 // Forcibly prevent out of range errors
\r
314 if ( $newVol < 0 ) $newVol = 0;
\r
315 if ( $newVol > 100 ) $newVol = 100;
\r
317 // If we're not compatible with SETVOL, we'll try adjusting using VOLUME
\r
318 if ( $this->_checkCompatibility(MPD_CMD_SETVOL) ) {
\r
319 if ( ! is_null($ret = $this->SendCommand(MPD_CMD_SETVOL,$newVol))) $this->volume = $newVol;
\r
321 $this->RefreshInfo(); // Get the latest volume
\r
322 if ( is_null($this->volume) ) {
\r
325 $modifier = ( $newVol - $this->volume );
\r
326 if ( ! is_null($ret = $this->SendCommand(MPD_CMD_VOLUME,$modifier))) $this->volume = $newVol;
\r
330 if ( $this->debugging ) echo "mpd->SetVolume() / return\n";
\r
336 * Retrieves a database directory listing of the <dir> directory and places the results into
\r
337 * a multidimensional array. If no directory is specified, the directory listing is at the
\r
338 * base of the MPD music path.
\r
340 function GetDir($dir = "") {
\r
341 if ( $this->debugging ) echo "mpd->GetDir()\n";
\r
342 $resp = $this->SendCommand(MPD_CMD_LSDIR,$dir);
\r
343 $dirlist = $this->_parseFileListResponse($resp);
\r
344 if ( $this->debugging ) echo "mpd->GetDir() / return ".print_r($dirlist)."\n";
\r
350 * Adds each track listed in a single-dimensional <trackArray>, which contains filenames
\r
351 * of tracks to add, to the end of the playlist. This is used to add many, many tracks to
\r
352 * the playlist in one swoop.
\r
354 function PLAddBulk($trackArray) {
\r
355 if ( $this->debugging ) echo "mpd->PLAddBulk()\n";
\r
356 $num_files = count($trackArray);
\r
357 for ( $i = 0; $i < $num_files; $i++ ) {
\r
358 $this->QueueCommand(MPD_CMD_PLADD,$trackArray[$i]);
\r
360 $resp = $this->SendCommandQueue();
\r
361 $this->RefreshInfo();
\r
362 if ( $this->debugging ) echo "mpd->PLAddBulk() / return\n";
\r
368 * Adds the file <file> to the end of the playlist. <file> must be a track in the MPD database.
\r
370 function PLAdd($fileName) {
\r
371 if ( $this->debugging ) echo "mpd->PLAdd()\n";
\r
372 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLADD,$fileName))) $this->RefreshInfo();
\r
373 if ( $this->debugging ) echo "mpd->PLAdd() / return\n";
\r
379 * Moves track number <origPos> to position <newPos> in the playlist. This is used to reorder
\r
380 * the songs in the playlist.
\r
382 function PLMoveTrack($origPos, $newPos) {
\r
383 if ( $this->debugging ) echo "mpd->PLMoveTrack()\n";
\r
384 if ( ! is_numeric($origPos) ) {
\r
385 $this->errStr = "PLMoveTrack(): argument 1 must be numeric";
\r
388 if ( $origPos < 0 or $origPos > $this->playlist_count ) {
\r
389 $this->errStr = "PLMoveTrack(): argument 1 out of range";
\r
392 if ( $newPos < 0 ) $newPos = 0;
\r
393 if ( $newPos > $this->playlist_count ) $newPos = $this->playlist_count;
\r
395 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLMOVETRACK,$origPos,$newPos))) $this->RefreshInfo();
\r
396 if ( $this->debugging ) echo "mpd->PLMoveTrack() / return\n";
\r
402 * Randomly reorders the songs in the playlist.
\r
404 function PLShuffle() {
\r
405 if ( $this->debugging ) echo "mpd->PLShuffle()\n";
\r
406 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLSHUFFLE))) $this->RefreshInfo();
\r
407 if ( $this->debugging ) echo "mpd->PLShuffle() / return\n";
\r
413 * Retrieves the playlist from <file>.m3u and loads it into the current playlist.
\r
415 function PLLoad($file) {
\r
416 if ( $this->debugging ) echo "mpd->PLLoad()\n";
\r
417 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLLOAD,$file))) $this->RefreshInfo();
\r
418 if ( $this->debugging ) echo "mpd->PLLoad() / return\n";
\r
424 * Retrieves the playlists info.
\r
426 function PLList() {
\r
427 if ( $this->debugging ) echo "mpd->PLList()\n";
\r
428 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_LISTS))) $this->RefreshInfo();
\r
429 if ( $this->debugging ) echo "mpd->PLList() / return\n";
\r
435 * Saves the playlist to <file>.m3u for later retrieval. The file is saved in the MPD playlist
\r
438 function PLSave($file) {
\r
439 if ( $this->debugging ) echo "mpd->PLSave()\n";
\r
440 $resp = $this->SendCommand(MPD_CMD_PLSAVE,$file);
\r
441 if ( $this->debugging ) echo "mpd->PLSave() / return\n";
\r
447 * Deletes playlist <file>.m3u in the MPD playlist directory.
\r
449 function PLDel($file) {
\r
450 if ( $this->debugging ) echo "mpd->PLDel()\n";
\r
451 $resp = $this->SendCommand(MPD_CMD_DELLIST,$file);
\r
452 if ( $this->debugging ) echo "mpd->PLDel() / return\n";
\r
458 * Empties the playlist.
\r
460 function PLClear() {
\r
461 if ( $this->debugging ) echo "mpd->PLClear()\n";
\r
462 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLCLEAR))) $this->RefreshInfo();
\r
463 if ( $this->debugging ) echo "mpd->PLClear() / return\n";
\r
470 * Move song from pos to the other
\r
472 function Move ($from,$to) {
\r
473 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLMOVETRACK,$from,$to))) $this->RefreshInfo();
\r
474 //die(print_r($resp));
\r
481 * Removes track <id> from the playlist.
\r
483 function PLRemove($id) {
\r
484 if ( $this->debugging ) echo "mpd->PLRemove()\n";
\r
485 if ( ! is_numeric($id) ) {
\r
486 $this->errStr = "PLRemove() : argument 1 must be a numeric value";
\r
489 if ( ! is_null($resp = $this->SendCommand(MPD_CMD_PLREMOVE,$id))) $this->RefreshInfo();
\r
490 if ( $this->debugging ) echo "mpd->PLRemove() / return\n";
\r
496 * Enables 'loop' mode -- tells MPD continually loop the playlist. The <repVal> parameter
\r
497 * is either 1 (on) or 0 (off).
\r
499 function SetRepeat($repVal) {
\r
500 if ( $this->debugging ) echo "mpd->SetRepeat()\n";
\r
501 $rpt = $this->SendCommand(MPD_CMD_REPEAT,$repVal);
\r
502 $this->repeat = $repVal;
\r
503 if ( $this->debugging ) echo "mpd->SetRepeat() / return\n";
\r
509 * Enables 'randomize' mode -- tells MPD to play songs in the playlist in random order. The
\r
510 * <rndVal> parameter is either 1 (on) or 0 (off).
\r
512 function SetRandom($rndVal) {
\r
513 if ( $this->debugging ) echo "mpd->SetRandom()\n";
\r
514 $resp = $this->SendCommand(MPD_CMD_RANDOM,$rndVal);
\r
515 $this->random = $rndVal;
\r
516 if ( $this->debugging ) echo "mpd->SetRandom() / return\n";
\r
522 * Shuts down the MPD server (aka sends the KILL command). This closes the current connection,
\r
523 * and prevents future communication with the server.
\r
525 function Shutdown() {
\r
526 if ( $this->debugging ) echo "mpd->Shutdown()\n";
\r
527 $resp = $this->SendCommand(MPD_CMD_SHUTDOWN);
\r
529 $this->connected = FALSE;
\r
530 unset($this->mpd_version);
\r
531 unset($this->errStr);
\r
532 unset($this->mpd_sock);
\r
534 if ( $this->debugging ) echo "mpd->Shutdown() / return\n";
\r
540 * Tells MPD to rescan the music directory for new tracks, and to refresh the Database. Tracks
\r
541 * cannot be played unless they are in the MPD database.
\r
543 function DBRefresh() {
\r
544 if ( $this->debugging ) echo "mpd->DBRefresh()\n";
\r
545 $resp = $this->SendCommand(MPD_CMD_REFRESH);
\r
547 // Update local variables
\r
548 $this->RefreshInfo();
\r
550 if ( $this->debugging ) echo "mpd->DBRefresh() / return\n";
\r
556 * Begins playing the songs in the MPD playlist.
\r
559 if ( $this->debugging ) echo "mpd->Play()\n";
\r
560 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PLAY) )) $this->RefreshInfo();
\r
561 if ( $this->debugging ) echo "mpd->Play() / return\n";
\r
567 * Stops playing the MPD.
\r
570 if ( $this->debugging ) echo "mpd->Stop()\n";
\r
571 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_STOP) )) $this->RefreshInfo();
\r
572 if ( $this->debugging ) echo "mpd->Stop() / return\n";
\r
578 * Toggles pausing on the MPD. Calling it once will pause the player, calling it again
\r
582 if ( $this->debugging ) echo "mpd->Pause()\n";
\r
583 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PAUSE) )) $this->RefreshInfo();
\r
584 if ( $this->debugging ) echo "mpd->Pause() / return\n";
\r
590 * Skips directly to the <idx> song in the MPD playlist.
\r
592 function SkipTo($idx) {
\r
593 if ( $this->debugging ) echo "mpd->SkipTo()\n";
\r
594 if ( ! is_numeric($idx) ) {
\r
595 $this->errStr = "SkipTo() : argument 1 must be a numeric value";
\r
598 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PLAY,$idx))) $this->RefreshInfo();
\r
599 if ( $this->debugging ) echo "mpd->SkipTo() / return\n";
\r
605 * Skips directly to a given position within a track in the MPD playlist. The <pos> argument,
\r
606 * given in seconds, is the track position to locate. The <track> argument, if supplied is
\r
607 * the track number in the playlist. If <track> is not specified, the current track is assumed.
\r
609 function SeekTo($pos, $track = -1) {
\r
610 if ( $this->debugging ) echo "mpd->SeekTo()\n";
\r
611 if ( ! is_numeric($pos) ) {
\r
612 $this->errStr = "SeekTo() : argument 1 must be a numeric value";
\r
615 if ( ! is_numeric($track) ) {
\r
616 $this->errStr = "SeekTo() : argument 2 must be a numeric value";
\r
619 if ( $track == -1 ) {
\r
620 $track = $this->current_track_id;
\r
623 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_SEEK,$track,$pos))) $this->RefreshInfo();
\r
624 if ( $this->debugging ) echo "mpd->SeekTo() / return\n";
\r
630 * Skips to the next song in the MPD playlist. If not playing, returns an error.
\r
633 if ( $this->debugging ) echo "mpd->Next()\n";
\r
634 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_NEXT))) $this->RefreshInfo();
\r
635 if ( $this->debugging ) echo "mpd->Next() / return\n";
\r
641 * Skips to the previous song in the MPD playlist. If not playing, returns an error.
\r
643 function Previous() {
\r
644 if ( $this->debugging ) echo "mpd->Previous()\n";
\r
645 if ( ! is_null($rpt = $this->SendCommand(MPD_CMD_PREV))) $this->RefreshInfo();
\r
646 if ( $this->debugging ) echo "mpd->Previous() / return\n";
\r
652 * Searches the MPD database. The search <type> should be one of the following:
\r
653 * MPD_SEARCH_ARTIST, MPD_SEARCH_TITLE, MPD_SEARCH_ALBUM
\r
654 * The search <string> is a case-insensitive locator string. Anything that contains
\r
655 * <string> will be returned in the results.
\r
657 function Search($type,$string) {
\r
658 if ( $this->debugging ) echo "mpd->Search()\n";
\r
659 if ( $type != MPD_SEARCH_ARTIST and
\r
660 $type != MPD_SEARCH_ALBUM and
\r
661 $type != MPD_SEARCH_TITLE ) {
\r
662 $this->errStr = "mpd->Search(): invalid search type";
\r
665 if ( is_null($resp = $this->SendCommand(MPD_CMD_SEARCH,$type,$string))) return NULL;
\r
666 $searchlist = $this->_parseFileListResponse($resp);
\r
668 if ( $this->debugging ) echo "mpd->Search() / return ".print_r($searchlist)."\n";
\r
669 return $searchlist;
\r
674 * Find() looks for exact matches in the MPD database. The find <type> should be one of
\r
676 * MPD_SEARCH_ARTIST, MPD_SEARCH_TITLE, MPD_SEARCH_ALBUM
\r
677 * The find <string> is a case-insensitive locator string. Anything that exactly matches
\r
678 * <string> will be returned in the results.
\r
680 function Find($type,$string) {
\r
681 if ( $this->debugging ) echo "mpd->Find()\n";
\r
682 if ( $type != MPD_SEARCH_ARTIST and
\r
683 $type != MPD_SEARCH_ALBUM and
\r
684 $type != MPD_SEARCH_TITLE ) {
\r
685 $this->errStr = "mpd->Find(): invalid find type";
\r
688 if ( is_null($resp = $this->SendCommand(MPD_CMD_FIND,$type,$string))) return NULL;
\r
689 $searchlist = $this->_parseFileListResponse($resp);
\r
691 if ( $this->debugging ) echo "mpd->Find() / return ".print_r($searchlist)."\n";
\r
692 return $searchlist;
\r
697 * Closes the connection to the MPD server.
\r
699 function Disconnect() {
\r
700 if ( $this->debugging ) echo "mpd->Disconnect()\n";
\r
701 fclose($this->mpd_sock);
\r
703 $this->connected = FALSE;
\r
704 unset($this->mpd_version);
\r
705 unset($this->errStr);
\r
706 unset($this->mpd_sock);
\r
711 * Returns the list of artists in the database in an associative array.
\r
713 function GetArtists() {
\r
714 if ( $this->debugging ) echo "mpd->GetArtists()\n";
\r
715 if ( is_null($resp = $this->SendCommand(MPD_CMD_TABLE, MPD_TBL_ARTIST))) return NULL;
\r
716 $arArray = array();
\r
718 $arLine = strtok($resp,"\n");
\r
721 while ( $arLine ) {
\r
722 list ( $element, $value ) = explode(": ",$arLine);
\r
723 if ( $element == "Artist" ) {
\r
726 $arArray[$arCounter] = $arName;
\r
729 $arLine = strtok("\n");
\r
731 if ( $this->debugging ) echo "mpd->GetArtists()\n";
\r
737 * Returns the list of albums in the database in an associative array. Optional parameter
\r
738 * is an artist Name which will list all albums by a particular artist.
\r
740 function GetAlbums( $ar = NULL) {
\r
741 if ( $this->debugging ) echo "mpd->GetAlbums()\n";
\r
742 if ( is_null($resp = $this->SendCommand(MPD_CMD_TABLE, MPD_TBL_ALBUM, $ar ))) return NULL;
\r
743 $alArray = array();
\r
745 $alLine = strtok($resp,"\n");
\r
748 while ( $alLine ) {
\r
749 list ( $element, $value ) = explode(": ",$alLine);
\r
750 if ( $element == "Album" ) {
\r
753 $alArray[$alCounter] = $alName;
\r
756 $alLine = strtok("\n");
\r
758 if ( $this->debugging ) echo "mpd->GetAlbums()\n";
\r
762 //*******************************************************************************//
\r
763 //***************************** INTERNAL FUNCTIONS ******************************//
\r
764 //*******************************************************************************//
\r
766 /* _computeVersionValue()
\r
768 * Computes a compatibility value from a version string
\r
771 function _computeVersionValue($verStr) {
\r
772 list ($ver_maj, $ver_min, $ver_rel ) = explode("\.",$verStr);
\r
773 return ( 100 * $ver_maj ) + ( 10 * $ver_min ) + ( $ver_rel );
\r
776 /* _checkCompatibility()
\r
778 * Check MPD command compatibility against our internal table. If there is no version
\r
779 * listed in the table, allow it by default.
\r
781 function _checkCompatibility($cmd) {
\r
782 // Check minimum compatibility
\r
783 $req_ver_low = $this->COMPATIBILITY_MIN_TBL[$cmd];
\r
784 $req_ver_hi = $this->COMPATIBILITY_MAX_TBL[$cmd];
\r
786 $mpd_ver = $this->_computeVersionValue($this->mpd_version);
\r
788 if ( $req_ver_low ) {
\r
789 $req_ver = $this->_computeVersionValue($req_ver_low);
\r
791 if ( $mpd_ver < $req_ver ) {
\r
792 $this->errStr = "Command '$cmd' is not compatible with this version of MPD, version ".$req_ver_low." required";
\r
797 // Check maxmum compatibility -- this will check for deprecations
\r
798 if ( $req_ver_hi ) {
\r
799 $req_ver = $this->_computeVersionValue($req_ver_hi);
\r
801 if ( $mpd_ver > $req_ver ) {
\r
802 $this->errStr = "Command '$cmd' has been deprecated in this version of MPD.";
\r
810 /* _parseFileListResponse()
\r
812 * Builds a multidimensional array with MPD response lists.
\r
814 * NOTE: This function is used internally within the class. It should not be used.
\r
816 function _parseFileListResponse($resp) {
\r
817 if ( is_null($resp) ) {
\r
820 $plistArray = array();
\r
821 $plistLine = strtok($resp,"\n");
\r
824 while ( $plistLine ) {
\r
825 list ( $element, $value ) = explode(": ",$plistLine);
\r
826 if($element == "file" || $element=="directory") {
\r
828 $plistArray[$plCounter]['name']=$value;
\r
829 $plistArray[$plCounter]['type']=$element;
\r
830 $plistArray[$plCounter]['title']=$value;
\r
832 if($element == "Name") {
\r
833 $plistArray[$plCounter]['title']=$value;
\r
835 $plistLine = strtok("\n");
\r
838 return $plistArray;
\r
841 /* _parsePlayListsResponse()
\r
843 * Builds a multidimensional array with MPD response lists.
\r
845 * NOTE: This function is used internally within the class. It should not be used.
\r
847 function _parsePlayListsResponse($resp) {
\r
848 if ( is_null($resp) ) {
\r
851 $plistArray = array();
\r
852 $plistLine = strtok($resp,"\n");
\r
855 while ( $plistLine ) {
\r
856 list ( $element, $value ) = explode(": ",$plistLine);
\r
857 if($element == "playlist") {
\r
859 $plistArray[$plCounter]['name']=$value;
\r
861 if($element == "Last-Modified") {
\r
862 $plistArray[$plCounter]['timestamp']=$value;
\r
864 $plistLine = strtok("\n");
\r
867 return $plistArray;
\r
872 * Updates all class properties with the values from the MPD server.
\r
874 * NOTE: This function is automatically called upon Connect() as of v1.1.
\r
876 function RefreshInfo() {
\r
877 // Get the Server Statistics
\r
878 $statStr = $this->SendCommand(MPD_CMD_STATISTICS);
\r
883 $statLine = strtok($statStr,"\n");
\r
884 while ( $statLine ) {
\r
885 list ( $element, $value ) = explode(": ",$statLine);
\r
886 $stats[$element] = $value;
\r
887 $statLine = strtok("\n");
\r
891 // Get the Server Status
\r
892 $statusStr = $this->SendCommand(MPD_CMD_STATUS);
\r
893 if ( ! $statusStr ) {
\r
897 $statusLine = strtok($statusStr,"\n");
\r
898 while ( $statusLine ) {
\r
899 list ( $element, $value ) = explode(": ",$statusLine);
\r
900 $status[$element] = $value;
\r
901 $statusLine = strtok("\n");
\r
905 // Get list of lists
\r
906 $plStr = $this->SendCommand(MPD_CMD_LISTS);
\r
907 $this->playlists = $this->_parsePlayListsResponse($plStr);
\r
909 // Get the Playlist
\r
910 $plStr = $this->SendCommand(MPD_CMD_PLLIST);
\r
911 $this->playlist = $this->_parseFileListResponse($plStr);
\r
912 $this->playlist_count = count($this->playlist);
\r
914 // Set Misc Other Variables
\r
915 $this->state = $status['state'];
\r
916 if ( ($this->state == MPD_STATE_PLAYING) || ($this->state == MPD_STATE_PAUSED) ) {
\r
917 $this->current_track_id = $status['song'];
\r
918 list ($this->current_track_position, $this->current_track_length ) = explode(":",$status['time']);
\r
920 $this->current_track_id = -1;
\r
921 $this->current_track_position = -1;
\r
922 $this->current_track_length = -1;
\r
925 $this->repeat = $status['repeat'];
\r
926 $this->random = $status['random'];
\r
928 $this->db_last_refreshed = $stats['db_update'];
\r
930 $this->volume = $status['volume'];
\r
931 $this->uptime = $stats['uptime'];
\r
932 $this->playtime = $stats['playtime'];
\r
933 $this->num_songs_played = $stats['songs_played'];
\r
934 $this->num_artists = $stats['num_artists'];
\r
935 $this->num_songs = $stats['num_songs'];
\r
936 $this->num_albums = $stats['num_albums'];
\r
940 /* ------------------ DEPRECATED METHODS -------------------*/
\r
941 /* GetStatistics()
\r
943 * Retrieves the 'statistics' variables from the server and tosses them into an array.
\r
945 * NOTE: This function really should not be used. Instead, use $this->[variable]. The function
\r
946 * will most likely be deprecated in future releases.
\r
948 function GetStatistics() {
\r
949 if ( $this->debugging ) echo "mpd->GetStatistics()\n";
\r
950 $stats = $this->SendCommand(MPD_CMD_STATISTICS);
\r
954 $statsArray = array();
\r
955 $statsLine = strtok($stats,"\n");
\r
956 while ( $statsLine ) {
\r
957 list ( $element, $value ) = explode(": ",$statsLine);
\r
958 $statsArray[$element] = $value;
\r
959 $statsLine = strtok("\n");
\r
962 if ( $this->debugging ) echo "mpd->GetStatistics() / return: " . print_r($statsArray) ."\n";
\r
963 return $statsArray;
\r
968 * Retrieves the 'status' variables from the server and tosses them into an array.
\r
970 * NOTE: This function really should not be used. Instead, use $this->[variable]. The function
\r
971 * will most likely be deprecated in future releases.
\r
973 function GetStatus() {
\r
974 if ( $this->debugging ) echo "mpd->GetStatus()\n";
\r
975 $status = $this->SendCommand(MPD_CMD_STATUS);
\r
979 $statusArray = array();
\r
980 $statusLine = strtok($status,"\n");
\r
981 while ( $statusLine ) {
\r
982 list ( $element, $value ) = explode(": ",$statusLine);
\r
983 $statusArray[$element] = $value;
\r
984 $statusLine = strtok("\n");
\r
987 if ( $this->debugging ) echo "mpd->GetStatus() / return: " . print_r($statusArray) ."\n";
\r
988 return $statusArray;
\r
993 * Retrieves the mixer volume from the server.
\r
995 * NOTE: This function really should not be used. Instead, use $this->volume. The function
\r
996 * will most likely be deprecated in future releases.
\r
998 function GetVolume() {
\r
999 if ( $this->debugging ) echo "mpd->GetVolume()\n";
\r
1000 $volLine = $this->SendCommand(MPD_CMD_STATUS);
\r
1001 if ( ! $volLine ) {
\r
1004 list ($vol) = sscanf($volLine,"volume: %d");
\r
1006 if ( $this->debugging ) echo "mpd->GetVolume() / return: $vol\n";
\r
1012 * Retrieves the playlist from the server and tosses it into a multidimensional array.
\r
1014 * NOTE: This function really should not be used. Instead, use $this->playlist. The function
\r
1015 * will most likely be deprecated in future releases.
\r
1017 function GetPlaylist() {
\r
1018 if ( $this->debugging ) echo "mpd->GetPlaylist()\n";
\r
1019 $resp = $this->SendCommand(MPD_CMD_PLLIST);
\r
1020 $playlist = $this->_parseFileListResponse($resp);
\r
1021 if ( $this->debugging ) echo "mpd->GetPlaylist() / return ".print_r($playlist)."\n";
\r
1025 /* ----------------- Command compatibility tables --------------------- */
\r
1026 var $COMPATIBILITY_MIN_TBL = array(
\r
1029 var $COMPATIBILITY_MAX_TBL = array(
\r
1032 } // ---------------------------- end of class ------------------------------
\r