/** * Wait until a playlist needs update. * @internal */ static gpointer xmms_playlist_updater_loop (xmms_playlist_updater_t *updater) { gchar *plname; xmms_set_thread_name ("x2 pls updater"); g_mutex_lock (updater->mutex); while (updater->keep_running) { if (!updater->stack) { g_cond_wait (updater->cond, updater->mutex); } else { plname = xmms_playlist_updater_pop (updater); g_mutex_unlock (updater->mutex); xmms_playlist_update (updater->playlist, plname); g_mutex_lock (updater->mutex); g_free (plname); } } g_mutex_unlock (updater->mutex); return NULL; }
static gpointer xmms_ipc_client_thread (gpointer data) { xmms_ipc_client_t *client = data; GSource *source; xmms_set_thread_name ("x2 client"); source = g_io_create_watch (client->iochan, G_IO_IN | G_IO_ERR | G_IO_HUP); g_source_set_callback (source, (GSourceFunc) xmms_ipc_client_read_cb, (gpointer) client, NULL); g_source_attach (source, g_main_loop_get_context (client->ml)); g_source_unref (source); g_main_loop_run (client->ml); xmms_ipc_client_destroy (client); return NULL; }
static void * xmms_output_filler (void *arg) { xmms_output_t *output = (xmms_output_t *)arg; xmms_xform_t *chain = NULL; gboolean last_was_kill = FALSE; char buf[4096]; xmms_error_t err; gint ret; xmms_error_reset (&err); xmms_set_thread_name ("x2 out filler"); g_mutex_lock (output->filler_mutex); while (output->filler_state != FILLER_QUIT) { if (output->filler_state == FILLER_STOP) { if (chain) { xmms_object_unref (chain); chain = NULL; } xmms_ringbuf_set_eos (output->filler_buffer, TRUE); g_cond_wait (output->filler_state_cond, output->filler_mutex); last_was_kill = FALSE; continue; } if (output->filler_state == FILLER_KILL) { if (chain) { xmms_object_unref (chain); chain = NULL; output->filler_state = FILLER_RUN; last_was_kill = TRUE; } else { output->filler_state = FILLER_STOP; } continue; } if (output->filler_state == FILLER_SEEK) { if (!chain) { XMMS_DBG ("Seek without chain, ignoring.."); output->filler_state = FILLER_STOP; continue; } ret = xmms_xform_this_seek (chain, output->filler_seek, XMMS_XFORM_SEEK_SET, &err); if (ret == -1) { XMMS_DBG ("Seeking failed: %s", xmms_error_message_get (&err)); } else { XMMS_DBG ("Seek ok! %d", ret); output->filler_skip = output->filler_seek - ret; if (output->filler_skip < 0) { XMMS_DBG ("Seeked %d samples too far! Updating position...", -output->filler_skip); output->filler_skip = 0; output->filler_seek = ret; } xmms_ringbuf_clear (output->filler_buffer); xmms_ringbuf_hotspot_set (output->filler_buffer, seek_done, NULL, output); } output->filler_state = FILLER_RUN; } if (!chain) { xmms_medialib_entry_t entry; xmms_output_song_changed_arg_t *hsarg; g_mutex_unlock (output->filler_mutex); entry = xmms_playlist_current_entry (output->playlist); if (!entry) { XMMS_DBG ("No entry from playlist!"); output->filler_state = FILLER_STOP; g_mutex_lock (output->filler_mutex); continue; } chain = xmms_xform_chain_setup (output->medialib, entry, output->format_list, FALSE); if (!chain) { xmms_medialib_session_t *session; do { session = xmms_medialib_session_begin (output->medialib); if (xmms_medialib_entry_property_get_int (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_STATUS) == XMMS_MEDIALIB_ENTRY_STATUS_NEW) { xmms_medialib_entry_remove (session, entry); } else { xmms_medialib_entry_status_set (session, entry, XMMS_MEDIALIB_ENTRY_STATUS_NOT_AVAILABLE); } } while (!xmms_medialib_session_commit (session)); if (!xmms_playlist_advance (output->playlist)) { XMMS_DBG ("End of playlist"); output->filler_state = FILLER_STOP; } g_mutex_lock (output->filler_mutex); continue; } hsarg = g_new0 (xmms_output_song_changed_arg_t, 1); hsarg->output = output; hsarg->chain = chain; hsarg->flush = last_was_kill; xmms_object_ref (chain); last_was_kill = FALSE; g_mutex_lock (output->filler_mutex); xmms_ringbuf_hotspot_set (output->filler_buffer, song_changed, song_changed_arg_free, hsarg); } xmms_ringbuf_wait_free (output->filler_buffer, sizeof (buf), output->filler_mutex); if (output->filler_state != FILLER_RUN) { XMMS_DBG ("State changed while waiting..."); continue; } g_mutex_unlock (output->filler_mutex); ret = xmms_xform_this_read (chain, buf, sizeof (buf), &err); g_mutex_lock (output->filler_mutex); if (ret > 0) { gint skip = MIN (ret, output->toskip); output->toskip -= skip; if (ret > skip) { xmms_ringbuf_write_wait (output->filler_buffer, buf + skip, ret - skip, output->filler_mutex); } } else { if (ret == -1) { /* print error */ xmms_error_reset (&err); } xmms_object_unref (chain); chain = NULL; if (!xmms_playlist_advance (output->playlist)) { XMMS_DBG ("End of playlist"); output->filler_state = FILLER_STOP; } } } if (chain) xmms_object_unref (chain); g_mutex_unlock (output->filler_mutex); return NULL; }
static gpointer xmms_output_monitor_volume_thread (gpointer data) { xmms_output_t *output = data; xmms_volume_map_t old, cur; if (!xmms_output_plugin_method_volume_get_available (output->plugin)) { return NULL; } xmms_set_thread_name ("x2 volume mon"); xmms_volume_map_init (&old); xmms_volume_map_init (&cur); while (output->monitor_volume_running) { cur.num_channels = 0; cur.status = xmms_output_plugin_method_volume_get (output->plugin, output, NULL, NULL, &cur.num_channels); if (cur.status) { /* check for sane values */ if (cur.num_channels < 1 || cur.num_channels > VOLUME_MAX_CHANNELS) { cur.status = FALSE; } else { cur.names = g_renew (const gchar *, cur.names, cur.num_channels); cur.values = g_renew (guint, cur.values, cur.num_channels); } } if (cur.status) { cur.status = xmms_output_plugin_method_volume_get (output->plugin, output, cur.names, cur.values, &cur.num_channels); } /* we failed at getting volume for one of the two maps or * we succeeded both times and they differ -> changed */ if ((cur.status ^ old.status) || (cur.status && old.status && !xmms_volume_map_equal (&old, &cur))) { /* emit the broadcast */ if (cur.status) { xmms_object_emit (XMMS_OBJECT (output), XMMS_IPC_SIGNAL_PLAYBACK_VOLUME_CHANGED, xmms_volume_map_to_dict (&cur)); } else { /** @todo When bug 691 is solved, emit an error here */ xmms_object_emit (XMMS_OBJECT (output), XMMS_IPC_SIGNAL_PLAYBACK_VOLUME_CHANGED, xmmsv_new_none ()); } } xmms_volume_map_copy (&cur, &old); g_usleep (G_USEC_PER_SEC); } xmms_volume_map_free (&old); xmms_volume_map_free (&cur); return NULL; }