File indexing completed on 2025-06-29 07:27:58
0001 /* 0002 FLAC decoder module for K3b. 0003 Based on the Ogg Vorbis module for same. 0004 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0005 SPDX-FileCopyrightText: 2003-2004 John Steele Scott <toojays@toojays.net> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 0010 #include "k3bflacdecoder.h" 0011 #include "k3bplugin_i18n.h" 0012 #include <config-k3b.h> 0013 #include <config-flac.h> 0014 0015 #include <QBuffer> 0016 #include <QDebug> 0017 #include <QFile> 0018 #include <QStringList> 0019 0020 #include <kpluginfactory.h> 0021 #include <string.h> 0022 #include <math.h> 0023 #include <FLAC++/metadata.h> 0024 #include <FLAC++/decoder.h> 0025 0026 K_PLUGIN_CLASS_WITH_JSON(K3bFLACDecoderFactory, "k3bflacdecoder.json") 0027 0028 #ifdef ENABLE_TAGLIB 0029 #include <tag.h> 0030 #include <flacfile.h> 0031 #endif 0032 0033 #if !defined FLACPP_API_VERSION_CURRENT || FLACPP_API_VERSION_CURRENT < 6 0034 #define LEGACY_FLAC 0035 #else 0036 #undef LEGACY_FLAC 0037 #endif 0038 0039 0040 class K3bFLACDecoder::Private 0041 #ifdef LEGACY_FLAC 0042 : public FLAC::Decoder::SeekableStream 0043 #else 0044 : public FLAC::Decoder::Stream 0045 #endif 0046 { 0047 public: 0048 void open(QFile* f) { 0049 file = f; 0050 file->open(QIODevice::ReadOnly); 0051 0052 //TODO port me to kde4 0053 //internalBuffer->flush(); 0054 0055 set_metadata_respond(FLAC__METADATA_TYPE_STREAMINFO); 0056 set_metadata_respond(FLAC__METADATA_TYPE_VORBIS_COMMENT); 0057 0058 init(); 0059 process_until_end_of_metadata(); 0060 } 0061 0062 void cleanup() { 0063 file->close(); 0064 finish(); 0065 delete comments; 0066 comments = 0; 0067 } 0068 0069 Private(QFile* f) 0070 #ifdef LEGACY_FLAC 0071 : FLAC::Decoder::SeekableStream(), 0072 #else 0073 : FLAC::Decoder::Stream(), 0074 #endif 0075 comments(0) { 0076 internalBuffer = new QBuffer(); 0077 internalBuffer->open(QIODevice::ReadWrite); 0078 0079 open(f); 0080 } 0081 0082 0083 ~Private() override { 0084 cleanup(); 0085 delete internalBuffer; 0086 } 0087 0088 bool seekToFrame(int frame); 0089 0090 QFile* file; 0091 QBuffer* internalBuffer; 0092 FLAC::Metadata::VorbisComment* comments; 0093 unsigned rate; 0094 unsigned channels; 0095 unsigned bitsPerSample; 0096 unsigned maxFramesize; 0097 unsigned maxBlocksize; 0098 unsigned minFramesize; 0099 unsigned minBlocksize; 0100 FLAC__uint64 samples; 0101 0102 protected: 0103 #ifdef LEGACY_FLAC 0104 virtual FLAC__SeekableStreamDecoderReadStatus read_callback(FLAC__byte buffer[], unsigned *bytes); 0105 virtual FLAC__SeekableStreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset); 0106 virtual FLAC__SeekableStreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset); 0107 virtual FLAC__SeekableStreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length); 0108 #else 0109 FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes) override; 0110 FLAC__StreamDecoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset) override; 0111 FLAC__StreamDecoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset) override; 0112 FLAC__StreamDecoderLengthStatus length_callback(FLAC__uint64 *stream_length) override; 0113 #endif 0114 bool eof_callback() override; 0115 void error_callback(FLAC__StreamDecoderErrorStatus) override{}; 0116 void metadata_callback(const ::FLAC__StreamMetadata *metadata) override; 0117 ::FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]) override; 0118 }; 0119 0120 bool K3bFLACDecoder::Private::seekToFrame(int frame) { 0121 FLAC__uint64 sample = static_cast<FLAC__uint64>(frame) * rate / 75; 0122 return seek_absolute(sample); 0123 } 0124 0125 bool K3bFLACDecoder::Private::eof_callback() { 0126 return file->atEnd(); 0127 } 0128 0129 #ifdef LEGACY_FLAC 0130 FLAC__SeekableStreamDecoderReadStatus K3bFLACDecoder::Private::read_callback(FLAC__byte buffer[], unsigned *bytes) { 0131 long retval = file->read((char *)buffer, (*bytes)); 0132 if(-1 == retval) { 0133 return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; 0134 } else { 0135 (*bytes) = retval; 0136 return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; 0137 } 0138 } 0139 #else 0140 FLAC__StreamDecoderReadStatus K3bFLACDecoder::Private::read_callback(FLAC__byte buffer[], size_t *bytes) { 0141 long retval = file->read((char *)buffer, (*bytes)); 0142 if(-1 == retval) { 0143 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; 0144 } else { 0145 (*bytes) = retval; 0146 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; 0147 } 0148 } 0149 #endif 0150 0151 #ifdef LEGACY_FLAC 0152 FLAC__SeekableStreamDecoderSeekStatus 0153 K3bFLACDecoder::Private::seek_callback(FLAC__uint64 absolute_byte_offset) { 0154 if(!file->seek(absolute_byte_offset)) 0155 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_ERROR; 0156 else 0157 return FLAC__SEEKABLE_STREAM_DECODER_SEEK_STATUS_OK; 0158 } 0159 #else 0160 FLAC__StreamDecoderSeekStatus 0161 K3bFLACDecoder::Private::seek_callback(FLAC__uint64 absolute_byte_offset) { 0162 if(file->seek(absolute_byte_offset) == false) 0163 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; 0164 else 0165 return FLAC__STREAM_DECODER_SEEK_STATUS_OK; 0166 } 0167 #endif 0168 0169 #ifdef LEGACY_FLAC 0170 FLAC__SeekableStreamDecoderTellStatus 0171 K3bFLACDecoder::Private::tell_callback(FLAC__uint64 *absolute_byte_offset) { 0172 (*absolute_byte_offset) = file->pos(); 0173 return FLAC__SEEKABLE_STREAM_DECODER_TELL_STATUS_OK; 0174 } 0175 #else 0176 FLAC__StreamDecoderTellStatus 0177 K3bFLACDecoder::Private::tell_callback(FLAC__uint64 *absolute_byte_offset) { 0178 (*absolute_byte_offset) = file->pos(); 0179 return FLAC__STREAM_DECODER_TELL_STATUS_OK; 0180 } 0181 #endif 0182 0183 #ifdef LEGACY_FLAC 0184 FLAC__SeekableStreamDecoderLengthStatus 0185 K3bFLACDecoder::Private::length_callback(FLAC__uint64 *stream_length) { 0186 (*stream_length) = file->size(); 0187 return FLAC__SEEKABLE_STREAM_DECODER_LENGTH_STATUS_OK; 0188 } 0189 #else 0190 FLAC__StreamDecoderLengthStatus 0191 K3bFLACDecoder::Private::length_callback(FLAC__uint64 *stream_length) { 0192 (*stream_length) = file->size(); 0193 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; 0194 } 0195 #endif 0196 0197 0198 void K3bFLACDecoder::Private::metadata_callback(const FLAC__StreamMetadata *metadata) { 0199 switch (metadata->type) { 0200 case FLAC__METADATA_TYPE_STREAMINFO: 0201 channels = metadata->data.stream_info.channels; 0202 rate = metadata->data.stream_info.sample_rate; 0203 bitsPerSample = metadata->data.stream_info.bits_per_sample; 0204 samples = metadata->data.stream_info.total_samples; 0205 maxFramesize = metadata->data.stream_info.max_framesize; 0206 minFramesize = metadata->data.stream_info.min_framesize; 0207 maxBlocksize = metadata->data.stream_info.max_blocksize; 0208 minBlocksize = metadata->data.stream_info.min_blocksize; 0209 break; 0210 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 0211 comments = new FLAC::Metadata::VorbisComment((FLAC__StreamMetadata *)metadata, true); 0212 break; 0213 default: 0214 break; 0215 } 0216 } 0217 0218 FLAC__StreamDecoderWriteStatus K3bFLACDecoder::Private::write_callback(const FLAC__Frame *frame, const FLAC__int32 * const buffer[]) { 0219 unsigned i, j; 0220 // Note that in canDecode we made sure that the input is 1-16 bit stereo or mono. 0221 unsigned samples = frame->header.blocksize; 0222 0223 for(i=0; i < samples; ++i) { 0224 // in FLAC channel 0 is left, 1 is right 0225 for(j=0; j < this->channels; ++j) { 0226 FLAC__int32 value = (buffer[j][i])<<(16 - frame->header.bits_per_sample); 0227 internalBuffer->putChar(value >> 8); // msb 0228 internalBuffer->putChar(value & 0xFF); // lsb 0229 } 0230 } 0231 0232 // Rewind the buffer so the decode method will take data from the beginning. 0233 internalBuffer->seek(0); 0234 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; 0235 } 0236 0237 K3bFLACDecoder::K3bFLACDecoder( QObject* parent ) 0238 : K3b::AudioDecoder( parent) 0239 { 0240 d = 0; 0241 } 0242 0243 0244 K3bFLACDecoder::~K3bFLACDecoder() 0245 { 0246 delete d; 0247 } 0248 0249 void K3bFLACDecoder::cleanup() 0250 { 0251 if (d) { 0252 d->cleanup(); 0253 d->open(new QFile(filename())); 0254 } 0255 else 0256 d = new Private(new QFile(filename())); 0257 } 0258 0259 bool K3bFLACDecoder::analyseFileInternal( K3b::Msf& frames, int& samplerate, int& ch ) 0260 { 0261 cleanup(); 0262 0263 frames = (unsigned long)ceil((d->samples * 75.0)/d->rate); 0264 samplerate = d->rate; 0265 ch = d->channels; 0266 0267 // add meta info 0268 if( d->comments != 0 ) { 0269 qDebug() << "(K3bFLACDecoder) unpacking Vorbis tags"; 0270 for( unsigned int i = 0; i < d->comments->get_num_comments(); ++i ) { 0271 QString key = QString::fromUtf8( d->comments->get_comment(i).get_field_name(), 0272 d->comments->get_comment(i).get_field_name_length() ); 0273 QString value = QString::fromUtf8( d->comments->get_comment(i).get_field_value(), 0274 d->comments->get_comment(i).get_field_value_length() ); 0275 0276 if( key.toUpper() == "TITLE" ) 0277 addMetaInfo( META_TITLE, value ); 0278 else if( key.toUpper() == "ARTIST" ) 0279 addMetaInfo( META_ARTIST, value ); 0280 else if( key.toUpper() == "DESCRIPTION" ) 0281 addMetaInfo( META_COMMENT, value ); 0282 } 0283 } 0284 #ifdef ENABLE_TAGLIB 0285 if ((d->comments == 0) || (d->comments->get_num_comments() == 0)) { 0286 // no Vorbis comments, check for ID3 tags 0287 qDebug() << "(K3bFLACDecoder) using taglib to read tag"; 0288 TagLib::FLAC::File f( QFile::encodeName(filename()) ); 0289 if( f.isOpen() ) { 0290 addMetaInfo( META_TITLE, TStringToQString( f.tag()->title() ) ); 0291 addMetaInfo( META_ARTIST, TStringToQString( f.tag()->artist() ) ); 0292 addMetaInfo( META_COMMENT, TStringToQString( f.tag()->comment() ) ); 0293 } 0294 } 0295 #endif 0296 0297 return true; 0298 } 0299 0300 0301 bool K3bFLACDecoder::initDecoderInternal() 0302 { 0303 cleanup(); 0304 0305 return true; 0306 } 0307 0308 0309 int K3bFLACDecoder::decodeInternal( char* _data, int maxLen ) 0310 { 0311 int bytesToCopy; 0312 int bytesCopied; 0313 int bytesAvailable; 0314 0315 #ifdef LEGACY_FLAC 0316 if(d->internalBuffer->size() == 0) { 0317 // want more data 0318 switch(d->get_state()) { 0319 case FLAC__SEEKABLE_STREAM_DECODER_END_OF_STREAM: 0320 d->finish(); 0321 break; 0322 case FLAC__SEEKABLE_STREAM_DECODER_OK: 0323 if(! d->process_single()) 0324 return -1; 0325 break; 0326 default: 0327 return -1; 0328 } 0329 } 0330 #else 0331 if(d->internalBuffer->size() == 0) { 0332 // want more data 0333 if(d->get_state() == FLAC__STREAM_DECODER_END_OF_STREAM) 0334 d->finish(); 0335 else if(d->get_state() < FLAC__STREAM_DECODER_END_OF_STREAM) { 0336 if(! d->process_single()) 0337 return -1; 0338 } 0339 else 0340 return -1; 0341 } 0342 #endif 0343 0344 bytesAvailable = d->internalBuffer->size() - d->internalBuffer->pos(); 0345 bytesToCopy = qMin(maxLen, bytesAvailable); 0346 bytesCopied = (int)d->internalBuffer->read(_data, bytesToCopy); 0347 0348 if(bytesCopied == bytesAvailable) { 0349 // reset the buffer 0350 d->internalBuffer->close(); 0351 d->internalBuffer->open(QIODevice::ReadWrite|QIODevice::Truncate); 0352 } 0353 0354 return bytesCopied; 0355 } 0356 0357 0358 bool K3bFLACDecoder::seekInternal( const K3b::Msf& pos ) 0359 { 0360 return d->seekToFrame(pos.totalFrames()); 0361 } 0362 0363 0364 QString K3bFLACDecoder::fileType() const 0365 { 0366 return i18n("FLAC"); 0367 } 0368 0369 0370 QStringList K3bFLACDecoder::supportedTechnicalInfos() const 0371 { 0372 return QString( i18n("Channels") + ';' + 0373 i18n("Sampling Rate") + ';' + 0374 i18n("Sample Size") ).split( ';' ); 0375 } 0376 0377 0378 QString K3bFLACDecoder::technicalInfo( const QString& info ) const 0379 { 0380 if( d->comments != 0 ) { 0381 if( info == i18n("Vendor") ) 0382 #ifdef FLAC_NEWER_THAN_1_1_1 0383 return QString::fromUtf8((char*)d->comments->get_vendor_string()); 0384 #else 0385 return QString::fromUtf8(d->comments->get_vendor_string().get_field()); 0386 #endif 0387 else if( info == i18n("Channels") ) 0388 return QString::number(d->channels); 0389 else if( info == i18n("Sampling Rate") ) 0390 return i18n("%1 Hz",d->rate); 0391 else if( info == i18n("Sample Size") ) 0392 return i18np("1 bit","%1 bits",d->bitsPerSample); 0393 } 0394 0395 return QString(); 0396 } 0397 0398 0399 0400 K3bFLACDecoderFactory::K3bFLACDecoderFactory( QObject* parent, const QVariantList& ) 0401 : K3b::AudioDecoderFactory( parent ) 0402 { 0403 } 0404 0405 0406 K3bFLACDecoderFactory::~K3bFLACDecoderFactory() 0407 { 0408 } 0409 0410 0411 K3b::AudioDecoder* K3bFLACDecoderFactory::createDecoder( QObject* parent) const 0412 { 0413 return new K3bFLACDecoder( parent ); 0414 } 0415 0416 0417 bool K3bFLACDecoderFactory::canDecode( const QUrl& url ) 0418 { 0419 // buffer large enough to read an ID3 tag header 0420 char buf[10]; 0421 0422 // Note: since file is created on the stack it will be closed automatically 0423 // by its destructor when this method (i.e. canDecode) returns. 0424 QFile file(url.toLocalFile()); 0425 0426 if(!file.open(QIODevice::ReadOnly)) { 0427 qDebug() << "(K3bFLACDecoder) Could not open file " << url.toLocalFile(); 0428 return false; 0429 } 0430 0431 // look for a fLaC magic number or ID3 tag header 0432 if(10 != file.read(buf, 10)) { 0433 qDebug() << "(K3bFLACDecorder) File " << url.toLocalFile() 0434 << " is too small to be a FLAC file" << Qt::endl; 0435 return false; 0436 } 0437 0438 if(0 == memcmp(buf, "ID3", 3)) { 0439 // Found ID3 tag, try and seek past it. 0440 qDebug() << "(K3bFLACDecorder) File " << url.toLocalFile() << ": found ID3 tag"; 0441 0442 // See www.id3.org for details of the header, note that the size field 0443 // unpacks to 7-bit bytes, then the +10 is for the header itself. 0444 int pos; 0445 pos = ((buf[6]<<21)|(buf[7]<<14)|(buf[8]<<7)|buf[9]) + 10; 0446 0447 qDebug() << "(K3bFLACDecoder) " << url.toLocalFile() << ": seeking to " 0448 << pos << Qt::endl; 0449 if(!file.seek(pos)) { 0450 qDebug() << "(K3bFLACDecoder) " << url.toLocalFile() << ": couldn't seek to " 0451 << pos << Qt::endl; 0452 return false; 0453 }else{ 0454 // seek was okay, try and read magic number into buf 0455 if(4 != file.read(buf, 4)) { 0456 qDebug() << "(K3bFLACDecorder) File " << url.toLocalFile() 0457 << " has ID3 tag but naught else!" << Qt::endl; 0458 return false; 0459 } 0460 } 0461 } 0462 0463 if(memcmp(buf, "fLaC", 4) != 0) { 0464 qDebug() << "(K3bFLACDecoder) " << url.toLocalFile() << ": not a FLAC file"; 0465 return false; 0466 } 0467 0468 FLAC::Metadata::StreamInfo info = FLAC::Metadata::StreamInfo(); 0469 if (!FLAC::Metadata::get_streaminfo(url.toLocalFile().toLocal8Bit(), info)) { 0470 qDebug() << "(K3bFLACDecoder) " << url.toLocalFile() << ": get_streaminfo failed"; 0471 return false; 0472 } 0473 0474 if((info.get_channels() <= 2) && 0475 (info.get_bits_per_sample() <= 16)) { 0476 return true; 0477 } else { 0478 qDebug() << "(K3bFLACDecoder) " << url.toLocalFile() << ": wrong format:" << Qt::endl 0479 << " channels: " 0480 << QString::number(info.get_channels()) << Qt::endl 0481 << " samplerate: " 0482 << QString::number(info.get_sample_rate()) << Qt::endl 0483 << " bits/sample: " 0484 << QString::number(info.get_bits_per_sample()) << Qt::endl; 0485 return false; 0486 } 0487 } 0488 0489 #include "k3bflacdecoder.moc" 0490 0491 #include "moc_k3bflacdecoder.cpp"