Project

General

Profile

fix-flac-playback-failure.patch

Case Of, August 29, 2022 20:25

View differences:

a/src/flac/flacng.h
99 99
void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
100 100

  
101 101
/* tools.c */
102
bool is_ogg_flac(VFSFile &file);
103 102
bool read_metadata(FLAC__StreamDecoder* decoder, callback_info* info);
104 103

  
105 104
#endif
106
-- b/src/flac/metadata.cc
105
++ a/src/flac/metadata.cc
......
134 134

  
135 135
bool FLACng::write_tuple(const char *filename, VFSFile &file, const Tuple &tuple)
136 136
{
137
    if (is_ogg_flac(file))
138
    {
139
        AUDERR("Writing Ogg FLAC tags is not currently supported!\n");
140
        return false;
141
    }
142

  
143 137
    AUDDBG("Update song tuple.\n");
144 138

  
145 139
    FLAC__Metadata_Iterator *iter;
......
281 275

  
282 276
    chain = FLAC__metadata_chain_new();
283 277

  
278
    if (!FLAC__metadata_chain_read_with_callbacks(chain, &file, io_callbacks))
284
    auto metadata_chain_read = is_ogg_flac(file) ?
285
        FLAC__metadata_chain_read_ogg_with_callbacks :
286
        FLAC__metadata_chain_read_with_callbacks;
287

  
288
    if (!metadata_chain_read(chain, &file, io_callbacks))
289 279
        goto ERR;
290 280

  
291 281
    iter = FLAC__metadata_iterator_new();
292
-- b/src/flac/plugin.cc
282
++ a/src/flac/plugin.cc
......
26 26

  
27 27
EXPORT FLACng aud_plugin_instance;
28 28

  
29
static FLAC__StreamDecoder *decoder;
30
static callback_info *cinfo;
29
using StreamDecoderPtr = SmartPtr<FLAC__StreamDecoder, FLAC__stream_decoder_delete>;
30
static StreamDecoderPtr s_decoder, s_ogg_decoder;
31
static callback_info s_cinfo;
32 31

  
33 32
bool FLACng::init()
34 33
{
34
    FLAC__StreamDecoderInitStatus ret;
35

  
35 36
    /* Callback structure and decoder for main decoding loop */
36
    auto flac_decoder = StreamDecoderPtr(FLAC__stream_decoder_new());
37
    auto ogg_flac_decoder = StreamDecoderPtr(FLAC__stream_decoder_new());
38 37

  
38
    cinfo = new callback_info;
39

  
40
    if ((decoder = FLAC__stream_decoder_new()) == nullptr)
39
    if (!flac_decoder || !ogg_flac_decoder)
40 41
    {
42
        AUDERR("Could not create the main FLAC decoder instance!\n");
41
        AUDERR("Could not create the FLAC decoder instances!\n");
42 43
        return false;
43 44
    }
44 45

  
46
    if (FLAC__STREAM_DECODER_INIT_STATUS_OK != (ret = FLAC__stream_decoder_init_stream(
47
        decoder,
48
        read_callback,
49
        seek_callback,
50
        tell_callback,
51
        length_callback,
52
        eof_callback,
53
        write_callback,
54
        metadata_callback,
55
        error_callback,
56
        cinfo)))
45
    auto ret1 = FLAC__stream_decoder_init_stream(flac_decoder.get(),
46
        read_callback, seek_callback, tell_callback, length_callback,
47
        eof_callback, write_callback, metadata_callback, error_callback,
48
        &s_cinfo);
49

  
50
    auto ret2 = FLAC__stream_decoder_init_ogg_stream(ogg_flac_decoder.get(),
51
        read_callback, seek_callback, tell_callback, length_callback,
52
        eof_callback, write_callback, metadata_callback, error_callback,
53
        &s_cinfo);
54

  
55
    if (ret1 != FLAC__STREAM_DECODER_INIT_STATUS_OK ||
56
        ret2 != FLAC__STREAM_DECODER_INIT_STATUS_OK)
57 57
    {
58
        AUDERR("Could not initialize the main FLAC decoder: %s(%d)\n",
59
            FLAC__StreamDecoderInitStatusString[ret], ret);
58
        AUDERR("Could not initialize the FLAC decoders!\n");
59 60
        return false;
60 61
    }
61 62

  
63
    AUDDBG("Plugin initialized.\n");
62
    s_decoder = std::move(flac_decoder);
63
    s_ogg_decoder = std::move(ogg_flac_decoder);
64

  
65 64
    return true;
66 65
}
67 66

  
68 67
void FLACng::cleanup()
69 68
{
69
    FLAC__stream_decoder_delete(decoder);
70
    delete cinfo;
70
    s_decoder.clear();
71
    s_ogg_decoder.clear();
72 71
}
73 72

  
74 73
bool FLACng::is_our_file(const char *filename, VFSFile &file)
......
116 115
{
117 116
    Index<char> play_buffer;
118 117
    bool error = false;
119
    bool stream = (file.fsize() < 0);
120
    auto tuple = stream ? get_playback_tuple() : Tuple();
121
    auto decoder = is_ogg_flac(file) ? s_ogg_decoder.get() : s_decoder.get();
122 118

  
119
    cinfo->fd = &file;
123
    s_cinfo.fd = &file;
124 120

  
121
    if (read_metadata(decoder, cinfo) == false)
125
    if (read_metadata(decoder, &s_cinfo) == false)
126 122
    {
127 123
        AUDERR("Could not prepare file for playing!\n");
128 124
        error = true;
125
        goto ERR_NO_CLOSE;
129
        goto ERR;
130 126
    }
131 127

  
132 128
    play_buffer.resize(BUFFER_SIZE_BYTE);
133 129

  
130
    set_stream_bitrate(cinfo->bitrate);
131
    open_audio(SAMPLE_FMT(cinfo->bits_per_sample), cinfo->sample_rate, cinfo->channels);
134
    if (stream && tuple.fetch_stream_info(file))
135
        set_playback_tuple(tuple.ref());
136

  
137
    set_stream_bitrate(s_cinfo.bitrate);
138
    open_audio(SAMPLE_FMT(s_cinfo.bits_per_sample), s_cinfo.sample_rate, s_cinfo.channels);
139 132

  
140 133
    while (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_END_OF_STREAM)
141 134
    {
......
145 138
        int seek_value = check_seek ();
146 139
        if (seek_value >= 0)
147 140
            FLAC__stream_decoder_seek_absolute (decoder, (int64_t)
141
             seek_value * cinfo->sample_rate / 1000);
148
             seek_value * s_cinfo.sample_rate / 1000);
149 142

  
150 143
        /* Try to decode a single frame of audio */
151 144
        if (FLAC__stream_decoder_process_single(decoder) == false)
......
155 148
            break;
156 149
        }
157 150

  
151
        squeeze_audio(cinfo->output_buffer.begin(), play_buffer.begin(),
152
         cinfo->buffer_used, cinfo->bits_per_sample);
153
        write_audio(play_buffer.begin(), cinfo->buffer_used *
154
         SAMPLE_SIZE(cinfo->bits_per_sample));
158
        if (stream && tuple.fetch_stream_info(file))
159
            set_playback_tuple(tuple.ref());
160

  
161
        squeeze_audio(s_cinfo.output_buffer.begin(), play_buffer.begin(),
162
         s_cinfo.buffer_used, s_cinfo.bits_per_sample);
163
        write_audio(play_buffer.begin(), s_cinfo.buffer_used *
164
         SAMPLE_SIZE(s_cinfo.bits_per_sample));
165 155

  
156
        cinfo->reset();
166
        s_cinfo.reset();
167 157
    }
168 158

  
159
ERR_NO_CLOSE:
160
    cinfo->reset();
169
ERR:
170
    s_cinfo.reset();
171 161

  
172 162
    if (FLAC__stream_decoder_flush(decoder) == false)
173 163
        AUDERR("Could not flush decoder state!\n");
174 164

  
175
    s_cinfo = callback_info();
176 165
    return ! error;
177 166
}
178 167

  
......
183 172

  
184 173
const char *const FLACng::exts[] = { "flac", "fla", nullptr };
185 174

  
175
const char *const FLACng::mimes[] = { "audio/flac", "audio/x-flac", nullptr };
186
const char *const FLACng::mimes[] = { "audio/flac", "audio/x-flac", "audio/ogg",
187
                                      "application/ogg", nullptr };
188
-- b/src/flac/tools.cc
176
++ a/src/flac/tools.cc
......
25 25

  
26 26
#include "flacng.h"
27 27

  
28
bool is_ogg_flac(VFSFile &file)
29
{
30
    /* TODO: detect Ogg FLAC by content too (not just MIME type) */
31
    String mime = file.get_metadata("content-type");
32
    return (mime && strstr(mime, "ogg"));
33
}
34

  
35 28
bool read_metadata(FLAC__StreamDecoder *decoder, callback_info *info)
36 29
{
37 30
    FLAC__StreamDecoderState ret;