summaryrefslogtreecommitdiff
path: root/decoders/decoder_mpg123.c
blob: ea263f53f213827ef8a39ca9fcea541634f6f922 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "decoder.h"

#include <mpg123.h>
#include <stdio.h>

static gboolean mpg123_decoder_init(gpointer *data) {
	mpg123_handle *handle;

	int error;
	mpg123_init();

	handle = mpg123_new("generic", &error);
	if(error) {
		g_warning("Error: %s", mpg123_plain_strerror(error));
		return FALSE;
	}

	error = mpg123_open_feed(handle);
	if(error) {
		g_warning("Error: %s", mpg123_plain_strerror(error));
	}

	/* force format for now */
	mpg123_format_none(handle);
	mpg123_format(handle, 44100, 2, MPG123_ENC_SIGNED_16);

	*data = handle;

	return TRUE;
}

static gssize mpg123_decoder_decode(gpointer data, GInputStream *input,
		GOutputStream *output) {
	mpg123_handle *handle = data;
	gssize size;
	int ret;
	const int inbuf_size = 0x400*8;
	const int outbuf_size = 0x400*8;
	unsigned char inbuf[inbuf_size];
	unsigned char outbuf[inbuf_size];

	gsize inbuf_read = g_input_stream_read(input, inbuf, inbuf_size, NULL, NULL);

	if(mpg123_feed(handle, inbuf, inbuf_read) != MPG123_OK) {
		g_debug("asdfasdf");
		g_warning(mpg123_strerror(handle));
		return -1;
	}

	ret = mpg123_read(handle, outbuf, outbuf_size, (size_t*)&size);

	if(ret == MPG123_NEW_FORMAT) {
		long rate;
		int channels, enc;
		mpg123_getformat(handle, &rate, &channels, &enc);
		g_debug("New format: %li Hz, %i channels, encoding value %i", rate, channels, enc);
		ret = mpg123_read(handle, outbuf, outbuf_size, (size_t*)&size);
	}

	if(ret != MPG123_OK && ret != MPG123_DONE && ret != MPG123_NEW_FORMAT
			&& ret != MPG123_NEED_MORE) {
		g_warning(mpg123_plain_strerror(ret));
		return -1;
	}

	g_output_stream_write(output, outbuf, size, NULL, NULL);

	return size;
}

static void mpg123_decoder_close(gpointer data) {
	mpg123_handle *handle = data;
	mpg123_close(handle);
	mpg123_delete(handle);
}

static const gchar * const decoder_mpg123_extensions[] = {
	"mp3", NULL,
};

const struct decoder_plugin decoder_mpg123_decoder = {
	.name = "mpg123",
	.extensions = decoder_mpg123_extensions,
	.init = mpg123_decoder_init,
	.decode = mpg123_decoder_decode,
	.close = mpg123_decoder_close,
};