diff options
Diffstat (limited to 'filter.c')
-rw-r--r-- | filter.c | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/filter.c b/filter.c new file mode 100644 index 0000000..00da459 --- /dev/null +++ b/filter.c @@ -0,0 +1,137 @@ +#include "esd-server.h" + +esd_player_t *esd_filter_list = NULL; + +translate_func_t esd_first_filter_func; + +/*******************************************************************/ +/* send the filter's buffer to it's associated socket, erase if EOF */ +int filter_write( void *buffer, int size, esd_format_t format, int rate ) +{ + int actual=0, total_data=0, data_size=0; + esd_player_t *filter=esd_filter_list, *erase=NULL; + + /* if no filters, skip it */ + if( !esd_filter_list ) { + return size; + } + + /* translate into the first filter buffer */ + data_size = esd_first_filter_func( filter->data_buffer, + filter->buffer_length, + filter->rate, + filter->format, + buffer, + size, + rate, + format ); + + /* hop through the list of filters */ + while( filter ) { + /* fprintf( stderr, "filter_write: writing to new filter...\n" ); */ + + /* write the data data_buffer to the socket */ + total_data = 0; + actual = 0; + erase = NULL; + + /* All of the data from the previous read has to be written. + * There's no way I can think of to get around this w/o losing data. + * Maybe by using fread and fwrite, to buffer the stuff, but in the + * end, all the data still has to be written from here to the buffer. + */ + while( total_data < data_size ) + { + ESD_WRITE_BIN( filter->source_id, filter->data_buffer + total_data, + data_size - total_data, actual, "flt wr" ); + + if ( actual <= 0 ) { + erase = filter; + total_data = data_size; + } else { + total_data += actual; + } + /* fprintf( stderr, "filter_write: just wrote %d bytes\n", actual ); */ + } + + /* make sure the filter is still alive before we read from it */ + if ( !erase ) { + actual = read_player( filter ); + if (actual >= 0) + filter->actual_length -= actual; + else + erase = filter; + } + + /* translate data to next filter whether current one is alive or not */ + if ( filter->next ) { + /* translate to next filter */ + data_size = filter->translate_func( filter->next->data_buffer, + filter->next->buffer_length, + filter->next->rate, + filter->next->format, + filter->data_buffer, + filter->buffer_length, + filter->rate, + filter->format ); + } else { + /* translate to audio buffer */ + data_size = filter->translate_func( buffer, + size, + rate, + format, + filter->data_buffer, + filter->buffer_length, + filter->rate, + filter->format ); + } + + /* next filter... */ + filter = filter->next; + + /* clean up any finished filters */ + if ( erase != NULL ) { + erase_filter( erase ); + erase = NULL; + } + } + + return data_size; +} + +/*******************************************************************/ +/* erase a filter from the filter list */ +void erase_filter( esd_player_t *filter ) +{ + esd_player_t *previous = NULL; + esd_player_t *current = esd_filter_list; + + /* iterate until we hit a NULL */ + while ( current != NULL ) + { + /* see if we hit the target filter */ + if ( current == filter ) { + if( previous != NULL ){ + /* we are deleting in the middle of the list */ + previous->next = current->next; + } else { + /* we are deleting the head of the list */ + esd_filter_list = current->next; + } + + /* TODO: delete if needed */ + free_player( filter ); + + return; + } + + /* iterate through the list */ + previous = current; + current = current->next; + } + + /* hmm, we didn't find the desired filter, just get on with life */ + ESDBG_TRACE( printf( "-%02d- filter not found\n", filter->source_id ); ); + return; +} + |