source: plugins_spip/spip2liquidsoap/classes/savonet.php @ 6285

Last change on this file since 6285 was 6285, checked in by kent1, 8 years ago

Eviter une erreur si les métadatas ne sont pas en array

File size: 10.3 KB
Line 
1<?php
2
3/**
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <franksp@internl.net> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return Frank Spijkerman
9 * ----------------------------------------------------------------------------
10 *
11 * @package savonet
12 * @copyright 2008, Frank Spijkerman
13 *  for the Savonet Project
14 */
15
16class savonet {
17        /**
18         * The hostname of the liquidsoap
19         * server
20         * @var string
21         */
22        private $hostname;
23
24        /**
25         * The post of the liquidsoap server
26         * @var integer
27         */
28        private $port;
29
30        /**
31         * Array for storage of the stream list,
32         * this is used for caching.
33         * @var array
34         */
35        private $streams = array();
36
37        /**
38         * Constructor
39         *
40         * Prepares some settings
41         *
42         * @param string $hostname
43         *   The hostname of liquidsoap
44         * @param integer $port
45         *   The port of liquidsoap, usualy 1234
46         */
47        function __construct($hostname = 'localhost', $port = 1234)
48        {
49                $this->hostname = $hostname;
50                $this->port = $port;
51        }
52
53        /**
54         * Destructor
55         *
56         * Disconnects the connection if there is any.
57         */
58        function __destruct()
59        {
60                // disconnect
61                $this->disconnect();
62        }
63
64        /**
65         * This function makes the connection to savonet
66         */
67        public function connect()
68        {
69                // Make this socket
70                if (!($this->sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) { 
71                        echo "Error Creating Socket: ".socket_strerror(socket_last_error()); 
72                        return false;
73        } 
74
75                // Connect
76                if (!($connected = @socket_connect($this->sock, $this->hostname, $this->port))){
77                        $this->sock = '';
78                        return false;
79                }else{
80                        $this->stream_list();
81                }
82        }
83
84        /**
85         * Disconnect from liquidsoap ;(
86         */
87        public function disconnect()
88        {
89                // say good bye politely, then close the socket.
90                if ($this->sock) {
91                        $this->write("exit");
92                        socket_close($this->sock);
93                }
94        }
95
96        /**
97         * queue_list
98         *
99         * Returns a list with the current items in the queue
100         *
101         * @param string $name
102         *   The name of the queue
103         * @return array
104         */
105        public function queue_list($name)
106        {
107                // check for the name
108                if (empty($name))
109                        return;
110
111                // Check if the stream is available
112                if (($stream = $this->checkStreamType($name, "queue")) === FALSE)
113                        throw new Exception("No such stream $name, or of the wrong type");
114
115                $data = $this->write($name . ".queue");
116
117                // Return an empty array when nothing in the queue
118                if (empty($data[0]))
119                        return array();
120
121                // Enrich the data with metadata
122                $rv = array();
123                foreach(explode(" ", $data[0]) as $i)
124                        $rv[] = $this->get_metadata($i);
125
126                return $rv;
127        }
128
129        /**
130         * queue_push
131         *
132         * Adds an URI to the queue
133         * @param string $name
134         * @param string $uri
135         */
136        public function queue_push($name, $uri)
137        {
138                // gimme some input
139                if (empty($name) && empty($uri))
140                        return;
141
142                // Check if the stream is available
143                if (($stream = $this->checkStreamType($name, "queue")) === FALSE)
144                        throw new Exception("No such stream $name, or of the wrong type");
145
146                $data = $this->write($name . ".push " . $uri);
147
148                // Check if valid uri
149                if (empty($data[0]))
150                        return array();
151
152                // Return the metadata aswel.
153                return $this->get_metadata($data[0]);
154        }
155
156        /**
157         * queue_move
158         *
159         * Moves a rid in the queue to a new position.
160         *
161         * @param string $name
162         *   Name of the queue
163         * @param string $rid
164         *   Record id
165         * @param string $pos
166         *   New position
167         */
168        public function queue_move($name, $rid, $pos)
169        {
170                // Gimme
171                if (empty($name) && !is_numeric($rid) &&
172                                !is_numeric($pos))
173                        return;
174
175                // Check if the stream is available
176                if (($stream = $this->checkStreamType($name, "queue")) === FALSE)
177                        throw new Exception("No such stream $name, or of the wrong type");
178
179                return $this->write($name . ".move $rid $pos");
180        }
181
182        /**
183         * queue_insert
184         *
185         * Inserts a rid at a specific pos.
186         *
187         * @param string $name
188         *   The name of the queue
189         * @param string $pos
190         *   The position
191         * @param string $uri
192         *   The uri
193         */
194        public function queue_insert($name, $pos, $uri)
195        {
196                // Check input
197                if (empty($name) && !is_numeric($pos) && empty($uri))
198                        return;
199
200                // Check if the stream is available
201                if (($stream = $this->checkStreamType($name, "queue")) === FALSE)
202                        throw new Exception("No such stream $name, or of the wrong type");
203
204                return $this->write($name . ".insert $pos $uri");
205        }
206
207        /**
208         * queue_remove
209         *
210         * Removes a rid from the queue
211         *
212         * @param string $name
213         * @param integer $rid
214         * @return array
215         */
216        public function queue_remove($name, $rid)
217        {
218                if (empty($name) && !is_numeric($rid))
219                        return;
220
221                // Check if the stream is available
222                if (($stream = $this->checkStreamType($name, "queue")) === FALSE)
223                        throw new Exception("No such stream $name, or of the wrong type");
224
225                return $this->write($name . ".remove " . $rid);
226        }
227
228        /**
229         * stream_list
230         *
231         * Fetches the list of available streams
232         * and formats it in a nice array and returns that.
233         *
234         * @return array
235         */
236        public function stream_list()
237        {
238                $retval = $this->write("list");
239                $list = array();
240                if(is_array($retval)){
241                        foreach ($retval as $rv){
242                                $rv = explode(" : ", $rv);
243                                $list_add['name'] = $rv[0];
244                                $list_add['type'] = $rv[1];
245                                unset($list_add['uri']);
246                                if($rv[1] == 'playlist'){
247                                        $url = $this->write($list_add['name'].".uri");
248                                        $list_add['uri'] = $url[0];
249                                }
250                                $list[] = $list_add;
251                        }
252                }
253                // save it for caching
254                $this->streams = $list;
255
256                return $list;
257        }
258
259        /**
260         * now_playing
261         *
262         * returns a formated string with the current
263         * thats playing.
264         *
265         * @return string $song
266         */
267        public function now_playing($retour='string')
268        {
269                $retval = $this->write("list");
270                if(is_array($retval)){
271                        foreach ($retval as $rv){
272                                $list = explode(" : ", $rv);
273                                if(preg_match('/output/',$rv)){
274                                        $output = $list[0];
275                                        break;
276                                }
277                        }
278                }
279                $metadatas_output = $this->write($output.'.metadata');
280
281                if(!is_array($metadatas_output))
282                        $metadatas_output = array();
283               
284                while (list(, $val) = each($metadatas_output)) {
285                    if ($val == '--- 1 ---') {
286                        break;
287                    }
288                   array_shift($metadatas_output);
289                }
290               
291                foreach ($metadatas_output as $rv)
292                {
293                        list($key, $value) = split('=', $rv, 2);
294                        // Remove the quotes
295                        $value = trim($value, '"');
296                        $md[$key] = $value;
297                }
298
299                if($retour== 'array'){
300                        return $md;
301                }
302               
303                $retour = $md['artist'] ? $md['artist']. " - ":'';
304                $retour .= $md['title'];
305                return $retour;
306        }
307
308        /**
309         * on_air
310         *
311         * @return int $current_song
312         *   return the 'rid' of the current song
313         */
314        public function on_air()
315        {
316                return $this->write("request.on_air");
317        }
318
319        /**
320         * checkStreamType
321         *
322         * Checks if the stream if of the correct type
323         *
324         * @param string $name
325         *   The name of the stream
326         * @param string $type
327         *   The type of the stream, like output. or queue.
328         */
329        private function checkStreamType($name, $type)
330        {
331                // Get the cache if empty
332                if (empty($this->streams))
333                        $this->stream_list();
334
335                foreach ($this->streams as $stream)
336                {
337                        // search for the name and check the type
338                        if ($stream['name'] == $name && strstr($stream['type'], $type))
339                                return $stream;
340                }
341
342                return FALSE;
343        }
344
345        /**
346         * Skip
347         *
348         * Skip is only available on a few stream types.
349         * so it has to check first it its allowed.
350         *
351         * @param string $name
352         *   The name of the stream
353         */
354        public function skip($name)
355        {
356                // Check the stream
357                if (($stream = $this->checkStreamType($name, "output.")) === FALSE)
358                        throw new Exception("No such stream $name, or of the wrong type");
359
360                $this->write($name . ".skip");
361        }
362
363        /**
364         * get_full_metadata
365         *
366         * @param string $name
367         *   The name of the stream
368         * @return Object
369         *   An object filled with all the infos.
370         */
371        public function get_full_metadata($name)
372        {
373                if (empty($name))
374                        return;
375
376                if (($stream = $this->checkStreamType($name, "output") === FALSE) && ($stream = $this->checkStreamType($name, "store_metadata") === FALSE))
377                        return false;
378
379                if($this->checkStreamType($name, "output") != FALSE){
380                        $retval = $this->write($name.".metadata");
381                }else{
382                        $retval = $this->write($name.".get");
383                }
384
385                // Lets parse it
386                $md = array();
387                $i = 0;
388                foreach ($retval as $rv)
389                {
390                        if(preg_match('/--- ([1-9].*) ---/',$rv)){
391                                $i = $i+1;
392                        }else{
393                                list($key, $value) = split('=', $rv, 2);
394                                // Remove the quotes
395                                $value = trim($value, '"');
396                                $md[$i][$key] = $value;
397                        }
398                }
399                return $md;
400        }
401
402        /**
403         * get_metadata
404         *
405         * @param string $rid
406         *   This id of the song.
407         * @return Object
408         *   An object filled with all the info.
409         */
410        public function get_metadata($rid)
411        {
412                if (empty($rid) OR !intval($rid))
413                        return;
414
415                $retval = $this->write("request.metadata " . $rid);
416
417                // No such request
418                if ($retval[0] == 'No such request.')
419                        return;
420                // Lets parse it
421                $md = array();
422                foreach ($retval as $rv)
423                {
424                        list($key, $value) = split('=', $rv, 2);
425                        // Remove the quotes
426                        $value = trim($value, '"');
427                        $md[$key] = $value;
428                }
429                return $md;
430        }
431
432        /**
433         * is_alive
434         *
435         * Connects to the savonet server and returns alive
436         *
437         * @return string
438         * Active Queue, 0 = none.
439         */
440        public function is_alive()
441        {
442                $test = $this->write("request.alive");
443                return $test;
444        }
445
446        /**
447         * write
448         *
449         * Writes and reads stuff from savo
450         * Because we are lazy.
451         *
452         * @param string $what
453         *   The msg thats getting passed to savonet.
454         */
455        function write($what)
456        {
457                if($this->is_connected()){
458
459                        // Write to socket
460                        if (socket_write($this->sock, $what . "\n") == FALSE)
461                                throw Exception("Unable to write to socket: " .
462                                        socket_strerror(socket_last_error())
463                                );
464                        if($what == "exit")
465                                return true;
466                        // Loop on each line and push it to an array
467                        while ($buffer = socket_read($this->sock, 512, PHP_NORMAL_READ))
468                        {
469                                if((trim($buffer) != '') && (!in_array(trim($buffer),array('BEGIN','END')))){
470                                        $buf[] = trim($buffer);
471                                }
472                                if (preg_match('/END/',$buffer)){
473                                        break;
474                                }
475                        }
476                        return $buf;
477                }else{
478                        return false;
479                }
480
481        }
482
483        /**
484         * is_connected
485         *
486         * Check if the connection is connected otherwise
487         * throws an exception if $throw is true.
488         *
489         * @params $throw bool
490         *   throws an exception or not. default true.
491         * @return bool
492         *   returns 1 if connected. 0 if not.
493         *   only returns 0 when $throw is false
494         */
495        public function is_connected($throw = false)
496        {
497                if ($this->sock == FALSE)
498                        if ($throw)
499                                throw new Exception("Socket is not connected.");
500                        else
501                                return false;
502
503                return 1;
504        }
505}
Note: See TracBrowser for help on using the repository browser.