| @@ -1,6 +1,7 @@ | |||
| SRCS= \ | |||
| Server.C \ | |||
| Peak_Server.C \ | |||
| Timeline_Server.C \ | |||
| main.C \ | |||
| Audio_File.C \ | |||
| @@ -17,6 +17,12 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #include "Peak_Server.H" | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include <sys/socket.h> | |||
| /* Peak Server | |||
| The peak server streams peak data to any timeline editors or other clients that ask for it. | |||
| @@ -27,6 +33,59 @@ | |||
| Response looks like (in binary floats): | |||
| > length min max min max min max | |||
| > channels length min max min max min max | |||
| length ... | |||
| */ | |||
| #include "Audio_File.H" | |||
| #include "Peaks.H" | |||
| typedef unsigned long tick_t; | |||
| #define PEAK_PORT 6100 | |||
| void | |||
| Peak_Server::handle_new ( int s ) | |||
| { | |||
| printf( "new connection\n" ); | |||
| } | |||
| void | |||
| Peak_Server::handle_hang_up ( int s ) | |||
| { | |||
| printf( "hangup\n" ); | |||
| } | |||
| void | |||
| Peak_Server::handle_request ( int s, const char *buf, int l ) | |||
| { | |||
| printf( "request: %s", buf ); | |||
| char source[512]; | |||
| float fpp; | |||
| tick_t start, end; | |||
| if ( 4 != sscanf( buf, "read_peaks \"%[^\"]\" %f %lu %lu", source, &fpp, &start, &end ) ) | |||
| fprintf( stderr, "error: malformed peak request!\n" ); | |||
| Audio_File *af = Audio_File::from_file( source ); | |||
| int channels = af->channels(); | |||
| send( s, &channels, sizeof( int ), 0 ); | |||
| for ( int i = 0; i < af->channels(); ++i ) | |||
| { | |||
| const Peaks *pk = af->peaks( i ); | |||
| int peaks = pk->fill_buffer( fpp, start, end ); | |||
| send( s, &peaks, sizeof( int ), 0 ); | |||
| send( s, pk->peakbuf(), peaks * sizeof( Peak ), 0 ); | |||
| } | |||
| delete af; | |||
| } | |||
| @@ -0,0 +1,40 @@ | |||
| /*******************************************************************************/ | |||
| /* Copyright (C) 2008 Jonathan Moore Liles */ | |||
| /* */ | |||
| /* This program is free software; you can redistribute it and/or modify it */ | |||
| /* under the terms of the GNU General Public License as published by the */ | |||
| /* Free Software Foundation; either version 2 of the License, or (at your */ | |||
| /* option) any later version. */ | |||
| /* */ | |||
| /* This program is distributed in the hope that it will be useful, but WITHOUT */ | |||
| /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ | |||
| /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */ | |||
| /* more details. */ | |||
| /* */ | |||
| /* You should have received a copy of the GNU General Public License along */ | |||
| /* with This program; see the file COPYING. If not,write to the Free Software */ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #pragma once | |||
| #include "Server.H" | |||
| class Peak_Server : public Server | |||
| { | |||
| protected: | |||
| void handle_new ( int s ); | |||
| void handle_hang_up ( int s ); | |||
| void handle_request ( int s, const char *s, int l ); | |||
| public: | |||
| Peak_Server ( int port ) : Server ( port ) | |||
| { | |||
| fork( true ); | |||
| echo( false ); | |||
| } | |||
| }; | |||
| @@ -38,27 +38,33 @@ | |||
| #include <math.h> | |||
| Peaks::peakbuffer Peaks::peakbuf; | |||
| Peaks::peakbuffer Peaks::_peakbuf; | |||
| /** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be | |||
| * called before any calls to operator[] */ | |||
| void | |||
| int | |||
| Peaks::fill_buffer ( float fpp, int s, int e ) const | |||
| { | |||
| _fpp = fpp; | |||
| if ( fpp < _peaks->chunksize ) | |||
| /* FIXME: repair this */ | |||
| // if ( fpp < _peaks->chunksize ) | |||
| { | |||
| /* looks like we're going to have to switch to a higher resolution peak file | |||
| or read directly from the source */ | |||
| read_peaks( s, e, (e - s) / fpp, fpp ); | |||
| /* FIXME: are we *SURE* we got them all? */ | |||
| return e - s; | |||
| } | |||
| else | |||
| { | |||
| /* we'll just downsample on the fly in this case--no need for extra copying into | |||
| the buffer */ | |||
| } | |||
| /* else */ | |||
| /* { */ | |||
| /* /\* we'll just downsample on the fly in this case--no need for extra copying into */ | |||
| /* the buffer *\/ */ | |||
| /* } */ | |||
| } | |||
| @@ -123,19 +129,19 @@ Peaks::read_peaks ( int s, int e, int npeaks, int chunksize ) const | |||
| { | |||
| printf( "reading peaks %d @ %d\n", npeaks, chunksize ); | |||
| if ( peakbuf.size < npeaks ) | |||
| if ( _peakbuf.size < npeaks ) | |||
| { | |||
| peakbuf.size = npeaks; | |||
| // printf( "reallocating peak buffer %li\n", peakbuf.size ); | |||
| peakbuf.buf = (peakdata*)realloc( peakbuf.buf, sizeof( peakdata ) + (peakbuf.size * sizeof( Peak )) ); | |||
| _peakbuf.size = npeaks; | |||
| // printf( "reallocating peak buffer %li\n", _peakbuf.size ); | |||
| _peakbuf.buf = (peakdata*)realloc( _peakbuf.buf, sizeof( peakdata ) + (_peakbuf.size * sizeof( Peak )) ); | |||
| } | |||
| _clip->open(); | |||
| _clip->seek( s ); | |||
| peakbuf.offset = s; | |||
| peakbuf.buf->chunksize = chunksize; | |||
| peakbuf.len = clip_read_peaks( peakbuf.buf->data, npeaks, chunksize ); | |||
| _peakbuf.offset = s; | |||
| _peakbuf.buf->chunksize = chunksize; | |||
| _peakbuf.len = clip_read_peaks( _peakbuf.buf->data, npeaks, chunksize ); | |||
| _clip->close(); | |||
| } | |||
| @@ -149,17 +155,17 @@ Peaks::peak ( nframes_t start, nframes_t end ) const | |||
| if ( _fpp < _peaks->chunksize ) | |||
| { | |||
| assert( _fpp == peakbuf.buf->chunksize ); | |||
| assert( _fpp == _peakbuf.buf->chunksize ); | |||
| start = (start - peakbuf.offset) / peakbuf.buf->chunksize; | |||
| end = (end - peakbuf.offset) / peakbuf.buf->chunksize; | |||
| start = (start - _peakbuf.offset) / _peakbuf.buf->chunksize; | |||
| end = (end - _peakbuf.offset) / _peakbuf.buf->chunksize; | |||
| if ( end > peakbuf.len ) | |||
| end = peakbuf.len; | |||
| if ( end > _peakbuf.len ) | |||
| end = _peakbuf.len; | |||
| // assert( peakbuf.len > start ); | |||
| // assert( _peakbuf.len > start ); | |||
| downsample( peakbuf.buf->data, start, end, &p.max, &p.min ); | |||
| downsample( _peakbuf.buf->data, start, end, &p.max, &p.min ); | |||
| } | |||
| else | |||
| { | |||
| @@ -175,17 +181,18 @@ Peaks::peak ( nframes_t start, nframes_t end ) const | |||
| /* virtual array. Index is a Pixel value, and it returns the | |||
| * (resampled) peaks for that pixel based on the current timeline | |||
| * zoom. */ | |||
| Peak & | |||
| Peaks::operator[] ( int X ) const | |||
| { | |||
| Peak p; | |||
| p.min = 0; | |||
| p.max = 0; | |||
| return p; | |||
| // return peak( timeline->x_to_ts( X ), timeline->x_to_ts( X + 1 ) ); | |||
| /* Peak & */ | |||
| /* Peaks::operator[] ( int X ) const */ | |||
| /* { */ | |||
| } | |||
| /* Peak p; */ | |||
| /* p.min = 0; */ | |||
| /* p.max = 0; */ | |||
| /* return p; */ | |||
| /* // return peak( timeline->x_to_ts( X ), timeline->x_to_ts( X + 1 ) ); */ | |||
| /* } */ | |||
| const char * | |||
| @@ -54,7 +54,7 @@ class Peaks | |||
| } | |||
| }; | |||
| static peakbuffer peakbuf; | |||
| static peakbuffer _peakbuf; | |||
| Audio_File *_clip; | |||
| int _channel; | |||
| @@ -96,10 +96,11 @@ public: | |||
| _channel = 0; | |||
| } | |||
| Peak *peakbuf ( void ) const { return Peaks::_peakbuf.buf->data; } | |||
| void clip ( Audio_File *c ) { _clip = c; } | |||
| void channel ( int v ) { _channel = v; } | |||
| void fill_buffer ( float fpp, int s, int e ) const; | |||
| int fill_buffer ( float fpp, int s, int e ) const; | |||
| void downsample ( Peak *peaks, int s, int e, float *mhi, float *mlo ) const; | |||
| void read ( int X, float *hi, float *lo ) const; | |||
| @@ -83,6 +83,8 @@ Server::listen_on_port ( int port ) | |||
| Server::Server ( int port ) | |||
| { | |||
| _port = port; | |||
| _echo = false; | |||
| _fork = false; | |||
| } | |||
| void | |||
| @@ -159,7 +161,7 @@ Server::run ( void ) | |||
| else | |||
| { | |||
| if ( echos() ) | |||
| if ( echo() ) | |||
| /* echo to others */ | |||
| for ( int j = maxfd; j-- ; ) | |||
| { | |||
| @@ -17,10 +17,14 @@ | |||
| /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
| /*******************************************************************************/ | |||
| #pragma once | |||
| class Server | |||
| { | |||
| int _port; | |||
| bool _echo; | |||
| bool _fork; | |||
| static int listen_on_port ( int port ); | |||
| @@ -29,9 +33,13 @@ public: | |||
| Server ( int port ); | |||
| void run ( void ); | |||
| bool echo ( void ) { return _echo; } | |||
| bool fork ( void ) { return _fork; } | |||
| void echo ( bool b ) { _echo = b; } | |||
| void fork ( bool b) { _fork = b; } | |||
| protected: | |||
| virtual bool echos ( void ) { return true; } | |||
| virtual void handle_hang_up ( int s ) = 0; | |||
| virtual void handle_new ( int s ) = 0; | |||
| @@ -34,5 +34,7 @@ public: | |||
| Timeline_Server ( int port ) : Server ( port ) | |||
| { | |||
| fork( false ); | |||
| echo( true ); | |||
| } | |||
| }; | |||
| @@ -26,6 +26,7 @@ | |||
| #include "Timeline_Server.H" | |||
| #include "Peak_Server.H" | |||
| /* TODO: | |||
| @@ -60,7 +61,13 @@ | |||
| int | |||
| main ( int argc, char **argv ) | |||
| { | |||
| Timeline_Server tls( 6110 ); | |||
| tls.run(); | |||
| /* Timeline_Server tls( 6110 ); */ | |||
| /* tls.run(); */ | |||
| Peak_Server pks( 6111 ); | |||
| pks.run(); | |||
| } | |||