Quanta droppings.
[adorno.git] / inc / mpdPlayer.php
blobce30e09aa8fd73ec7f9b3b66d5c63a4994fb2614
1 <?php
3 error_log( "Using MPD backend: ". $c->daemon_type );
4 class mpdConnection {
5 var $active; // Once it actually is...
6 var $mpd;
7 var $status;
9 /**
10 * Create a minimally initialised connection object
12 function mpdConnection() {
13 $this->active = false;
14 $this->mpd = false;
15 $this->status = array();
18 /**
19 * Connect to the remote mpd
21 function Connect() {
22 global $c;
24 $this->mpd = stream_socket_client($c->mpd['connection'], $errno, $errstr, 2);
25 $result = fgets($this->mpd, 8192);
26 $this->active = true;
29 /**
30 * Do a question/response pair with the daemon
32 function Daemon( $say ) {
33 if ( ! $this->active ) $this->Connect();
35 $say .= "\n";
36 fwrite($this->mpd, $say );
38 $result = "";
39 while ( ! feof($this->mpd) ) {
40 $line = fgets($this->mpd, 8192);
41 if ( strncmp($line, 'OK', 2) == "0" ) break;
42 $result .= $line;
43 if ( strncmp($line, 'ACK', 3) == "0" ) break;
46 return $result;
49 /**
50 * Query the MPD about it's current status
52 function UpdateStatus() {
53 $status = split( "\n", $this->Daemon( "status" ) );
54 foreach( $status AS $k => $v ) {
55 list( $key, $value ) = preg_split( '/:\s*/', $v, 2);
56 $this->status[$key] = $value;
61 /**
62 * Play a track. If the current status is 'stop' then we
63 * first clear the playlist and after tell mpd to play.
65 function Play( $track ) {
66 global $c;
68 $this->UpdateStatus();
69 $stopped = ( $this->status['state'] == 'stop' );
71 $track = str_replace( $c->mpd['prefix'], '', $track);
73 $result = $this->Daemon("add $track");
74 if ( preg_match( '/ACK.*not found/', $result, $matches ) ) {
75 $result = $this->Daemon("update $track");
76 sleep(1);
77 for( $counter=0; $this->UpdateStatus() && isset($this->status['updating_db']) && $counter++ < 10; sleep(1) );
78 $result = $this->Daemon("add $track");
80 if ( $stopped ) $this->Daemon( sprintf('play %d', $this->status['playlistlength']) );
84 /**
85 * Query the MPD about it's current playlist and position
87 function GetCurrent() {
88 global $c;
90 $this->UpdateStatus();
91 $songnow = (object) array();
92 if ( $this->status['state'] == 'stop' ) return $songnow;
94 $current = split( "\n", $this->Daemon( "currentsong" ) );
95 foreach( $current AS $k => $v ) {
96 list( $key, $value ) = preg_split( '/:\s*/', $v, 2);
97 if ( $key == 'file' ) {
98 $songnow->track = $c->mpd['prefix'] . $value;
99 break;
102 if ( $this->status['state'] == 'play' ) {
103 $seconds_in = preg_replace( '/:.*$/', '', $this->status['time']);
104 $songnow->started = date( 'Y-m-d H:i:s', time() - $seconds_in );
106 return $songnow;
110 * Query the MPD about it's current playlist and position
112 function GetQueue() {
113 global $c;
115 $this->UpdateStatus();
116 $next = $this->status['song'] + 1;
117 $this->queue = array();
119 $filename = "";
121 $playlist = split( "\n", $this->Daemon( "playlistinfo" ) );
122 foreach( $playlist AS $k => $v ) {
123 list( $key, $value ) = preg_split( '/:\s*/', $v, 2);
125 switch( $key ) {
126 case 'file':
127 $filename = $c->mpd['prefix'] . $value;
128 break;
129 case 'Pos':
130 $pos = $value - $next;
131 if ( $pos >= 0 ) {
132 $this->queue[$pos] = $filename;
134 break;
138 return $this->queue;
143 $GLOBALS["mpd"] = new mpdConnection();
149 /******************************************************************
150 * The actual API the web interface calls is then very simple...
151 ******************************************************************/
154 * Queue a file for playing
156 function daemon_play_track( $path ) {
157 global $mpd;
158 error_log("adorno: DBG: Trying to play '$path'");
159 $mpd->Play( $path );
164 * Get a list of the files currently queued for the future
166 function daemon_get_queue() {
167 global $mpd;
168 $q = $mpd->GetQueue();
169 return $q;
174 * Get the currently playing track and it's starting time
176 function daemon_current_track() {
177 global $mpd;
178 return $mpd->GetCurrent();
183 * Get the currently playing track and it's starting time
185 function daemon_other_command( $action, $track ) {
186 global $mpd;
187 switch( $action ) {
188 case 'pause':
189 $mpd->Daemon($action);
190 break;
191 case 'next':
192 $mpd->Daemon($action);
193 break;
194 default:
195 error_log("adorno: ERROR: Unsupported command '$action'" );
198 return true;