comparison src/crossfade/crossfade.h @ 3059:2e241e90494a

Import work in progress xmms-crossfade rewrite.
author William Pitcock <nenolod@atheme.org>
date Fri, 24 Apr 2009 05:57:35 -0500
parents
children 6a6a731fdaf8
comparison
equal deleted inserted replaced
3058:2e649bf16ebc 3059:2e241e90494a
1 /*
2 * XMMS Crossfade Plugin
3 * Copyright (C) 2000-2007 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 #define COMPILE_FOR_AUDACIOUS
28 #define AUDACIOUS_ABI_VERSION 2
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #if !defined(HAVE_GLIB_THREADS)
35 # include <pthread.h>
36 #endif
37 #include <glib.h>
38
39 #include <audacious/plugin.h>
40 #include <audacious/playlist.h>
41 #include <audacious/auddrct.h>
42 #include <audacious/configdb.h>
43 #include <audacious/util.h>
44
45 #include "debug.h"
46
47 #undef VOLUME_NORMALIZER
48 #define TIMING_COMMENTS
49
50 #define OUTPUT_RATE the_rate
51 #define OUTPUT_NCH 2
52 #define OUTPUT_BPS (OUTPUT_RATE * OUTPUT_NCH * 2)
53
54 #if defined(HAVE_LIBSAMPLERATE)
55 # define MAX_RATE 192000
56 #else
57 # define MAX_RATE 48000
58 #endif
59
60 #define SYNC_OUTPUT_TIMEOUT 2000
61
62 #define OUTPUT_METHOD_BUILTIN_OSS 0
63 #define OUTPUT_METHOD_PLUGIN 1
64 #define OUTPUT_METHOD_BUILTIN_NULL 2
65
66 #define FADE_CONFIG_XFADE 0
67 #define FADE_CONFIG_MANUAL 1
68 #define FADE_CONFIG_ALBUM 2
69 #define FADE_CONFIG_START 3
70 #define FADE_CONFIG_STOP 4
71 #define FADE_CONFIG_EOP 5
72 #define FADE_CONFIG_SEEK 6
73 #define FADE_CONFIG_PAUSE 7
74 #define FADE_CONFIG_TIMING 8
75 #define MAX_FADE_CONFIGS 9
76
77 #define FADE_TYPE_REOPEN 0
78 #define FADE_TYPE_FLUSH 1
79 #define FADE_TYPE_NONE 2
80 #define FADE_TYPE_PAUSE 3
81 #define FADE_TYPE_SIMPLE_XF 4
82 #define FADE_TYPE_ADVANCED_XF 5
83 #define FADE_TYPE_FADEIN 6
84 #define FADE_TYPE_FADEOUT 7
85 #define FADE_TYPE_PAUSE_NONE 8
86 #define FADE_TYPE_PAUSE_ADV 9
87 #define MAX_FADE_TYPES 10
88
89 #define TYPEMASK_XFADE ((1 << FADE_TYPE_REOPEN) | \
90 (1 << FADE_TYPE_NONE) | \
91 (1 << FADE_TYPE_PAUSE) | \
92 (1 << FADE_TYPE_SIMPLE_XF) | \
93 (1 << FADE_TYPE_ADVANCED_XF))
94
95 #define TYPEMASK_MANUAL ((1 << FADE_TYPE_REOPEN) | \
96 (1 << FADE_TYPE_FLUSH) | \
97 (1 << FADE_TYPE_NONE) | \
98 (1 << FADE_TYPE_PAUSE) | \
99 (1 << FADE_TYPE_SIMPLE_XF) | \
100 (1 << FADE_TYPE_ADVANCED_XF))
101
102 #define TYPEMASK_ALBUM ((1 << FADE_TYPE_NONE))
103
104 #define TYPEMASK_START ((1 << FADE_TYPE_NONE) | \
105 (1 << FADE_TYPE_FADEIN))
106
107 #define TYPEMASK_STOP ((1 << FADE_TYPE_NONE) | \
108 (1 << FADE_TYPE_FADEOUT))
109
110 #define TYPEMASK_EOP ((1 << FADE_TYPE_NONE) | \
111 (1 << FADE_TYPE_FADEOUT))
112
113 #define TYPEMASK_SEEK ((1 << FADE_TYPE_FLUSH) | \
114 (1 << FADE_TYPE_NONE) | \
115 (1 << FADE_TYPE_SIMPLE_XF))
116
117 #define TYPEMASK_PAUSE ((1 << FADE_TYPE_PAUSE_NONE) | \
118 (1 << FADE_TYPE_PAUSE_ADV))
119
120 #define TYPEMASK_TIMING (0)
121
122 #define FC_OFFSET_NONE 0
123 #define FC_OFFSET_LOCK_IN 1
124 #define FC_OFFSET_LOCK_OUT 2
125 #define FC_OFFSET_CUSTOM 3
126
127 #define DEFAULT_OSS_ALT_AUDIO_DEVICE "/dev/dsp"
128 #define DEFAULT_OSS_ALT_MIXER_DEVICE "/dev/mixer"
129 #define DEFAULT_OP_CONFIG_STRING "libOSS.so=0,1,2304,0; libdisk_writer.so=1,0,2304,1"
130 #define DEFAULT_OP_NAME "libALSA.so"
131 #define DEFAULT_EP_NAME "libnormvol.so"
132
133 #define DEFAULT_OP_CONFIG \
134 { FALSE, FALSE, 2304, FALSE }
135
136 #define CONFIG_DEFAULT \
137 { 0, /* output_method */ \
138 44100, /* output_rate */ \
139 2, /* output_quality */ \
140 0, /* oss_audio_device */ \
141 FALSE, /* oss_use_alt_audio_device */ \
142 NULL, /* oss_alt_audio_device */ \
143 0, /* oss_mixer_device */ \
144 FALSE, /* oss_use_alt_mixer_device */ \
145 NULL, /* oss_alt_mixer_device */ \
146 FALSE, /* oss_mixer_use_master */ \
147 0, /* oss_buffer_size_ms */ \
148 250, /* oss_preload_size_ms */ \
149 22, /* oss_fragments */ \
150 12, /* oss_fragment_size */ \
151 FALSE, /* oss_maxbuf_enable */ \
152 NULL, /* op_config_string */ \
153 NULL, /* op_name */ \
154 NULL, /* ep_name */ \
155 FALSE, /* ep_enable */ \
156 TRUE, /* volnorm_enable */ \
157 8000, /* volnorm_target */ \
158 FALSE, /* volnorm_use_qa */ \
159 10000, /* mix_size_ms */ \
160 TRUE, /* mix_size_auto */ \
161 \
162 { /* fc[MAX_FADE_CONFIGS] */ \
163 { FADE_CONFIG_XFADE, /* config */ \
164 FADE_TYPE_ADVANCED_XF, /* type */ \
165 2000, /* pause_len_ms */ \
166 6000, /* simple_len_ms */ \
167 TRUE, 4000, 0, /* out_enable, _len_ms, _volume */ \
168 FC_OFFSET_CUSTOM, /* ofs_type */ \
169 FC_OFFSET_CUSTOM, -6000, /* ofs_type_wanted, ofs_custom_ms */ \
170 TRUE, /* in_locked */ \
171 FALSE, 4000, 33, /* in_enable, _len_ms, _volume */ \
172 FALSE, /* - */ \
173 0, /* - */ \
174 FALSE, /* - */ \
175 0, 0, /* - */ \
176 FALSE, /* flush */ \
177 TYPEMASK_XFADE /* type_mask */ \
178 }, \
179 { FADE_CONFIG_MANUAL, /* config */ \
180 FADE_TYPE_SIMPLE_XF, /* type */ \
181 2000, /* pause_len_ms */ \
182 1000, /* simple_len_ms */ \
183 TRUE, 500, 0, /* out_enable, _len_ms, _volume */ \
184 FC_OFFSET_CUSTOM, /* ofs_type */ \
185 FC_OFFSET_CUSTOM, -500, /* ofs_type_wanted, ofs_custom_ms */ \
186 TRUE, /* in_locked */ \
187 FALSE, 500, 50, /* in_enable, _len_ms, _volume */ \
188 FALSE, /* flush_pause_enable */ \
189 500, /* flush_in_len_ms */ \
190 FALSE, /* flush_in_enable */ \
191 500, 0, /* flush_in_len_ms, _volume */ \
192 TRUE, /* flush */ \
193 TYPEMASK_MANUAL /* type_mask */ \
194 }, \
195 { FADE_CONFIG_ALBUM, /* config */ \
196 FADE_TYPE_NONE, /* type */ \
197 0, /* - */ \
198 0, /* - */ \
199 FALSE, 0, 0, /* - */ \
200 FC_OFFSET_NONE, /* - */ \
201 FC_OFFSET_NONE, 0, /* - */ \
202 FALSE, /* - */ \
203 FALSE, 1000, 0, /* - */ \
204 FALSE, /* - */ \
205 0, /* - */ \
206 FALSE, /* - */ \
207 0, 0, /* - */ \
208 FALSE, /* flush */ \
209 TYPEMASK_ALBUM /* type_mask */ \
210 }, \
211 { FADE_CONFIG_START, /* config */ \
212 FADE_TYPE_FADEIN, /* type */ \
213 0, /* - */ \
214 0, /* - */ \
215 FALSE, 0, 0, /* - */ \
216 FC_OFFSET_NONE, /* - */ \
217 FC_OFFSET_NONE, 0, /* - */ \
218 FALSE, /* - */ \
219 FALSE, 100, 0, /* - in_len_ms, _volume */ \
220 FALSE, /* - */ \
221 0, /* - */ \
222 FALSE, /* - */ \
223 0, 0, /* - */ \
224 TRUE, /* flush */ \
225 TYPEMASK_START /* type_mask */ \
226 }, \
227 { FADE_CONFIG_STOP, /* config */ \
228 FADE_TYPE_FADEOUT, /* type */ \
229 0, /* - */ \
230 0, /* - */ \
231 FALSE, 100, 0, /* - out_len_ms, _volume */ \
232 FC_OFFSET_NONE, /* - */ \
233 FC_OFFSET_NONE, 500, /* - ofs_custom_ms */ \
234 FALSE, /* - */ \
235 FALSE, 0, 0, /* - */ \
236 FALSE, /* - */ \
237 0, /* - */ \
238 FALSE, /* - */ \
239 0, 0, /* - */ \
240 TRUE, /* flush */ \
241 TYPEMASK_STOP /* type_mask */ \
242 }, \
243 { FADE_CONFIG_EOP, /* config */ \
244 FADE_TYPE_FADEOUT, /* type */ \
245 0, /* - */ \
246 0, /* - */ \
247 FALSE, 100, 0, /* - out_len_ms, _volume */ \
248 FC_OFFSET_NONE, /* - */ \
249 FC_OFFSET_NONE, 500, /* - ofs_custom_ms */ \
250 FALSE, /* - */ \
251 FALSE, 0, 0, /* - */ \
252 FALSE, /* - */ \
253 0, /* - */ \
254 FALSE, /* - */ \
255 0, 0, /* - */ \
256 FALSE, /* flush */ \
257 TYPEMASK_EOP /* type_mask */ \
258 }, \
259 { FADE_CONFIG_SEEK, /* config */ \
260 FADE_TYPE_SIMPLE_XF, /* type */ \
261 0, /* - */ \
262 50, /* simple_len_ms */ \
263 FALSE, 0, 0, /* - */ \
264 FC_OFFSET_NONE, /* - */ \
265 FC_OFFSET_NONE, 0, /* - */ \
266 FALSE, /* - */ \
267 FALSE, 1000, 0, /* - */ \
268 FALSE, /* - */ \
269 0, /* - */ \
270 FALSE, /* - */ \
271 0, 0, /* - */ \
272 TRUE, /* flush */ \
273 TYPEMASK_SEEK /* type_mask */ \
274 }, \
275 { FADE_CONFIG_PAUSE, /* config */ \
276 FADE_TYPE_PAUSE_ADV, /* type */ \
277 0, /* - */ \
278 0, /* - */ \
279 TRUE, 100, 0, /* - out_len_ms, - */ \
280 FC_OFFSET_NONE, /* - */ \
281 FC_OFFSET_NONE, 100, /* - ofs_custom_ms */ \
282 FALSE, /* - */ \
283 TRUE, 100, 0, /* - in_len_ms, - */ \
284 FALSE, /* - */ \
285 0, /* - */ \
286 FALSE, /* - */ \
287 0, 0, /* - */ \
288 FALSE, /* - */ \
289 TYPEMASK_PAUSE /* type_mask */ \
290 }, \
291 { FADE_CONFIG_TIMING, /* config */ \
292 FADE_TYPE_ADVANCED_XF, /* type */ \
293 0, /* - */ \
294 0, /* - */ \
295 TRUE, 0, 0, /* out_enable, _len_ms, _volume */ \
296 FC_OFFSET_CUSTOM, /* - */ \
297 FC_OFFSET_CUSTOM, 0, /* - ofs_custom_ms */ \
298 FALSE, /* - */ \
299 TRUE, 0, 0, /* in_enable, _len_ms, _volume */ \
300 FALSE, /* - */ \
301 0, /* - */ \
302 FALSE, /* - */ \
303 0, 0, /* - */ \
304 FALSE, /* flush */ \
305 TYPEMASK_TIMING, /* type_mask */ \
306 500, /* out_skip_ms */ \
307 500 /* in_skip_ms */ \
308 } \
309 }, \
310 TRUE, /* gap_lead_enable */ \
311 500, /* gap_lead_len_ms */ \
312 512, /* gap_lead_level */ \
313 TRUE, /* gap_trail_enable */ \
314 500, /* gap_trail_len_ms */ \
315 512, /* gap_trail_level */ \
316 TRUE, /* gap_trail_locked */ \
317 TRUE, /* gap_crossing */ \
318 FALSE, /* enable_debug */ \
319 FALSE, /* enable_monitor */ \
320 TRUE, /* enable_mixer */ \
321 FALSE, /* mixer_reverse */ \
322 FALSE, /* mixer_software */ \
323 75, /* mixer_vol_left */ \
324 75, /* mixer_vol_right */ \
325 500, /* songchange_timeout */ \
326 0, /* preload_size_ms */ \
327 TRUE, /* album detection */ \
328 FALSE, /* no_xfade_if_same_file */ \
329 FALSE, /* enable_http_workaround */ \
330 FALSE, /* enable_op_max_used */ \
331 250, /* op_max_used_ms */ \
332 FALSE, /* output_keep_opened */ \
333 NULL, /* presets */ \
334 250 /* sync_size_ms */ \
335 }
336
337
338 #define DEBUG(x) { if (config->enable_debug) debug x; }
339 #define PERROR(x) { if (config->enable_debug) perror(x); }
340
341 #define WRAP(x,n) (((x)<0)?((n)-(x))%(n):((x)%(n)))
342 #define B2MS(x) ((gint)((gint64)(x)*1000/OUTPUT_BPS))
343 #define MS2B(x) ((gint)((gint64)(x)*OUTPUT_BPS/1000))
344
345
346 /* get plugin info (imported by XMMS) */
347 OutputPlugin *get_oplugin_info();
348 OutputPlugin *get_crossfade_oplugin_info();
349
350 #include "player.h"
351
352 /* utilities */
353 void xfade_usleep(gint usec);
354
355 /* config change callbacks */
356 void xfade_realize_config();
357 void xfade_realize_ep_config();
358
359
360 typedef struct
361 {
362 gint mix_size; /* mixing buffer length */
363 gint sync_size; /* additional buffer space for mix timing */
364 gint preload_size; /* preload buffer length */
365
366 /* ---------------------------------------------------------------------- */
367
368 gpointer data; /* buffer */
369 gint size; /* total buffer length */
370
371 /* ---------------------------------------------------------------------- */
372
373 gint used; /* length */
374 gint rd_index; /* offset */
375
376 gint preload; /* > 0: preloading */
377
378 /* ---------------------------------------------------------------------- */
379
380 gint mix; /* > 0: mixing new data into buffer */
381
382 gint fade; /* > 0: fading in new data */
383 gint fade_len; /* length of fadein */
384 gfloat fade_scale; /* 1.0f - in_level */
385
386 #define GAP_SKIPPING_POSITIVE -1
387 #define GAP_SKIPPING_NEGATIVE -2
388 #define GAP_SKIPPING_DONE -3
389 gint gap; /* > 0: removing (leading) gap */
390 gint gap_len; /* max. len of gap, 0=disabled */
391 gint gap_level; /* max. sample value+1 to be considered "silent" */
392 gint gap_killed; /* number of bytes that were killed last time */
393 gint gap_skipped; /* negative/positive samples skipped */
394
395 gint skip; /* > 0: skipping beginning of song */
396 gint skip_len; /* total number of samples to skip */
397
398 /* ---------------------------------------------------------------------- */
399
400 gint silence; /* > 0: delay until start of silence */
401 gint silence_len; /* > 0: inserting silence */
402
403 gint reopen; /* >= 0: countdown to reopen device (disk_writer hack) */
404 gboolean reopen_sync; /* TRUE: sync output plugin before reopening */
405
406 gint pause; /* >= 0: countdown to pause output plugin */
407 }
408 buffer_t;
409
410 typedef struct
411 {
412 gint config; // one of FADE_CONFIG_*, constant
413 gint type; // one of FADE_TYPE_*
414
415 gint pause_len_ms; // PAUSE
416
417 gint simple_len_ms; // SIMPLE_XF
418
419 gboolean out_enable; // ADVANCED_XF
420 gint out_len_ms; // ADVANCED_XF, FADEOUT, PAUSE
421 gint out_volume; // ADVANCED_XF, FADEOUT
422
423 gint ofs_type; // ADVANCED_XF
424 gint ofs_type_wanted; // ADVANCED_XF
425 gint ofs_custom_ms; // ADVANCED_XF, FADEOUT (additional silence), PAUSE
426
427 gboolean in_locked; // ADVANCED_XF
428 gboolean in_enable; // ADVANCED_XF, FLUSH
429 gint in_len_ms; // ADVANCED_XF, FLUSH, FADEIN, PAUSE
430 gint in_volume; // ADVANCED_XF, FLUSH, FADEIN
431
432 gboolean flush_pause_enable; // FLUSH
433 gint flush_pause_len_ms; // FLUSH
434 gboolean flush_in_enable; // FLUSH
435 gint flush_in_len_ms; // FLUSH
436 gint flush_in_volume; // FLUSH
437
438 /* additional stuff which is not configureable by the user */
439 gboolean flush; // TRUE for manual, FALSE for xfade config
440 guint32 type_mask; // bitmask for FADE_TYPEs
441
442 /* new fields as of v0.3.11: skip beginning/end of song */
443 gint out_skip_ms;
444 gint in_skip_ms;
445 }
446 fade_config_t;
447
448 typedef struct
449 {
450 gboolean throttle_enable;
451 gboolean max_write_enable;
452 gint max_write_len;
453 gboolean force_reopen;
454 }
455 plugin_config_t;
456
457 typedef struct
458 {
459 /* output: method */
460 gint output_method;
461 gint output_rate;
462 gint output_quality;
463
464 /* output: builtin OSS */
465 gint oss_audio_device;
466 gboolean oss_use_alt_audio_device;
467 gchar *oss_alt_audio_device;
468
469 gint oss_mixer_device;
470 gboolean oss_use_alt_mixer_device;
471 gchar *oss_alt_mixer_device;
472 gboolean oss_mixer_use_master;
473
474 gint oss_buffer_size_ms;
475 gint oss_preload_size_ms;
476
477 gint oss_fragments;
478 gint oss_fragment_size;
479 gboolean oss_maxbuf_enable;
480
481 /* output: plugin */
482 gchar *op_config_string; /* stores configs for all plugins */
483 gchar *op_name; /* name of the current plugin */
484
485 /* effects */
486 gchar *ep_name;
487 gboolean ep_enable;
488 gboolean volnorm_enable;
489 gboolean volnorm_use_qa;
490 gint volnorm_target;
491
492 /* crossfader */
493 gint mix_size_ms;
494 gboolean mix_size_auto;
495 fade_config_t fc[MAX_FADE_CONFIGS];
496
497 /* gap killer */
498 gboolean gap_lead_enable;
499 gint gap_lead_len_ms;
500 gint gap_lead_level;
501
502 gboolean gap_trail_enable;
503 gint gap_trail_len_ms;
504 gint gap_trail_level;
505 gboolean gap_trail_locked;
506
507 gboolean gap_crossing;
508
509 /* misc */
510 gboolean enable_debug;
511 gboolean enable_monitor;
512
513 gboolean enable_mixer;
514 gboolean mixer_reverse;
515 gboolean mixer_software;
516 gint mixer_vol_left;
517 gint mixer_vol_right;
518
519 gint songchange_timeout;
520 gint preload_size_ms;
521 gboolean album_detection;
522 gboolean no_xfade_if_same_file;
523 gboolean enable_http_workaround;
524 gboolean enable_op_max_used;
525 gint op_max_used_ms;
526 gboolean output_keep_opened;
527
528 /* presets */
529 GList *presets;
530
531 /* additional stuff which is not configureable by the user */
532 gint sync_size_ms;
533
534 /* additional stuff which is not saved to the config file */
535 gint page;
536 gint oss_page;
537 gint xf_index;
538 }
539 config_t;
540
541
542 /* some global vars... we should really get rid of those somehow */
543 extern config_t *config;
544 extern config_t config_default;
545 extern buffer_t *buffer;
546
547 #if defined(HAVE_GLIB_THREADS)
548 # define MUTEX GStaticMutex
549 # define MUTEX_LOCK(mutex) g_static_mutex_lock(mutex)
550 # define MUTEX_UNLOCK(mutex) g_static_mutex_unlock(mutex)
551 # define MUTEX_INITIALIZER G_STATIC_MUTEX_INIT
552 # define THREAD GThread *
553 # define THREAD_CREATE(thread,func) !(thread = g_thread_create(func, NULL, TRUE, NULL))
554 # define THREAD_EXIT(rval) g_thread_exit(rval)
555 # define THREAD_JOIN(thread) g_thread_join(thread)
556 # define SCHED_YIELD g_thread_yield()
557 #else
558 # define MUTEX pthread_mutex_t
559 # define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex)
560 # define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex)
561 # define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
562 # define THREAD pthread_t
563 # define THREAD_CREATE(thread,func) pthread_create(&thread,NULL,func,NULL)
564 # define THREAD_EXIT(rval) pthread_exit(rval)
565 # define THREAD_JOIN(thread) pthread_join(thread,NULL)
566 # if defined(_POSIX_PRIORITY_SCHEDULING)
567 # define SCHED_YIELD sched_yield()
568 # else
569 # define SCHED_YIELD { }
570 # endif
571 #endif
572
573 extern gboolean opened; /* XMMS-crossfade is opened */
574 extern gboolean output_opened; /* the output plugin is opened */
575 extern gint output_offset;
576 extern gint64 output_streampos;
577
578 extern OutputPlugin *the_op;
579 extern gint the_rate;
580
581 #endif /* _CROSSFADE_H_ */