Fix stream playing
[adorno.git] / inc / vlcPlayer.php
blobd52f7a3cc2dec6a83c093da70937a49143b0938d
1 <?php
3 error_log( "Using VLC backend: ". $c->daemon_type );
4 class vlcConnection {
5 var $active; // Once it actually is...
6 var $vlc;
7 var $status;
9 /**
10 * Create a minimally initialised connection object
12 function vlcConnection() {
13 $this->active = false;
14 $this->vlc = false;
15 $this->status = array();
18 /**
19 * Connect to the remote vlc
21 function Connect() {
22 global $c;
24 if ( ! $this->vlc ) {
25 $this->vlc = stream_socket_client($c->vlc['connection'], $errno, $errstr, 1);
26 if ( ! $this->vlc ) {
27 error_log( sprintf( "vlcPlayer: ERROR: Failed to connect to '%s'. Error %d: %s", $c->vlc['connection'], $errno, $errstr) );
28 $this->vlc = 'connection failed';
29 return;
31 error_log( "vlcPlayer: Connected to ".$c->vlc['connection'] );
32 $this->active = true;
36 /**
37 * Do a question/response pair with the daemon
39 function Daemon( $say, $end_pattern = 'command' ) {
40 if ( ! $this->active ) $this->Connect();
42 $result = (object) array( 'text' => "" );
43 if ( ! $this->active ) return $result;
45 if ( $end_pattern == 'command' ) {
46 $command = preg_replace( '/\s.*$/', '', $say);
47 $end_pattern = "^$command: returned (\d+) \((.+)\)";
50 fwrite($this->vlc, $say . "\n" );
51 stream_set_timeout($this->vlc, 0, 50000);
53 while ( ! feof($this->vlc) ) {
54 $line = fgets($this->vlc, 8192);
55 // echo "<p>$line</p>\n";
56 $result->text .= $line;
57 if ( preg_match( "/$end_pattern/", $line, $matches) ) {
58 $result->matches = $matches;
59 break;
63 error_log( sprintf("vlcPlayer: Sent '%s' and result was '%s'", $say, $result->text) );
65 return $result;
69 /**
70 * Query the vlc for a simple command which just returns a single data value
72 function DaemonSimple( $command ) {
73 $response = $this->Daemon( $command, '^(\S+)\s*$' );
74 return $response->matches[1];
78 /**
79 * Query the vlc about it's current status
81 function UpdateStatus() {
82 $this->status = array();
84 $response = $this->Daemon( "status" );
85 $lines = split( "\n", $response->text );
86 foreach( $lines AS $k => $v ) {
87 $v = str_replace( 'status change: ( ', '', $v);
88 $v = preg_replace( '/ \)\s*$/', '', $v );
89 list( $key, $value ) = preg_split( '/:\s*/', $v, 2);
90 $this->status[$key] = $value;
93 $this->status['time'] = $this->DaemonSimple( "get_time" );
94 $this->status['started'] = date( 'Y-m-d H:i:s', time() - $this->status['time']);
95 $this->status['length'] = $this->DaemonSimple( "get_length" );
97 $this->status['state'] = ( $this->DaemonSimple("is_playing") == "1" ? "play" : "stop" );
102 * Play a track. If the current status is 'stop' then we
103 * first clear the playlist and after tell vlc to play.
105 function Play( $track ) {
106 global $c;
108 $result = $this->Daemon( sprintf('enqueue %s', $track) );
110 $this->UpdateStatus();
111 if ( $this->status['state'] == 'stop' ) {
112 $this->GetQueue();
113 $this->Daemon( sprintf('goto %d', count($this->playlist) - 1 ) );
120 * Query the vlc about it's current playlist and position
122 function GetCurrent() {
123 global $c;
125 $this->UpdateStatus();
126 $songnow = (object) array();
127 if ( $this->status['state'] == 'stop' ) return $songnow;
129 $response = $this->Daemon( "playlist" );
130 $current = split( "\n", $response->text );
131 foreach( $current AS $k => $v ) {
132 if ( preg_match( '/^\|\*.* (.*)\|([^\|]*)\|\s*$/', $v, $matches ) ) {
133 $songnow->track = $matches[1];
134 $songnow->type = $matches[2];
137 if ( $this->status['state'] == 'play' ) {
138 $songnow->started = $this->status['started'];
140 return $songnow;
144 * Query the vlc about it's current playlist and position
146 function GetQueue() {
147 global $c;
149 // $this->UpdateStatus();
150 $this->queue = array();
151 $this->playlist = array();
153 $this->current = "";
155 $response = $this->Daemon( "playlist" );
156 $playlist = split( "\n", $response->text );
157 foreach( $playlist AS $k => $v ) {
158 if ( preg_match( '/^\| .* (.*)\|([^\|]*)\|\s*$/', $v, $matches ) ) {
159 $this->playlist[] = $matches[1];
160 if ( $this->current != "" ) {
161 $this->queue[] = $matches[1];
164 elseif ( preg_match( '/^\|\*.* (.*)\|([^\|]*)\|\s*$/', $v, $matches ) ) {
165 $this->playlist[] = $matches[1];
166 $this->current = $matches[1];
170 return $this->queue;
175 $GLOBALS["vlc"] = new vlcConnection();
181 /******************************************************************
182 * The actual API the web interface calls is then very simple...
183 ******************************************************************/
186 * Queue a file for playing
188 function daemon_play_track( $path ) {
189 global $vlc;
190 error_log("adorno: DBG: Trying to play '$path'");
191 $vlc->Play( $path );
196 * Get a list of the files currently queued for the future
198 function daemon_get_queue() {
199 global $vlc;
200 $q = $vlc->GetQueue();
201 return $q;
206 * Get the currently playing track and it's starting time
208 function daemon_current_track() {
209 global $vlc;
210 return $vlc->GetCurrent();
215 * Get the currently playing track and it's starting time
217 function daemon_other_command( $action, $track ) {
218 global $vlc;
219 switch( $action ) {
220 case 'pause':
221 $vlc->Daemon($action);
222 break;
223 case 'next':
224 $vlc->Daemon($action);
225 break;
226 default:
227 error_log("adorno: ERROR: Unsupported command '$action'" );
230 return true;