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 <gtk/gtk.h>
00024 #include <string.h>
00025
00026 #include "debug.h"
00027 #include "fft.h"
00028 #include "interface.h"
00029 #include "misc.h"
00030 #include "plugin.h"
00031 #include "plugins.h"
00032 #include "ui_preferences.h"
00033 #include "visualization.h"
00034 #include "vis_runner.h"
00035
00036 static GList * vis_funcs[AUD_VIS_TYPES];
00037
00038 typedef struct {
00039 PluginHandle * plugin;
00040 VisPlugin * header;
00041 GtkWidget * widget;
00042 } LoadedVis;
00043
00044 static int running = FALSE;
00045 static GList * loaded_vis_plugins = NULL;
00046
00047 void vis_func_add (int type, GCallback func)
00048 {
00049 g_return_if_fail (type >= 0 && type < AUD_VIS_TYPES);
00050 vis_funcs[type] = g_list_prepend (vis_funcs[type], (void *) func);
00051
00052 vis_runner_enable (TRUE);
00053 }
00054
00055 void vis_func_remove (GCallback func)
00056 {
00057 bool_t disable = TRUE;
00058
00059 for (int i = 0; i < AUD_VIS_TYPES; i ++)
00060 {
00061 vis_funcs[i] = g_list_remove_all (vis_funcs[i], (void *) func);
00062 if (vis_funcs[i])
00063 disable = FALSE;
00064 }
00065
00066 if (disable)
00067 vis_runner_enable (FALSE);
00068 }
00069
00070 void vis_send_clear (void)
00071 {
00072 for (GList * node = vis_funcs[AUD_VIS_TYPE_CLEAR]; node; node = node->next)
00073 {
00074 void (* func) (void) = (void (*) (void)) node->data;
00075 func ();
00076 }
00077 }
00078
00079 static void pcm_to_mono (const float * data, float * mono, int channels)
00080 {
00081 if (channels == 1)
00082 memcpy (mono, data, sizeof (float) * 512);
00083 else
00084 {
00085 float * set = mono;
00086 while (set < & mono[512])
00087 {
00088 * set ++ = (data[0] + data[1]) / 2;
00089 data += channels;
00090 }
00091 }
00092 }
00093
00094 void vis_send_audio (const float * data, int channels)
00095 {
00096 float mono[512];
00097 float freq[256];
00098
00099 if (vis_funcs[AUD_VIS_TYPE_MONO_PCM] || vis_funcs[AUD_VIS_TYPE_FREQ])
00100 pcm_to_mono (data, mono, channels);
00101 if (vis_funcs[AUD_VIS_TYPE_FREQ])
00102 calc_freq (mono, freq);
00103
00104 for (GList * node = vis_funcs[AUD_VIS_TYPE_MONO_PCM]; node; node = node->next)
00105 {
00106 void (* func) (const float *) = (void (*) (const float *)) node->data;
00107 func (mono);
00108 }
00109
00110 for (GList * node = vis_funcs[AUD_VIS_TYPE_MULTI_PCM]; node; node = node->next)
00111 {
00112 void (* func) (const float *, int) = (void (*) (const float *, int)) node->data;
00113 func (data, channels);
00114 }
00115
00116 for (GList * node = vis_funcs[AUD_VIS_TYPE_FREQ]; node; node = node->next)
00117 {
00118 void (* func) (const float *) = (void (*) (const float *)) node->data;
00119 func (freq);
00120 }
00121 }
00122
00123 static int vis_find_cb (LoadedVis * vis, PluginHandle * plugin)
00124 {
00125 return (vis->plugin == plugin) ? 0 : -1;
00126 }
00127
00128 static void vis_load (PluginHandle * plugin)
00129 {
00130 GList * node = g_list_find_custom (loaded_vis_plugins, plugin,
00131 (GCompareFunc) vis_find_cb);
00132 if (node != NULL)
00133 return;
00134
00135 AUDDBG ("Loading %s.\n", plugin_get_name (plugin));
00136 VisPlugin * header = plugin_get_header (plugin);
00137 g_return_if_fail (header != NULL);
00138
00139 LoadedVis * vis = g_slice_new (LoadedVis);
00140 vis->plugin = plugin;
00141 vis->header = header;
00142 vis->widget = NULL;
00143
00144 if (header->get_widget != NULL)
00145 vis->widget = header->get_widget ();
00146
00147 if (vis->widget != NULL)
00148 {
00149 AUDDBG ("Adding %s to interface.\n", plugin_get_name (plugin));
00150 g_signal_connect (vis->widget, "destroy", (GCallback)
00151 gtk_widget_destroyed, & vis->widget);
00152 interface_add_plugin_widget (plugin, vis->widget);
00153 }
00154
00155 if (PLUGIN_HAS_FUNC (header, clear))
00156 vis_func_add (AUD_VIS_TYPE_CLEAR, (GCallback) header->clear);
00157 if (PLUGIN_HAS_FUNC (header, render_mono_pcm))
00158 vis_func_add (AUD_VIS_TYPE_MONO_PCM, (GCallback) header->render_mono_pcm);
00159 if (PLUGIN_HAS_FUNC (header, render_multi_pcm))
00160 vis_func_add (AUD_VIS_TYPE_MULTI_PCM, (GCallback) header->render_multi_pcm);
00161 if (PLUGIN_HAS_FUNC (header, render_freq))
00162 vis_func_add (AUD_VIS_TYPE_FREQ, (GCallback) header->render_freq);
00163
00164 loaded_vis_plugins = g_list_prepend (loaded_vis_plugins, vis);
00165 }
00166
00167 static void vis_unload (PluginHandle * plugin)
00168 {
00169 GList * node = g_list_find_custom (loaded_vis_plugins, plugin,
00170 (GCompareFunc) vis_find_cb);
00171 if (node == NULL)
00172 return;
00173
00174 AUDDBG ("Unloading %s.\n", plugin_get_name (plugin));
00175 LoadedVis * vis = node->data;
00176 loaded_vis_plugins = g_list_delete_link (loaded_vis_plugins, node);
00177
00178 VisPlugin * header = vis->header;
00179 if (PLUGIN_HAS_FUNC (header, clear))
00180 vis_func_remove ((GCallback) header->clear);
00181 if (PLUGIN_HAS_FUNC (header, render_mono_pcm))
00182 vis_func_remove ((GCallback) header->render_mono_pcm);
00183 if (PLUGIN_HAS_FUNC (header, render_multi_pcm))
00184 vis_func_remove ((GCallback) header->render_multi_pcm);
00185 if (PLUGIN_HAS_FUNC (header, render_freq))
00186 vis_func_remove ((GCallback) header->render_freq);
00187
00188 if (vis->widget != NULL)
00189 {
00190 AUDDBG ("Removing %s from interface.\n", plugin_get_name (plugin));
00191 interface_remove_plugin_widget (plugin, vis->widget);
00192 g_return_if_fail (vis->widget == NULL);
00193 }
00194
00195 g_slice_free (LoadedVis, vis);
00196 }
00197
00198 static bool_t vis_init_cb (PluginHandle * plugin)
00199 {
00200 vis_load (plugin);
00201 return TRUE;
00202 }
00203
00204 void vis_init (void)
00205 {
00206 g_return_if_fail (! running);
00207 running = TRUE;
00208
00209 plugin_for_enabled (PLUGIN_TYPE_VIS, (PluginForEachFunc) vis_init_cb, NULL);
00210 }
00211
00212 static void vis_cleanup_cb (LoadedVis * vis)
00213 {
00214 vis_unload (vis->plugin);
00215 }
00216
00217 void vis_cleanup (void)
00218 {
00219 g_return_if_fail (running);
00220 running = FALSE;
00221
00222 g_list_foreach (loaded_vis_plugins, (GFunc) vis_cleanup_cb, NULL);
00223 }
00224
00225 bool_t vis_plugin_start (PluginHandle * plugin)
00226 {
00227 VisPlugin * vp = plugin_get_header (plugin);
00228 g_return_val_if_fail (vp != NULL, FALSE);
00229
00230 if (vp->init != NULL && ! vp->init ())
00231 return FALSE;
00232
00233 if (running)
00234 vis_load (plugin);
00235
00236 return TRUE;
00237 }
00238
00239 void vis_plugin_stop (PluginHandle * plugin)
00240 {
00241 VisPlugin * vp = plugin_get_header (plugin);
00242 g_return_if_fail (vp != NULL);
00243
00244 if (running)
00245 vis_unload (plugin);
00246
00247 if (vp->settings != NULL)
00248 plugin_preferences_cleanup (vp->settings);
00249 if (vp->cleanup != NULL)
00250 vp->cleanup ();
00251 }
00252
00253 PluginHandle * vis_plugin_by_widget ( void * widget)
00254 {
00255 g_return_val_if_fail (widget, NULL);
00256
00257 for (GList * node = loaded_vis_plugins; node; node = node->next)
00258 {
00259 LoadedVis * vis = node->data;
00260 if (vis->widget == widget)
00261 return vis->plugin;
00262 }
00263
00264 return NULL;
00265 }