22 struct xmms_output_plugin_St {
32 gboolean write_running;
35 GThread *write_thread;
50 static gpointer xmms_output_plugin_writer (gpointer data);
58 g_mutex_free (plugin->api_mutex);
59 g_mutex_free (plugin->write_mutex);
60 g_cond_free (plugin->write_cond);
62 g_cond_free (plugin->status_cond);
63 g_mutex_free (plugin->status_mutex);
75 res->api_mutex = g_mutex_new ();
76 res->write_mutex = g_mutex_new ();
77 res->write_cond = g_cond_new ();
79 res->status_cond = g_cond_new ();
80 res->status_mutex = g_mutex_new ();
90 g_return_if_fail (plugin);
106 g_return_val_if_fail (plugin, FALSE);
109 if (!(plugin->methods.new &&
110 plugin->methods.destroy &&
111 plugin->methods.flush)) {
112 XMMS_DBG (
"Missing: new, destroy or flush!");
116 w = !!plugin->methods.write;
117 s = !!plugin->methods.status;
120 XMMS_DBG (
"Plugin needs to provide either write or status.");
124 o = !!plugin->methods.open;
125 c = !!plugin->methods.close;
130 XMMS_DBG (
"Write type misses open or close.");
136 XMMS_DBG (
"Status type has open or close.");
148 const gchar *default_value,
165 g_return_val_if_fail (output, FALSE);
166 g_return_val_if_fail (plugin, FALSE);
168 if (plugin->methods.new) {
169 ret = plugin->methods.new (output);
172 if (ret && !plugin->methods.status) {
173 plugin->write_running = TRUE;
174 plugin->write_thread = g_thread_create (xmms_output_plugin_writer,
188 g_return_if_fail (output);
189 g_return_if_fail (plugin);
191 if (plugin->write_thread) {
192 xmms_output_plugin_writer_status_wait (plugin, output,
195 plugin->write_running = FALSE;
197 g_cond_signal (plugin->write_cond);
198 g_thread_join (plugin->write_thread);
199 plugin->write_thread = NULL;
202 if (plugin->methods.destroy) {
203 g_mutex_lock (plugin->api_mutex);
204 plugin->methods.destroy (output);
205 g_mutex_unlock (plugin->api_mutex);
214 g_return_if_fail (output);
215 g_return_if_fail (plugin);
217 if (plugin->methods.flush) {
218 g_mutex_lock (plugin->api_mutex);
219 plugin->methods.flush (output);
220 g_mutex_unlock (plugin->api_mutex);
228 g_return_val_if_fail (plugin, FALSE);
230 if (plugin->methods.format_set_always) {
244 g_return_val_if_fail (output, FALSE);
245 g_return_val_if_fail (plugin, FALSE);
247 if (plugin->methods.format_set) {
248 g_mutex_lock (plugin->api_mutex);
249 res = plugin->methods.format_set (output, st);
250 g_mutex_unlock (plugin->api_mutex);
251 }
else if (plugin->methods.format_set_always) {
252 g_mutex_lock (plugin->api_mutex);
253 res = plugin->methods.format_set_always (output, st);
254 g_mutex_unlock (plugin->api_mutex);
267 g_return_val_if_fail (output, FALSE);
268 g_return_val_if_fail (plugin, FALSE);
270 if (plugin->methods.status) {
271 res = plugin->methods.status (output, st);
272 }
else if (plugin->write_thread) {
273 XMMS_DBG (
"Running status changed... %d", st);
274 res = xmms_output_plugin_writer_status (plugin, output, st);
286 g_return_val_if_fail (output, FALSE);
287 g_return_val_if_fail (plugin, FALSE);
289 if (plugin->methods.latency_get) {
290 ret = plugin->methods.latency_get (output);
300 g_return_val_if_fail (plugin, FALSE);
302 return !!plugin->methods.volume_set;
309 const gchar *chan, guint val)
311 gboolean res = FALSE;
313 g_return_val_if_fail (output, FALSE);
314 g_return_val_if_fail (plugin, FALSE);
316 if (plugin->methods.volume_set) {
317 res = plugin->methods.volume_set (output, chan, val);
327 g_return_val_if_fail (plugin, FALSE);
329 return !!plugin->methods.volume_get;
336 const gchar **n, guint *x, guint *y)
338 gboolean res = FALSE;
340 g_return_val_if_fail (output, FALSE);
341 g_return_val_if_fail (plugin, FALSE);
343 if (plugin->methods.volume_get) {
344 res = plugin->methods.volume_get (output, n, x, y);
358 g_mutex_lock (plugin->write_mutex);
359 plugin->wanted_status = status;
360 plugin->write_output = output;
361 g_cond_signal (plugin->write_cond);
362 g_mutex_unlock (plugin->write_mutex);
372 g_mutex_lock (plugin->status_mutex);
374 if (plugin->wanted_status != status) {
375 xmms_output_plugin_writer_status (plugin, output, status);
378 while (plugin->status != status) {
379 g_cond_wait (plugin->status_cond, plugin->status_mutex);
382 g_mutex_unlock (plugin->status_mutex);
387 xmms_output_plugin_writer (gpointer data)
396 g_mutex_lock (plugin->write_mutex);
398 while (plugin->write_running) {
401 g_mutex_lock (plugin->api_mutex);
402 plugin->methods.close (output);
403 g_mutex_unlock (plugin->api_mutex);
408 g_mutex_lock (plugin->status_mutex);
409 plugin->status = plugin->wanted_status;
410 g_cond_signal (plugin->status_cond);
411 g_mutex_unlock (plugin->status_mutex);
414 g_cond_wait (plugin->write_cond, plugin->write_mutex);
420 g_mutex_lock (plugin->api_mutex);
421 plugin->methods.flush (output);
422 g_mutex_unlock (plugin->api_mutex);
425 g_mutex_lock (plugin->status_mutex);
426 plugin->status = plugin->wanted_status;
427 g_cond_signal (plugin->status_cond);
428 g_mutex_unlock (plugin->status_mutex);
430 g_cond_wait (plugin->write_cond, plugin->write_mutex);
435 output = plugin->write_output;
437 g_mutex_lock (plugin->api_mutex);
438 ret = plugin->methods.open (output);
439 g_mutex_unlock (plugin->api_mutex);
449 g_mutex_lock (plugin->status_mutex);
450 plugin->status = plugin->wanted_status;
451 g_cond_signal (plugin->status_cond);
452 g_mutex_unlock (plugin->status_mutex);
454 g_mutex_unlock (plugin->write_mutex);
460 xmms_error_reset (&err);
462 g_mutex_lock (plugin->api_mutex);
463 plugin->methods.write (output, buffer, ret, &err);
464 g_mutex_unlock (plugin->api_mutex);
467 XMMS_DBG (
"Write method set error bit");
469 g_mutex_lock (plugin->write_mutex);
471 g_mutex_unlock (plugin->write_mutex);
476 g_mutex_lock (plugin->write_mutex);
482 g_mutex_unlock (plugin->write_mutex);
484 XMMS_DBG (
"Output driving thread exiting!");