Nicely working now with several small javascript widgets.
[adorno.git] / inc / xmms2Player.php
blobabc134c6bbfe6125883d60758592cfdd58ed66fe
1 <?php
3 putenv('COLUMNS=500');
4 putenv('XMMS_PATH=tcp://127.0.0.1:9667/');
6 error_log( "Using XMMS backend: ". $c->daemon_type );
7 class xmms2Connection {
8 var $active; // Once it actually is...
9 var $xmms2;
10 var $status;
12 /**
13 * Create a minimally initialised connection object
15 function xmms2Connection() {
16 $this->active = false;
17 $this->xmms2 = false;
18 $this->status = false;
21 /**
22 * Connect to the remote xmms2
23 * - a complete fake.
25 function Connect() {
26 global $c;
28 $this->xmms2 = true;
29 $this->active = true;
32 /**
33 * Do a question/response pair with the daemon
35 function OldDaemon( $say ) {
36 if ( ! $this->active ) $this->Connect();
38 $command = 'LC_ALL=en_NZ.UTF8 xmms2 ' . $say . ' 2>&1';
39 $output = array();
40 $retval = 0;
41 error_log("adorno: DBG: XMMS2CMD: >>>$command<<<");
42 exec( $command, &$output, &$retval );
44 if ( preg_match( '#Could not connect to xmms2d#i', $output[0] ) ) {
45 exec( 'xmms2-launcher', &$output, &$retval );
46 error_log("adorno: DBG: Launching XMMS2 daemon: ($retval) - " . $output[0]);
47 exec( 'xmms2 playlist type Default queue', &$output, &$retval );
48 error_log("adorno: DBG: Launching XMMS2 daemon: ($retval) - " . $output[0]);
49 $output = array();
50 $retval = 0;
51 exec( $command, &$output, &$retval );
53 return $output;
56 /**
57 * Do a question/response pair with the daemon via nyxmms2
59 function Daemon( $say ) {
60 if ( ! $this->active ) $this->Connect();
62 $command = 'LC_ALL=en_NZ.UTF8 nyxmms2 ' . $say . ' 2>&1';
63 $output = array();
64 $retval = 0;
65 error_log("adorno: DBG: NYCLICMD: >>>$command<<<");
66 exec( $command, &$output, &$retval );
68 if ( preg_match( '#Could not connect to #i', $output[0] ) ) {
69 exec( 'xmms2-launcher', &$output, &$retval );
70 error_log("adorno: DBG: Launching XMMS2 daemon: ($retval) - " . $output[0]);
71 exec( 'xmms2 playlist type Default queue', &$output, &$retval );
72 error_log("adorno: DBG: Launching XMMS2 daemon: ($retval) - " . $output[0]);
73 $output = array();
74 $retval = 0;
75 exec( $command, &$output, &$retval );
77 return $output;
80 /**
81 * Query the xmms2 about it's current status
83 function UpdateStatus( $force = false ) {
84 if ( ! $force && is_array($this->status) ) return;
85 $this->status = array();
86 $status = $this->Daemon( "status" );
87 $this->status['state'] = preg_replace( '/:.*$/', '', $status[0]);
88 $status = $this->Daemon( "info" );
89 foreach( $status AS $k => $v ) {
90 list( $key, $value ) = preg_split( '/ = /', $v, 2);
91 if ( preg_match( '/\b(url|laststarted|duration|mime|album|artist|title)\s*$/', $key, $matches ) ) {
92 $key = $matches[1];
94 if ( preg_match( '/\%[0-9a-f][0-9a-f]/i', $value ) ) {
95 $value = rawurldecode($value);
97 // printf( "<p>status[%s] = [[%s]]</p>\n", $key, $value );
98 $this->status[$key] = $value;
104 * Encode a filename to escape spaces & stuff.
106 function EncodeFileName( $track ) {
107 if ( preg_match( '#[a-z]{3,7}://#', $track ) ) {
108 return $track;
110 $encoded = str_replace( chr(92), '\\\\', $track);
111 $encoded = str_replace( '"', '\\"', $track);
112 // $encoded = str_replace( "'", "\\'", $track);
113 // $encoded = preg_replace( '/([\\\'"#&;`|*?~<>^\(\)[]{}$ ])/', '\\\\\1', $encoded);
114 # $encoded = escapeshellarg($track);
115 $encoded = '"file://' . $encoded . '"';
116 error_log( "Trying to play: $encoded" );
117 return $encoded;
122 * Play a track. Xmms2 is OK if we tell it to play when it is already.
124 function Play( $track ) {
125 global $c;
127 $this->UpdateStatus( ($this->status['state'] == 'Stopped') );
129 // Replace ' with '' so escapeshellcmd reliably ignores it, then with \' afterwards
130 $this->Daemon("add ". $this->EncodeFileName($track));
131 if ( $this->status['state'] == 'Stopped' ) {
132 $this->Daemon("next");
133 $this->Daemon("play");
135 else
136 $this->Daemon("play");
141 * Move a track in the playlist
143 function MoveTrack( $index, $offset ) {
144 if ( $index < 1 || ($index + $offset) < 1 ) return; // Can't move playing track
146 $this->Daemon( sprintf("move %d %d", $index, $index + $offset ) );
151 * Query the xmms2 about it's current playlist and position
153 function GetCurrent() {
154 global $c;
156 $this->UpdateStatus();
157 $songnow = (object) array();
158 $songnow->started = date( 'Y-m-d H:i:s', $this->status['laststarted'] );
159 $songnow->track = str_replace( 'file://', '', $this->status['url'] );
160 $songnow->duration = intval($this->status['duration']) / 1000;
161 $songnow->finishing = date( 'Y-m-d H:i:s', $this->status['laststarted'] + $songnow->duration);
162 $songnow->state = $this->status['state'];
164 // printf( "<p>Song now is: %s started %s, finishes %s</p>\n", $songnow->track, $songnow->started, $songnow->finishing );
166 return $songnow;
170 * Query the xmms2 about it's current playlist and position
172 function GetQueue() {
173 global $c;
175 $this->UpdateStatus();
177 $this->queue = array();
179 $filename = "";
180 $pos = -1;
182 $playlist = $this->Daemon( "list" );
183 foreach( $playlist AS $k => $v ) {
185 $filename = $v;
186 if ( preg_match( '{@@(.+)@@}', $v, $matches ) ) $filename = $matches[1];
187 // echo "<p>$filename</p>\n";
188 if ( $pos >= 0 ) {
189 if ( substr($filename,0,7) == 'file://' ) {
190 $filename = substr( $filename, 7 );
191 $filename = urldecode( $filename );
192 $this->queue[$pos++] = $filename;
195 else if ( $pos < 0 && substr( $v, 0, 2) == '->' ) {
196 $pos = 0;
197 // echo "<p>Pos($pos) $k == $v</p>\n";
199 else {
200 // echo "<p>Pos($pos) $k -> $v</p>\n";
204 return $this->queue;
209 $GLOBALS["xmms2"] = new xmms2Connection();
215 /******************************************************************
216 * The actual API the web interface calls is then very simple...
217 ******************************************************************/
220 * Queue a file for playing
222 function daemon_play_track( $path ) {
223 global $xmms2;
224 error_log("adorno: DBG: Trying to play '$path'");
225 $xmms2->Play( $path );
230 * Get a list of the files currently queued for the future
232 function daemon_get_queue() {
233 global $xmms2;
234 $q = $xmms2->GetQueue();
235 return $q;
240 * Get the currently playing track and it's starting time
242 function daemon_current_track() {
243 global $xmms2;
244 return $xmms2->GetCurrent();
249 * Get the currently playing track and it's starting time
251 function daemon_other_command( $action, $track ) {
252 global $xmms2;
253 switch( $action ) {
254 case 'resume':
255 $xmms2->Daemon('play');
256 break;
257 case 'pause':
258 $xmms2->Daemon($action);
259 break;
260 case 'next':
261 $xmms2->Daemon($action);
262 break;
263 default:
264 error_log("adorno: WARNING: Unsupported command '$action'" );
265 $xmms2->Daemon($action);
266 break;
269 return true;
273 * Get the currently playing track and it's starting time
275 function daemon_move( $index, $offset ) {
276 global $xmms2;
277 return $xmms2->MoveTrack($index,$offset);