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 ((RunningEffect *) node->data)->header->flush ();
00120
00121 pthread_mutex_unlock (& mutex);
00122 }
00123
00124 void effect_finish (float * * data, int * samples)
00125 {
00126 pthread_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 pthread_mutex_unlock (& mutex);
00132 }
00133
00134 int effect_decoder_to_output_time (int time)
00135 {
00136 pthread_mutex_lock (& mutex);
00137
00138 for (GList * node = running_effects; node != NULL; node = node->next)
00139 {
00140 if (PLUGIN_HAS_FUNC (((RunningEffect *) node->data)->header, decoder_to_output_time))
00141 time = ((RunningEffect *) node->data)->header->decoder_to_output_time (time);
00142 }
00143
00144 pthread_mutex_unlock (& mutex);
00145 return time;
00146 }
00147
00148 int effect_output_to_decoder_time (int time)
00149 {
00150 pthread_mutex_lock (& mutex);
00151
00152 for (GList * node = g_list_last (running_effects); node != NULL; node = node->prev)
00153 {
00154 if (PLUGIN_HAS_FUNC (((RunningEffect *) node->data)->header, output_to_decoder_time))
00155 time = ((RunningEffect *) node->data)->header->output_to_decoder_time (time);
00156 }
00157
00158 pthread_mutex_unlock (& mutex);
00159 return time;
00160 }
00161
00162 static int effect_find_cb (RunningEffect * effect, PluginHandle * plugin)
00163 {
00164 return (effect->plugin == plugin) ? 0 : -1;
00165 }
00166
00167 static int effect_compare (RunningEffect * a, RunningEffect * b)
00168 {
00169 return plugin_compare (a->plugin, b->plugin);
00170 }
00171
00172 static void effect_insert (PluginHandle * plugin, EffectPlugin * header)
00173 {
00174 if (g_list_find_custom (running_effects, plugin, (GCompareFunc)
00175 effect_find_cb) != NULL)
00176 return;
00177
00178 AUDDBG ("Adding %s without reset.\n", plugin_get_name (plugin));
00179 RunningEffect * effect = g_malloc (sizeof (RunningEffect));
00180 effect->plugin = plugin;
00181 effect->header = header;
00182 effect->remove_flag = FALSE;
00183
00184 running_effects = g_list_insert_sorted (running_effects, effect,
00185 (GCompareFunc) effect_compare);
00186 GList * node = g_list_find (running_effects, effect);
00187
00188 int channels, rate;
00189 if (node->prev != NULL)
00190 {
00191 RunningEffect * prev = node->prev->data;
00192 AUDDBG ("Added %s after %s.\n", plugin_get_name (plugin),
00193 plugin_get_name (prev->plugin));
00194 channels = prev->channels_returned;
00195 rate = prev->rate_returned;
00196 }
00197 else
00198 {
00199 AUDDBG ("Added %s as first effect.\n", plugin_get_name (plugin));
00200 channels = input_channels;
00201 rate = input_rate;
00202 }
00203
00204 AUDDBG ("Starting %s at %d channels, %d Hz.\n", plugin_get_name (plugin),
00205 channels, rate);
00206 header->start (& channels, & rate);
00207 effect->channels_returned = channels;
00208 effect->rate_returned = rate;
00209 }
00210
00211 static void effect_remove (PluginHandle * plugin)
00212 {
00213 GList * node = g_list_find_custom (running_effects, plugin, (GCompareFunc)
00214 effect_find_cb);
00215 if (node == NULL)
00216 return;
00217
00218 AUDDBG ("Removing %s without reset.\n", plugin_get_name (plugin));
00219 ((RunningEffect *) node->data)->remove_flag = TRUE;
00220 }
00221
00222 static void effect_enable (PluginHandle * plugin, EffectPlugin * ep, bool_t
00223 enable)
00224 {
00225 if (ep->preserves_format)
00226 {
00227 pthread_mutex_lock (& mutex);
00228
00229 if (enable)
00230 effect_insert (plugin, ep);
00231 else
00232 effect_remove (plugin);
00233
00234 pthread_mutex_unlock (& mutex);
00235 }
00236 else
00237 {
00238 AUDDBG ("Reset to add/remove %s.\n", plugin_get_name (plugin));
00239 int time = playback_get_time ();
00240 bool_t paused = playback_get_paused ();
00241 playback_stop ();
00242 playback_play (time, paused);
00243 }
00244 }
00245
00246 bool_t effect_plugin_start (PluginHandle * plugin)
00247 {
00248 if (playback_get_playing ())
00249 {
00250 EffectPlugin * ep = plugin_get_header (plugin);
00251 g_return_val_if_fail (ep != NULL, FALSE);
00252 effect_enable (plugin, ep, TRUE);
00253 }
00254
00255 return TRUE;
00256 }
00257
00258 void effect_plugin_stop (PluginHandle * plugin)
00259 {
00260 if (playback_get_playing ())
00261 {
00262 EffectPlugin * ep = plugin_get_header (plugin);
00263 g_return_if_fail (ep != NULL);
00264 effect_enable (plugin, ep, FALSE);
00265 }
00266 }