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!");
gboolean xmms_output_plugin_method_format_set(xmms_output_plugin_t *plugin, xmms_output_t *output, xmms_stream_type_t *st)
xmms_config_property_t * xmms_plugin_config_property_register(xmms_plugin_t *plugin, const gchar *name, const gchar *default_value, xmms_object_handler_t cb, gpointer userdata)
#define xmms_error_iserror(e)
struct xmms_stream_type_St xmms_stream_type_t
xmms_config_property_t * xmms_config_lookup(const gchar *path)
Look up a config key from the global config.
gboolean xmms_output_plugin_method_status(xmms_output_plugin_t *plugin, xmms_output_t *output, gint st)
gint xmms_output_read(xmms_output_t *output, char *buffer, gint len)
Read a number of bytes of data from the output buffer into a buffer.
const gchar * xmms_plugin_shortname_get(const xmms_plugin_t *plugin)
guint xmms_output_plugin_method_latency_get(xmms_output_plugin_t *plugin, xmms_output_t *output)
gboolean xmms_output_plugin_method_new(xmms_output_plugin_t *plugin, xmms_output_t *output)
Output functions that lets XMMS2 talk to the soundcard.
gboolean xmms_output_plugin_verify(xmms_plugin_t *_plugin)
void xmms_output_plugin_method_flush(xmms_output_plugin_t *plugin, xmms_output_t *output)
gint xmms_config_property_get_int(const xmms_config_property_t *prop)
Return the value of a config property as an int.
gboolean xmms_output_plugin_method_volume_set_available(xmms_output_plugin_t *plugin)
#define xmms_log_error(fmt,...)
struct xmms_output_St xmms_output_t
struct xmms_output_plugin_St xmms_output_plugin_t
gboolean xmms_output_plugin_methods_volume_set(xmms_output_plugin_t *plugin, xmms_output_t *output, const gchar *chan, guint val)
void xmms_plugin_destroy(xmms_plugin_t *plugin)
gboolean xmms_output_plugin_method_volume_get_available(xmms_output_plugin_t *plugin)
gboolean xmms_output_plugin_format_set_always(xmms_output_plugin_t *plugin)
Check if an output plugin needs format updates on each track change.
#define XMMS_DBG(fmt,...)
xmms_config_property_t * xmms_output_plugin_config_property_register(xmms_output_plugin_t *plugin, const gchar *name, const gchar *default_value, xmms_object_handler_t cb, gpointer userdata)
Register a configuration directive in the plugin setup function.
#define xmms_object_new(objtype, destroyfunc)
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
struct xmms_config_property_St xmms_config_property_t
gboolean xmms_output_plugin_method_volume_get(xmms_output_plugin_t *plugin, xmms_output_t *output, const gchar **n, guint *x, guint *y)
void(* xmms_object_handler_t)(xmms_object_t *object, xmmsv_t *data, gpointer userdata)
void xmms_output_plugin_method_destroy(xmms_output_plugin_t *plugin, xmms_output_t *output)
xmms_plugin_t * xmms_output_plugin_new(void)
void xmms_output_plugin_methods_set(xmms_output_plugin_t *plugin, xmms_output_methods_t *methods)
Register the output plugin functions.
void xmms_output_set_error(xmms_output_t *output, xmms_error_t *error)
Set an error.