Beispiel #1
0
static gint64
xmms_ringbuf_plugin_seek (xmms_xform_t *xform, gint64 offset, xmms_xform_seek_mode_t whence, xmms_error_t *error)
{
	xmms_ringbuf_priv_t *priv;
	gint64 res = -1;

	priv = xmms_xform_private_data_get (xform);

	g_mutex_lock (&priv->state_lock);
	if (priv->state == STATE_BUFFERING) {
		priv->state = STATE_WANT_SEEK;
		priv->seek_offset = offset;
		priv->seek_whence = whence;
		xmms_ringbuf_set_eos (priv->buffer, TRUE);
		while (priv->state == STATE_WANT_SEEK) {
			g_cond_wait (&priv->state_cond, &priv->state_lock);
		}
		xmms_ringbuf_set_eos (priv->buffer, FALSE);
		if (priv->state == STATE_SEEK_DONE) {
			res = priv->seek_res;
			priv->state = STATE_WANT_BUFFER;
		}
	}
	g_cond_signal (&priv->state_cond);
	g_mutex_unlock (&priv->state_lock);

	return res;
}
Beispiel #2
0
static gboolean
song_changed (void *data)
{
	/* executes in the output thread; NOT the filler thread */
	xmms_output_song_changed_arg_t *arg = (xmms_output_song_changed_arg_t *)data;
	xmms_medialib_entry_t entry;

	entry = xmms_xform_entry_get (arg->chain);

	XMMS_DBG ("Running hotspot! Song changed!! %d", entry);

	arg->output->played = 0;
	arg->output->current_entry = entry;

	if (!xmms_output_format_set (arg->output, xmms_xform_outtype_get (arg->chain))) {
		XMMS_DBG ("Couldn't set format, stopping filler..");
		xmms_output_filler_state_nolock (arg->output, FILLER_STOP);
		xmms_ringbuf_set_eos (arg->output->filler_buffer, TRUE);
		return FALSE;
	}

	if (arg->flush)
		xmms_output_flush (arg->output);

	xmms_object_emit_f (XMMS_OBJECT (arg->output),
	                    XMMS_IPC_SIGNAL_OUTPUT_CURRENTID,
	                    XMMSV_TYPE_UINT32,
	                    entry);

	return TRUE;
}
Beispiel #3
0
static void
xmms_output_filler_state_nolock (xmms_output_t *output, xmms_output_filler_state_t state)
{
	output->filler_state = state;
	g_cond_signal (output->filler_state_cond);
	if (state == FILLER_QUIT || state == FILLER_STOP || state == FILLER_KILL) {
		xmms_ringbuf_clear (output->filler_buffer);
	}
	if (state != FILLER_STOP) {
		xmms_ringbuf_set_eos (output->filler_buffer, FALSE);
	}
}
Beispiel #4
0
static void
fill (xmms_xform_t *xform, xmms_ringbuf_priv_t *priv)
{
	xmms_error_t err;
	char buf[4096];
	int res;

	res = xmms_xform_read (xform, buf, sizeof (buf), &err);
	if (res > 0) {
		xmms_ringbuf_write_wait (priv->buffer, buf, res, &priv->buffer_lock);
	} else if (res == -1) {
		/* XXX copy error */
		g_mutex_lock (&priv->state_lock);
		priv->state = STATE_WANT_STOP;
	} else {
		xmms_ringbuf_set_eos (priv->buffer, TRUE);
		priv->state = STATE_WANT_STOP;
	}
}
Beispiel #5
0
static gboolean
song_changed (void *data)
{
	/* executes in the output thread; NOT the filler thread */
	xmms_output_song_changed_arg_t *arg = (xmms_output_song_changed_arg_t *)data;
	xmms_medialib_entry_t entry;
	xmms_stream_type_t *type;

	entry = xmms_xform_entry_get (arg->chain);

	XMMS_DBG ("Running hotspot! Song changed!! %d", entry);

	arg->output->played = 0;
	arg->output->current_entry = entry;

	type = xmms_xform_outtype_get (arg->chain);

	if (!xmms_output_format_set (arg->output, type)) {
		gint fmt, rate, chn;

		fmt = xmms_stream_type_get_int (type, XMMS_STREAM_TYPE_FMT_FORMAT);
		rate = xmms_stream_type_get_int (type, XMMS_STREAM_TYPE_FMT_SAMPLERATE);
		chn = xmms_stream_type_get_int (type, XMMS_STREAM_TYPE_FMT_CHANNELS);

		XMMS_DBG ("Couldn't set format %s/%d/%d, stopping filler..",
		          xmms_sample_name_get (fmt), rate, chn);

		xmms_output_filler_state_nolock (arg->output, FILLER_STOP);
		xmms_ringbuf_set_eos (arg->output->filler_buffer, TRUE);
		return FALSE;
	}

	if (arg->flush)
		xmms_output_flush (arg->output);

	xmms_object_emit (XMMS_OBJECT (arg->output),
	                  XMMS_IPC_SIGNAL_PLAYBACK_CURRENTID,
	                  xmmsv_new_int (entry));

	return TRUE;
}
Beispiel #6
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);

	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 *arg;
			xmms_medialib_session_t *session;

			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 (entry, output->format_list, FALSE);
			if (!chain) {
				session = xmms_medialib_begin_write ();
				if (xmms_medialib_entry_property_get_int (session, entry, XMMS_MEDIALIB_ENTRY_PROPERTY_STATUS) == XMMS_MEDIALIB_ENTRY_STATUS_NEW) {
					xmms_medialib_end (session);
					xmms_medialib_entry_remove (entry);
				} else {
					xmms_medialib_entry_status_set (session, entry, XMMS_MEDIALIB_ENTRY_STATUS_NOT_AVAILABLE);
					xmms_medialib_entry_send_update (entry);
					xmms_medialib_end (session);
				}

				if (!xmms_playlist_advance (output->playlist)) {
					XMMS_DBG ("End of playlist");
					output->filler_state = FILLER_STOP;
				}
				g_mutex_lock (output->filler_mutex);
				continue;
			}

			arg = g_new0 (xmms_output_song_changed_arg_t, 1);
			arg->output = output;
			arg->chain = chain;
			arg->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, arg);
		}

		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;
			}
		}

	}
	g_mutex_unlock (output->filler_mutex);
	return NULL;
}