comparison Plugins/Output/crossfade/crossfade.h @ 259:88b38e2414a1 trunk

[svn] First attempt at porting the crossfade plugin; patches from bug #363 applied, GThreadified, includes fixed. Will most probably not compile as of yet.
author chainsaw
date Sun, 04 Dec 2005 15:58:55 -0800
parents
children 5fd398406cf7
comparison
equal deleted inserted replaced
258:f4a57eac3ba3 259:88b38e2414a1
1 /*
2 * XMMS Crossfade Plugin
3 * Copyright (C) 2000-2004 Peter Eisenlohr <peter@eisenlohr.org>
4 *
5 * based on the original OSS Output Plugin
6 * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 * USA.
22 */
23
24 #ifndef _CROSSFADE_H_
25 #define _CROSSFADE_H_
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <gdk/gdk.h>
32 #include <gtk/gtk.h>
33
34 #include "audacious/plugin.h"
35 #include "libaudacious/beepctrl.h"
36 #include "libaudacious/configfile.h"
37 #include "libaudacious/util.h"
38
39 #include "debug.h"
40
41 #undef VOLUME_NORMALIZER
42 #undef SONGCHANGE_TIMEOUT
43
44 #define OUTPUT_RATE the_rate
45 #define OUTPUT_NCH 2
46 #define OUTPUT_BPS (OUTPUT_RATE * OUTPUT_NCH * 2)
47
48 #define SYNC_OUTPUT_TIMEOUT 2000
49
50 #define OUTPUT_METHOD_BUILTIN_OSS 0
51 #define OUTPUT_METHOD_PLUGIN 1
52 #define OUTPUT_METHOD_BUILTIN_NULL 2
53
54 #define FADE_CONFIG_XFADE 0
55 #define FADE_CONFIG_MANUAL 1
56 #define FADE_CONFIG_ALBUM 2
57 #define FADE_CONFIG_START 3
58 #define FADE_CONFIG_STOP 4
59 #define FADE_CONFIG_EOP 5
60 #define FADE_CONFIG_SEEK 6
61 #define FADE_CONFIG_PAUSE 7
62 #define FADE_CONFIG_TIMING 8
63 #define MAX_FADE_CONFIGS 9
64
65 #define FADE_TYPE_REOPEN 0
66 #define FADE_TYPE_FLUSH 1
67 #define FADE_TYPE_NONE 2
68 #define FADE_TYPE_PAUSE 3
69 #define FADE_TYPE_SIMPLE_XF 4
70 #define FADE_TYPE_ADVANCED_XF 5
71 #define FADE_TYPE_FADEIN 6
72 #define FADE_TYPE_FADEOUT 7
73 #define FADE_TYPE_PAUSE_NONE 8
74 #define FADE_TYPE_PAUSE_ADV 9
75 #define MAX_FADE_TYPES 10
76
77 #define TYPEMASK_XFADE ((1 << FADE_TYPE_REOPEN) | \
78 (1 << FADE_TYPE_NONE) | \
79 (1 << FADE_TYPE_PAUSE) | \
80 (1 << FADE_TYPE_SIMPLE_XF) | \
81 (1 << FADE_TYPE_ADVANCED_XF))
82
83 #define TYPEMASK_MANUAL ((1 << FADE_TYPE_REOPEN) | \
84 (1 << FADE_TYPE_FLUSH) | \
85 (1 << FADE_TYPE_NONE) | \
86 (1 << FADE_TYPE_PAUSE) | \
87 (1 << FADE_TYPE_SIMPLE_XF) | \
88 (1 << FADE_TYPE_ADVANCED_XF))
89
90 #define TYPEMASK_ALBUM ((1 << FADE_TYPE_NONE))
91
92 #define TYPEMASK_START ((1 << FADE_TYPE_NONE) | \
93 (1 << FADE_TYPE_FADEIN))
94
95 #define TYPEMASK_STOP ((1 << FADE_TYPE_NONE) | \
96 (1 << FADE_TYPE_FADEOUT))
97
98 #define TYPEMASK_EOP ((1 << FADE_TYPE_NONE) | \
99 (1 << FADE_TYPE_FADEOUT))
100
101 #define TYPEMASK_SEEK ((1 << FADE_TYPE_FLUSH) | \
102 (1 << FADE_TYPE_NONE) | \
103 (1 << FADE_TYPE_SIMPLE_XF))
104
105 #define TYPEMASK_PAUSE ((1 << FADE_TYPE_PAUSE_NONE) | \
106 (1 << FADE_TYPE_PAUSE_ADV))
107
108 #define TYPEMASK_TIMING (0)
109
110 #define FC_OFFSET_NONE 0
111 #define FC_OFFSET_LOCK_IN 1
112 #define FC_OFFSET_LOCK_OUT 2
113 #define FC_OFFSET_CUSTOM 3
114
115 #define DEFAULT_OSS_ALT_AUDIO_DEVICE "/dev/dsp"
116 #define DEFAULT_OSS_ALT_MIXER_DEVICE "/dev/mixer"
117 #define DEFAULT_OP_CONFIG_STRING "libOSS.so=0,1,2304,0; libdisk_writer.so=1,0,2304,1"
118 #define DEFAULT_OP_NAME "libOSS.so"
119 #define DEFAULT_EP_NAME "libnormvol.so"
120
121 #define DEFAULT_OP_CONFIG \
122 { FALSE, FALSE, 2304, FALSE }
123
124 #define CONFIG_DEFAULT \
125 { 0, /* output_method */ \
126 44100, /* output_rate */ \
127 2, /* output_quality */ \
128 0, /* oss_audio_device */ \
129 FALSE, /* oss_use_alt_audio_device */ \
130 NULL, /* oss_alt_audio_device */ \
131 0, /* oss_mixer_device */ \
132 FALSE, /* oss_use_alt_mixer_device */ \
133 NULL, /* oss_alt_mixer_device */ \
134 FALSE, /* oss_mixer_use_master */ \
135 0, /* oss_buffer_size_ms */ \
136 250, /* oss_preload_size_ms */ \
137 22, /* oss_fragments */ \
138 12, /* oss_fragment_size */ \
139 FALSE, /* oss_maxbuf_enable */ \
140 NULL, /* op_config_string */ \
141 NULL, /* op_name */ \
142 NULL, /* ep_name */ \
143 FALSE, /* ep_enable */ \
144 TRUE, /* volnorm_enable */ \
145 8000, /* volnorm_target */ \
146 FALSE, /* volnorm_use_qa */ \
147 10000, /* mix_size_ms */ \
148 TRUE, /* mix_size_auto */ \
149 \
150 { /* fc[MAX_FADE_CONFIGS] */ \
151 { FADE_CONFIG_XFADE, /* config */ \
152 FADE_TYPE_ADVANCED_XF, /* type */ \
153 2000, /* pause_len_ms */ \
154 6000, /* simple_len_ms */ \
155 TRUE, 4000, 0, /* out_enable, _len_ms, _volume */ \
156 FC_OFFSET_CUSTOM, /* ofs_type */ \
157 FC_OFFSET_CUSTOM, -6000, /* ofs_type_wanted, ofs_custom_ms */ \
158 TRUE, /* in_locked */ \
159 FALSE, 4000, 33, /* in_enable, _len_ms, _volume */ \
160 FALSE, /* - */ \
161 0, /* - */ \
162 FALSE, /* - */ \
163 0, 0, /* - */ \
164 FALSE, /* flush */ \
165 TYPEMASK_XFADE /* type_mask */ \
166 }, \
167 { FADE_CONFIG_MANUAL, /* config */ \
168 FADE_TYPE_SIMPLE_XF, /* type */ \
169 2000, /* pause_len_ms */ \
170 1000, /* simple_len_ms */ \
171 TRUE, 500, 0, /* out_enable, _len_ms, _volume */ \
172 FC_OFFSET_CUSTOM, /* ofs_type */ \
173 FC_OFFSET_CUSTOM, -500, /* ofs_type_wanted, ofs_custom_ms */ \
174 TRUE, /* in_locked */ \
175 FALSE, 500, 50, /* in_enable, _len_ms, _volume */ \
176 FALSE, /* flush_pause_enable */ \
177 500, /* flush_in_len_ms */ \
178 FALSE, /* flush_in_enable */ \
179 500, 0, /* flush_in_len_ms, _volume */ \
180 TRUE, /* flush */ \
181 TYPEMASK_MANUAL /* type_mask */ \
182 }, \
183 { FADE_CONFIG_ALBUM, /* config */ \
184 FADE_TYPE_NONE, /* type */ \
185 0, /* - */ \
186 0, /* - */ \
187 FALSE, 0, 0, /* - */ \
188 FC_OFFSET_NONE, /* - */ \
189 FC_OFFSET_NONE, 0, /* - */ \
190 FALSE, /* - */ \
191 FALSE, 1000, 0, /* - */ \
192 FALSE, /* - */ \
193 0, /* - */ \
194 FALSE, /* - */ \
195 0, 0, /* - */ \
196 FALSE, /* flush */ \
197 TYPEMASK_ALBUM /* type_mask */ \
198 }, \
199 { FADE_CONFIG_START, /* config */ \
200 FADE_TYPE_FADEIN, /* type */ \
201 0, /* - */ \
202 0, /* - */ \
203 FALSE, 0, 0, /* - */ \
204 FC_OFFSET_NONE, /* - */ \
205 FC_OFFSET_NONE, 0, /* - */ \
206 FALSE, /* - */ \
207 FALSE, 100, 0, /* - in_len_ms, _volume */ \
208 FALSE, /* - */ \
209 0, /* - */ \
210 FALSE, /* - */ \
211 0, 0, /* - */ \
212 TRUE, /* flush */ \
213 TYPEMASK_START /* type_mask */ \
214 }, \
215 { FADE_CONFIG_STOP, /* config */ \
216 FADE_TYPE_FADEOUT, /* type */ \
217 0, /* - */ \
218 0, /* - */ \
219 FALSE, 100, 0, /* - out_len_ms, _volume */ \
220 FC_OFFSET_NONE, /* - */ \
221 FC_OFFSET_NONE, 500, /* - ofs_custom_ms */ \
222 FALSE, /* - */ \
223 FALSE, 0, 0, /* - */ \
224 FALSE, /* - */ \
225 0, /* - */ \
226 FALSE, /* - */ \
227 0, 0, /* - */ \
228 TRUE, /* flush */ \
229 TYPEMASK_STOP /* type_mask */ \
230 }, \
231 { FADE_CONFIG_EOP, /* config */ \
232 FADE_TYPE_FADEOUT, /* type */ \
233 0, /* - */ \
234 0, /* - */ \
235 FALSE, 100, 0, /* - out_len_ms, _volume */ \
236 FC_OFFSET_NONE, /* - */ \
237 FC_OFFSET_NONE, 500, /* - ofs_custom_ms */ \
238 FALSE, /* - */ \
239 FALSE, 0, 0, /* - */ \
240 FALSE, /* - */ \
241 0, /* - */ \
242 FALSE, /* - */ \
243 0, 0, /* - */ \
244 FALSE, /* flush */ \
245 TYPEMASK_EOP /* type_mask */ \
246 }, \
247 { FADE_CONFIG_SEEK, /* config */ \
248 FADE_TYPE_SIMPLE_XF, /* type */ \
249 0, /* - */ \
250 50, /* simple_len_ms */ \
251 FALSE, 0, 0, /* - */ \
252 FC_OFFSET_NONE, /* - */ \
253 FC_OFFSET_NONE, 0, /* - */ \
254 FALSE, /* - */ \
255 FALSE, 1000, 0, /* - */ \
256 FALSE, /* - */ \
257 0, /* - */ \
258 FALSE, /* - */ \
259 0, 0, /* - */ \
260 TRUE, /* flush */ \
261 TYPEMASK_SEEK /* type_mask */ \
262 }, \
263 { FADE_CONFIG_PAUSE, /* config */ \
264 FADE_TYPE_PAUSE_ADV, /* type */ \
265 0, /* - */ \
266 0, /* - */ \
267 TRUE, 100, 0, /* - out_len_ms, - */ \
268 FC_OFFSET_NONE, /* - */ \
269 FC_OFFSET_NONE, 100, /* - ofs_custom_ms */ \
270 FALSE, /* - */ \
271 TRUE, 100, 0, /* - in_len_ms, - */ \
272 FALSE, /* - */ \
273 0, /* - */ \
274 FALSE, /* - */ \
275 0, 0, /* - */ \
276 FALSE, /* - */ \
277 TYPEMASK_PAUSE /* type_mask */ \
278 }, \
279 { FADE_CONFIG_TIMING, /* config */ \
280 FADE_TYPE_NONE, /* type */ \
281 0, /* - */ \
282 0, /* - */ \
283 TRUE, 0, 0, /* out_enable, _len_ms, - */ \
284 FC_OFFSET_CUSTOM, /* - */ \
285 FC_OFFSET_CUSTOM, 0, /* - ofs_custom_ms */ \
286 FALSE, /* - */ \
287 TRUE, 0, 0, /* in_enable, _len_ms, - */ \
288 FALSE, /* - */ \
289 0, /* - */ \
290 FALSE, /* - */ \
291 0, 0, /* - */ \
292 FALSE, /* flush */ \
293 TYPEMASK_TIMING /* type_mask */ \
294 } \
295 }, \
296 TRUE, /* gap_lead_enable */ \
297 500, /* gap_lead_len_ms */ \
298 512, /* gap_lead_level */ \
299 TRUE, /* gap_trail_enable */ \
300 500, /* gap_trail_len_ms */ \
301 512, /* gap_trail_level */ \
302 TRUE, /* gap_trail_locked */ \
303 TRUE, /* gap_crossing */ \
304 FALSE, /* enable_debug */ \
305 FALSE, /* enable_monitor */ \
306 TRUE, /* enable_mixer */ \
307 FALSE, /* mixer_reverse */ \
308 FALSE, /* mixer_software */ \
309 75, /* mixer_vol_left */ \
310 75, /* mixer_vol_right */ \
311 500, /* songchange_timeout */ \
312 0, /* preload_size_ms */ \
313 TRUE, /* album detection */ \
314 FALSE, /* no_xfade_if_same_file */ \
315 FALSE, /* enable_http_workaround */ \
316 FALSE, /* enable_op_max_used */ \
317 250, /* op_max_used_ms */ \
318 FALSE, /* output_keep_opened */ \
319 NULL, /* presets */ \
320 250 /* sync_size_ms */ \
321 }
322
323
324 #define DEBUG(x) {if(config->enable_debug) debug x;}
325 #define PERROR(x) {if(config->enable_debug) perror(x);}
326
327 #define WRAP(x,n) (((x)<0)?((n)-(x))%(n):((x)%(n)))
328 #define B2MS(x) ((gint)((gint64)(x)*1000/OUTPUT_BPS))
329 #define MS2B(x) ((gint)((gint64)(x)*OUTPUT_BPS/1000))
330
331
332 /* get plugin info (imported by XMMS) */
333 OutputPlugin *get_oplugin_info();
334 OutputPlugin *get_crossfade_oplugin_info();
335
336 /* xmms internal prototypes */ /* XMMS */
337 gint ctrlsocket_get_session_id();
338 #ifndef HAVE_BEEP
339 gboolean get_input_playing();
340 #else
341 gboolean bmp_playback_get_playing();
342 #endif
343 GList *get_output_list();
344 GList *get_effect_list();
345 gint get_playlist_position();
346 gint playlist_get_current_length();
347 #ifdef HAVE_PLAYLIST_GET_FILENAME
348 gchar *playlist_get_filename(gint pos);
349 #endif
350
351 /* config change callbacks */
352 void xfade_realize_config();
353 void xfade_realize_ep_config();
354
355
356 typedef struct
357 {
358 gint mix_size; /* mixing buffer length */
359 gint sync_size; /* additional buffer space for mix timing */
360 gint preload_size; /* preload buffer length */
361
362 /* ---------------------------------------------------------------------- */
363
364 gpointer data; /* buffer */
365 gint size; /* total buffer length */
366
367 /* ---------------------------------------------------------------------- */
368
369 gint used; /* length */
370 gint rd_index; /* offset */
371
372 gint preload; /* > 0: preloading */
373
374 /* ---------------------------------------------------------------------- */
375
376 gint mix; /* > 0: mixing new data into buffer */
377
378 gint fade; /* > 0: fading in new data */
379 gint fade_len; /* length of fadein */
380 gfloat fade_scale; /* 1.0f - in_level */
381
382 #define GAP_SKIPPING_POSITIVE -1
383 #define GAP_SKIPPING_NEGATIVE -2
384 #define GAP_SKIPPING_DONE -3
385 gint gap; /* > 0: removing (leading) gap */
386 gint gap_len; /* max. len of gap, 0=disabled */
387 gint gap_level; /* max. sample value+1 to be considered "silent" */
388 gint gap_killed; /* number of bytes that were killed last time */
389 gint gap_skipped; /* negative/positive samples skipped */
390
391 /* ---------------------------------------------------------------------- */
392
393 gint silence; /* > 0: delay until start of silence */
394 gint silence_len; /* > 0: inserting silence */
395
396 gint reopen; /* >= 0: countdown to reopen device (disk_writer hack) */
397 gboolean reopen_sync; /* TRUE: sync output plugin before reopening */
398
399 gint pause; /* >= 0: countdown to pause output plugin */
400 }
401 buffer_t;
402
403 typedef struct
404 {
405 gint config; // one of FADE_CONFIG_*, constant
406 gint type; // one of FADE_TYPE_*
407
408 gint pause_len_ms; // PAUSE
409
410 gint simple_len_ms; // SIMPLE_XF
411
412 gboolean out_enable; // ADVANCED_XF
413 gint out_len_ms; // ADVANCED_XF, FADEOUT, PAUSE
414 gint out_volume; // ADVANCED_XF, FADEOUT
415
416 gint ofs_type; // ADVANCED_XF
417 gint ofs_type_wanted; // ADVANCED_XF
418 gint ofs_custom_ms; // ADVANCED_XF, FADEOUT (additional silence), PAUSE
419
420 gboolean in_locked; // ADVANCED_XF
421 gboolean in_enable; // ADVANCED_XF, FLUSH
422 gint in_len_ms; // ADVANCED_XF, FLUSH, FADEIN, PAUSE
423 gint in_volume; // ADVANCED_XF, FLUSH, FADEIN
424
425 gboolean flush_pause_enable; // FLUSH
426 gint flush_pause_len_ms; // FLUSH
427 gboolean flush_in_enable; // FLUSH
428 gint flush_in_len_ms; // FLUSH
429 gint flush_in_volume; // FLUSH
430
431 /* additional stuff which is not configureable by the user */
432 gboolean flush; // TRUE for manual, FALSE for xfade config
433 guint32 type_mask; // bitmask for FADE_TYPEs
434 }
435 fade_config_t;
436
437 typedef struct
438 {
439 gboolean throttle_enable;
440 gboolean max_write_enable;
441 gint max_write_len;
442 gboolean force_reopen;
443 }
444 plugin_config_t;
445
446 typedef struct
447 {
448 /* output: method */
449 gint output_method;
450 gint output_rate;
451 gint output_quality;
452
453 /* output: builtin OSS */
454 gint oss_audio_device;
455 gboolean oss_use_alt_audio_device;
456 gchar *oss_alt_audio_device;
457
458 gint oss_mixer_device;
459 gboolean oss_use_alt_mixer_device;
460 gchar *oss_alt_mixer_device;
461 gboolean oss_mixer_use_master;
462
463 gint oss_buffer_size_ms;
464 gint oss_preload_size_ms;
465
466 gint oss_fragments;
467 gint oss_fragment_size;
468 gboolean oss_maxbuf_enable;
469
470 /* output: plugin */
471 gchar *op_config_string; /* stores configs for all plugins */
472 gchar *op_name; /* name of the current plugin */
473
474 /* effects */
475 gchar *ep_name;
476 gboolean ep_enable;
477 gboolean volnorm_enable;
478 gboolean volnorm_use_qa;
479 gint volnorm_target;
480
481 /* crossfader */
482 gint mix_size_ms;
483 gboolean mix_size_auto;
484 fade_config_t fc[MAX_FADE_CONFIGS];
485
486 /* gap killer */
487 gboolean gap_lead_enable;
488 gint gap_lead_len_ms;
489 gint gap_lead_level;
490
491 gboolean gap_trail_enable;
492 gint gap_trail_len_ms;
493 gint gap_trail_level;
494 gboolean gap_trail_locked;
495
496 gboolean gap_crossing;
497
498 /* misc */
499 gboolean enable_debug;
500 gboolean enable_monitor;
501
502 gboolean enable_mixer;
503 gboolean mixer_reverse;
504 gboolean mixer_software;
505 gint mixer_vol_left;
506 gint mixer_vol_right;
507
508 gint songchange_timeout;
509 gint preload_size_ms;
510 gboolean album_detection;
511 gboolean no_xfade_if_same_file;
512 gboolean enable_http_workaround;
513 gboolean enable_op_max_used;
514 gint op_max_used_ms;
515 gboolean output_keep_opened;
516
517 /* presets */
518 GList *presets;
519
520 /* additional stuff which is not configureable by the user */
521 gint sync_size_ms;
522
523 /* additional stuff which is not saved to the config file */
524 gint page;
525 gint oss_page;
526 gint xf_index;
527 }
528 config_t;
529
530
531 /* some global vars... we should really get rid of those somehow */
532 extern config_t *config;
533 extern config_t config_default;
534 extern buffer_t *buffer;
535
536 extern GStaticMutex buffer_mutex;
537
538 extern gboolean opened; /* XMMS-crossfade is opened */
539 extern gboolean output_opened; /* the output plugin is opened */
540 extern gint output_offset;
541 extern gint64 output_streampos;
542
543 extern OutputPlugin *the_op;
544 extern gint the_rate;
545
546 #endif /* _CROSSFADE_H_ */