Beispiel #1
0
size_t decoder_read(struct decoder *decoder,
		    struct input_stream *is,
		    void *buffer, size_t length)
{
	size_t nbytes;

	assert(decoder == NULL ||
	       dc.state == DECODE_STATE_START ||
	       dc.state == DECODE_STATE_DECODE);
	assert(is != NULL);
	assert(buffer != NULL);

	if (length == 0)
		return 0;

	while (true) {
		/* XXX don't allow decoder==NULL */
		if (decoder != NULL &&
		    /* ignore the SEEK command during initialization,
		       the plugin should handle that after it has
		       initialized successfully */
		    (dc.command != DECODE_COMMAND_SEEK ||
		     (dc.state != DECODE_STATE_START && !decoder->seeking)) &&
		    dc.command != DECODE_COMMAND_NONE)
			return 0;

		nbytes = input_stream_read(is, buffer, length);
		if (nbytes > 0 || input_stream_eof(is))
			return nbytes;

		/* sleep for a fraction of a second! */
		/* XXX don't sleep, wait for an event instead */
		g_usleep(10000);
	}
}
Beispiel #2
0
static void
pcm_stream_decode(struct decoder *decoder, struct input_stream *is)
{
	static const struct audio_format audio_format = {
		.sample_rate = 44100,
		.format = SAMPLE_FORMAT_S16,
		.channels = 2,
	};
	GError *error = NULL;
	enum decoder_command cmd;

	double time_to_size = audio_format_time_to_size(&audio_format);

	float total_time = -1;
	if (is->size >= 0)
		total_time = is->size / time_to_size;

	decoder_initialized(decoder, &audio_format, is->seekable, total_time);

	do {
		char buffer[4096];

		size_t nbytes = decoder_read(decoder, is,
					     buffer, sizeof(buffer));

		if (nbytes == 0 && input_stream_eof(is))
			break;

		cmd = nbytes > 0
			? decoder_data(decoder, is,
				       buffer, nbytes, 0)
			: decoder_get_command(decoder);
		if (cmd == DECODE_COMMAND_SEEK) {
			goffset offset = (goffset)(time_to_size *
						   decoder_seek_where(decoder));
			if (input_stream_seek(is, offset, SEEK_SET, &error)) {
				decoder_command_finished(decoder);
			} else {
				g_warning("seeking failed: %s", error->message);
				g_error_free(error);
				decoder_seek_error(decoder);
			}

			cmd = DECODE_COMMAND_NONE;
		}
	} while (cmd == DECODE_COMMAND_NONE);
}

static const char *const pcm_mime_types[] = {
	/* for streams obtained by the cdio_paranoia input plugin */
	"audio/x-mpd-cdda-pcm",
	NULL
};

const struct decoder_plugin pcm_decoder_plugin = {
	.name = "pcm",
	.stream_decode = pcm_stream_decode,
	.mime_types = pcm_mime_types,
};
static int
dump_input_stream(struct input_stream *is)
{
	GError *error = NULL;
	char buffer[4096];
	size_t num_read;
	ssize_t num_written;

	/* wait until the stream becomes ready */

	while (!is->ready) {
		int ret = input_stream_buffer(is, &error);
		if (ret < 0) {
			/* error */
			g_warning("%s", error->message);
			g_error_free(error);
			return 2;
		}

		if (ret == 0)
			/* nothing was buffered - wait */
			g_usleep(10000);
	}

	/* print meta data */

	if (is->mime != NULL)
		g_printerr("MIME type: %s\n", is->mime);

	/* read data and tags from the stream */

	while (!input_stream_eof(is)) {
		struct tag *tag = input_stream_tag(is);
		if (tag != NULL) {
			g_printerr("Received a tag:\n");
			tag_save(stderr, tag);
			tag_free(tag);
		}

		num_read = input_stream_read(is, buffer, sizeof(buffer),
					     &error);
		if (num_read == 0) {
			if (error != NULL) {
				g_warning("%s", error->message);
				g_error_free(error);
			}

			break;
		}

		num_written = write(1, buffer, num_read);
		if (num_written <= 0)
			break;
	}

	return 0;
}
/**
 * Simple data fetcher.
 * @param url path or url of data to fetch.
 * @return data fetched, or NULL on error. Must be freed with g_free.
 */
static char *
lastfm_get(const char *url, GMutex *mutex, GCond *cond)
{
	struct input_stream *input_stream;
	GError *error = NULL;
	char buffer[4096];
	size_t length = 0, nbytes;

	input_stream = input_stream_open(url, mutex, cond, &error);
	if (input_stream == NULL) {
		if (error != NULL) {
			g_warning("%s", error->message);
			g_error_free(error);
		}

		return NULL;
	}

	g_mutex_lock(mutex);

	input_stream_wait_ready(input_stream);

	do {
		nbytes = input_stream_read(input_stream, buffer + length,
					   sizeof(buffer) - length, &error);
		if (nbytes == 0) {
			if (error != NULL) {
				g_warning("%s", error->message);
				g_error_free(error);
			}

			if (input_stream_eof(input_stream))
				break;

			/* I/O error */
			g_mutex_unlock(mutex);
			input_stream_close(input_stream);
			return NULL;
		}

		length += nbytes;
	} while (length < sizeof(buffer));

	g_mutex_unlock(mutex);

	input_stream_close(input_stream);
	return g_strndup(buffer, length);
}
Beispiel #5
0
size_t decoder_read(struct decoder *decoder,
		    struct input_stream *is,
		    void *buffer, size_t length)
{
	const struct decoder_control *dc =
		decoder != NULL ? decoder->dc : NULL;
	GError *error = NULL;
	size_t nbytes;

	assert(decoder == NULL ||
	       dc->state == DECODE_STATE_START ||
	       dc->state == DECODE_STATE_DECODE);
	assert(is != NULL);
	assert(buffer != NULL);

	if (length == 0)
		return 0;

	while (true) {
		/* XXX don't allow decoder==NULL */
		if (decoder != NULL &&
		    /* ignore the SEEK command during initialization,
		       the plugin should handle that after it has
		       initialized successfully */
		    (dc->command != DECODE_COMMAND_SEEK ||
		     (dc->state != DECODE_STATE_START && !decoder->seeking)) &&
		    dc->command != DECODE_COMMAND_NONE)
			return 0;

		nbytes = input_stream_read(is, buffer, length, &error);

		if (G_UNLIKELY(nbytes == 0 && error != NULL)) {
			g_warning("%s", error->message);
			g_error_free(error);
			return 0;
		}

		if (nbytes > 0 || input_stream_eof(is))
			return nbytes;

		/* sleep for a fraction of a second! */
		/* XXX don't sleep, wait for an event instead */
		g_usleep(10000);
	}
}
Beispiel #6
0
static int
dump_input_stream(struct input_stream *is)
{
	GError *error = NULL;
	char buffer[4096];
	size_t num_read;
	ssize_t num_written;

	input_stream_lock(is);

	/* wait until the stream becomes ready */

	input_stream_wait_ready(is);

	if (!input_stream_check(is, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		input_stream_unlock(is);
		return EXIT_FAILURE;
	}

	/* print meta data */

	if (is->mime != NULL)
		g_printerr("MIME type: %s\n", is->mime);

	/* read data and tags from the stream */

	while (!input_stream_eof(is)) {
		struct tag *tag = input_stream_tag(is);
		if (tag != NULL) {
			g_printerr("Received a tag:\n");
			tag_save(stderr, tag);
			tag_free(tag);
		}

		num_read = input_stream_read(is, buffer, sizeof(buffer),
					     &error);
		if (num_read == 0) {
			if (error != NULL) {
				g_warning("%s", error->message);
				g_error_free(error);
			}

			break;
		}

		num_written = write(1, buffer, num_read);
		if (num_written <= 0)
			break;
	}

	if (!input_stream_check(is, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		input_stream_unlock(is);
		return EXIT_FAILURE;
	}

	input_stream_unlock(is);

	return 0;
}
/**
 * Read JSON data and parse it using the given YAJL parser.
 * @param url URL of the JSON data.
 * @param hand YAJL parser handle.
 * @return -1 on error, 0 on success.
 */
static int
soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* cond)
{
	struct input_stream *input_stream;
	GError *error = NULL;
	char buffer[4096];
	unsigned char *ubuffer = (unsigned char *)buffer;
	size_t nbytes;

	input_stream = input_stream_open(url, mutex, cond, &error);
	if (input_stream == NULL) {
		if (error != NULL) {
			g_warning("%s", error->message);
			g_error_free(error);
		}
		return -1;
	}

	g_mutex_lock(mutex);
	input_stream_wait_ready(input_stream);

	yajl_status stat;
	int done = 0;

	while (!done) {
		nbytes = input_stream_read(input_stream, buffer, sizeof(buffer), &error);
		if (nbytes == 0) {
			if (error != NULL) {
				g_warning("%s", error->message);
				g_error_free(error);
			}
			if (input_stream_eof(input_stream)) {
				done = true;
			} else {
				g_mutex_unlock(mutex);
				input_stream_close(input_stream);
				return -1;
			}
		}

		if (done)
			stat = yajl_parse_complete(hand);
		else
			stat = yajl_parse(hand, ubuffer, nbytes);

		if (stat != yajl_status_ok &&
			stat != yajl_status_insufficient_data)
		{
			unsigned char *str = yajl_get_error(hand, 1, ubuffer, nbytes);
			g_warning("%s", str);
			yajl_free_error(hand, str);
			break;
		}
	}

	g_mutex_unlock(mutex);
	input_stream_close(input_stream);

	return 0;
}