temporary fix for libtool bug
[platform/upstream/flac.git] / src / plugin_xmms / plugin.c
index 51e51b8..6052182 100644 (file)
@@ -1,5 +1,5 @@
 /* libxmms-flac - XMMS FLAC input plugin
- * Copyright (C) 2000,2001  Josh Coalson
+ * Copyright (C) 2000,2001,2002  Josh Coalson
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -32,7 +32,7 @@
 #define min(x,y) ((x)<(y)?(x):(y))
 
 typedef struct {
-       byte raw[128];
+       FLAC__byte raw[128];
        char title[31];
        char artist[31];
        char album[31];
@@ -44,9 +44,10 @@ typedef struct {
 } id3v1_struct;
 
 typedef struct {
-       bool abort_flag;
-       bool is_playing;
-       bool eof;
+       FLAC__bool abort_flag;
+       FLAC__bool is_playing;
+       FLAC__bool eof;
+       FLAC__bool play_thread_open; /* if true, is_playing must also be true */
        unsigned total_samples;
        unsigned bits_per_sample;
        unsigned channels;
@@ -66,11 +67,13 @@ static int  FLAC_XMMS__get_time();
 static void FLAC_XMMS__cleanup();
 static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length);
 
-static bool get_id3v1_tag_(const char *filename, id3v1_struct *tag);
+static FLAC__bool get_id3v1_tag_(const char *filename, id3v1_struct *tag);
 static void *play_loop_(void *arg);
-static bool decoder_init_(const char *filename);
-static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data);
-static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
+static FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder);
+static void safe_decoder_finish_(FLAC__FileDecoder *decoder);
+static void safe_decoder_delete_(FLAC__FileDecoder *decoder);
+static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
+static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
 static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
 
 
@@ -103,13 +106,13 @@ InputPlugin flac_ip =
 };
 
 #define SAMPLES_PER_WRITE 512
-static byte reservoir_[FLAC__MAX_BLOCK_SIZE * 2 * 2 * 2]; /* *2 for max bytes-per-sample, *2 for max channels, another *2 for overflow */
-static byte output_[FLAC__MAX_BLOCK_SIZE * 2 * 2]; /* *2 for max bytes-per-sample, *2 for max channels */
-static unsigned reservoir_samples_;
-static FLAC__FileDecoder *decoder_;
+static FLAC__byte reservoir_[FLAC__MAX_BLOCK_SIZE * 2 * 2 * 2]; /* *2 for max bytes-per-sample, *2 for max channels, another *2 for overflow */
+static FLAC__byte output_[FLAC__MAX_BLOCK_SIZE * 2 * 2]; /* *2 for max bytes-per-sample, *2 for max channels */
+static unsigned reservoir_samples_ = 0;
+static FLAC__FileDecoder *decoder_ = 0;
 static file_info_struct file_info_;
 static pthread_t decode_thread_;
-static bool audio_error_ = false;
+static FLAC__bool audio_error_ = false;
 
 InputPlugin *get_iplugin_info()
 {
@@ -127,8 +130,8 @@ int FLAC_XMMS__is_our_file(char *filename)
        char *ext;
 
        ext = strrchr(filename, '.');
-       if (ext)
-               if (!strcasecmp(ext, ".flac") || !strcasecmp(ext, ".fla"))
+       if(ext)
+               if(!strcasecmp(ext, ".flac") || !strcasecmp(ext, ".fla"))
                        return 1;
        return 0;
 }
@@ -138,22 +141,28 @@ void FLAC_XMMS__play_file(char *filename)
        FILE *f;
        id3v1_struct tag;
 
+       reservoir_samples_ = 0;
+       audio_error_ = false;
+       file_info_.abort_flag = false;
+       file_info_.is_playing = false;
+       file_info_.eof = false;
+       file_info_.play_thread_open = false;
+
        if(0 == (f = fopen(filename, "r")))
                return;
        fclose(f);
 
-       if(!decoder_init_(filename))
+       if(decoder_ == 0)
+               return;
+
+       if(!safe_decoder_init_(filename, decoder_))
                return;
 
-       reservoir_samples_ = 0;
-       audio_error_ = false;
        file_info_.is_playing = true;
-       file_info_.eof = false;
 
-       if (flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) {
+       if(flac_ip.output->open_audio(file_info_.sample_format, file_info_.sample_rate, file_info_.channels) == 0) {
                audio_error_ = true;
-               if(decoder_ && FLAC__file_decoder_get_state(decoder_) != FLAC__FILE_DECODER_UNINITIALIZED)
-                       FLAC__file_decoder_finish(decoder_);
+               safe_decoder_finish_(decoder_);
                return;
        }
 
@@ -161,6 +170,7 @@ void FLAC_XMMS__play_file(char *filename)
        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);
 
        file_info_.seek_to_in_sec = -1;
+       file_info_.play_thread_open = true;
        pthread_create(&decode_thread_, NULL, play_loop_, NULL);
 }
 
@@ -168,10 +178,12 @@ void FLAC_XMMS__stop()
 {
        if(file_info_.is_playing) {
                file_info_.is_playing = false;
-               pthread_join(decode_thread_, NULL);
+               if(file_info_.play_thread_open) {
+                       file_info_.play_thread_open = false;
+                       pthread_join(decode_thread_, NULL);
+               }
                flac_ip.output->close_audio();
-               if(decoder_ && FLAC__file_decoder_get_state(decoder_) != FLAC__FILE_DECODER_UNINITIALIZED)
-                       FLAC__file_decoder_finish(decoder_);
+               safe_decoder_finish_(decoder_);
        }
 }
 
@@ -201,55 +213,44 @@ int FLAC_XMMS__get_time()
 
 void FLAC_XMMS__cleanup()
 {
-       if(decoder_)
-               FLAC__file_decoder_delete(decoder_);
+       safe_decoder_delete_(decoder_);
+       decoder_ = 0;
 }
 
 void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
 {
        id3v1_struct tag;
+       FLAC__StreamMetadata streaminfo;
+
+       if(0 == filename)
+               filename = "";
+
+       if(!FLAC__metadata_get_streaminfo(filename, &streaminfo)) {
+               /* @@@ how to report the error? */
+               if(title) {
+                       static const char *errtitle = "Invalid FLAC File: ";
+                       *title = g_malloc(strlen(errtitle) + 1 + strlen(filename) + 1 + 1);
+                       sprintf(*title, "%s\"%s\"", errtitle, filename);
+               }
+               if(length_in_msec)
+                       *length_in_msec = -1;
+               return;
+       }
 
        if(title) {
                (void)get_id3v1_tag_(filename, &tag);
                *title = g_malloc(strlen(tag.description)+1);
                strcpy(*title, tag.description);
        }
-       if(length_in_msec) {
-               FLAC__FileDecoder *tmp_decoder = FLAC__file_decoder_new();
-               file_info_struct tmp_file_info;
-               if(0 == tmp_decoder) {
-                       *length_in_msec = -1;
-                       return;
-               }
-               tmp_file_info.abort_flag = false;
-               FLAC__file_decoder_set_md5_checking(tmp_decoder, false);
-               FLAC__file_decoder_set_filename(tmp_decoder, filename);
-               FLAC__file_decoder_set_write_callback(tmp_decoder, write_callback_);
-               FLAC__file_decoder_set_metadata_callback(tmp_decoder, metadata_callback_);
-               FLAC__file_decoder_set_error_callback(tmp_decoder, error_callback_);
-               FLAC__file_decoder_set_client_data(tmp_decoder, &tmp_file_info);
-               if(FLAC__file_decoder_init(tmp_decoder) != FLAC__FILE_DECODER_OK) {
-                       *length_in_msec = -1;
-                       return;
-               }
-               if(!FLAC__file_decoder_process_metadata(tmp_decoder)) {
-                       *length_in_msec = -1;
-                       return;
-               }
-
-               *length_in_msec = (int)tmp_file_info.length_in_msec;
-
-               if(FLAC__file_decoder_get_state(tmp_decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
-                       FLAC__file_decoder_finish(tmp_decoder);
-               FLAC__file_decoder_delete(tmp_decoder);
-       }
+       if(length_in_msec)
+               *length_in_msec = streaminfo.data.stream_info.total_samples * 10 / (streaminfo.data.stream_info.sample_rate / 100);
 }
 
 /***********************************************************************
  * local routines
  **********************************************************************/
 
-bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
+FLAC__bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
 {
        const char *temp;
        FILE *f = fopen(filename, "rb");
@@ -286,8 +287,8 @@ bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
                memcpy(tag->album, tag->raw+63, 30);
                memcpy(year_str, tag->raw+93, 4); year_str[4] = '\0'; tag->year = atoi(year_str);
                memcpy(tag->comment, tag->raw+97, 30);
-               tag->genre = (unsigned)((byte)tag->raw[127]);
-               tag->track = (unsigned)((byte)tag->raw[126]);
+               tag->genre = (unsigned)((FLAC__byte)tag->raw[127]);
+               tag->track = (unsigned)((FLAC__byte)tag->raw[126]);
 
                sprintf(tag->description, "%s - %s", tag->artist, tag->title);
 
@@ -297,7 +298,6 @@ bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
 
 void *play_loop_(void *arg)
 {
-
        (void)arg;
 
        while(file_info_.is_playing) {
@@ -307,8 +307,12 @@ void *play_loop_(void *arg)
                                        file_info_.eof = true;
                                        break;
                                }
-                               else if(!FLAC__file_decoder_process_one_frame(decoder_))
+                               else if(!FLAC__file_decoder_process_one_frame(decoder_)) {
+                                       /*@@@ this should probably be a dialog */
+                                       fprintf(stderr, "libxmms-flac: READ ERROR processing frame\n");
+                                       file_info_.eof = true;
                                        break;
+                               }
                        }
                        if(reservoir_samples_ > 0) {
                                const unsigned channels = file_info_.channels;
@@ -336,20 +340,19 @@ void *play_loop_(void *arg)
                }
                else
                        xmms_usleep(10000);
-               if (file_info_.seek_to_in_sec != -1) {
+               if(file_info_.seek_to_in_sec != -1) {
                        const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec;
                        unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples);
-                       if(FLAC__file_decoder_seek_absolute(decoder_, (uint64)target_sample)) {
+                       if(FLAC__file_decoder_seek_absolute(decoder_, (FLAC__uint64)target_sample)) {
                                flac_ip.output->flush(file_info_.seek_to_in_sec * 1000);
                                file_info_.seek_to_in_sec = -1;
                                file_info_.eof = false;
                                reservoir_samples_ = 0;
                        }
                }
-
        }
-       if(decoder_ && FLAC__file_decoder_get_state(decoder_) != FLAC__FILE_DECODER_UNINITIALIZED)
-               FLAC__file_decoder_finish(decoder_);
+
+       safe_decoder_finish_(decoder_);
 
        /* are these two calls necessary? */
        flac_ip.output->buffer_free();
@@ -359,62 +362,76 @@ void *play_loop_(void *arg)
        return 0; /* to silence the compiler warning about not returning a value */
 }
 
-bool decoder_init_(const char *filename)
+FLAC__bool safe_decoder_init_(const char *filename, FLAC__FileDecoder *decoder)
 {
-       if(decoder_ == 0)
+       if(decoder == 0)
                return false;
 
-       FLAC__file_decoder_set_md5_checking(decoder_, false);
-       FLAC__file_decoder_set_filename(decoder_, filename);
-       FLAC__file_decoder_set_write_callback(decoder_, write_callback_);
-       FLAC__file_decoder_set_metadata_callback(decoder_, metadata_callback_);
-       FLAC__file_decoder_set_error_callback(decoder_, error_callback_);
-       FLAC__file_decoder_set_client_data(decoder_, &file_info_);
-       if(FLAC__file_decoder_init(decoder_) != FLAC__FILE_DECODER_OK)
-               return false;
+       safe_decoder_finish_(decoder);
 
-       file_info_.abort_flag = false;
+       FLAC__file_decoder_set_md5_checking(decoder, false);
+       FLAC__file_decoder_set_filename(decoder, filename);
+       FLAC__file_decoder_set_write_callback(decoder, write_callback_);
+       FLAC__file_decoder_set_metadata_callback(decoder, metadata_callback_);
+       FLAC__file_decoder_set_error_callback(decoder, error_callback_);
+       FLAC__file_decoder_set_client_data(decoder, &file_info_);
+       if(FLAC__file_decoder_init(decoder) != FLAC__FILE_DECODER_OK)
+               return false;
 
-       if(!FLAC__file_decoder_process_metadata(decoder_))
+       if(!FLAC__file_decoder_process_metadata(decoder))
                return false;
 
        return true;
 }
 
-FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const int32 *buffer[], void *client_data)
+void safe_decoder_finish_(FLAC__FileDecoder *decoder)
+{
+       if(decoder && FLAC__file_decoder_get_state(decoder) != FLAC__FILE_DECODER_UNINITIALIZED)
+               FLAC__file_decoder_finish(decoder);
+}
+
+void safe_decoder_delete_(FLAC__FileDecoder *decoder)
+{
+       if(decoder) {
+               safe_decoder_finish_(decoder);
+               FLAC__file_decoder_delete(decoder);
+       }
+}
+
+FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
 {
        file_info_struct *file_info = (file_info_struct *)client_data;
        const unsigned bps = file_info->bits_per_sample, channels = file_info->channels, wide_samples = frame->header.blocksize;
        unsigned wide_sample, sample, channel;
-       int8 *scbuffer = (int8*)reservoir_;
-       int16 *ssbuffer = (int16*)reservoir_;
+       FLAC__int8 *scbuffer = (FLAC__int8*)reservoir_;
+       FLAC__int16 *ssbuffer = (FLAC__int16*)reservoir_;
 
        (void)decoder;
 
        if(file_info->abort_flag)
-               return FLAC__STREAM_DECODER_WRITE_ABORT;
+               return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
 
        if(bps == 8) {
                for(sample = reservoir_samples_*channels, wide_sample = 0; wide_sample < wide_samples; wide_sample++)
                        for(channel = 0; channel < channels; channel++, sample++)
-                               scbuffer[sample] = (int8)buffer[channel][wide_sample];
+                               scbuffer[sample] = (FLAC__int8)buffer[channel][wide_sample];
        }
        else if(bps == 16) {
                for(sample = reservoir_samples_*channels, wide_sample = 0; wide_sample < wide_samples; wide_sample++)
                        for(channel = 0; channel < channels; channel++, sample++)
-                               ssbuffer[sample] = (int16)buffer[channel][wide_sample];
+                               ssbuffer[sample] = (FLAC__int16)buffer[channel][wide_sample];
        }
        else {
                file_info->abort_flag = true;
-               return FLAC__STREAM_DECODER_WRITE_ABORT;
+               return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
        }
 
        reservoir_samples_ += wide_samples;
 
-       return FLAC__STREAM_DECODER_WRITE_CONTINUE;
+       return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
 
-void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
+void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
 {
        file_info_struct *file_info = (file_info_struct *)client_data;
        (void)decoder;
@@ -443,6 +460,6 @@ void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorS
 {
        file_info_struct *file_info = (file_info_struct *)client_data;
        (void)decoder;
-       if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
+       if(status != FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC)
                file_info->abort_flag = true;
 }