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