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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#include "decoder.h"
#include <mpg123.h>
#include <stdio.h>
static gboolean mpg123_decoder_init(struct decoder *decoder) {
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);
decoder->data = handle;
return TRUE;
}
static gssize mpg123_decoder_decode(struct decoder *decoder, GInputStream *input,
GOutputStream *output, GError **error) {
mpg123_handle *handle = decoder->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");
*error = g_error_new(decoder_quark(), DECODER_CODE_ERROR, 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);
decoder->rate = rate;
/* TODO: mpg123 uses native byte order, add endian check here */
/* assuming little endian for now... */
switch(enc) {
case MPG123_ENC_SIGNED_16:
decoder->format = AUDIO_FORMAT_S16LE;
break;
default:
*error = g_error_new(decoder_quark(), DECODER_CODE_ERROR, g_strdup("unknown audio format"));
return -1;
}
decoder->channels = channels;
}
if(ret != MPG123_OK && ret != MPG123_DONE && ret != MPG123_NEW_FORMAT
&& ret != MPG123_NEED_MORE) {
*error = g_error_new(decoder_quark(), DECODER_CODE_ERROR, mpg123_plain_strerror(ret));
return -1;
}
if(size == 0) {
*error = g_error_new(decoder_quark(), DECODER_CODE_DONE, "done");
return -1;
}
g_output_stream_write(output, outbuf, size, NULL, NULL);
return size;
}
static void mpg123_decoder_close(struct decoder *decoder) {
mpg123_handle *handle = decoder->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,
};
|