~ubuntu-branches/ubuntu/precise/flac/precise-updates

« back to all changes in this revision

Viewing changes to src/plugin_winamp2/playback.c

  • Committer: Bazaar Package Importer
  • Author(s): Joshua Kwan
  • Date: 2007-05-29 22:56:36 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070529225636-ljeff8xxip09qaap
Tags: 1.1.4-1
* New upstream release. closes: #405167, #411311
  - libOggFLAC and libOggFLAC++ have been merged into libFLAC, so
    remove their corresponding packages.
  - Because of the API changes required to effect the above, there has
    been yet another soname bump. libflac7 -> libflac8 and
    libflac++5 -> libflac++6. Emails have been dispatched to the
    maintainers of dependent packages.
* Some notes on patches that were removed:
  - 02_stdin_stdout, 06_manpage_mention_utf8_convert: merged upstream
  - 08_manpage_warnings: Upstream has changed the manpage so it defintely
    can't fit in in 80 cols, so just forget about it. We'll live.
  - 05_eof_warnings_are_errors: Upstream decided to add a -w option to
    flac to treat all warnings as errors. I am going to defer to that
    for now, but if people think it's stupid let me know and I'll port
    the patch forward.
  - 04_stack_smasher: was a backport from 1.1.3, so it's obsolete.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* in_flac - Winamp2 FLAC input plugin
2
 
 * Copyright (C) 2000,2001,2002,2003,2004,2005  Josh Coalson
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU General Public License
6
 
 * as published by the Free Software Foundation; either version 2
7
 
 * of the License, or (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
 
2
 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Lesser General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2.1 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
10
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Lesser General Public License for more details.
13
13
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17
17
 */
18
18
 
 
19
#if HAVE_CONFIG_H
 
20
#  include <config.h>
 
21
#endif
 
22
 
 
23
#include <limits.h> /* for INT_MAX */
19
24
#include <stdlib.h>
20
25
#include <string.h> /* for memmove() */
21
26
#include "playback.h"
34
39
 *  callbacks
35
40
 */
36
41
 
37
 
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 
42
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
38
43
{
39
 
        file_info_struct *file_info = (file_info_struct*)client_data;
40
 
        const unsigned channels = file_info->channels, wide_samples = frame->header.blocksize;
 
44
        stream_data_struct *stream_data = (stream_data_struct*)client_data;
 
45
        const unsigned channels = stream_data->channels, wide_samples = frame->header.blocksize;
41
46
        unsigned channel;
42
47
 
43
48
        (void)decoder;
44
49
 
45
 
        if (file_info->abort_flag)
 
50
        if (stream_data->abort_flag)
46
51
                return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
47
52
 
48
53
        for (channel = 0; channel < channels; channel++)
53
58
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
54
59
}
55
60
 
56
 
static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 
61
static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
57
62
{
58
 
        file_info_struct *file_info = (file_info_struct*)client_data;
 
63
        stream_data_struct *stream_data = (stream_data_struct*)client_data;
59
64
        (void)decoder;
60
65
 
61
66
        if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
62
67
        {
63
 
                FLAC__ASSERT(metadata->data.stream_info.total_samples < 0x100000000); /* this plugin can only handle < 4 gigasamples */
64
 
                file_info->total_samples = (unsigned)(metadata->data.stream_info.total_samples&0xfffffffful);
65
 
                file_info->bits_per_sample = metadata->data.stream_info.bits_per_sample;
66
 
                file_info->channels = metadata->data.stream_info.channels;
67
 
                file_info->sample_rate = metadata->data.stream_info.sample_rate;
 
68
                stream_data->total_samples = metadata->data.stream_info.total_samples;
 
69
                stream_data->bits_per_sample = metadata->data.stream_info.bits_per_sample;
 
70
                stream_data->channels = metadata->data.stream_info.channels;
 
71
                stream_data->sample_rate = metadata->data.stream_info.sample_rate;
68
72
 
69
 
                if (file_info->bits_per_sample!=8 && file_info->bits_per_sample!=16 && file_info->bits_per_sample!=24)
 
73
                if (stream_data->bits_per_sample!=8 && stream_data->bits_per_sample!=16 && stream_data->bits_per_sample!=24)
70
74
                {
71
75
                        FLAC_plugin__show_error("This plugin can only handle 8/16/24-bit samples.");
72
 
                        file_info->abort_flag = true;
 
76
                        stream_data->abort_flag = true;
73
77
                        return;
74
78
                }
75
 
                file_info->length_in_msec = (unsigned)((double)file_info->total_samples / (double)file_info->sample_rate * 1000.0 + 0.5);
 
79
 
 
80
                {
 
81
                        /* with VC++ you have to spoon feed it the casting from uint64->int64->double */
 
82
                        FLAC__uint64 l = (FLAC__uint64)((double)(FLAC__int64)stream_data->total_samples / (double)stream_data->sample_rate * 1000.0 + 0.5);
 
83
                        if (l > INT_MAX)
 
84
                                l = INT_MAX;
 
85
                        stream_data->length_in_msec = (int)l;
 
86
                }
76
87
        }
77
88
        else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
78
89
        {
79
 
                double gain, peak;
80
 
                if (grabbag__replaygain_load_from_vorbiscomment(metadata, cfg.replaygain.album_mode, &gain, &peak))
 
90
                double reference, gain, peak;
 
91
                if (grabbag__replaygain_load_from_vorbiscomment(metadata, cfg.replaygain.album_mode, /*strict=*/false, &reference, &gain, &peak))
81
92
                {
82
 
                        file_info->has_replaygain = true;
83
 
                        file_info->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)cfg.replaygain.preamp, !cfg.replaygain.hard_limit);
 
93
                        stream_data->has_replaygain = true;
 
94
                        stream_data->replay_scale = grabbag__replaygain_compute_scale_factor(peak, gain, (double)cfg.replaygain.preamp, !cfg.replaygain.hard_limit);
84
95
                }
85
96
        }
86
97
}
87
98
 
88
 
static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
 
99
static void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
89
100
{
90
 
        file_info_struct *file_info = (file_info_struct*)client_data;
 
101
        stream_data_struct *stream_data = (stream_data_struct*)client_data;
91
102
        (void)decoder;
92
103
 
93
104
        if (cfg.misc.stop_err || status!=FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
94
 
                file_info->abort_flag = true;
 
105
                stream_data->abort_flag = true;
95
106
}
96
107
 
97
108
/*
98
109
 *  init/delete
99
110
 */
100
111
 
101
 
FLAC__bool FLAC_plugin__decoder_init(FLAC__FileDecoder *decoder, const char *filename, FLAC__int64 filesize, file_info_struct *file_info, output_config_t *config)
 
112
FLAC__bool FLAC_plugin__decoder_init(FLAC__StreamDecoder *decoder, const char *filename, FLAC__int64 filesize, stream_data_struct *stream_data, output_config_t *config)
102
113
{
 
114
        FLAC__StreamDecoderInitStatus init_status;
 
115
 
103
116
        FLAC__ASSERT(decoder);
104
117
        FLAC_plugin__decoder_finish(decoder);
105
118
        /* init decoder */
106
 
        FLAC__file_decoder_set_md5_checking(decoder, false);
107
 
        FLAC__file_decoder_set_filename(decoder, filename);
108
 
        FLAC__file_decoder_set_metadata_ignore_all(decoder);
109
 
        FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
110
 
        FLAC__file_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
111
 
        FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback);
112
 
        FLAC__file_decoder_set_write_callback(decoder, write_callback);
113
 
        FLAC__file_decoder_set_error_callback(decoder, error_callback);
114
 
        FLAC__file_decoder_set_client_data(decoder, file_info);
 
119
        FLAC__stream_decoder_set_md5_checking(decoder, false);
 
120
        FLAC__stream_decoder_set_metadata_ignore_all(decoder);
 
121
        FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
 
122
        FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
115
123
 
116
 
        if (FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
 
124
        if ((init_status = FLAC__stream_decoder_init_file(decoder, filename, write_callback, metadata_callback, error_callback, /*client_data=*/stream_data)) != FLAC__STREAM_DECODER_INIT_STATUS_OK)
117
125
        {
118
 
                FLAC_plugin__show_error("Error while initializing decoder (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
 
126
                FLAC_plugin__show_error("Error while initializing decoder (%s [%s]).", FLAC__StreamDecoderInitStatusString[init_status], FLAC__stream_decoder_get_resolved_state_string(decoder));
119
127
                return false;
120
128
        }
121
129
        /* process */
122
130
        cfg = *config;
123
131
        wide_samples_in_reservoir_ = 0;
124
 
        file_info->is_playing = false;
125
 
        file_info->abort_flag = false;
126
 
        file_info->has_replaygain = false;
 
132
        stream_data->is_playing = false;
 
133
        stream_data->abort_flag = false;
 
134
        stream_data->has_replaygain = false;
127
135
 
128
 
        if (!FLAC__file_decoder_process_until_end_of_metadata(decoder))
 
136
        if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
129
137
        {
130
 
                FLAC_plugin__show_error("Error while processing metadata (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
 
138
                FLAC_plugin__show_error("Error while processing metadata (%s).", FLAC__stream_decoder_get_resolved_state_string(decoder));
131
139
                return false;
132
140
        }
133
141
        /* check results */
134
 
        if (file_info->abort_flag) return false;                /* metadata callback already popped up the error dialog */
 
142
        if (stream_data->abort_flag) return false;                /* metadata callback already popped up the error dialog */
135
143
        /* init replaygain */
136
 
        file_info->output_bits_per_sample = file_info->has_replaygain && cfg.replaygain.enable ?
 
144
        stream_data->output_bits_per_sample = stream_data->has_replaygain && cfg.replaygain.enable ?
137
145
                cfg.resolution.replaygain.bps_out :
138
 
                cfg.resolution.normal.dither_24_to_16 ? min(file_info->bits_per_sample, 16) : file_info->bits_per_sample;
 
146
                cfg.resolution.normal.dither_24_to_16 ? min(stream_data->bits_per_sample, 16) : stream_data->bits_per_sample;
139
147
 
140
 
        if (file_info->has_replaygain && cfg.replaygain.enable && cfg.resolution.replaygain.dither)
141
 
                FLAC__replaygain_synthesis__init_dither_context(&file_info->dither_context, file_info->bits_per_sample, cfg.resolution.replaygain.noise_shaping);
 
148
        if (stream_data->has_replaygain && cfg.replaygain.enable && cfg.resolution.replaygain.dither)
 
149
                FLAC__replaygain_synthesis__init_dither_context(&stream_data->dither_context, stream_data->bits_per_sample, cfg.resolution.replaygain.noise_shaping);
142
150
        /* more inits */
143
 
        file_info->eof = false;
144
 
        file_info->seek_to = -1;
145
 
        file_info->is_playing = true;
146
 
        file_info->average_bps = (unsigned)(filesize / (125.*file_info->total_samples/file_info->sample_rate));
 
151
        stream_data->eof = false;
 
152
        stream_data->seek_to = -1;
 
153
        stream_data->is_playing = true;
 
154
        stream_data->average_bps = (unsigned)(filesize / (125.*(double)(FLAC__int64)stream_data->total_samples/(double)stream_data->sample_rate));
147
155
        
148
156
        bh_index_last_w = 0;
149
157
        bh_index_last_o = BITRATE_HIST_SIZE;
154
162
        return true;
155
163
}
156
164
 
157
 
void FLAC_plugin__decoder_finish(FLAC__FileDecoder *decoder)
 
165
void FLAC_plugin__decoder_finish(FLAC__StreamDecoder *decoder)
158
166
{
159
 
        if (decoder && FLAC__file_decoder_get_state(decoder)!=FLAC__FILE_DECODER_UNINITIALIZED)
160
 
                FLAC__file_decoder_finish(decoder);
 
167
        if (decoder && FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_UNINITIALIZED)
 
168
                (void)FLAC__stream_decoder_finish(decoder);
161
169
}
162
170
 
163
 
void FLAC_plugin__decoder_delete(FLAC__FileDecoder *decoder)
 
171
void FLAC_plugin__decoder_delete(FLAC__StreamDecoder *decoder)
164
172
{
165
173
        if (decoder)
166
174
        {
167
175
                FLAC_plugin__decoder_finish(decoder);
168
 
                FLAC__file_decoder_delete(decoder);
 
176
                FLAC__stream_decoder_delete(decoder);
169
177
        }
170
178
}
171
179
 
173
181
 *  decode
174
182
 */
175
183
 
176
 
int FLAC_plugin__seek(FLAC__FileDecoder *decoder, file_info_struct *file_info)
 
184
int FLAC_plugin__seek(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data)
177
185
{
178
186
        int pos;
179
 
        const FLAC__uint64 target_sample =
180
 
                (FLAC__uint64)file_info->total_samples*file_info->seek_to / file_info->length_in_msec;
181
 
 
182
 
        if (!FLAC__file_decoder_seek_absolute(decoder, target_sample))
183
 
                return -1;
184
 
 
185
 
        file_info->seek_to = -1;
186
 
        file_info->eof = false;
 
187
        FLAC__uint64 target_sample = stream_data->total_samples * stream_data->seek_to / stream_data->length_in_msec;
 
188
 
 
189
        if (stream_data->total_samples > 0 && target_sample >= stream_data->total_samples && target_sample > 0)
 
190
                target_sample = stream_data->total_samples - 1;
 
191
 
 
192
        /* even if the seek fails we have to reset these so that we don't repeat the seek */
 
193
        stream_data->seek_to = -1;
 
194
        stream_data->eof = false;
187
195
        wide_samples_in_reservoir_ = 0;
188
 
        pos = (int)(target_sample*1000 / file_info->sample_rate);
 
196
        pos = (int)(target_sample*1000 / stream_data->sample_rate);
 
197
 
 
198
        if (!FLAC__stream_decoder_seek_absolute(decoder, target_sample)) {
 
199
                if(FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_SEEK_ERROR)
 
200
                        FLAC__stream_decoder_flush(decoder);
 
201
                pos = -1;
 
202
        }
189
203
 
190
204
        bh_index_last_o = bh_index_last_w = (pos/BITRATE_HIST_SEGMENT_MSEC) % BITRATE_HIST_SIZE;
191
 
        if (!FLAC__file_decoder_get_decode_position(decoder, &decode_position))
 
205
        if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position))
192
206
                decode_position = 0;
193
207
 
194
208
        return pos;
195
209
}
196
210
 
197
 
unsigned FLAC_plugin__decode(FLAC__FileDecoder *decoder, file_info_struct *file_info, char *sample_buffer)
 
211
unsigned FLAC_plugin__decode(FLAC__StreamDecoder *decoder, stream_data_struct *stream_data, char *sample_buffer)
198
212
{
199
213
        /* fill reservoir */
200
214
        while (wide_samples_in_reservoir_ < SAMPLES_PER_WRITE)
201
215
        {
202
 
                if (FLAC__file_decoder_get_state(decoder) == FLAC__FILE_DECODER_END_OF_FILE)
203
 
                {
204
 
                        file_info->eof = true;
205
 
                        break;
206
 
                }
207
 
                else if (!FLAC__file_decoder_process_single(decoder))
208
 
                {
209
 
                        FLAC_plugin__show_error("Error while processing frame (%s).", FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(decoder)]);
210
 
                        file_info->eof = true;
211
 
                        break;
212
 
                }
213
 
                if (!FLAC__file_decoder_get_decode_position(decoder, &decode_position))
 
216
                if (FLAC__stream_decoder_get_state(decoder) == FLAC__STREAM_DECODER_END_OF_STREAM)
 
217
                {
 
218
                        stream_data->eof = true;
 
219
                        break;
 
220
                }
 
221
                else if (!FLAC__stream_decoder_process_single(decoder))
 
222
                {
 
223
                        FLAC_plugin__show_error("Error while processing frame (%s).", FLAC__stream_decoder_get_resolved_state_string(decoder));
 
224
                        stream_data->eof = true;
 
225
                        break;
 
226
                }
 
227
                if (!FLAC__stream_decoder_get_decode_position(decoder, &decode_position))
214
228
                        decode_position = 0;
215
229
        }
216
230
        /* output samples */
217
231
        if (wide_samples_in_reservoir_ > 0)
218
232
        {
219
233
                const unsigned n = min(wide_samples_in_reservoir_, SAMPLES_PER_WRITE);
220
 
                const unsigned channels = file_info->channels;
 
234
                const unsigned channels = stream_data->channels;
221
235
                unsigned i;
222
236
                int bytes;
223
237
 
224
 
                if (cfg.replaygain.enable && file_info->has_replaygain)
 
238
                if (cfg.replaygain.enable && stream_data->has_replaygain)
225
239
                {
226
240
                        bytes = FLAC__replaygain_synthesis__apply_gain(
227
241
                                sample_buffer,
228
242
                                true, /* little_endian_data_out */
229
 
                                file_info->output_bits_per_sample == 8, /* unsigned_data_out */
 
243
                                stream_data->output_bits_per_sample == 8, /* unsigned_data_out */
230
244
                                reservoir__,
231
245
                                n,
232
246
                                channels,
233
 
                                file_info->bits_per_sample,
234
 
                                file_info->output_bits_per_sample,
235
 
                                file_info->replay_scale,
 
247
                                stream_data->bits_per_sample,
 
248
                                stream_data->output_bits_per_sample,
 
249
                                stream_data->replay_scale,
236
250
                                cfg.replaygain.hard_limit,
237
251
                                cfg.resolution.replaygain.dither,
238
 
                                &file_info->dither_context
 
252
                                &stream_data->dither_context
239
253
                        );
240
254
                }
241
255
                else
245
259
                                reservoir__,
246
260
                                n,
247
261
                                channels,
248
 
                                file_info->bits_per_sample,
249
 
                                file_info->output_bits_per_sample
 
262
                                stream_data->bits_per_sample,
 
263
                                stream_data->output_bits_per_sample
250
264
                        );
251
265
                }
252
266
 
258
272
        }
259
273
        else
260
274
        {
261
 
                file_info->eof = true;
 
275
                stream_data->eof = true;
262
276
                return 0;
263
277
        }
264
278
}
265
279
 
266
 
int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, file_info_struct *file_info)
 
280
int FLAC_plugin__get_rate(unsigned written_time, unsigned output_time, stream_data_struct *stream_data)
267
281
{
268
282
        static int bitrate_history_[BITRATE_HIST_SIZE];
269
283
        unsigned bh_index_w = (written_time/BITRATE_HIST_SEGMENT_MSEC) % BITRATE_HIST_SIZE;
275
289
                bitrate_history_[(bh_index_w + BITRATE_HIST_SIZE-1)%BITRATE_HIST_SIZE] =
276
290
                        decode_position>decode_position_last && written_time > written_time_last ?
277
291
                        (unsigned)(8000*(decode_position - decode_position_last)/(written_time - written_time_last)) :
278
 
                        file_info->average_bps;
 
292
                        stream_data->average_bps;
279
293
 
280
294
                bh_index_last_w = bh_index_w;
281
295
                written_time_last = written_time;