~ubuntu-branches/ubuntu/trusty/mpd/trusty

« back to all changes in this revision

Viewing changes to src/decoder_api.c

  • Committer: Bazaar Package Importer
  • Author(s): Angel Abad
  • Date: 2011-02-02 12:26:30 UTC
  • mfrom: (1.5.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110202122630-bdyx8w4k94doz4fs
Tags: 0.16.1-1ubuntu1
* Merge from debian unstable. Remaining changes:
  - debian/control:
    + Don't build-depend 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.
  - debian/control, debian/rules:
    + Add libmp3lame-dev to the build dependencies and enable lame.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2003-2009 The Music Player Daemon Project
 
2
 * Copyright (C) 2003-2010 The Music Player Daemon Project
3
3
 * http://www.musicpd.org
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
17
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
18
 */
19
19
 
 
20
#include "config.h"
20
21
#include "decoder_api.h"
21
22
#include "decoder_internal.h"
22
23
#include "decoder_control.h"
24
25
#include "audio.h"
25
26
#include "song.h"
26
27
#include "buffer.h"
27
 
 
28
 
#include "normalize.h"
29
28
#include "pipe.h"
30
29
#include "chunk.h"
 
30
#include "replay_gain_config.h"
31
31
 
32
32
#include <glib.h>
33
33
 
37
37
#undef G_LOG_DOMAIN
38
38
#define G_LOG_DOMAIN "decoder"
39
39
 
40
 
void decoder_initialized(G_GNUC_UNUSED struct decoder * decoder,
41
 
                         const struct audio_format *audio_format,
42
 
                         bool seekable, float total_time)
 
40
void
 
41
decoder_initialized(struct decoder *decoder,
 
42
                    const struct audio_format *audio_format,
 
43
                    bool seekable, float total_time)
43
44
{
44
 
        assert(dc.state == DECODE_STATE_START);
45
 
        assert(dc.pipe != NULL);
 
45
        struct decoder_control *dc = decoder->dc;
 
46
        struct audio_format_string af_string;
 
47
 
 
48
        assert(dc->state == DECODE_STATE_START);
 
49
        assert(dc->pipe != NULL);
46
50
        assert(decoder != NULL);
47
51
        assert(decoder->stream_tag == NULL);
48
52
        assert(decoder->decoder_tag == NULL);
51
55
        assert(audio_format_defined(audio_format));
52
56
        assert(audio_format_valid(audio_format));
53
57
 
54
 
        dc.in_audio_format = *audio_format;
55
 
        getOutputAudioFormat(audio_format, &dc.out_audio_format);
56
 
 
57
 
        dc.seekable = seekable;
58
 
        dc.total_time = total_time;
59
 
 
60
 
        dc.state = DECODE_STATE_DECODE;
61
 
        notify_signal(&pc.notify);
62
 
 
63
 
        g_debug("audio_format=%u:%u:%u, seekable=%s",
64
 
                dc.in_audio_format.sample_rate, dc.in_audio_format.bits,
65
 
                dc.in_audio_format.channels,
 
58
        dc->in_audio_format = *audio_format;
 
59
        getOutputAudioFormat(audio_format, &dc->out_audio_format);
 
60
 
 
61
        dc->seekable = seekable;
 
62
        dc->total_time = total_time;
 
63
 
 
64
        decoder_lock(dc);
 
65
        dc->state = DECODE_STATE_DECODE;
 
66
        decoder_unlock(dc);
 
67
 
 
68
        player_lock_signal();
 
69
 
 
70
        g_debug("audio_format=%s, seekable=%s",
 
71
                audio_format_to_string(&dc->in_audio_format, &af_string),
66
72
                seekable ? "true" : "false");
67
73
 
68
 
        if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format))
69
 
                g_debug("converting to %u:%u:%u",
70
 
                        dc.out_audio_format.sample_rate,
71
 
                        dc.out_audio_format.bits,
72
 
                        dc.out_audio_format.channels);
73
 
}
74
 
 
75
 
char *decoder_get_uri(G_GNUC_UNUSED struct decoder *decoder)
76
 
{
77
 
        assert(dc.pipe != NULL);
78
 
 
79
 
        return song_get_uri(dc.current_song);
 
74
        if (!audio_format_equals(&dc->in_audio_format,
 
75
                                 &dc->out_audio_format))
 
76
                g_debug("converting to %s",
 
77
                        audio_format_to_string(&dc->out_audio_format,
 
78
                                               &af_string));
80
79
}
81
80
 
82
81
enum decoder_command decoder_get_command(G_GNUC_UNUSED struct decoder * decoder)
83
82
{
84
 
        assert(dc.pipe != NULL);
85
 
 
86
 
        return dc.command;
 
83
        const struct decoder_control *dc = decoder->dc;
 
84
 
 
85
        assert(dc->pipe != NULL);
 
86
 
 
87
        return dc->command;
87
88
}
88
89
 
89
 
void decoder_command_finished(G_GNUC_UNUSED struct decoder * decoder)
 
90
void
 
91
decoder_command_finished(struct decoder *decoder)
90
92
{
91
 
        assert(dc.command != DECODE_COMMAND_NONE);
92
 
        assert(dc.command != DECODE_COMMAND_SEEK ||
93
 
               dc.seek_error || decoder->seeking);
94
 
        assert(dc.pipe != NULL);
 
93
        struct decoder_control *dc = decoder->dc;
 
94
 
 
95
        decoder_lock(dc);
 
96
 
 
97
        assert(dc->command != DECODE_COMMAND_NONE);
 
98
        assert(dc->command != DECODE_COMMAND_SEEK ||
 
99
               dc->seek_error || decoder->seeking);
 
100
        assert(dc->pipe != NULL);
95
101
 
96
102
        if (decoder->seeking) {
97
103
                decoder->seeking = false;
99
105
                /* delete frames from the old song position */
100
106
 
101
107
                if (decoder->chunk != NULL) {
102
 
                        music_buffer_return(dc.buffer, decoder->chunk);
 
108
                        music_buffer_return(dc->buffer, decoder->chunk);
103
109
                        decoder->chunk = NULL;
104
110
                }
105
111
 
106
 
                music_pipe_clear(dc.pipe, dc.buffer);
 
112
                music_pipe_clear(dc->pipe, dc->buffer);
 
113
 
 
114
                decoder->timestamp = dc->seek_where;
107
115
        }
108
116
 
109
 
        dc.command = DECODE_COMMAND_NONE;
110
 
        notify_signal(&pc.notify);
 
117
        dc->command = DECODE_COMMAND_NONE;
 
118
        decoder_unlock(dc);
 
119
 
 
120
        player_lock_signal();
111
121
}
112
122
 
113
123
double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
114
124
{
115
 
        assert(dc.command == DECODE_COMMAND_SEEK);
116
 
        assert(dc.pipe != NULL);
 
125
        const struct decoder_control *dc = decoder->dc;
 
126
 
 
127
        assert(dc->command == DECODE_COMMAND_SEEK);
 
128
        assert(dc->pipe != NULL);
117
129
 
118
130
        decoder->seeking = true;
119
131
 
120
 
        return dc.seek_where;
 
132
        return dc->seek_where;
121
133
}
122
134
 
123
135
void decoder_seek_error(struct decoder * decoder)
124
136
{
125
 
        assert(dc.command == DECODE_COMMAND_SEEK);
126
 
        assert(dc.pipe != NULL);
127
 
 
128
 
        dc.seek_error = true;
 
137
        struct decoder_control *dc = decoder->dc;
 
138
 
 
139
        assert(dc->command == DECODE_COMMAND_SEEK);
 
140
        assert(dc->pipe != NULL);
 
141
 
 
142
        dc->seek_error = true;
129
143
        decoder->seeking = false;
130
144
 
131
145
        decoder_command_finished(decoder);
135
149
                    struct input_stream *is,
136
150
                    void *buffer, size_t length)
137
151
{
 
152
        const struct decoder_control *dc =
 
153
                decoder != NULL ? decoder->dc : NULL;
 
154
        GError *error = NULL;
138
155
        size_t nbytes;
139
156
 
140
157
        assert(decoder == NULL ||
141
 
               dc.state == DECODE_STATE_START ||
142
 
               dc.state == DECODE_STATE_DECODE);
 
158
               dc->state == DECODE_STATE_START ||
 
159
               dc->state == DECODE_STATE_DECODE);
143
160
        assert(is != NULL);
144
161
        assert(buffer != NULL);
145
162
 
152
169
                    /* ignore the SEEK command during initialization,
153
170
                       the plugin should handle that after it has
154
171
                       initialized successfully */
155
 
                    (dc.command != DECODE_COMMAND_SEEK ||
156
 
                     (dc.state != DECODE_STATE_START && !decoder->seeking)) &&
157
 
                    dc.command != DECODE_COMMAND_NONE)
158
 
                        return 0;
159
 
 
160
 
                nbytes = input_stream_read(is, buffer, length);
 
172
                    (dc->command != DECODE_COMMAND_SEEK ||
 
173
                     (dc->state != DECODE_STATE_START && !decoder->seeking)) &&
 
174
                    dc->command != DECODE_COMMAND_NONE)
 
175
                        return 0;
 
176
 
 
177
                nbytes = input_stream_read(is, buffer, length, &error);
 
178
 
 
179
                if (G_UNLIKELY(nbytes == 0 && error != NULL)) {
 
180
                        g_warning("%s", error->message);
 
181
                        g_error_free(error);
 
182
                        return 0;
 
183
                }
 
184
 
161
185
                if (nbytes > 0 || input_stream_eof(is))
162
186
                        return nbytes;
163
187
 
167
191
        }
168
192
}
169
193
 
 
194
void
 
195
decoder_timestamp(struct decoder *decoder, double t)
 
196
{
 
197
        assert(decoder != NULL);
 
198
        assert(t >= 0);
 
199
 
 
200
        decoder->timestamp = t;
 
201
}
 
202
 
170
203
/**
171
204
 * Sends a #tag as-is to the music pipe.  Flushes the current chunk
172
205
 * (decoder.chunk) if there is one.
181
214
                /* there is a partial chunk - flush it, we want the
182
215
                   tag in a new chunk */
183
216
                decoder_flush_chunk(decoder);
184
 
                notify_signal(&pc.notify);
 
217
                player_lock_signal();
185
218
        }
186
219
 
187
220
        assert(decoder->chunk == NULL);
188
221
 
189
222
        chunk = decoder_get_chunk(decoder, is);
190
223
        if (chunk == NULL) {
191
 
                assert(dc.command != DECODE_COMMAND_NONE);
192
 
                return dc.command;
 
224
                assert(decoder->dc->command != DECODE_COMMAND_NONE);
 
225
                return decoder->dc->command;
193
226
        }
194
227
 
195
228
        chunk->tag = tag_dup(tag);
225
258
decoder_data(struct decoder *decoder,
226
259
             struct input_stream *is,
227
260
             const void *_data, size_t length,
228
 
             float data_time, uint16_t bitRate,
229
 
             struct replay_gain_info *replay_gain_info)
 
261
             uint16_t kbit_rate)
230
262
{
 
263
        struct decoder_control *dc = decoder->dc;
231
264
        const char *data = _data;
232
 
 
233
 
        assert(dc.state == DECODE_STATE_DECODE);
234
 
        assert(dc.pipe != NULL);
235
 
        assert(length % audio_format_frame_size(&dc.in_audio_format) == 0);
236
 
 
237
 
        if (dc.command == DECODE_COMMAND_STOP ||
238
 
            dc.command == DECODE_COMMAND_SEEK ||
 
265
        GError *error = NULL;
 
266
        enum decoder_command cmd;
 
267
 
 
268
        assert(dc->state == DECODE_STATE_DECODE);
 
269
        assert(dc->pipe != NULL);
 
270
        assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
 
271
 
 
272
        decoder_lock(dc);
 
273
        cmd = dc->command;
 
274
        decoder_unlock(dc);
 
275
 
 
276
        if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
239
277
            length == 0)
240
 
                return dc.command;
 
278
                return cmd;
241
279
 
242
280
        /* send stream tags */
243
281
 
244
282
        if (update_stream_tag(decoder, is)) {
245
 
                enum decoder_command cmd;
246
 
 
247
283
                if (decoder->decoder_tag != NULL) {
248
284
                        /* merge with tag from decoder plugin */
249
285
                        struct tag *tag;
250
286
 
251
 
                        tag = tag_merge(decoder->stream_tag,
252
 
                                        decoder->decoder_tag);
 
287
                        tag = tag_merge(decoder->decoder_tag,
 
288
                                        decoder->stream_tag);
253
289
                        cmd = do_send_tag(decoder, is, tag);
254
290
                        tag_free(tag);
255
291
                } else
260
296
                        return cmd;
261
297
        }
262
298
 
263
 
        if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
 
299
        if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
264
300
                data = pcm_convert(&decoder->conv_state,
265
 
                                   &dc.in_audio_format, data, length,
266
 
                                   &dc.out_audio_format, &length);
267
 
 
268
 
                /* under certain circumstances, pcm_convert() may
269
 
                   return an empty buffer - this condition should be
270
 
                   investigated further, but for now, do this check as
271
 
                   a workaround: */
272
 
                if (data == NULL)
273
 
                        return DECODE_COMMAND_NONE;
 
301
                                   &dc->in_audio_format, data, length,
 
302
                                   &dc->out_audio_format, &length,
 
303
                                   &error);
 
304
                if (data == NULL) {
 
305
                        /* the PCM conversion has failed - stop
 
306
                           playback, since we have no better way to
 
307
                           bail out */
 
308
                        g_warning("%s", error->message);
 
309
                        return DECODE_COMMAND_STOP;
 
310
                }
274
311
        }
275
312
 
276
313
        while (length > 0) {
281
318
 
282
319
                chunk = decoder_get_chunk(decoder, is);
283
320
                if (chunk == NULL) {
284
 
                        assert(dc.command != DECODE_COMMAND_NONE);
285
 
                        return dc.command;
 
321
                        assert(dc->command != DECODE_COMMAND_NONE);
 
322
                        return dc->command;
286
323
                }
287
324
 
288
 
                dest = music_chunk_write(chunk, &dc.out_audio_format,
289
 
                                         data_time, bitRate, &nbytes);
 
325
                dest = music_chunk_write(chunk, &dc->out_audio_format,
 
326
                                         decoder->timestamp -
 
327
                                         dc->song->start_ms / 1000.0,
 
328
                                         kbit_rate, &nbytes);
290
329
                if (dest == NULL) {
291
330
                        /* the chunk is full, flush it */
292
331
                        decoder_flush_chunk(decoder);
293
 
                        notify_signal(&pc.notify);
 
332
                        player_lock_signal();
294
333
                        continue;
295
334
                }
296
335
 
303
342
 
304
343
                memcpy(dest, data, nbytes);
305
344
 
306
 
                /* apply replay gain or normalization */
307
 
 
308
 
                if (replay_gain_info != NULL &&
309
 
                    replay_gain_mode != REPLAY_GAIN_OFF)
310
 
                        replay_gain_apply(replay_gain_info, dest, nbytes,
311
 
                                          &dc.out_audio_format);
312
 
                else if (normalizationEnabled)
313
 
                        normalizeData(dest, nbytes, &dc.out_audio_format);
314
 
 
315
345
                /* expand the music pipe chunk */
316
346
 
317
 
                full = music_chunk_expand(chunk, &dc.out_audio_format, nbytes);
 
347
                full = music_chunk_expand(chunk, &dc->out_audio_format, nbytes);
318
348
                if (full) {
319
349
                        /* the chunk is full, flush it */
320
350
                        decoder_flush_chunk(decoder);
321
 
                        notify_signal(&pc.notify);
 
351
                        player_lock_signal();
322
352
                }
323
353
 
324
354
                data += nbytes;
325
355
                length -= nbytes;
 
356
 
 
357
                decoder->timestamp += (double)nbytes /
 
358
                        audio_format_time_to_size(&dc->out_audio_format);
 
359
 
 
360
                if (dc->song->end_ms > 0 &&
 
361
                    decoder->timestamp >= dc->song->end_ms / 1000.0)
 
362
                        /* the end of this range has been reached:
 
363
                           stop decoding */
 
364
                        return DECODE_COMMAND_STOP;
326
365
        }
327
366
 
328
367
        return DECODE_COMMAND_NONE;
332
371
decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
333
372
            const struct tag *tag)
334
373
{
 
374
        G_GNUC_UNUSED const struct decoder_control *dc = decoder->dc;
335
375
        enum decoder_command cmd;
336
376
 
337
 
        assert(dc.state == DECODE_STATE_DECODE);
338
 
        assert(dc.pipe != NULL);
 
377
        assert(dc->state == DECODE_STATE_DECODE);
 
378
        assert(dc->pipe != NULL);
339
379
        assert(tag != NULL);
340
380
 
341
381
        /* save the tag */
363
403
 
364
404
        return cmd;
365
405
}
 
406
 
 
407
float
 
408
decoder_replay_gain(struct decoder *decoder,
 
409
                    const struct replay_gain_info *replay_gain_info)
 
410
{
 
411
        float return_db = 0;
 
412
        assert(decoder != NULL);
 
413
 
 
414
        if (replay_gain_info != NULL) {
 
415
                static unsigned serial;
 
416
                if (++serial == 0)
 
417
                        serial = 1;
 
418
 
 
419
                if (REPLAY_GAIN_OFF != replay_gain_mode) {
 
420
                        return_db = 20.0 * log10f(
 
421
                                replay_gain_tuple_scale(
 
422
                                        &replay_gain_info->tuples[replay_gain_get_real_mode()],
 
423
                                        replay_gain_preamp, replay_gain_missing_preamp,
 
424
                                        replay_gain_limit));
 
425
                }
 
426
 
 
427
                decoder->replay_gain_info = *replay_gain_info;
 
428
                decoder->replay_gain_serial = serial;
 
429
 
 
430
                if (decoder->chunk != NULL) {
 
431
                        /* flush the current chunk because the new
 
432
                           replay gain values affect the following
 
433
                           samples */
 
434
                        decoder_flush_chunk(decoder);
 
435
                        player_lock_signal();
 
436
                }
 
437
        } else
 
438
                decoder->replay_gain_serial = 0;
 
439
 
 
440
        return return_db;
 
441
}
 
442
 
 
443
void
 
444
decoder_mixramp(struct decoder *decoder, float replay_gain_db,
 
445
                char *mixramp_start, char *mixramp_end)
 
446
{
 
447
        assert(decoder != NULL);
 
448
        struct decoder_control *dc = decoder->dc;
 
449
        assert(dc != NULL);
 
450
 
 
451
        dc->replay_gain_db = replay_gain_db;
 
452
        dc_mixramp_start(dc, mixramp_start);
 
453
        dc_mixramp_end(dc, mixramp_end);
 
454
}