Mercurial > audlegacy-plugins
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/crossfade/crossfade.h Fri Apr 24 05:57:35 2009 -0500 @@ -0,0 +1,581 @@ +/* + * XMMS Crossfade Plugin + * Copyright (C) 2000-2007 Peter Eisenlohr <peter@eisenlohr.org> + * + * based on the original OSS Output Plugin + * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef _CROSSFADE_H_ +#define _CROSSFADE_H_ + +#define COMPILE_FOR_AUDACIOUS +#define AUDACIOUS_ABI_VERSION 2 + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if !defined(HAVE_GLIB_THREADS) +# include <pthread.h> +#endif +#include <glib.h> + +#include <audacious/plugin.h> +#include <audacious/playlist.h> +#include <audacious/auddrct.h> +#include <audacious/configdb.h> +#include <audacious/util.h> + +#include "debug.h" + +#undef VOLUME_NORMALIZER +#define TIMING_COMMENTS + +#define OUTPUT_RATE the_rate +#define OUTPUT_NCH 2 +#define OUTPUT_BPS (OUTPUT_RATE * OUTPUT_NCH * 2) + +#if defined(HAVE_LIBSAMPLERATE) +# define MAX_RATE 192000 +#else +# define MAX_RATE 48000 +#endif + +#define SYNC_OUTPUT_TIMEOUT 2000 + +#define OUTPUT_METHOD_BUILTIN_OSS 0 +#define OUTPUT_METHOD_PLUGIN 1 +#define OUTPUT_METHOD_BUILTIN_NULL 2 + +#define FADE_CONFIG_XFADE 0 +#define FADE_CONFIG_MANUAL 1 +#define FADE_CONFIG_ALBUM 2 +#define FADE_CONFIG_START 3 +#define FADE_CONFIG_STOP 4 +#define FADE_CONFIG_EOP 5 +#define FADE_CONFIG_SEEK 6 +#define FADE_CONFIG_PAUSE 7 +#define FADE_CONFIG_TIMING 8 +#define MAX_FADE_CONFIGS 9 + +#define FADE_TYPE_REOPEN 0 +#define FADE_TYPE_FLUSH 1 +#define FADE_TYPE_NONE 2 +#define FADE_TYPE_PAUSE 3 +#define FADE_TYPE_SIMPLE_XF 4 +#define FADE_TYPE_ADVANCED_XF 5 +#define FADE_TYPE_FADEIN 6 +#define FADE_TYPE_FADEOUT 7 +#define FADE_TYPE_PAUSE_NONE 8 +#define FADE_TYPE_PAUSE_ADV 9 +#define MAX_FADE_TYPES 10 + +#define TYPEMASK_XFADE ((1 << FADE_TYPE_REOPEN) | \ + (1 << FADE_TYPE_NONE) | \ + (1 << FADE_TYPE_PAUSE) | \ + (1 << FADE_TYPE_SIMPLE_XF) | \ + (1 << FADE_TYPE_ADVANCED_XF)) + +#define TYPEMASK_MANUAL ((1 << FADE_TYPE_REOPEN) | \ + (1 << FADE_TYPE_FLUSH) | \ + (1 << FADE_TYPE_NONE) | \ + (1 << FADE_TYPE_PAUSE) | \ + (1 << FADE_TYPE_SIMPLE_XF) | \ + (1 << FADE_TYPE_ADVANCED_XF)) + +#define TYPEMASK_ALBUM ((1 << FADE_TYPE_NONE)) + +#define TYPEMASK_START ((1 << FADE_TYPE_NONE) | \ + (1 << FADE_TYPE_FADEIN)) + +#define TYPEMASK_STOP ((1 << FADE_TYPE_NONE) | \ + (1 << FADE_TYPE_FADEOUT)) + +#define TYPEMASK_EOP ((1 << FADE_TYPE_NONE) | \ + (1 << FADE_TYPE_FADEOUT)) + +#define TYPEMASK_SEEK ((1 << FADE_TYPE_FLUSH) | \ + (1 << FADE_TYPE_NONE) | \ + (1 << FADE_TYPE_SIMPLE_XF)) + +#define TYPEMASK_PAUSE ((1 << FADE_TYPE_PAUSE_NONE) | \ + (1 << FADE_TYPE_PAUSE_ADV)) + +#define TYPEMASK_TIMING (0) + +#define FC_OFFSET_NONE 0 +#define FC_OFFSET_LOCK_IN 1 +#define FC_OFFSET_LOCK_OUT 2 +#define FC_OFFSET_CUSTOM 3 + +#define DEFAULT_OSS_ALT_AUDIO_DEVICE "/dev/dsp" +#define DEFAULT_OSS_ALT_MIXER_DEVICE "/dev/mixer" +#define DEFAULT_OP_CONFIG_STRING "libOSS.so=0,1,2304,0; libdisk_writer.so=1,0,2304,1" +#define DEFAULT_OP_NAME "libALSA.so" +#define DEFAULT_EP_NAME "libnormvol.so" + +#define DEFAULT_OP_CONFIG \ +{ FALSE, FALSE, 2304, FALSE } + +#define CONFIG_DEFAULT \ +{ 0, /* output_method */ \ + 44100, /* output_rate */ \ + 2, /* output_quality */ \ + 0, /* oss_audio_device */ \ + FALSE, /* oss_use_alt_audio_device */ \ + NULL, /* oss_alt_audio_device */ \ + 0, /* oss_mixer_device */ \ + FALSE, /* oss_use_alt_mixer_device */ \ + NULL, /* oss_alt_mixer_device */ \ + FALSE, /* oss_mixer_use_master */ \ + 0, /* oss_buffer_size_ms */ \ + 250, /* oss_preload_size_ms */ \ + 22, /* oss_fragments */ \ + 12, /* oss_fragment_size */ \ + FALSE, /* oss_maxbuf_enable */ \ + NULL, /* op_config_string */ \ + NULL, /* op_name */ \ + NULL, /* ep_name */ \ + FALSE, /* ep_enable */ \ + TRUE, /* volnorm_enable */ \ + 8000, /* volnorm_target */ \ + FALSE, /* volnorm_use_qa */ \ + 10000, /* mix_size_ms */ \ + TRUE, /* mix_size_auto */ \ + \ + { /* fc[MAX_FADE_CONFIGS] */ \ + { FADE_CONFIG_XFADE, /* config */ \ + FADE_TYPE_ADVANCED_XF, /* type */ \ + 2000, /* pause_len_ms */ \ + 6000, /* simple_len_ms */ \ + TRUE, 4000, 0, /* out_enable, _len_ms, _volume */ \ + FC_OFFSET_CUSTOM, /* ofs_type */ \ + FC_OFFSET_CUSTOM, -6000, /* ofs_type_wanted, ofs_custom_ms */ \ + TRUE, /* in_locked */ \ + FALSE, 4000, 33, /* in_enable, _len_ms, _volume */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + FALSE, /* flush */ \ + TYPEMASK_XFADE /* type_mask */ \ + }, \ + { FADE_CONFIG_MANUAL, /* config */ \ + FADE_TYPE_SIMPLE_XF, /* type */ \ + 2000, /* pause_len_ms */ \ + 1000, /* simple_len_ms */ \ + TRUE, 500, 0, /* out_enable, _len_ms, _volume */ \ + FC_OFFSET_CUSTOM, /* ofs_type */ \ + FC_OFFSET_CUSTOM, -500, /* ofs_type_wanted, ofs_custom_ms */ \ + TRUE, /* in_locked */ \ + FALSE, 500, 50, /* in_enable, _len_ms, _volume */ \ + FALSE, /* flush_pause_enable */ \ + 500, /* flush_in_len_ms */ \ + FALSE, /* flush_in_enable */ \ + 500, 0, /* flush_in_len_ms, _volume */ \ + TRUE, /* flush */ \ + TYPEMASK_MANUAL /* type_mask */ \ + }, \ + { FADE_CONFIG_ALBUM, /* config */ \ + FADE_TYPE_NONE, /* type */ \ + 0, /* - */ \ + 0, /* - */ \ + FALSE, 0, 0, /* - */ \ + FC_OFFSET_NONE, /* - */ \ + FC_OFFSET_NONE, 0, /* - */ \ + FALSE, /* - */ \ + FALSE, 1000, 0, /* - */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + FALSE, /* flush */ \ + TYPEMASK_ALBUM /* type_mask */ \ + }, \ + { FADE_CONFIG_START, /* config */ \ + FADE_TYPE_FADEIN, /* type */ \ + 0, /* - */ \ + 0, /* - */ \ + FALSE, 0, 0, /* - */ \ + FC_OFFSET_NONE, /* - */ \ + FC_OFFSET_NONE, 0, /* - */ \ + FALSE, /* - */ \ + FALSE, 100, 0, /* - in_len_ms, _volume */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + TRUE, /* flush */ \ + TYPEMASK_START /* type_mask */ \ + }, \ + { FADE_CONFIG_STOP, /* config */ \ + FADE_TYPE_FADEOUT, /* type */ \ + 0, /* - */ \ + 0, /* - */ \ + FALSE, 100, 0, /* - out_len_ms, _volume */ \ + FC_OFFSET_NONE, /* - */ \ + FC_OFFSET_NONE, 500, /* - ofs_custom_ms */ \ + FALSE, /* - */ \ + FALSE, 0, 0, /* - */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + TRUE, /* flush */ \ + TYPEMASK_STOP /* type_mask */ \ + }, \ + { FADE_CONFIG_EOP, /* config */ \ + FADE_TYPE_FADEOUT, /* type */ \ + 0, /* - */ \ + 0, /* - */ \ + FALSE, 100, 0, /* - out_len_ms, _volume */ \ + FC_OFFSET_NONE, /* - */ \ + FC_OFFSET_NONE, 500, /* - ofs_custom_ms */ \ + FALSE, /* - */ \ + FALSE, 0, 0, /* - */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + FALSE, /* flush */ \ + TYPEMASK_EOP /* type_mask */ \ + }, \ + { FADE_CONFIG_SEEK, /* config */ \ + FADE_TYPE_SIMPLE_XF, /* type */ \ + 0, /* - */ \ + 50, /* simple_len_ms */ \ + FALSE, 0, 0, /* - */ \ + FC_OFFSET_NONE, /* - */ \ + FC_OFFSET_NONE, 0, /* - */ \ + FALSE, /* - */ \ + FALSE, 1000, 0, /* - */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + TRUE, /* flush */ \ + TYPEMASK_SEEK /* type_mask */ \ + }, \ + { FADE_CONFIG_PAUSE, /* config */ \ + FADE_TYPE_PAUSE_ADV, /* type */ \ + 0, /* - */ \ + 0, /* - */ \ + TRUE, 100, 0, /* - out_len_ms, - */ \ + FC_OFFSET_NONE, /* - */ \ + FC_OFFSET_NONE, 100, /* - ofs_custom_ms */ \ + FALSE, /* - */ \ + TRUE, 100, 0, /* - in_len_ms, - */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + FALSE, /* - */ \ + TYPEMASK_PAUSE /* type_mask */ \ + }, \ + { FADE_CONFIG_TIMING, /* config */ \ + FADE_TYPE_ADVANCED_XF, /* type */ \ + 0, /* - */ \ + 0, /* - */ \ + TRUE, 0, 0, /* out_enable, _len_ms, _volume */ \ + FC_OFFSET_CUSTOM, /* - */ \ + FC_OFFSET_CUSTOM, 0, /* - ofs_custom_ms */ \ + FALSE, /* - */ \ + TRUE, 0, 0, /* in_enable, _len_ms, _volume */ \ + FALSE, /* - */ \ + 0, /* - */ \ + FALSE, /* - */ \ + 0, 0, /* - */ \ + FALSE, /* flush */ \ + TYPEMASK_TIMING, /* type_mask */ \ + 500, /* out_skip_ms */ \ + 500 /* in_skip_ms */ \ + } \ + }, \ + TRUE, /* gap_lead_enable */ \ + 500, /* gap_lead_len_ms */ \ + 512, /* gap_lead_level */ \ + TRUE, /* gap_trail_enable */ \ + 500, /* gap_trail_len_ms */ \ + 512, /* gap_trail_level */ \ + TRUE, /* gap_trail_locked */ \ + TRUE, /* gap_crossing */ \ + FALSE, /* enable_debug */ \ + FALSE, /* enable_monitor */ \ + TRUE, /* enable_mixer */ \ + FALSE, /* mixer_reverse */ \ + FALSE, /* mixer_software */ \ + 75, /* mixer_vol_left */ \ + 75, /* mixer_vol_right */ \ + 500, /* songchange_timeout */ \ + 0, /* preload_size_ms */ \ + TRUE, /* album detection */ \ + FALSE, /* no_xfade_if_same_file */ \ + FALSE, /* enable_http_workaround */ \ + FALSE, /* enable_op_max_used */ \ + 250, /* op_max_used_ms */ \ + FALSE, /* output_keep_opened */ \ + NULL, /* presets */ \ + 250 /* sync_size_ms */ \ +} + + +#define DEBUG(x) { if (config->enable_debug) debug x; } +#define PERROR(x) { if (config->enable_debug) perror(x); } + +#define WRAP(x,n) (((x)<0)?((n)-(x))%(n):((x)%(n))) +#define B2MS(x) ((gint)((gint64)(x)*1000/OUTPUT_BPS)) +#define MS2B(x) ((gint)((gint64)(x)*OUTPUT_BPS/1000)) + + +/* get plugin info (imported by XMMS) */ +OutputPlugin *get_oplugin_info(); +OutputPlugin *get_crossfade_oplugin_info(); + +#include "player.h" + +/* utilities */ +void xfade_usleep(gint usec); + +/* config change callbacks */ +void xfade_realize_config(); +void xfade_realize_ep_config(); + + +typedef struct +{ + gint mix_size; /* mixing buffer length */ + gint sync_size; /* additional buffer space for mix timing */ + gint preload_size; /* preload buffer length */ + + /* ---------------------------------------------------------------------- */ + + gpointer data; /* buffer */ + gint size; /* total buffer length */ + + /* ---------------------------------------------------------------------- */ + + gint used; /* length */ + gint rd_index; /* offset */ + + gint preload; /* > 0: preloading */ + + /* ---------------------------------------------------------------------- */ + + gint mix; /* > 0: mixing new data into buffer */ + + gint fade; /* > 0: fading in new data */ + gint fade_len; /* length of fadein */ + gfloat fade_scale; /* 1.0f - in_level */ + +#define GAP_SKIPPING_POSITIVE -1 +#define GAP_SKIPPING_NEGATIVE -2 +#define GAP_SKIPPING_DONE -3 + gint gap; /* > 0: removing (leading) gap */ + gint gap_len; /* max. len of gap, 0=disabled */ + gint gap_level; /* max. sample value+1 to be considered "silent" */ + gint gap_killed; /* number of bytes that were killed last time */ + gint gap_skipped; /* negative/positive samples skipped */ + + gint skip; /* > 0: skipping beginning of song */ + gint skip_len; /* total number of samples to skip */ + + /* ---------------------------------------------------------------------- */ + + gint silence; /* > 0: delay until start of silence */ + gint silence_len; /* > 0: inserting silence */ + + gint reopen; /* >= 0: countdown to reopen device (disk_writer hack) */ + gboolean reopen_sync; /* TRUE: sync output plugin before reopening */ + + gint pause; /* >= 0: countdown to pause output plugin */ +} +buffer_t; + +typedef struct +{ + gint config; // one of FADE_CONFIG_*, constant + gint type; // one of FADE_TYPE_* + + gint pause_len_ms; // PAUSE + + gint simple_len_ms; // SIMPLE_XF + + gboolean out_enable; // ADVANCED_XF + gint out_len_ms; // ADVANCED_XF, FADEOUT, PAUSE + gint out_volume; // ADVANCED_XF, FADEOUT + + gint ofs_type; // ADVANCED_XF + gint ofs_type_wanted; // ADVANCED_XF + gint ofs_custom_ms; // ADVANCED_XF, FADEOUT (additional silence), PAUSE + + gboolean in_locked; // ADVANCED_XF + gboolean in_enable; // ADVANCED_XF, FLUSH + gint in_len_ms; // ADVANCED_XF, FLUSH, FADEIN, PAUSE + gint in_volume; // ADVANCED_XF, FLUSH, FADEIN + + gboolean flush_pause_enable; // FLUSH + gint flush_pause_len_ms; // FLUSH + gboolean flush_in_enable; // FLUSH + gint flush_in_len_ms; // FLUSH + gint flush_in_volume; // FLUSH + + /* additional stuff which is not configureable by the user */ + gboolean flush; // TRUE for manual, FALSE for xfade config + guint32 type_mask; // bitmask for FADE_TYPEs + + /* new fields as of v0.3.11: skip beginning/end of song */ + gint out_skip_ms; + gint in_skip_ms; +} +fade_config_t; + +typedef struct +{ + gboolean throttle_enable; + gboolean max_write_enable; + gint max_write_len; + gboolean force_reopen; +} +plugin_config_t; + +typedef struct +{ + /* output: method */ + gint output_method; + gint output_rate; + gint output_quality; + + /* output: builtin OSS */ + gint oss_audio_device; + gboolean oss_use_alt_audio_device; + gchar *oss_alt_audio_device; + + gint oss_mixer_device; + gboolean oss_use_alt_mixer_device; + gchar *oss_alt_mixer_device; + gboolean oss_mixer_use_master; + + gint oss_buffer_size_ms; + gint oss_preload_size_ms; + + gint oss_fragments; + gint oss_fragment_size; + gboolean oss_maxbuf_enable; + + /* output: plugin */ + gchar *op_config_string; /* stores configs for all plugins */ + gchar *op_name; /* name of the current plugin */ + + /* effects */ + gchar *ep_name; + gboolean ep_enable; + gboolean volnorm_enable; + gboolean volnorm_use_qa; + gint volnorm_target; + + /* crossfader */ + gint mix_size_ms; + gboolean mix_size_auto; + fade_config_t fc[MAX_FADE_CONFIGS]; + + /* gap killer */ + gboolean gap_lead_enable; + gint gap_lead_len_ms; + gint gap_lead_level; + + gboolean gap_trail_enable; + gint gap_trail_len_ms; + gint gap_trail_level; + gboolean gap_trail_locked; + + gboolean gap_crossing; + + /* misc */ + gboolean enable_debug; + gboolean enable_monitor; + + gboolean enable_mixer; + gboolean mixer_reverse; + gboolean mixer_software; + gint mixer_vol_left; + gint mixer_vol_right; + + gint songchange_timeout; + gint preload_size_ms; + gboolean album_detection; + gboolean no_xfade_if_same_file; + gboolean enable_http_workaround; + gboolean enable_op_max_used; + gint op_max_used_ms; + gboolean output_keep_opened; + + /* presets */ + GList *presets; + + /* additional stuff which is not configureable by the user */ + gint sync_size_ms; + + /* additional stuff which is not saved to the config file */ + gint page; + gint oss_page; + gint xf_index; +} +config_t; + + +/* some global vars... we should really get rid of those somehow */ +extern config_t *config; +extern config_t config_default; +extern buffer_t *buffer; + +#if defined(HAVE_GLIB_THREADS) +# define MUTEX GStaticMutex +# define MUTEX_LOCK(mutex) g_static_mutex_lock(mutex) +# define MUTEX_UNLOCK(mutex) g_static_mutex_unlock(mutex) +# define MUTEX_INITIALIZER G_STATIC_MUTEX_INIT +# define THREAD GThread * +# define THREAD_CREATE(thread,func) !(thread = g_thread_create(func, NULL, TRUE, NULL)) +# define THREAD_EXIT(rval) g_thread_exit(rval) +# define THREAD_JOIN(thread) g_thread_join(thread) +# define SCHED_YIELD g_thread_yield() +#else +# define MUTEX pthread_mutex_t +# define MUTEX_LOCK(mutex) pthread_mutex_lock(mutex) +# define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(mutex) +# define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +# define THREAD pthread_t +# define THREAD_CREATE(thread,func) pthread_create(&thread,NULL,func,NULL) +# define THREAD_EXIT(rval) pthread_exit(rval) +# define THREAD_JOIN(thread) pthread_join(thread,NULL) +# if defined(_POSIX_PRIORITY_SCHEDULING) +# define SCHED_YIELD sched_yield() +# else +# define SCHED_YIELD { } +# endif +#endif + +extern gboolean opened; /* XMMS-crossfade is opened */ +extern gboolean output_opened; /* the output plugin is opened */ +extern gint output_offset; +extern gint64 output_streampos; + +extern OutputPlugin *the_op; +extern gint the_rate; + +#endif /* _CROSSFADE_H_ */