Roxen.git / server / modules / icecast / icecast.pike

version» Context lines:

Roxen.git/server/modules/icecast/icecast.pike:1: + // This is a roxen module. Copyright © 2001 - 2009, Roxen IS. +    inherit "module"; - constant cvs_version="$Id: icecast.pike,v 1.7 2001/04/17 04:34:09 per Exp $"; + constant cvs_version="$Id$";   constant thread_safe=1;      #define BSIZE 8192   #define METAINTERVAL 4192      #include <module.h>   #include <roxen.h>   #include <stat.h>   #include <request_trace.h>   
Roxen.git/server/modules/icecast/icecast.pike:59:    void call_callbacks( mixed ... args )    {    foreach( callbacks, function f )    if( mixed e = catch( f(@args) ) )    {    werror(describe_backtrace( e ) );    remove_callback( f );    }    }    -  static int last_hrtime, base_time; +  protected int last_hrtime, base_time;       int realtime()    {    if(!last_hrtime)    {    last_hrtime = gethrtime();    base_time = 0;    }    else    {
Roxen.git/server/modules/icecast/icecast.pike:117:    }    call_out( feeder_thread, 0.02 );    }       void start()    {    feeder_thread( ); // not actually a thread right now.    }       // Low level code. -  static string buffer; -  static int bpos; +  protected string buffer; +  protected int bpos;    -  static string|int getbytes( int n, int|void s ) +  protected string|int getbytes( int n, int|void s )    {    if( !fd )    fd = playlist->next_file();    if( !fd )    return s?0:-1;       if( !buffer || !strlen(buffer) )    {    bpos = 0;    buffer = fd->read( BSIZE );
Roxen.git/server/modules/icecast/icecast.pike:170:    {    bpos = 0;    buffer = fd->read( BSIZE );    if( !buffer || !strlen( buffer ) )    return -1;    }    }    return res;    }    -  static int rate_of(int r) +  protected int rate_of(int r)    {    switch(r)    {    case 0: return 44100;    case 1: return 48000;    case 2: return 32000;    default:return 44100;    }    }    -  static array(array(int)) bitrates = +  protected array(array(int)) bitrates =    ({    ({0,32,64,96,128,160,192,224,256,288,320,352,384,416,448}),    ({0,32,48,56,64,80,96,112,128,160,192,224,256,320,384}),    ({0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}),    });    -  static string get_frame() +  protected string get_frame()    {    string data;    /* Find header */    int trate = 0;    int patt = 0;    int by, p=0, sw=0;    while( (by = getbytes( 1 )) > 0 )    {    patt <<= 8;    patt |= by;    p++;    if( (patt & 0xfff0) == 0xfff0 )    { -  int srate, channels, layer, ID, pad, blen; +  int srate, layer, ID, pad, blen;    int header = ((patt&0xffff)<<16);    if( (by = getbytes( 2 )) < 0 )    break;    header |= by;       string data = sprintf("%4c",header);    patt=0;    header <<= 12;       int getbits( int n )
Roxen.git/server/modules/icecast/icecast.pike:302:    denied++;    return Roxen.http_string_answer( "Too early\n" );    }       connections++;    int use_metadata;    string i, metahd="";    string protocol = "ICY";       werror("%O\n", id->request_headers ); -  if( id->request_headers[ "icy-metadata" ] ) +  if( 0 && id->request_headers[ "icy-metadata" ] )    { - // use_metadata = (int)id->request_headers[ "icy-metadata" ]; - // if( use_metadata ) - // metahd = "icy-metaint:"+METAINTERVAL+"\r\n"; +  use_metadata = (int)id->request_headers[ "icy-metadata" ]; +  if( use_metadata ) +  metahd = "icy-metaint:"+METAINTERVAL+"\r\n";    }       if( id->request_headers[ "x-audiocast-udpport" ] )    {    protocol = "AudioCast";    i = ("HTTP/1.0 200 OK\r\n"    "Server: "+roxen.version()+"\r\n"    "Content-type: audio/mpeg\r\n"    "x-audiocast-gengre:"+(meta->gengre||"unknown")+"\r\n"    +((meta->url||url)?"x-audiocast-url:"+(meta->url||url)+"\r\n":"")+
Roxen.git/server/modules/icecast/icecast.pike:342:    "icy-gengre:"+(meta->gengre||"unknown")+"\r\n"    +((meta->url||url)?"icy-url:"+(meta->url||url)+"\r\n":"")+    "icy-pub:1\r\n"    "icy-br:"+(stream->bitrate/1000)+"\r\n"    "\r\n" );    }    if( initial )    i += initial;       conn += ({ Connection( id->my_fd, i,protocol,use_metadata, -  stream, +  stream, this_object(),    lambda( Connection c ){    int pt = time()-c->connected;    conn -= ({ c });    total_time += pt;    if( pt > max_time )    max_time = pt;    successful++;    connections--;    } ) });    return Roxen.http_pipe_in_progress( );
Roxen.git/server/modules/icecast/icecast.pike:410:   }      mapping(string:Location) locations = ([]);      int __id=1;      class Connection   {    Stdio.File fd;    MPEGStream stream; -  int do_meta, last_meta; +  Location location; +  int do_meta, meta_cnt;    string protocol;    int sent, skipped; // frames. -  int sent_bytes; +  int sent_bytes, sent_meta;    int id = __id++;    array buffer = ({});    string current_block;    function _ccb;    mapping current_md;       int connected = time();       string status()    {    if(!fd)    return "Closed stream\n";    return sprintf( "%d. %s Time: %ds Remote: %s "    "%d sent, %d skipped<br />",id,protocol,    time()-connected,    (fd->query_address()/" ")[0],    sent, skipped );    }    -  +  string old_mdkey;    string gen_metadata( )    { -  if(!current_md ) +  string s = " "; +  if( !current_md )    current_md = stream->playlist->metadata(); -  string s = sprintf( " StreamTitle='%s';StreamUrl='%s';", +  if( (current_md->name||current_md->path)+current_md->url != old_mdkey ) +  { +  old_mdkey = (current_md->name||current_md->path)+current_md->url; +  s = sprintf( " StreamTitle='%s';StreamUrl='%s';",    current_md->name || current_md->path, -  "")+"\0"; -  while( strlen(s) & 15 ) s+= "\0"; -  s[0]=strlen(s); +  current_md->url || location->url ); +  } +  while( strlen(s) & 15 ) +  s+= "\0"; +  s[ 0 ]=strlen(s)/16; +  werror("%O\n", s );    return s;    }    -  static void callback( string frame ) +  protected void callback( string frame )    {    buffer += ({ frame });    if( sizeof( buffer ) > 100 )    {    skipped++;    buffer = buffer[1..];    }    if( sizeof( buffer ) == 1 )    {    remove_call_out( send_more );    call_out( send_more, 0.01 );    }    }       int headers_done;    -  static void send_more() +  protected void send_more()    {    if( !strlen(current_block) )    {    headers_done = 1;    if( !sizeof(buffer) )    return;    current_block = buffer[0];       if( do_meta )    { -  if( (strlen( current_block ) + sent_bytes) - last_meta >= METAINTERVAL ) +  meta_cnt += strlen( current_block ); +  if( meta_cnt >= METAINTERVAL )    { -  last_meta = (strlen( current_block ) + sent_bytes); -  current_block += gen_metadata(); +  string meta; +  meta_cnt -= METAINTERVAL; +  int rest = strlen(current_block)-meta_cnt-1; +  sent_meta += strlen(meta = gen_metadata()); +  current_block = current_block[..rest]+meta+current_block[rest];    }    }    buffer = buffer[1..];    sent++;    }    int n = fd->write( current_block );    if( n > 0 )    {    if( headers_done )    sent_bytes += n;    current_block = current_block[n..];    }    else if( n < 0 )    closed();    }    -  static void md_callback( mapping metadata ) +  protected void md_callback( mapping metadata )    {    current_md = metadata;    }    -  static void closed( ) +  protected void closed( )    {    fd->set_blocking( );    fd = 0;    stream->remove_callback( callback );    stream->playlist->remove_md_callback( md_callback );    _ccb( this_object() );    werror("Closed from client side\n");   // destruct( this_object() );    }    -  static void create( Stdio.File _fd, string buffer, +  protected void create( Stdio.File _fd, string buffer,    string prot, int _meta, MPEGStream _stream, -  function _closed ) +  Location _loc, function _closed )    { -  +  location = _loc;    protocol = prot;    fd = _fd;    do_meta = _meta;    stream = _stream;    _ccb = _closed;    current_block = buffer;    fd->set_nonblocking( lambda(){}, send_more, closed );    if( stream )    stream->add_callback( callback );    if( stream->playlist )
Roxen.git/server/modules/icecast/icecast.pike:595:    mapping decode_stream( string s )    {    mapping m = ([]);    array a = s/"\0";    m->location = a[0];    if( sizeof( a ) > 1 ) m->playlist = a[1];    if( sizeof( a ) > 2 ) m->jingle = a[2];    if( sizeof( a ) > 3 ) m->maxconn = (int)a[3];    if( sizeof( a ) > 4 ) m->url = a[4];    if( sizeof( a ) > 5 ) m->name = a[5]; -  if( !strlen( m->jingle ) ) m_delete( m, "jingle" ); -  if( !strlen( m->url ) ) m_delete( m, "url" ); -  if( !strlen( m->name ) ) m_delete( m, "name" ); +  if( !m->jingle || !strlen( m->jingle ) ) m_delete( m, "jingle" ); +  if( !m->url || !strlen( m->url ) ) m_delete( m, "url" ); +  if( !m->name || !strlen( m->name ) ) m_delete( m, "name" );    return m;    }    array(mapping) get_streams()    {    return map( query(), decode_stream );    }   }      void create()   {