Пример #1
0
/**
 * 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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}