Mercurial > mplayer.hg
annotate libao2/ao_plugin.c @ 13815:8d8800a5f662
-sync 1.798
-some Polish fixes
author | wight |
---|---|
date | Sat, 30 Oct 2004 17:49:53 +0000 |
parents | 6c5620360391 |
children | a92101a7eb49 |
rev | line source |
---|---|
6237 | 1 #include "../config.h" |
2 | |
3096 | 3 #include <stdio.h> |
4 #include <stdlib.h> | |
6237 | 5 #include <string.h> |
3096 | 6 |
13467 | 7 #include "mp_msg.h" |
8 #include "help_mp.h" | |
3194
1648d11fc36c
commandline configuration of audio plugins now through struct, format conversion plugin added
anders
parents:
3107
diff
changeset
|
9 #include "afmt.h" |
3096 | 10 #include "audio_out.h" |
11 #include "audio_out_internal.h" | |
12 | |
13 #include "audio_plugin.h" | |
14 | |
15 static ao_info_t info = | |
16 { | |
17 "Plugin audio output", | |
18 "plugin", | |
19 "Anders", | |
20 "" | |
21 }; | |
22 | |
23 LIBAO_EXTERN(plugin) | |
24 | |
3107 | 25 #define plugin(i) (ao_plugin_local_data.plugins[i]) |
26 #define driver() (ao_plugin_local_data.driver) | |
3096 | 27 |
3107 | 28 // local data |
3096 | 29 typedef struct ao_plugin_local_data_s |
30 { | |
4313 | 31 void* buf; // Output data buffer |
32 int len; // Amount of data in buffer | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
33 int channels; |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
34 int format; |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
35 int bpm; //bit of format |
4313 | 36 float bps; // Bytes per second out |
37 ao_functions_t* driver; // Output driver | |
3107 | 38 ao_plugin_functions_t** plugins; // List of used plugins |
3194
1648d11fc36c
commandline configuration of audio plugins now through struct, format conversion plugin added
anders
parents:
3107
diff
changeset
|
39 ao_plugin_functions_t* available_plugins[NPL]; // List of available plugins |
3096 | 40 } ao_plugin_local_data_t; |
41 | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
42 static ao_plugin_local_data_t ao_plugin_local_data={NULL,0,0,0,0,0.0,NULL,NULL,AO_PLUGINS}; |
3096 | 43 |
4313 | 44 // global data |
4896 | 45 volatile ao_plugin_data_t ao_plugin_data; // Data used by the plugins |
4859 | 46 ao_plugin_cfg_t ao_plugin_cfg=CFG_DEFAULTS; // Set in cfg-mplayer.h |
3096 | 47 |
48 // to set/get/query special features/parameters | |
9633
12b1790038b0
64bit libao2 fix by Jens Axboe <mplayer-dev@kernel.dk>
alex
parents:
8979
diff
changeset
|
49 static int control(int cmd,void *arg){ |
3107 | 50 switch(cmd){ |
51 case AOCONTROL_SET_PLUGIN_DRIVER: | |
9633
12b1790038b0
64bit libao2 fix by Jens Axboe <mplayer-dev@kernel.dk>
alex
parents:
8979
diff
changeset
|
52 ao_plugin_local_data.driver=arg; |
3107 | 53 return CONTROL_OK; |
4859 | 54 case AOCONTROL_GET_VOLUME: |
55 case AOCONTROL_SET_VOLUME: | |
56 { | |
57 int r=audio_plugin_volume.control(cmd,arg); | |
58 if(CONTROL_OK != r) | |
59 return driver()->control(cmd,arg); | |
60 else | |
61 return r; | |
62 } | |
3107 | 63 default: |
64 return driver()->control(cmd,arg); | |
65 } | |
66 return CONTROL_UNKNOWN; | |
67 } | |
68 | |
69 // Recursive function for adding plugins | |
70 // return 1 for success and 0 for error | |
71 int add_plugin(int i,char* cfg){ | |
72 int cnt=0; | |
73 // Find end of plugin name | |
74 while((cfg[cnt]!=',')&&(cfg[cnt]!='\0')&&(cnt<100)) cnt++; | |
75 if(cnt >= 100) | |
76 return 0; | |
77 | |
3680 | 78 // Is this the last iteration or just another plugin |
3107 | 79 if(cfg[cnt]=='\0'){ |
5773 | 80 ao_plugin_local_data.plugins=malloc((i+2)*sizeof(ao_plugin_functions_t*)); |
3107 | 81 if(ao_plugin_local_data.plugins){ |
82 ao_plugin_local_data.plugins[i+1]=NULL; | |
83 // Find the plugin matching the cfg string name | |
84 cnt=0; | |
85 while(ao_plugin_local_data.available_plugins[cnt] && cnt<20){ | |
86 if(0==strcmp(ao_plugin_local_data.available_plugins[cnt]->info->short_name,cfg)){ | |
87 ao_plugin_local_data.plugins[i]=ao_plugin_local_data.available_plugins[cnt]; | |
88 return 1; | |
89 } | |
90 cnt++; | |
91 } | |
13467 | 92 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_PLUGIN_InvalidPlugin,cfg); |
3107 | 93 return 0; |
94 } | |
95 else | |
96 return 0; | |
97 } else { | |
98 cfg[cnt]='\0'; | |
99 if(add_plugin(i+1,&cfg[cnt+1])){ | |
100 cnt=0; | |
101 // Find the plugin matching the cfg string name | |
102 while(ao_plugin_local_data.available_plugins[cnt] && cnt < 20){ | |
103 if(0==strcmp(ao_plugin_local_data.available_plugins[cnt]->info->short_name,cfg)){ | |
104 ao_plugin_local_data.plugins[i]=ao_plugin_local_data.available_plugins[cnt]; | |
105 return 1; | |
106 } | |
107 cnt++; | |
108 } | |
13467 | 109 mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_PLUGIN_InvalidPlugin,cfg); |
3107 | 110 return 0; |
111 } | |
112 else | |
113 return 0; | |
114 } | |
115 return 0; // Will never happen... | |
3096 | 116 } |
117 | |
118 // open & setup audio device and plugins | |
119 // return: 1=success 0=fail | |
120 static int init(int rate,int channels,int format,int flags){ | |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
121 int use_plugin[NPL]; |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
122 int x,npl,unused=0; |
3096 | 123 int ok=1; |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
124 char *config; |
3096 | 125 |
4313 | 126 // Create list of plugins from cfg option |
3096 | 127 int i=0; |
3194
1648d11fc36c
commandline configuration of audio plugins now through struct, format conversion plugin added
anders
parents:
3107
diff
changeset
|
128 if(ao_plugin_cfg.plugin_list){ |
8979 | 129 config = malloc(strlen(ao_plugin_cfg.plugin_list)+1); |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
130 if(!config) return 0; |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
131 if(!strcpy(config, ao_plugin_cfg.plugin_list) || !add_plugin(i,config)){ |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
132 free(config); |
3107 | 133 return 0; |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
134 } |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
135 free(config); |
3107 | 136 } |
3096 | 137 |
138 /* Set input parameters and itterate through plugins each plugin | |
139 changes the parameters according to its output */ | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
140 |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
141 ao_plugin_local_data.format=format; |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
142 ao_plugin_local_data.channels=channels; |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
143 ao_plugin_local_data.bpm=audio_out_format_bits(format); |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
144 |
3096 | 145 ao_plugin_data.rate=rate; |
146 ao_plugin_data.channels=channels; | |
147 ao_plugin_data.format=format; | |
148 ao_plugin_data.sz_mult=1; | |
149 ao_plugin_data.sz_fix=0; | |
150 ao_plugin_data.delay_mult=1; | |
151 ao_plugin_data.delay_fix=0; | |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
152 |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
6372
diff
changeset
|
153 for(i=0;i<NPL && plugin(i);i++){ |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
154 use_plugin[i]=plugin(i)->init(); |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
155 if(!use_plugin[i]) plugin(i)->uninit(); |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
156 } |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
157 npl=i; |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
6372
diff
changeset
|
158 for(i=0;i<npl && plugin(i);i++) |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
159 if(!use_plugin[i+unused]){ |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
160 unused++; |
7472
c4434bdf6e51
tons of warning fixes, also some 10l bugfixes, including Dominik's PVA bug
arpi
parents:
6372
diff
changeset
|
161 for(x=i;x<npl && plugin(x+1);x++) plugin(x)=plugin(x+1); |
6319
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
162 plugin(x)=NULL; |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
163 npl--; |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
164 i--; |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
165 } |
76baa05a63ab
disables those plugins that can't handle the audio format.
arpi
parents:
6237
diff
changeset
|
166 i=npl; |
3096 | 167 |
4313 | 168 // Calculate bps |
169 ao_plugin_local_data.bps=(float)(ao_plugin_data.rate * | |
170 ao_plugin_data.channels); | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
171 ao_plugin_local_data.bps*=audio_out_format_bits(ao_plugin_data.format)/8; |
4313 | 172 |
3107 | 173 // This should never happen but check anyway |
174 if(NULL==ao_plugin_local_data.driver) | |
175 return 0; | |
176 | |
3096 | 177 ok = driver()->init(ao_plugin_data.rate, |
3107 | 178 ao_plugin_data.channels, |
179 ao_plugin_data.format, | |
180 flags); | |
3096 | 181 if(!ok) return 0; |
182 | |
183 /* Now that the driver is initialized we can calculate and set the | |
184 input and output buffers for each plugin */ | |
185 ao_plugin_data.len=driver()->get_space(); | |
3107 | 186 while((i>0) && ok) |
3194
1648d11fc36c
commandline configuration of audio plugins now through struct, format conversion plugin added
anders
parents:
3107
diff
changeset
|
187 ok=plugin(--i)->control(AOCONTROL_PLUGIN_SET_LEN,0); |
3107 | 188 |
189 if(!ok) return 0; | |
3096 | 190 |
4374
0a95c5074c50
Fixed sig 11 caused by resampling plugin, some cosmetic changes and speed improvements
anders
parents:
4313
diff
changeset
|
191 // Allocate output buffer |
4313 | 192 if(ao_plugin_local_data.buf) |
193 free(ao_plugin_local_data.buf); | |
194 ao_plugin_local_data.buf=malloc(MAX_OUTBURST); | |
195 | |
196 if(!ao_plugin_local_data.buf) return 0; | |
197 | |
3096 | 198 return 1; |
199 } | |
200 | |
201 // close audio device | |
12145 | 202 static void uninit(int immed){ |
3096 | 203 int i=0; |
12145 | 204 driver()->uninit(immed); |
3096 | 205 while(plugin(i)) |
206 plugin(i++)->uninit(); | |
3107 | 207 if(ao_plugin_local_data.plugins) |
208 free(ao_plugin_local_data.plugins); | |
5050 | 209 ao_plugin_local_data.plugins=NULL; |
4313 | 210 if(ao_plugin_local_data.buf) |
211 free(ao_plugin_local_data.buf); | |
5050 | 212 ao_plugin_local_data.buf=NULL; |
3096 | 213 } |
214 | |
215 // stop playing and empty buffers (for seeking/pause) | |
216 static void reset(){ | |
217 int i=0; | |
218 driver()->reset(); | |
219 while(plugin(i)) | |
220 plugin(i++)->reset(); | |
4313 | 221 ao_plugin_local_data.len=0; |
3096 | 222 } |
223 | |
224 // stop playing, keep buffers (for pause) | |
225 static void audio_pause(){ | |
226 driver()->pause(); | |
227 } | |
228 | |
229 // resume playing, after audio_pause() | |
230 static void audio_resume(){ | |
231 driver()->resume(); | |
232 } | |
233 | |
234 // return: how many bytes can be played without blocking | |
235 static int get_space(){ | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
236 double sz; |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
237 int isz; |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
238 sz=(double)(driver()->get_space()); |
4313 | 239 if(sz+(double)ao_plugin_local_data.len > (double)MAX_OUTBURST) |
240 sz=(double)MAX_OUTBURST-(double)ao_plugin_local_data.len; | |
3096 | 241 sz*=ao_plugin_data.sz_mult; |
242 sz+=ao_plugin_data.sz_fix; | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
243 isz=(int)(sz); |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
244 isz-=isz%(ao_plugin_local_data.channels*ao_plugin_local_data.bpm/8); |
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
245 return isz; |
3096 | 246 } |
247 | |
248 // plays 'len' bytes of 'data' | |
249 // return: number of bytes played | |
250 static int play(void* data,int len,int flags){ | |
4313 | 251 int l,i=0; |
252 // Limit length to avoid over flow in plugins | |
4922 | 253 int tmp = get_space(); |
3096 | 254 int ret_len =(tmp<len)?tmp:len; |
6372 | 255 // keep all channels of each sample together |
256 ret_len -= ret_len % (ao_plugin_local_data.channels*ao_plugin_local_data.bpm/8); | |
4375 | 257 if(ret_len){ |
258 // Filter data | |
259 ao_plugin_data.len=ret_len; | |
260 ao_plugin_data.data=data; | |
6027
7c26ef54ff14
fixed sdl+resample bug coused by float point to int rounding error
iive
parents:
5773
diff
changeset
|
261 |
4376 | 262 while(plugin(i)) |
4375 | 263 plugin(i++)->play(); |
264 // Copy data to output buffer | |
265 memcpy(ao_plugin_local_data.buf+ao_plugin_local_data.len, | |
266 ao_plugin_data.data,ao_plugin_data.len); | |
267 // Send data to output | |
268 l=driver()->play(ao_plugin_local_data.buf, | |
269 ao_plugin_data.len+ao_plugin_local_data.len,flags); | |
270 // Save away unsent data | |
271 ao_plugin_local_data.len=ao_plugin_data.len+ao_plugin_local_data.len-l; | |
272 memcpy(ao_plugin_local_data.buf,ao_plugin_local_data.buf+l, | |
273 ao_plugin_local_data.len); | |
274 } | |
3096 | 275 return ret_len; |
276 } | |
277 | |
278 // return: delay in seconds between first and last sample in buffer | |
279 static float get_delay(){ | |
280 float delay=driver()->get_delay(); | |
4313 | 281 delay+=(float)ao_plugin_local_data.len/ao_plugin_local_data.bps; |
3096 | 282 delay*=ao_plugin_data.delay_mult; |
283 delay+=ao_plugin_data.delay_fix; | |
284 return delay; | |
285 } | |
286 | |
287 | |
3279
d6ea11bed983
Commandline interface to ao_plugin updated according to mplayers complex parameter format and plugin pl_format finished (alpha code needs testing)
anders
parents:
3194
diff
changeset
|
288 |
d6ea11bed983
Commandline interface to ao_plugin updated according to mplayers complex parameter format and plugin pl_format finished (alpha code needs testing)
anders
parents:
3194
diff
changeset
|
289 |