Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * effect.c 00003 * Copyright 2010 John Lindgren 00004 * 00005 * This file is part of Audacious. 00006 * 00007 * Audacious is free software: you can redistribute it and/or modify it under 00008 * the terms of the GNU General Public License as published by the Free Software 00009 * Foundation, version 2 or version 3 of the License. 00010 * 00011 * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY 00012 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 00013 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along with 00016 * Audacious. If not, see <http://www.gnu.org/licenses/>. 00017 * 00018 * The Audacious team does not consider modular code linking to Audacious or 00019 * using our public API to be a derived work. 00020 */ 00021 00022 #include <glib.h> 00023 00024 #include "debug.h" 00025 #include "effect.h" 00026 #include "output.h" 00027 #include "playback.h" 00028 #include "plugin.h" 00029 #include "plugins.h" 00030 00031 typedef struct { 00032 PluginHandle * plugin; 00033 EffectPlugin * header; 00034 gint channels_returned, rate_returned; 00035 gboolean remove_flag; 00036 } RunningEffect; 00037 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 AUDDBG ("Starting effects.\n"); 00067 g_list_foreach (running_effects, (GFunc) g_free, NULL); 00068 g_list_free (running_effects); 00069 running_effects = NULL; 00070 00071 input_channels = * channels; 00072 input_rate = * rate; 00073 00074 EffectStartState state = {channels, rate}; 00075 plugin_for_enabled (PLUGIN_TYPE_EFFECT, (PluginForEachFunc) effect_start_cb, 00076 & state); 00077 running_effects = g_list_reverse (running_effects); 00078 } 00079 00080 typedef struct 00081 { 00082 gfloat * * data; 00083 gint * samples; 00084 } EffectProcessState; 00085 00086 static void effect_process_cb (RunningEffect * effect, EffectProcessState * 00087 state) 00088 { 00089 if (effect->remove_flag) 00090 { 00091 effect->header->finish (state->data, state->samples); 00092 effect->header->finish (state->data, state->samples); 00093 00094 running_effects = g_list_remove (running_effects, effect); 00095 g_free (effect); 00096 } 00097 else 00098 effect->header->process (state->data, state->samples); 00099 } 00100 00101 void effect_process (gfloat * * data, gint * samples) 00102 { 00103 EffectProcessState state = {data, samples}; 00104 g_list_foreach (running_effects, (GFunc) effect_process_cb, & state); 00105 } 00106 00107 void effect_flush (void) 00108 { 00109 for (GList * node = running_effects; node != NULL; node = node->next) 00110 ((RunningEffect *) node->data)->header->flush (); 00111 } 00112 00113 void effect_finish (gfloat * * data, gint * samples) 00114 { 00115 for (GList * node = running_effects; node != NULL; node = node->next) 00116 ((RunningEffect *) node->data)->header->finish (data, samples); 00117 } 00118 00119 gint effect_decoder_to_output_time (gint time) 00120 { 00121 for (GList * node = running_effects; node != NULL; node = node->next) 00122 time = ((RunningEffect *) node->data)->header->decoder_to_output_time 00123 (time); 00124 return time; 00125 } 00126 00127 gint effect_output_to_decoder_time (gint time) 00128 { 00129 for (GList * node = g_list_last (running_effects); node != NULL; node = 00130 node->prev) 00131 time = ((RunningEffect *) node->data)->header->output_to_decoder_time 00132 (time); 00133 return time; 00134 } 00135 00136 static gint effect_find_cb (RunningEffect * effect, PluginHandle * plugin) 00137 { 00138 return (effect->plugin == plugin) ? 0 : -1; 00139 } 00140 00141 static gint effect_compare (RunningEffect * a, RunningEffect * b) 00142 { 00143 return plugin_compare (a->plugin, b->plugin); 00144 } 00145 00146 static void effect_insert (PluginHandle * plugin, EffectPlugin * header) 00147 { 00148 if (g_list_find_custom (running_effects, plugin, (GCompareFunc) 00149 effect_find_cb) != NULL) 00150 return; 00151 00152 AUDDBG ("Adding %s without reset.\n", plugin_get_name (plugin)); 00153 RunningEffect * effect = g_malloc (sizeof (RunningEffect)); 00154 effect->plugin = plugin; 00155 effect->header = header; 00156 effect->remove_flag = FALSE; 00157 00158 running_effects = g_list_insert_sorted (running_effects, effect, 00159 (GCompareFunc) effect_compare); 00160 GList * node = g_list_find (running_effects, effect); 00161 00162 gint channels, rate; 00163 if (node->prev != NULL) 00164 { 00165 RunningEffect * prev = node->prev->data; 00166 AUDDBG ("Added %s after %s.\n", plugin_get_name (plugin), 00167 plugin_get_name (prev->plugin)); 00168 channels = prev->channels_returned; 00169 rate = prev->rate_returned; 00170 } 00171 else 00172 { 00173 AUDDBG ("Added %s as first effect.\n", plugin_get_name (plugin)); 00174 channels = input_channels; 00175 rate = input_rate; 00176 } 00177 00178 AUDDBG ("Starting %s at %d channels, %d Hz.\n", plugin_get_name (plugin), 00179 channels, rate); 00180 header->start (& channels, & rate); 00181 effect->channels_returned = channels; 00182 effect->rate_returned = rate; 00183 } 00184 00185 static void effect_remove (PluginHandle * plugin) 00186 { 00187 GList * node = g_list_find_custom (running_effects, plugin, (GCompareFunc) 00188 effect_find_cb); 00189 if (node == NULL) 00190 return; 00191 00192 AUDDBG ("Removing %s without reset.\n", plugin_get_name (plugin)); 00193 ((RunningEffect *) node->data)->remove_flag = TRUE; 00194 } 00195 00196 void effect_plugin_enable (PluginHandle * plugin, gboolean enable) 00197 { 00198 plugin_set_enabled (plugin, enable); 00199 00200 if (playback_get_playing ()) 00201 { 00202 EffectPlugin * header = plugin_get_header (plugin); 00203 g_return_if_fail (header != NULL); 00204 00205 if (header->preserves_format) 00206 { 00207 if (enable) 00208 effect_insert (plugin, header); 00209 else 00210 effect_remove (plugin); 00211 } 00212 else 00213 { 00214 AUDDBG ("Reset to add/remove %s.\n", plugin_get_name (plugin)); 00215 set_current_output_plugin (current_output_plugin); 00216 } 00217 } 00218 }