Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
effect.c
Go to the documentation of this file.
1 /*
2  * effect.c
3  * Copyright 2010 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <pthread.h>
22 
23 #include "debug.h"
24 #include "drct.h"
25 #include "effect.h"
26 #include "misc.h"
27 #include "plugin.h"
28 #include "plugins.h"
29 
30 typedef struct {
33  int channels_returned, rate_returned;
36 
37 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
38 static GList * running_effects = NULL; /* (RunningEffect *) */
40 
41 typedef struct {
42  int * channels, * rate;
44 
46 {
47  AUDDBG ("Starting %s at %d channels, %d Hz.\n", plugin_get_name (plugin),
48  * state->channels, * state->rate);
49  EffectPlugin * header = plugin_get_header (plugin);
50  g_return_val_if_fail (header != NULL, TRUE);
51  header->start (state->channels, state->rate);
52 
53  RunningEffect * effect = g_malloc (sizeof (RunningEffect));
54  effect->plugin = plugin;
55  effect->header = header;
56  effect->channels_returned = * state->channels;
57  effect->rate_returned = * state->rate;
58  effect->remove_flag = FALSE;
59 
60  running_effects = g_list_prepend (running_effects, effect);
61  return TRUE;
62 }
63 
64 void effect_start (int * channels, int * rate)
65 {
66  pthread_mutex_lock (& mutex);
67 
68  AUDDBG ("Starting effects.\n");
69  g_list_foreach (running_effects, (GFunc) g_free, NULL);
70  g_list_free (running_effects);
72 
74  input_rate = * rate;
75 
76  EffectStartState state = {channels, rate};
78  & state);
79  running_effects = g_list_reverse (running_effects);
80 
81  pthread_mutex_unlock (& mutex);
82 }
83 
84 typedef struct {
85  float * * data;
86  int * samples;
88 
90  state)
91 {
92  if (effect->remove_flag)
93  {
94  /* call finish twice to completely drain buffers */
95  effect->header->finish (state->data, state->samples);
96  effect->header->finish (state->data, state->samples);
97 
98  running_effects = g_list_remove (running_effects, effect);
99  g_free (effect);
100  }
101  else
102  effect->header->process (state->data, state->samples);
103 }
104 
105 void effect_process (float * * data, int * samples)
106 {
107  pthread_mutex_lock (& mutex);
108 
109  EffectProcessState state = {data, samples};
110  g_list_foreach (running_effects, (GFunc) effect_process_cb, & state);
111 
112  pthread_mutex_unlock (& mutex);
113 }
114 
115 void effect_flush (void)
116 {
117  pthread_mutex_lock (& mutex);
118 
119  for (GList * node = running_effects; node != NULL; node = node->next)
120  {
121  if (PLUGIN_HAS_FUNC (((RunningEffect *) node->data)->header, flush))
122  ((RunningEffect *) node->data)->header->flush ();
123  }
124 
125  pthread_mutex_unlock (& mutex);
126 }
127 
128 void effect_finish (float * * data, int * samples)
129 {
130  pthread_mutex_lock (& mutex);
131 
132  for (GList * node = running_effects; node != NULL; node = node->next)
133  ((RunningEffect *) node->data)->header->finish (data, samples);
134 
135  pthread_mutex_unlock (& mutex);
136 }
137 
138 int effect_adjust_delay (int delay)
139 {
140  pthread_mutex_lock (& mutex);
141 
142  for (GList * node = g_list_last (running_effects); node != NULL; node = node->prev)
143  {
144  if (PLUGIN_HAS_FUNC (((RunningEffect *) node->data)->header, adjust_delay))
145  delay = ((RunningEffect *) node->data)->header->adjust_delay (delay);
146  }
147 
148  pthread_mutex_unlock (& mutex);
149  return delay;
150 }
151 
153 {
154  return (effect->plugin == plugin) ? 0 : -1;
155 }
156 
158 {
159  return plugin_compare (a->plugin, b->plugin);
160 }
161 
163 {
164  if (g_list_find_custom (running_effects, plugin, (GCompareFunc)
165  effect_find_cb) != NULL)
166  return;
167 
168  AUDDBG ("Adding %s without reset.\n", plugin_get_name (plugin));
169  RunningEffect * effect = g_malloc (sizeof (RunningEffect));
170  effect->plugin = plugin;
171  effect->header = header;
172  effect->remove_flag = FALSE;
173 
174  running_effects = g_list_insert_sorted (running_effects, effect,
175  (GCompareFunc) effect_compare);
176  GList * node = g_list_find (running_effects, effect);
177 
178  int channels, rate;
179  if (node->prev != NULL)
180  {
181  RunningEffect * prev = node->prev->data;
182  AUDDBG ("Added %s after %s.\n", plugin_get_name (plugin),
183  plugin_get_name (prev->plugin));
184  channels = prev->channels_returned;
185  rate = prev->rate_returned;
186  }
187  else
188  {
189  AUDDBG ("Added %s as first effect.\n", plugin_get_name (plugin));
190  channels = input_channels;
191  rate = input_rate;
192  }
193 
194  AUDDBG ("Starting %s at %d channels, %d Hz.\n", plugin_get_name (plugin),
195  channels, rate);
196  header->start (& channels, & rate);
197  effect->channels_returned = channels;
198  effect->rate_returned = rate;
199 }
200 
202 {
203  GList * node = g_list_find_custom (running_effects, plugin, (GCompareFunc)
205  if (node == NULL)
206  return;
207 
208  AUDDBG ("Removing %s without reset.\n", plugin_get_name (plugin));
209  ((RunningEffect *) node->data)->remove_flag = TRUE;
210 }
211 
213  enable)
214 {
215  if (ep->preserves_format)
216  {
217  pthread_mutex_lock (& mutex);
218 
219  if (enable)
220  effect_insert (plugin, ep);
221  else
222  effect_remove (plugin);
223 
224  pthread_mutex_unlock (& mutex);
225  }
226  else
227  {
228  AUDDBG ("Reset to add/remove %s.\n", plugin_get_name (plugin));
230  }
231 }
232 
234 {
235  if (drct_get_playing ())
236  {
237  EffectPlugin * ep = plugin_get_header (plugin);
238  g_return_val_if_fail (ep != NULL, FALSE);
239  effect_enable (plugin, ep, TRUE);
240  }
241 
242  return TRUE;
243 }
244 
246 {
247  if (drct_get_playing ())
248  {
249  EffectPlugin * ep = plugin_get_header (plugin);
250  g_return_if_fail (ep != NULL);
251  effect_enable (plugin, ep, FALSE);
252  }
253 }
static int channels
Definition: equalizer.c:54
static int input_channels
Definition: effect.c:39
bool_t effect_plugin_start(PluginHandle *plugin)
Definition: effect.c:233
static bool_t effect_start_cb(PluginHandle *plugin, EffectStartState *state)
Definition: effect.c:45
int plugin_compare(PluginHandle *a, PluginHandle *b)
static float a[EQ_BANDS][2]
Definition: equalizer.c:55
int effect_adjust_delay(int delay)
Definition: effect.c:138
static float b[EQ_BANDS][2]
Definition: equalizer.c:56
#define PLUGIN_HAS_FUNC(p, func)
Definition: plugin.h:515
static void flush(void)
Definition: vis_runner.c:104
void effect_process(float **data, int *samples)
Definition: effect.c:105
void effect_finish(float **data, int *samples)
Definition: effect.c:128
#define FALSE
Definition: core.h:35
int * rate
Definition: effect.c:42
static void effect_insert(PluginHandle *plugin, EffectPlugin *header)
Definition: effect.c:162
static void effect_remove(PluginHandle *plugin)
Definition: effect.c:201
static void effect_enable(PluginHandle *plugin, EffectPlugin *ep, bool_t enable)
Definition: effect.c:212
void effect_plugin_stop(PluginHandle *plugin)
Definition: effect.c:245
Index Index bool_t
Definition: playlist-api.h:122
#define AUDDBG(...)
Definition: debug.h:30
void(* finish)(float **data, int *samples)
Definition: plugin.h:239
const void * plugin_get_header(PluginHandle *plugin)
static int effect_find_cb(RunningEffect *effect, PluginHandle *plugin)
Definition: effect.c:152
bool_t preserves_format
Definition: plugin.h:254
int rate_returned
Definition: effect.c:33
int * channels
Definition: effect.c:42
#define NULL
Definition: core.h:27
void effect_flush(void)
Definition: effect.c:115
EffectPlugin * header
Definition: effect.c:32
bool_t(* PluginForEachFunc)(PluginHandle *plugin, void *data)
Definition: plugins.h:27
void effect_start(int *channels, int *rate)
Definition: effect.c:64
#define TRUE
Definition: core.h:37
static GList * running_effects
Definition: effect.c:38
static int effect_compare(RunningEffect *a, RunningEffect *b)
Definition: effect.c:157
static int rate
Definition: equalizer.c:54
PLUGIN_COMMON_FIELDS void(* start)(int *channels, int *rate)
Definition: plugin.h:224
PluginHandle * plugin
Definition: effect.c:31
static int input_rate
Definition: effect.c:39
void output_reset(int type)
Definition: output.c:507
int channels_returned
Definition: effect.c:33
void(* process)(float **data, int *samples)
Definition: plugin.h:231
void plugin_for_enabled(int type, PluginForEachFunc func, void *data)
float ** data
Definition: effect.c:85
static void effect_process_cb(RunningEffect *effect, EffectProcessState *state)
Definition: effect.c:89
void data PluginHandle plugin
Definition: plugins-api.h:54
bool_t remove_flag
Definition: effect.c:34
const char * plugin_get_name(PluginHandle *plugin)
static pthread_mutex_t mutex
Definition: effect.c:37
bool_t drct_get_playing(void)
Definition: playback.c:472