Location: PHPKode > scripts > PHP Shoutcast Server > php-shoutcast-server/shoutcast.php
<?php // $Id$
/*
 * Copyright (c) sk89q <http://sk89q.therisenrealm.com>
 * Licensed under the GNU General Public License v3
*/

class Shoutcast
{	
    public $server_hook_id = 'SHOUTCAST';

    public $address = '0.0.0.0';
    public $port = 45400;
    
    public $server;
    public $source;
    
    public $metadata_interval = 8192;
    
    public $server_name;
    public $server_genre;
    public $server_url;
    public $server_public;
    
    public $note_string = 'This stream requires <a href="http://www.winamp.com/">Winamp</a>';
    private $server_string = 'PHPShoutcast/1.0';
    
    public function hook_to_server() 
    {
        $this->server->hook_processor($this->server_hook_id, $this);
        
        $err = array();
        $master = stream_socket_server("tcp://{$this->address}:{$this->port}", 
            $err['errno'], $err['errstr']);

        $this->server->hook_master($this->server_hook_id, $master);
    }
    
    public function server_interweave() 
    {            
        $media_data = $this->source->data_chunk();
        foreach($this->server->listeners as $listener) {
            if ($this->server->clients[$listener]['processor'] == $this->server_hook_id && 
                $this->server->clients[$listener]['type'] == 'child' &&
                $this->server->clients[$listener]['_i'] == '1') {                    
                /*if ($this->server->clients[$listener]['_audiodatasent'] + strlen($media_data) > $this->metadata_interval) {
                    $new_data = substr($media_data, 0, $this->metadata_interval - $this->server->clients[$listener]['_audiodatasent']);
                    @stream_socket_sendto($listener, $new_data);
                    
                    $metadata = $this->source->playlist[$this->source->current_index][0];
                    
                    if (strlen($metadata) % 16 == 0) {
                        $pad = 16;
                    } else {
                        $pad = 16 - (strlen($metadata) - (strlen($metadata) % 16));
                    }
                    
                    $metadata .= pack(str_repeat('x', $pad));
                    
                    $metadata = pack('c', strlen($metadata) / 16) . $metadata;
                    echo "\n" . strlen($metadata) . '-' . strlen($metadata) / 16 . '-' . $pad;
                    @stream_socket_sendto($listener, $pad);
                    
                    $new_data = substr($media_data, $this->metadata_interval - $this->server->clients[$listener]['_audiodatasent'] + 1);
                    $this->server->clients[$listener]['_audiodatasent'] = strlen($new_data);
                    @stream_socket_sendto($listener, $new_data);
                    unset($new_data);
                } else {*/
                    $this->server->clients[$listener]['_audiodatasent'] += strlen($media_data);
                    @fwrite($listener, $media_data);
                //}
            }
        }
    }
    
    public function server_new_connection(&$new_client) 
    {
        $this->server->listeners[] = $new_client;
        $this->server->clients[$new_client] = array(
            'processor' => $this->server_hook_id,
            'type' => 'child',
            '_i' => 0,
          );
        stream_set_blocking($new_client, 0);
    }
    
    public function server_data_in(&$client, $data) 
    {
        $data = str_replace("\r", "", $data);
        $lines = explode("\n", $data);
        
        $request = '';
        $headers = array();
        $body = '';
        
        $seen_request = false;
        $seen_headers = false;
        
        foreach($lines as $line) {
            $trimmed = trim($line);
            if (!$seen_request) {
                $request = $trimmed;
                $seen_request = true;
            } elseif(!$seen_headers && $trimmed == '') {
                $seen_headers = true;
            } elseif(!$seen_headers) {
                $header = explode(':', $trimmed, 2);
                $headers[strtolower($header[0])] = ltrim($header[1]);
            } else {
                $body .= $line;
            }
        }
        
        if (preg_match('`GET / HTTP/1\.(0|1)`', $request)) {
            $this->server->clients[$client]['_i'] = 1;
            $this->server->clients[$client]['_useragent'] = $headers['user-agent'];
            $this->server->clients[$client]['_metadata'] = intval($headers['icy-metadata']);
            $this->server->clients[$client]['_remote'] = stream_socket_get_name($client, true);
            $this->server->clients[$client]['_joined'] = time();
        
            $welcome = "ICY 200 OK\r\n";
            $welcome .= "Content-Type:audio/mpeg\r\n";
            $welcome .= "icy-notice1:" . $this->notice_string . "\r\n";
            $welcome .= "icy-notice2:" . $this->server_string . "\r\n";
            if ($this->server_name) $welcome .= "icy-name:{$this->server_name}\r\n";
            if ($this->server_genre) $welcome .= "icy-genre:{$this->server_genre}\r\n";
            if ($this->server_url) $welcome .= "icy-url:{$this->server_url}\r\n";
            $welcome .= "icy-pub:" . ($this->server_public ? 1 : 0) . "\r\n";
            $welcome .= "icy-br:" . $this->source->bitrate . "\r\n";
            //$welcome .= "icy-prebuffer:" . $this->source->bitrate . "\r\n";
            //$welcome .= "icy-metaint:8192\r\n";
            $welcome .= "\r\n";
            
            if (!$this->source->new_track) {
                $welcome .= $this->source->track_header;
            }
            
            @stream_socket_sendto($client, $welcome);
            
            $this->list_users();
        }
    }
    
    public function server_lost_connection(&$client) 
    {                
        foreach($this->server->listeners as $k => $l) if ($l == $client) unset($this->server->listeners[$k]);
        foreach($this->server->clients as $k => $l) if ($k == $client) unset($this->server->clients[$k]);
        @fclose($client);
        
        $this->list_users();
    }
    
    public function list_users() 
    {
        $count = 0;
        $list = '';
        
        foreach($this->server->listeners as $listener) {
            if ($this->server->clients[$listener]['processor'] == $this->server_hook_id && 
                $this->server->clients[$listener]['type'] == 'child' &&
                $this->server->clients[$listener]['_i'] == '1') {
                $client = $this->server->clients[$listener];
                
                $count++;
                $list .= "\n" . sprintf('* %-22s %s', $client['_remote'], $client['_useragent']);
            }
        }
    
        echo <<<EOB
\n\n\n
<Users Listening: {$count}>$list
EOB;
    }
}

Return current item: PHP Shoutcast Server