21 struct xmms_output_plugin_St {
31 gboolean write_running;
34 GThread *write_thread;
49 static gpointer xmms_output_plugin_writer (gpointer data);
57 g_mutex_free (plugin->api_mutex);
58 g_mutex_free (plugin->write_mutex);
59 g_cond_free (plugin->write_cond);
61 g_cond_free (plugin->status_cond);
62 g_mutex_free (plugin->status_mutex);
74 res->api_mutex = g_mutex_new ();
75 res->write_mutex = g_mutex_new ();
76 res->write_cond = g_cond_new ();
78 res->status_cond = g_cond_new ();
79 res->status_mutex = g_mutex_new ();
89 g_return_if_fail (plugin);
105 g_return_val_if_fail (plugin, FALSE);
108 if (!(plugin->methods.new &&
109 plugin->methods.destroy &&
110 plugin->methods.flush)) {
111 XMMS_DBG (
"Missing: new, destroy or flush!");
115 w = !!plugin->methods.write;
116 s = !!plugin->methods.status;
119 XMMS_DBG (
"Plugin needs to provide either write or status.");
123 o = !!plugin->methods.open;
124 c = !!plugin->methods.close;
129 XMMS_DBG (
"Write type misses open or close.");
135 XMMS_DBG (
"Status type has open or close.");
147 const gchar *default_value,
164 g_return_val_if_fail (output, FALSE);
165 g_return_val_if_fail (plugin, FALSE);
167 if (plugin->methods.new) {
168 ret = plugin->methods.new (output);
171 if (ret && !plugin->methods.status) {
172 plugin->write_running = TRUE;
173 plugin->write_thread = g_thread_create (xmms_output_plugin_writer,
187 g_return_if_fail (output);
188 g_return_if_fail (plugin);
190 if (plugin->write_thread) {
191 xmms_output_plugin_writer_status_wait (plugin, output,
194 plugin->write_running = FALSE;
196 g_cond_signal (plugin->write_cond);
197 g_thread_join (plugin->write_thread);
198 plugin->write_thread = NULL;
201 if (plugin->methods.destroy) {
202 g_mutex_lock (plugin->api_mutex);
203 plugin->methods.destroy (output);
204 g_mutex_unlock (plugin->api_mutex);
213 g_return_if_fail (output);
214 g_return_if_fail (plugin);
216 if (plugin->methods.flush) {
217 g_mutex_lock (plugin->api_mutex);
218 plugin->methods.flush (output);
219 g_mutex_unlock (plugin->api_mutex);
227 g_return_val_if_fail (plugin, FALSE);
229 if (plugin->methods.format_set_always) {
243 g_return_val_if_fail (output, FALSE);
244 g_return_val_if_fail (plugin, FALSE);
246 if (plugin->methods.format_set) {
247 g_mutex_lock (plugin->api_mutex);
248 res = plugin->methods.format_set (output, st);
249 g_mutex_unlock (plugin->api_mutex);
250 }
else if (plugin->methods.format_set_always) {
251 g_mutex_lock (plugin->api_mutex);
252 res = plugin->methods.format_set_always (output, st);
253 g_mutex_unlock (plugin->api_mutex);
266 g_return_val_if_fail (output, FALSE);
267 g_return_val_if_fail (plugin, FALSE);
269 if (plugin->methods.status) {
270 res = plugin->methods.status (output, st);
271 }
else if (plugin->write_thread) {
272 XMMS_DBG (
"Running status changed... %d", st);
273 res = xmms_output_plugin_writer_status (plugin, output, st);
285 g_return_val_if_fail (output, FALSE);
286 g_return_val_if_fail (plugin, FALSE);
288 if (plugin->methods.latency_get) {
289 ret = plugin->methods.latency_get (output);
299 g_return_val_if_fail (plugin, FALSE);
301 return !!plugin->methods.volume_set;
308 const gchar *chan, guint val)
310 gboolean res = FALSE;
312 g_return_val_if_fail (output, FALSE);
313 g_return_val_if_fail (plugin, FALSE);
315 if (plugin->methods.volume_set) {
316 res = plugin->methods.volume_set (output, chan, val);
326 g_return_val_if_fail (plugin, FALSE);
328 return !!plugin->methods.volume_get;
335 const gchar **n, guint *x, guint *y)
337 gboolean res = FALSE;
339 g_return_val_if_fail (output, FALSE);
340 g_return_val_if_fail (plugin, FALSE);
342 if (plugin->methods.volume_get) {
343 res = plugin->methods.volume_get (output, n, x, y);
357 g_mutex_lock (plugin->write_mutex);
358 plugin->wanted_status = status;
359 plugin->write_output = output;
360 g_cond_signal (plugin->write_cond);
361 g_mutex_unlock (plugin->write_mutex);
371 g_mutex_lock (plugin->status_mutex);
373 if (plugin->wanted_status != status) {
374 xmms_output_plugin_writer_status (plugin, output, status);
377 while (plugin->status != status) {
378 g_cond_wait (plugin->status_cond, plugin->status_mutex);
381 g_mutex_unlock (plugin->status_mutex);
386 xmms_output_plugin_writer (gpointer data)
393 g_mutex_lock (plugin->write_mutex);
395 while (plugin->write_running) {
398 g_mutex_lock (plugin->api_mutex);
399 plugin->methods.close (output);
400 g_mutex_unlock (plugin->api_mutex);
405 g_mutex_lock (plugin->status_mutex);
406 plugin->status = plugin->wanted_status;
407 g_cond_signal (plugin->status_cond);
408 g_mutex_unlock (plugin->status_mutex);
411 g_cond_wait (plugin->write_cond, plugin->write_mutex);
417 g_mutex_lock (plugin->api_mutex);
418 plugin->methods.flush (output);
419 g_mutex_unlock (plugin->api_mutex);
422 g_mutex_lock (plugin->status_mutex);
423 plugin->status = plugin->wanted_status;
424 g_cond_signal (plugin->status_cond);
425 g_mutex_unlock (plugin->status_mutex);
427 g_cond_wait (plugin->write_cond, plugin->write_mutex);
432 output = plugin->write_output;
434 g_mutex_lock (plugin->api_mutex);
435 ret = plugin->methods.open (output);
436 g_mutex_unlock (plugin->api_mutex);
446 g_mutex_lock (plugin->status_mutex);
447 plugin->status = plugin->wanted_status;
448 g_cond_signal (plugin->status_cond);
449 g_mutex_unlock (plugin->status_mutex);
451 g_mutex_unlock (plugin->write_mutex);
457 xmms_error_reset (&err);
459 g_mutex_lock (plugin->api_mutex);
460 plugin->methods.write (output, buffer, ret, &err);
461 g_mutex_unlock (plugin->api_mutex);
464 XMMS_DBG (
"Write method set error bit");
466 g_mutex_lock (plugin->write_mutex);
468 g_mutex_unlock (plugin->write_mutex);
473 g_mutex_lock (plugin->write_mutex);
479 g_mutex_unlock (plugin->write_mutex);
481 XMMS_DBG (
"Output driving thread exiting!");