00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <glib.h>
00023
00024 #include "debug.h"
00025 #include "effect.h"
00026 #include "playback.h"
00027 #include "plugin.h"
00028 #include "plugins.h"
00029
00030 typedef struct {
00031 PluginHandle * plugin;
00032 EffectPlugin * header;
00033 gint channels_returned, rate_returned;
00034 gboolean remove_flag;
00035 } RunningEffect;
00036
00037 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
00038 static GList * running_effects = NULL;
00039 static gint input_channels, input_rate;
00040
00041 typedef struct {
00042 gint * channels, * rate;
00043 } EffectStartState;
00044
00045 static gboolean effect_start_cb (PluginHandle * plugin, EffectStartState * state)
00046 {
00047 AUDDBG ("Starting %s at %d channels, %d Hz.\n", plugin_get_name (plugin),
00048 * state->channels, * state->rate);
00049 EffectPlugin * header = plugin_get_header (plugin);
00050 g_return_val_if_fail (header != NULL, TRUE);
00051 header->start (state->channels, state->rate);
00052
00053 RunningEffect * effect = g_malloc (sizeof (RunningEffect));
00054 effect->plugin = plugin;
00055 effect->header = header;
00056 effect->channels_returned = * state->channels;
00057 effect->rate_returned = * state->rate;
00058 effect->remove_flag = FALSE;
00059
00060 running_effects = g_list_prepend (running_effects, effect);
00061 return TRUE;
00062 }
00063
00064 void effect_start (gint * channels, gint * rate)
00065 {
00066 g_static_mutex_lock (& mutex);
00067
00068 AUDDBG ("Starting effects.\n");
00069 g_list_foreach (running_effects, (GFunc) g_free, NULL);
00070 g_list_free (running_effects);
00071 running_effects = NULL;
00072
00073 input_channels = * channels;
00074 input_rate = * rate;
00075
00076 EffectStartState state = {channels, rate};
00077 plugin_for_enabled (PLUGIN_TYPE_EFFECT, (PluginForEachFunc) effect_start_cb,
00078 & state);
00079 running_effects = g_list_reverse (running_effects);
00080
00081 g_static_mutex_unlock (& mutex);
00082 }
00083
00084 typedef struct {
00085 gfloat * * data;
00086 gint * samples;
00087 } EffectProcessState;
00088
00089 static void effect_process_cb (RunningEffect * effect, EffectProcessState *
00090 state)
00091 {
00092 if (effect->remove_flag)
00093 {
00094 effect->header->finish (state->data, state->samples);
00095 effect->header->finish (state->data, state->samples);
00096
00097 running_effects = g_list_remove (running_effects, effect);
00098 g_free (effect);
00099 }
00100 else
00101 effect->header->process (state->data, state->samples);
00102 }
00103
00104 void effect_process (gfloat * * data, gint * samples)
00105 {
00106 g_static_mutex_lock (& mutex);
00107
00108 EffectProcessState state = {data, samples};
00109 g_list_foreach (running_effects, (GFunc) effect_process_cb, & state);
00110
00111 g_static_mutex_unlock (& mutex);
00112 }
00113
00114 void effect_flush (void)
00115 {
00116 g_static_mutex_lock (& mutex);
00117
00118 for (GList * node = running_effects; node != NULL; node = node->next)
00119 ((RunningEffect *) node->data)->header->flush ();
00120
00121 g_static_mutex_unlock (& mutex);
00122 }
00123
00124 void effect_finish (gfloat * * data, gint * samples)
00125 {
00126 g_static_mutex_lock (& mutex);
00127
00128 for (GList * node = running_effects; node != NULL; node = node->next)
00129 ((RunningEffect *) node->data)->header->finish (data, samples);
00130
00131 g_static_mutex_unlock (& mutex);
00132 }
00133
00134 gint effect_decoder_to_output_time (gint time)
00135 {
00136 g_static_mutex_lock (& mutex);
00137
00138 for (GList * node = running_effects; node != NULL; node = node->next)
00139 time = ((RunningEffect *) node->data)->header->decoder_to_output_time
00140 (time);
00141
00142 g_static_mutex_unlock (& mutex);
00143 return time;
00144 }
00145
00146 gint effect_output_to_decoder_time (gint time)
00147 {
00148 g_static_mutex_lock (& mutex);
00149
00150 for (GList * node = g_list_last (running_effects); node != NULL; node =
00151 node->prev)
00152 time = ((RunningEffect *) node->data)->header->output_to_decoder_time
00153 (time);
00154
00155 g_static_mutex_unlock (& mutex);
00156 return time;
00157 }
00158
00159 static gint effect_find_cb (RunningEffect * effect, PluginHandle * plugin)
00160 {
00161 return (effect->plugin == plugin) ? 0 : -1;
00162 }
00163
00164 static gint effect_compare (RunningEffect * a, RunningEffect * b)
00165 {
00166 return plugin_compare (a->plugin, b->plugin);
00167 }
00168
00169 static void effect_insert (PluginHandle * plugin, EffectPlugin * header)
00170 {
00171 if (g_list_find_custom (running_effects, plugin, (GCompareFunc)
00172 effect_find_cb) != NULL)
00173 return;
00174
00175 AUDDBG ("Adding %s without reset.\n", plugin_get_name (plugin));
00176 RunningEffect * effect = g_malloc (sizeof (RunningEffect));
00177 effect->plugin = plugin;
00178 effect->header = header;
00179 effect->remove_flag = FALSE;
00180
00181 running_effects = g_list_insert_sorted (running_effects, effect,
00182 (GCompareFunc) effect_compare);
00183 GList * node = g_list_find (running_effects, effect);
00184
00185 gint channels, rate;
00186 if (node->prev != NULL)
00187 {
00188 RunningEffect * prev = node->prev->data;
00189 AUDDBG ("Added %s after %s.\n", plugin_get_name (plugin),
00190 plugin_get_name (prev->plugin));
00191 channels = prev->channels_returned;
00192 rate = prev->rate_returned;
00193 }
00194 else
00195 {
00196 AUDDBG ("Added %s as first effect.\n", plugin_get_name (plugin));
00197 channels = input_channels;
00198 rate = input_rate;
00199 }
00200
00201 AUDDBG ("Starting %s at %d channels, %d Hz.\n", plugin_get_name (plugin),
00202 channels, rate);
00203 header->start (& channels, & rate);
00204 effect->channels_returned = channels;
00205 effect->rate_returned = rate;
00206 }
00207
00208 static void effect_remove (PluginHandle * plugin)
00209 {
00210 GList * node = g_list_find_custom (running_effects, plugin, (GCompareFunc)
00211 effect_find_cb);
00212 if (node == NULL)
00213 return;
00214
00215 AUDDBG ("Removing %s without reset.\n", plugin_get_name (plugin));
00216 ((RunningEffect *) node->data)->remove_flag = TRUE;
00217 }
00218
00219 static void effect_enable (PluginHandle * plugin, EffectPlugin * ep, gboolean
00220 enable)
00221 {
00222 if (ep->preserves_format)
00223 {
00224 g_static_mutex_lock (& mutex);
00225
00226 if (enable)
00227 effect_insert (plugin, ep);
00228 else
00229 effect_remove (plugin);
00230
00231 g_static_mutex_unlock (& mutex);
00232 }
00233 else
00234 {
00235 AUDDBG ("Reset to add/remove %s.\n", plugin_get_name (plugin));
00236 gint time = playback_get_time ();
00237 gboolean paused = playback_get_paused ();
00238 playback_stop ();
00239 playback_play (time, paused);
00240 }
00241 }
00242
00243 gboolean effect_plugin_start (PluginHandle * plugin)
00244 {
00245 if (playback_get_playing ())
00246 {
00247 EffectPlugin * ep = plugin_get_header (plugin);
00248 g_return_val_if_fail (ep != NULL, FALSE);
00249 effect_enable (plugin, ep, TRUE);
00250 }
00251
00252 return TRUE;
00253 }
00254
00255 void effect_plugin_stop (PluginHandle * plugin)
00256 {
00257 if (playback_get_playing ())
00258 {
00259 EffectPlugin * ep = plugin_get_header (plugin);
00260 g_return_if_fail (ep != NULL);
00261 effect_enable (plugin, ep, FALSE);
00262 }
00263 }