forked from Distrotech/esound
-
Notifications
You must be signed in to change notification settings - Fork 0
/
filter.c
137 lines (116 loc) · 3.54 KB
/
filter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#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;
}