~ubuntu-branches/ubuntu/maverick/mpd/maverick-proposed

« back to all changes in this revision

Viewing changes to src/decoder/oggflac_plugin.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia
  • Date: 2009-10-23 12:38:20 UTC
  • mfrom: (1.1.12 upstream) (2.2.6 sid)
  • Revision ID: james.westby@ubuntu.com-20091023123820-rxt21lmekscxbkbt
Tags: 0.15.4-1ubuntu1
* Merge from debian unstable, Ubuntu remaining changes:
  - debian/control:
    + Don't build-depends on libmikmod2-dev (Debian bug #510675).
    + Move avahi-daemon from Suggests field to Recommends field.
  - debian/mpd.init.d:
    + Read mpd user from mpd.conf.
* Also fixes LP: #332332.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* the Music Player Daemon (MPD)
2
 
 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3
 
 * This project's homepage is: http://www.musicpd.org
4
 
 *
5
 
 * OggFLAC support (half-stolen from flac_plugin.c :))
6
 
 * (c) 2005 by Eric Wong <normalperson@yhbt.net>
 
1
/*
 
2
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 
3
 * http://www.musicpd.org
7
4
 *
8
5
 * This program is free software; you can redistribute it and/or modify
9
6
 * it under the terms of the GNU General Public License as published by
14
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
13
 * GNU General Public License for more details.
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
 
 
20
/*
 
21
 * OggFLAC support (half-stolen from flac_plugin.c :))
20
22
 */
21
23
 
22
24
#include "_flac_common.h"
23
25
#include "_ogg_common.h"
24
26
 
 
27
#include <glib.h>
25
28
#include <OggFLAC/seekable_stream_decoder.h>
 
29
#include <assert.h>
26
30
#include <unistd.h>
27
31
 
28
 
static void oggflac_cleanup(FlacData * data,
 
32
static void oggflac_cleanup(struct flac_data *data,
29
33
                            OggFLAC__SeekableStreamDecoder * decoder)
30
34
{
31
 
        if (data->replayGainInfo)
32
 
                replay_gain_info_free(data->replayGainInfo);
 
35
        if (data->replay_gain_info)
 
36
                replay_gain_info_free(data->replay_gain_info);
33
37
        if (decoder)
34
38
                OggFLAC__seekable_stream_decoder_delete(decoder);
35
39
}
36
40
 
37
 
static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(mpd_unused const
 
41
static OggFLAC__SeekableStreamDecoderReadStatus of_read_cb(G_GNUC_UNUSED const
38
42
                                                           OggFLAC__SeekableStreamDecoder
39
43
                                                           * decoder,
40
44
                                                           FLAC__byte buf[],
41
45
                                                           unsigned *bytes,
42
46
                                                           void *fdata)
43
47
{
44
 
        FlacData *data = (FlacData *) fdata;
 
48
        struct flac_data *data = (struct flac_data *) fdata;
45
49
        size_t r;
46
50
 
47
 
        r = decoder_read(data->decoder, data->inStream, (void *)buf, *bytes);
 
51
        r = decoder_read(data->decoder, data->input_stream,
 
52
                         (void *)buf, *bytes);
48
53
        *bytes = r;
49
54
 
50
 
        if (r == 0 && !input_stream_eof(data->inStream) &&
 
55
        if (r == 0 && !input_stream_eof(data->input_stream) &&
51
56
            decoder_get_command(data->decoder) == DECODE_COMMAND_NONE)
52
57
                return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR;
53
58
 
54
59
        return OggFLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK;
55
60
}
56
61
 
57
 
static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(mpd_unused const
 
62
static OggFLAC__SeekableStreamDecoderSeekStatus of_seek_cb(G_GNUC_UNUSED const
58
63
                                                           OggFLAC__SeekableStreamDecoder
59
64
                                                           * decoder,
60
65
                                                           FLAC__uint64 offset,
61
66
                                                           void *fdata)
62
67
{
63
 
        FlacData *data = (FlacData *) fdata;
 
68
        struct flac_data *data = (struct flac_data *) fdata;
64
69
 
65
 
        if (!input_stream_seek(data->inStream, offset, SEEK_SET))
 
70
        if (!input_stream_seek(data->input_stream, offset, SEEK_SET))
66
71
                return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR;
67
72
 
68
73
        return OggFLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK;
69
74
}
70
75
 
71
 
static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(mpd_unused const
 
76
static OggFLAC__SeekableStreamDecoderTellStatus of_tell_cb(G_GNUC_UNUSED const
72
77
                                                           OggFLAC__SeekableStreamDecoder
73
78
                                                           * decoder,
74
79
                                                           FLAC__uint64 *
75
80
                                                           offset, void *fdata)
76
81
{
77
 
        FlacData *data = (FlacData *) fdata;
 
82
        struct flac_data *data = (struct flac_data *) fdata;
78
83
 
79
 
        *offset = (long)(data->inStream->offset);
 
84
        *offset = (long)(data->input_stream->offset);
80
85
 
81
86
        return OggFLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK;
82
87
}
83
88
 
84
 
static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(mpd_unused const
 
89
static OggFLAC__SeekableStreamDecoderLengthStatus of_length_cb(G_GNUC_UNUSED const
85
90
                                                               OggFLAC__SeekableStreamDecoder
86
91
                                                               * decoder,
87
92
                                                               FLAC__uint64 *
88
93
                                                               length,
89
94
                                                               void *fdata)
90
95
{
91
 
        FlacData *data = (FlacData *) fdata;
 
96
        struct flac_data *data = (struct flac_data *) fdata;
92
97
 
93
 
        if (data->inStream->size < 0)
 
98
        if (data->input_stream->size < 0)
94
99
                return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_ERROR;
95
100
 
96
 
        *length = (size_t) (data->inStream->size);
 
101
        *length = (size_t) (data->input_stream->size);
97
102
 
98
103
        return OggFLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK;
99
104
}
100
105
 
101
 
static FLAC__bool of_EOF_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * decoder,
 
106
static FLAC__bool of_EOF_cb(G_GNUC_UNUSED const OggFLAC__SeekableStreamDecoder * decoder,
102
107
                            void *fdata)
103
108
{
104
 
        FlacData *data = (FlacData *) fdata;
 
109
        struct flac_data *data = (struct flac_data *) fdata;
105
110
 
106
111
        return (decoder_get_command(data->decoder) != DECODE_COMMAND_NONE &&
107
112
                decoder_get_command(data->decoder) != DECODE_COMMAND_SEEK) ||
108
 
                input_stream_eof(data->inStream);
 
113
                input_stream_eof(data->input_stream);
109
114
}
110
115
 
111
 
static void of_error_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * decoder,
 
116
static void of_error_cb(G_GNUC_UNUSED const OggFLAC__SeekableStreamDecoder * decoder,
112
117
                        FLAC__StreamDecoderErrorStatus status, void *fdata)
113
118
{
114
 
        flac_error_common_cb("oggflac", status, (FlacData *) fdata);
 
119
        flac_error_common_cb("oggflac", status, (struct flac_data *) fdata);
115
120
}
116
121
 
117
122
static void oggflacPrintErroredState(OggFLAC__SeekableStreamDecoderState state)
145
150
        }
146
151
}
147
152
 
148
 
static FLAC__StreamDecoderWriteStatus oggflacWrite(mpd_unused const
149
 
                                                   OggFLAC__SeekableStreamDecoder
150
 
                                                   * decoder,
151
 
                                                   const FLAC__Frame * frame,
152
 
                                                   const FLAC__int32 *
153
 
                                                   const buf[], void *vdata)
 
153
static FLAC__StreamDecoderWriteStatus
 
154
oggflac_write_cb(G_GNUC_UNUSED const OggFLAC__SeekableStreamDecoder *decoder,
 
155
                 const FLAC__Frame *frame, const FLAC__int32 *const buf[],
 
156
                 void *vdata)
154
157
{
155
 
        FlacData *data = (FlacData *) vdata;
 
158
        struct flac_data *data = (struct flac_data *) vdata;
156
159
        FLAC__uint32 samples = frame->header.blocksize;
157
 
        float timeChange;
 
160
        float time_change;
158
161
 
159
 
        timeChange = ((float)samples) / frame->header.sample_rate;
160
 
        data->time += timeChange;
 
162
        time_change = ((float)samples) / frame->header.sample_rate;
 
163
        data->time += time_change;
161
164
 
162
165
        return flac_common_write(data, frame, buf);
163
166
}
164
167
 
165
168
/* used by TagDup */
166
 
static void of_metadata_dup_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * decoder,
 
169
static void of_metadata_dup_cb(G_GNUC_UNUSED const OggFLAC__SeekableStreamDecoder * decoder,
167
170
                               const FLAC__StreamMetadata * block, void *vdata)
168
171
{
169
 
        FlacData *data = (FlacData *) vdata;
 
172
        struct flac_data *data = (struct flac_data *) vdata;
 
173
 
 
174
        assert(data->tag != NULL);
170
175
 
171
176
        switch (block->type) {
172
177
        case FLAC__METADATA_TYPE_STREAMINFO:
173
 
                if (!data->tag)
174
 
                        data->tag = tag_new();
175
178
                data->tag->time = ((float)block->data.stream_info.
176
179
                                   total_samples) /
177
180
                    block->data.stream_info.sample_rate + 0.5;
178
181
                return;
179
182
        case FLAC__METADATA_TYPE_VORBIS_COMMENT:
180
 
                copyVorbisCommentBlockToMpdTag(block, data->tag);
 
183
                flac_vorbis_comments_to_tag(data->tag, NULL, block);
181
184
        default:
182
185
                break;
183
186
        }
184
187
}
185
188
 
186
189
/* used by decode */
187
 
static void of_metadata_decode_cb(mpd_unused const OggFLAC__SeekableStreamDecoder * dec,
 
190
static void of_metadata_decode_cb(G_GNUC_UNUSED const OggFLAC__SeekableStreamDecoder * dec,
188
191
                                  const FLAC__StreamMetadata * block,
189
192
                                  void *vdata)
190
193
{
191
 
        flac_metadata_common_cb(block, (FlacData *) vdata);
 
194
        flac_metadata_common_cb(block, (struct flac_data *) vdata);
192
195
}
193
196
 
194
 
static OggFLAC__SeekableStreamDecoder
195
 
    * full_decoder_init_and_read_metadata(FlacData * data,
196
 
                                          unsigned int metadata_only)
 
197
static OggFLAC__SeekableStreamDecoder *
 
198
full_decoder_init_and_read_metadata(struct flac_data *data,
 
199
                                    unsigned int metadata_only)
197
200
{
198
201
        OggFLAC__SeekableStreamDecoder *decoder = NULL;
199
202
        unsigned int s = 1;
222
225
        s &= OggFLAC__seekable_stream_decoder_set_eof_callback(decoder,
223
226
                                                               of_EOF_cb);
224
227
        s &= OggFLAC__seekable_stream_decoder_set_write_callback(decoder,
225
 
                                                                 oggflacWrite);
 
228
                                                                 oggflac_write_cb);
226
229
        s &= OggFLAC__seekable_stream_decoder_set_metadata_respond(decoder,
227
230
                                                                   FLAC__METADATA_TYPE_VORBIS_COMMENT);
228
231
        s &= OggFLAC__seekable_stream_decoder_set_error_callback(decoder,
255
258
}
256
259
 
257
260
/* public functions: */
258
 
static struct tag *oggflac_TagDup(const char *file)
 
261
static struct tag *
 
262
oggflac_tag_dup(const char *file)
259
263
{
260
 
        struct input_stream inStream;
 
264
        struct input_stream input_stream;
261
265
        OggFLAC__SeekableStreamDecoder *decoder;
262
 
        FlacData data;
 
266
        struct flac_data data;
263
267
 
264
 
        if (!input_stream_open(&inStream, file))
 
268
        if (!input_stream_open(&input_stream, file))
265
269
                return NULL;
266
 
        if (ogg_stream_type_detect(&inStream) != FLAC) {
267
 
                input_stream_close(&inStream);
 
270
        if (ogg_stream_type_detect(&input_stream) != FLAC) {
 
271
                input_stream_close(&input_stream);
268
272
                return NULL;
269
273
        }
270
274
 
271
 
        init_FlacData(&data, NULL, &inStream);
 
275
        flac_data_init(&data, NULL, &input_stream);
 
276
 
 
277
        data.tag = tag_new();
272
278
 
273
279
        /* errors here won't matter,
274
280
         * data.tag will be set or unset, that's all we care about */
275
281
        decoder = full_decoder_init_and_read_metadata(&data, 1);
276
282
 
277
283
        oggflac_cleanup(&data, decoder);
278
 
        input_stream_close(&inStream);
 
284
        input_stream_close(&input_stream);
 
285
 
 
286
        if (!tag_is_defined(data.tag)) {
 
287
                tag_free(data.tag);
 
288
                data.tag = NULL;
 
289
        }
279
290
 
280
291
        return data.tag;
281
292
}
282
293
 
283
294
static void
284
 
oggflac_decode(struct decoder * mpd_decoder, struct input_stream *inStream)
 
295
oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream)
285
296
{
286
297
        OggFLAC__SeekableStreamDecoder *decoder = NULL;
287
 
        FlacData data;
 
298
        struct flac_data data;
288
299
 
289
 
        if (ogg_stream_type_detect(inStream) != FLAC)
 
300
        if (ogg_stream_type_detect(input_stream) != FLAC)
290
301
                return;
291
302
 
292
 
        init_FlacData(&data, mpd_decoder, inStream);
 
303
        flac_data_init(&data, mpd_decoder, input_stream);
293
304
 
294
305
        if (!(decoder = full_decoder_init_and_read_metadata(&data, 0))) {
295
306
                goto fail;
304
315
        }
305
316
 
306
317
        decoder_initialized(mpd_decoder, &data.audio_format,
307
 
                            inStream->seekable, data.total_time);
 
318
                            input_stream->seekable, data.total_time);
308
319
 
309
320
        while (true) {
310
321
                OggFLAC__seekable_stream_decoder_process_single(decoder);
313
324
                        break;
314
325
                }
315
326
                if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_SEEK) {
316
 
                        FLAC__uint64 sampleToSeek = decoder_seek_where(mpd_decoder) *
 
327
                        FLAC__uint64 seek_sample = decoder_seek_where(mpd_decoder) *
317
328
                            data.audio_format.sample_rate + 0.5;
318
329
                        if (OggFLAC__seekable_stream_decoder_seek_absolute
319
 
                            (decoder, sampleToSeek)) {
320
 
                                data.time = ((float)sampleToSeek) /
 
330
                            (decoder, seek_sample)) {
 
331
                                data.time = ((float)seek_sample) /
321
332
                                    data.audio_format.sample_rate;
322
333
                                data.position = 0;
323
334
                                decoder_command_finished(mpd_decoder);
336
347
        oggflac_cleanup(&data, decoder);
337
348
}
338
349
 
339
 
static const char *const oggflac_Suffixes[] = { "ogg", "oga", NULL };
 
350
static const char *const oggflac_suffixes[] = { "ogg", "oga", NULL };
340
351
static const char *const oggflac_mime_types[] = {
341
352
        "audio/x-flac+ogg",
342
353
        "application/ogg",
344
355
        NULL
345
356
};
346
357
 
347
 
const struct decoder_plugin oggflacPlugin = {
 
358
const struct decoder_plugin oggflac_decoder_plugin = {
348
359
        .name = "oggflac",
349
360
        .stream_decode = oggflac_decode,
350
 
        .tag_dup = oggflac_TagDup,
351
 
        .suffixes = oggflac_Suffixes,
 
361
        .tag_dup = oggflac_tag_dup,
 
362
        .suffixes = oggflac_suffixes,
352
363
        .mime_types = oggflac_mime_types
353
364
};