add support for 8-bps files
[platform/upstream/flac.git] / src / plugin_xmms / plugin.c
1 /* libxmms-flac - XMMS FLAC input plugin
2  * Copyright (C) 2000,2001  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,
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.
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.
17  */
18
19 #include <pthread.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <assert.h>
24 #include <glib.h>
25
26 #include "xmms/plugin.h"
27 #include "xmms/util.h"
28 #include "FLAC/all.h"
29
30 typedef struct {
31         byte raw[128];
32         char title[31];
33         char artist[31];
34         char album[31];
35         char comment[31];
36         unsigned year;
37         unsigned track; /* may be 0 if v1 (not v1.1) tag */
38         unsigned genre;
39         char description[1024]; /* the formatted description passed to xmms */
40 } id3v1_struct;
41
42 typedef struct {
43         bool abort_flag;
44         bool is_playing;
45         bool eof;
46         unsigned total_samples;
47         unsigned bits_per_sample;
48         unsigned channels;
49         unsigned sample_rate;
50         unsigned length_in_msec;
51         AFormat sample_format;
52         int seek_to_in_sec;
53 } file_info_struct;
54
55 static void FLAC_XMMS__init();
56 static int  FLAC_XMMS__is_our_file(char *filename);
57 static void FLAC_XMMS__play_file(char *filename);
58 static void FLAC_XMMS__stop();
59 static void FLAC_XMMS__pause(short p);
60 static void FLAC_XMMS__seek(int time);
61 static int  FLAC_XMMS__get_time();
62 static void FLAC_XMMS__cleanup();
63 static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length);
64
65 static bool get_id3v1_tag_(const char *filename, id3v1_struct *tag);
66 static void *play_loop_(void *arg);
67 static bool decoder_init_(const char *filename);
68 static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data);
69 static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
70 static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
71
72
73 InputPlugin flac_ip =
74 {
75         NULL,
76         NULL,
77         "FLAC Player v" FLAC__VERSION_STRING,
78         FLAC_XMMS__init,
79         NULL,
80         NULL,
81         FLAC_XMMS__is_our_file,
82         NULL,
83         FLAC_XMMS__play_file,
84         FLAC_XMMS__stop,
85         FLAC_XMMS__pause,
86         FLAC_XMMS__seek,
87         NULL,
88         FLAC_XMMS__get_time,
89         NULL,
90         NULL,
91         FLAC_XMMS__cleanup,
92         NULL,
93         NULL,
94         NULL,
95         NULL,
96         FLAC_XMMS__get_song_info,
97         NULL,                   /* file_info_box */
98         NULL
99 };
100
101 static byte reservoir_[FLAC__MAX_BLOCK_SIZE * 2 * 2 * 2]; /* *2 for max bytes-per-sample, *2 for max channels, another *2 for overflow */
102 #ifdef RESERVOIR_TEST
103 static byte output_[FLAC__MAX_BLOCK_SIZE * 2 * 2]; /* *2 for max bytes-per-sample, *2 for max channels */
104 #endif
105 static unsigned reservoir_samples_;
106 static FLAC__FileDecoder *decoder_;
107 static file_info_struct file_info_;
108 static pthread_t decode_thread_;
109 static bool audio_error_ = false;
110
111 InputPlugin *get_iplugin_info()
112 {
113         flac_ip.description = g_strdup_printf("FLAC Player v%s", FLAC__VERSION_STRING);
114         return &flac_ip;
115 }
116
117 void FLAC_XMMS__init()
118 {
119         decoder_ = FLAC__file_decoder_get_new_instance();
120 }
121
122 int FLAC_XMMS__is_our_file(char *filename)
123 {
124         char *ext;
125
126         ext = strrchr(filename, '.');
127         if (ext)
128                 if (!strcasecmp(ext, ".flac") || !strcasecmp(ext, ".fla"))
129                         return 1;
130         return 0;
131 }
132
133 void FLAC_XMMS__play_file(char *filename)
134 {
135         FILE *f;
136         id3v1_struct tag;
137
138         if(0 == (f = fopen(filename, "r")))
139                 return;
140         fclose(f);
141
142         if(!decoder_init_(filename))
143                 return;
144
145         reservoir_samples_ = 0;
146         audio_error_ = false;
147         file_info_.is_playing = true;
148         file_info_.eof = false;
149
150         if (flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) {
151                 audio_error_ = true;
152                 if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
153                         FLAC__file_decoder_finish(decoder_);
154                 return;
155         }
156
157         (void)get_id3v1_tag_(filename, &tag);
158         flac_ip.set_info(tag.description, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels);
159
160         file_info_.seek_to_in_sec = -1;
161         pthread_create(&decode_thread_, NULL, play_loop_, NULL);
162 }
163
164 void FLAC_XMMS__stop()
165 {
166         if(file_info_.is_playing) {
167                 file_info_.is_playing = false;
168                 pthread_join(decode_thread_, NULL);
169                 flac_ip.output->close_audio();
170                 if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
171                         FLAC__file_decoder_finish(decoder_);
172         }
173 }
174
175 void FLAC_XMMS__pause(short p)
176 {
177         flac_ip.output->pause(p);
178 }
179
180 void FLAC_XMMS__seek(int time)
181 {
182         file_info_.seek_to_in_sec = time;
183         file_info_.eof = false;
184
185         while(file_info_.seek_to_in_sec != -1)
186                 xmms_usleep(10000);
187 }
188
189 int FLAC_XMMS__get_time()
190 {
191         if(audio_error_)
192                 return -2;
193         if(!file_info_.is_playing || (file_info_.eof && !flac_ip.output->buffer_playing()))
194                 return -1;
195         else
196                 return flac_ip.output->output_time();
197 }
198
199 void FLAC_XMMS__cleanup()
200 {
201         if(decoder_)
202                 FLAC__file_decoder_free_instance(decoder_);
203 }
204
205 void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
206 {
207         id3v1_struct tag;
208
209         if(title) {
210                 (void)get_id3v1_tag_(filename, &tag);
211                 *title = g_malloc(strlen(tag.description)+1);
212                 strcpy(*title, tag.description);
213         }
214         if(length_in_msec) {
215                 FLAC__FileDecoder *tmp_decoder = FLAC__file_decoder_get_new_instance();
216                 file_info_struct tmp_file_info;
217                 if(0 == tmp_decoder) {
218                         *length_in_msec = -1;
219                         return;
220                 }
221                 tmp_file_info.abort_flag = false;
222                 tmp_decoder->check_md5 = false; /* turn off MD5 checking in the decoder */
223                 if(FLAC__file_decoder_init(tmp_decoder, filename, write_callback_, metadata_callback_, error_callback_, &tmp_file_info) != FLAC__FILE_DECODER_OK) {
224                         *length_in_msec = -1;
225                         return;
226                 }
227                 if(!FLAC__file_decoder_process_metadata(tmp_decoder)) {
228                         *length_in_msec = -1;
229                         return;
230                 }
231
232                 *length_in_msec = (int)tmp_file_info.length_in_msec;
233
234                 if(tmp_decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
235                         FLAC__file_decoder_finish(tmp_decoder);
236                 FLAC__file_decoder_free_instance(tmp_decoder);
237         }
238 }
239
240 /***********************************************************************
241  * local routines
242  **********************************************************************/
243
244 bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
245 {
246         const char *temp;
247         FILE *f = fopen(filename, "rb");
248         memset(tag, 0, sizeof(id3v1_struct));
249
250         /* set the title and description to the filename by default */
251         temp = strrchr(filename, '/');
252         if(!temp)
253                 temp = filename;
254         else
255                 temp++;
256         strcpy(tag->description, temp);
257         *strrchr(tag->description, '.') = '\0';
258         strncpy(tag->title, tag->description, 30); tag->title[30] = '\0';
259
260         if(0 == f)
261                 return false;
262         if(-1 == fseek(f, -128, SEEK_END)) {
263                 fclose(f);
264                 return false;
265         }
266         if(fread(tag->raw, 1, 128, f) < 128) {
267                 fclose(f);
268                 return false;
269         }
270         fclose(f);
271         if(strncmp(tag->raw, "TAG", 3))
272                 return false;
273         else {
274                 char year_str[5];
275
276                 memcpy(tag->title, tag->raw+3, 30);
277                 memcpy(tag->artist, tag->raw+33, 30);
278                 memcpy(tag->album, tag->raw+63, 30);
279                 memcpy(year_str, tag->raw+93, 4); year_str[4] = '\0'; tag->year = atoi(year_str);
280                 memcpy(tag->comment, tag->raw+97, 30);
281                 tag->genre = (unsigned)((byte)tag->raw[127]);
282                 tag->track = (unsigned)((byte)tag->raw[126]);
283
284                 sprintf(tag->description, "%s - %s", tag->artist, tag->title);
285
286                 return true;
287         }
288 }
289
290 #ifndef RESERVOIR_TEST
291 void *play_loop_(void *arg)
292 {
293
294         (void)arg;
295
296         while(file_info_.is_playing) {
297                 if(!file_info_.eof) {
298                         (void)FLAC__file_decoder_process_one_frame(decoder_);
299                         if(reservoir_samples_ > 0) {
300                                 unsigned bytes = reservoir_samples_ * ((file_info_.bits_per_sample+7)/8) * file_info_.channels;
301                                 flac_ip.add_vis_pcm(flac_ip.output->written_time(), file_info_.sample_format, file_info_.channels, bytes, reservoir_);
302                                 while(flac_ip.output->buffer_free() < (int)bytes && file_info_.is_playing && file_info_.seek_to_in_sec == -1)
303                                         xmms_usleep(10000);
304                                 if(file_info_.is_playing && file_info_.seek_to_in_sec == -1)
305                                         flac_ip.output->write_audio(reservoir_, bytes);
306                                 reservoir_samples_ = 0;
307                         }
308                         else {
309                                 file_info_.eof = true;
310                                 xmms_usleep(10000);
311                         }
312                 }
313                 else
314                         xmms_usleep(10000);
315                 if (file_info_.seek_to_in_sec != -1) {
316                         const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec;
317                         unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples);
318                         if(FLAC__file_decoder_seek_absolute(decoder_, (uint64)target_sample)) {
319                                 flac_ip.output->flush(file_info_.seek_to_in_sec * 1000);
320                                 file_info_.seek_to_in_sec = -1;
321                                 file_info_.eof = false;
322                         }
323                 }
324
325         }
326         if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
327                 FLAC__file_decoder_finish(decoder_);
328
329         /* are these two calls necessary? */
330         flac_ip.output->buffer_free();
331         flac_ip.output->buffer_free();
332
333         pthread_exit(NULL);
334         return 0; /* to silence the compiler warning about not returning a value */
335 }
336 #else
337 void *play_loop_(void *arg)
338 {
339
340         (void)arg;
341
342         while(file_info_.is_playing) {
343                 if(!file_info_.eof) {
344                         while(reservoir_samples_ < 576) {
345                                 if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE) {
346                                         file_info_.eof = true;
347                                         break;
348                                 }
349                                 else if(!FLAC__file_decoder_process_one_frame(decoder_))
350                                         break;
351                         }
352                         if(reservoir_samples_ > 0) {
353                                 const unsigned channels = file_info_.channels;
354                                 const unsigned bytes_per_sample = (file_info_.bits_per_sample+7)/8;
355                                 unsigned i, n = min(reservoir_samples_, 576), delta;
356                                 unsigned bytes = n * bytes_per_sample * channels;
357
358                                 for(i = 0; i < bytes; i++)
359                                         output_[i] = reservoir_[i];
360                                 delta = i;
361                                 for( ; i < reservoir_samples_*bytes_per_sample*channels; i++)
362                                         reservoir[i-delta] = reservoir[i];
363                                 reservoir_samples_ -= n;
364
365                                 flac_ip.add_vis_pcm(flac_ip.output->written_time(), file_info_.sample_format, channels, bytes, output_);
366                                 while(flac_ip.output->buffer_free() < (int)bytes && file_info_.is_playing && file_info_.seek_to_in_sec == -1)
367                                         xmms_usleep(10000);
368                                 if(file_info_.is_playing && file_info_.seek_to_in_sec == -1)
369                                         flac_ip.output->write_audio(output_, bytes);
370                         }
371                         else {
372                                 file_info_.eof = true;
373                                 xmms_usleep(10000);
374                         }
375                 }
376                 else
377                         xmms_usleep(10000);
378                 if (file_info_.seek_to_in_sec != -1) {
379                         const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec;
380                         unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples);
381                         if(FLAC__file_decoder_seek_absolute(decoder_, (uint64)target_sample)) {
382                                 flac_ip.output->flush(file_info_.seek_to_in_sec * 1000);
383                                 file_info_.seek_to_in_sec = -1;
384                                 file_info_.eof = false;
385                                 reservoir_samples_ = 0;
386                         }
387                 }
388
389         }
390         if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
391                 FLAC__file_decoder_finish(decoder_);
392
393         /* are these two calls necessary? */
394         flac_ip.output->buffer_free();
395         flac_ip.output->buffer_free();
396
397         pthread_exit(NULL);
398         return 0; /* to silence the compiler warning about not returning a value */
399 }
400 #endif
401
402 bool decoder_init_(const char *filename)
403 {
404         if(decoder_ == 0)
405                 return false;
406
407         decoder_->check_md5 = false; /* turn off MD5 checking in the decoder */
408
409         if(FLAC__file_decoder_init(decoder_, filename, write_callback_, metadata_callback_, error_callback_, &file_info_) != FLAC__FILE_DECODER_OK)
410                 return false;
411
412         file_info_.abort_flag = false;
413
414         if(!FLAC__file_decoder_process_metadata(decoder_))
415                 return false;
416
417         return true;
418 }
419
420 #ifndef RESERVOIR_TEST
421 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data)
422 {
423         file_info_struct *file_info = (file_info_struct *)client_data;
424         const unsigned bps = file_info->bits_per_sample, channels = file_info->channels, wide_samples = frame->header.blocksize;
425         unsigned wide_sample, sample, channel;
426         int8 *scbuffer = (int8*)reservoir_;
427         int16 *ssbuffer = (int16*)reservoir_;
428
429         (void)decoder;
430
431         if(file_info->abort_flag)
432                 return FLAC__STREAM_DECODER_WRITE_ABORT;
433
434         if(bps == 8) {
435                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
436                         for(channel = 0; channel < channels; channel++, sample++)
437                                 scbuffer[sample] = (int8)buffer[channel][wide_sample];
438         }
439         else if(bps == 16) {
440                 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
441                         for(channel = 0; channel < channels; channel++, sample++)
442                                 ssbuffer[sample] = (int16)buffer[channel][wide_sample];
443         }
444         else {
445                 file_info->abort_flag = true;
446                 return FLAC__STREAM_DECODER_WRITE_ABORT;
447         }
448
449         reservoir_samples_ = wide_samples;
450
451         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
452 }
453 #else
454 FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data)
455 {
456         file_info_struct *file_info = (file_info_struct *)client_data;
457         const unsigned bps = file_info->bits_per_sample, channels = file_info->channels, wide_samples = frame->header.blocksize;
458         unsigned wide_sample, sample, channel;
459         int8 *scbuffer = (int8*)reservoir_;
460         int16 *ssbuffer = (int16*)reservoir_;
461
462         (void)decoder;
463
464         if(file_info->abort_flag)
465                 return FLAC__STREAM_DECODER_WRITE_ABORT;
466
467         if(bps == 8) {
468                 for(sample = reservoir_samples_*channels, wide_sample = 0; wide_sample < wide_samples; wide_sample++)
469                         for(channel = 0; channel < channels; channel++, sample++)
470                                 scbuffer[sample] = (int8)buffer[channel][wide_sample];
471         }
472         else if(bps == 16) {
473                 for(sample = reservoir_samples_*channels, wide_sample = 0; wide_sample < wide_samples; wide_sample++)
474                         for(channel = 0; channel < channels; channel++, sample++)
475                                 ssbuffer[sample] = (int16)buffer[channel][wide_sample];
476         }
477         else {
478                 file_info->abort_flag = true;
479                 return FLAC__STREAM_DECODER_WRITE_ABORT;
480         }
481
482         reservoir_samples_ += wide_samples;
483
484         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
485 }
486 #endif
487
488 void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
489 {
490         file_info_struct *file_info = (file_info_struct *)client_data;
491         (void)decoder;
492         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
493                 assert(metadata->data.stream_info.total_samples < 0x100000000); /* this plugin can only handle < 4 gigasamples */
494                 file_info->total_samples = (unsigned)(metadata->data.stream_info.total_samples&0xffffffff);
495                 file_info->bits_per_sample = metadata->data.stream_info.bits_per_sample;
496                 file_info->channels = metadata->data.stream_info.channels;
497                 file_info->sample_rate = metadata->data.stream_info.sample_rate;
498
499                 if(file_info->bits_per_sample == 8) {
500                         file_info->sample_format = FMT_S8;
501                 }
502                 else if(file_info->bits_per_sample == 16) {
503                         file_info->sample_format = FMT_S16_NE;
504                 }
505                 else {
506                         file_info->abort_flag = true;
507                         return;
508                 }
509                 file_info->length_in_msec = file_info->total_samples * 10 / (file_info->sample_rate / 100);
510         }
511 }
512
513 void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
514 {
515         file_info_struct *file_info = (file_info_struct *)client_data;
516         (void)decoder;
517         if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
518                 file_info->abort_flag = true;
519 }