24 #include <id3/globals.h> 25 #include <id3/misc_support.h> 30 #include <QLatin1Char> 58 m_parent_widget(Q_NULLPTR)
84 qDebug(
"crc = 0x%08X", header.crc);
85 if ((header.crc == MP3CRC_MISMATCH) || (header.crc == MP3CRC_ERROR_SIZE)) {
87 if (header.layer == MPEGLAYER_II) {
88 qWarning(
"WARNING: file is MPEG layer II, CRC calculation " 89 "in id3lib is probably wrong - CRC check skipped");
92 i18n(
"The file has an invalid checksum.\n" 93 "Do you still want to continue?"),
94 QString(), QString(), QString(),
95 _(
"accept_mp3_invalid_checksum"))
96 != KMessageBox::Continue)
return false;
101 switch (header.layer) {
118 qWarning(
"unknown mpeg layer '%d'", header.layer);
122 switch (header.version) {
129 case MPEGVERSION_2_5:
133 qWarning(
"unknown mpeg version '%d'", header.version);
138 QVariant(header.bitrate));
143 unsigned int tracks = 0;
144 switch (header.channelmode) {
145 case MP3CHANNELMODE_SINGLE_CHANNEL:
148 case MP3CHANNELMODE_STEREO:
151 case MP3CHANNELMODE_JOINT_STEREO:
154 case MP3CHANNELMODE_DUAL_CHANNEL:
159 mode = mode.setNum(header.channelmode, 16);
161 i18n(
"The file contains an invalid channel mode 0x" 162 "%1\nAssuming Mono...", mode))
163 != KMessageBox::Continue)
return false;
177 if (header.channelmode == MP3CHANNELMODE_JOINT_STEREO) {
178 int modeext = header.modeext;
179 if (header.layer >= 3) modeext += 4;
182 int modeext = header.modeext;
191 if (header.emphasis > 0)
201 info.
setRate(header.frequency);
203 info.
setLength(header.time * header.frequency);
213 if (tag.NumFrames() < 1)
return true;
221 ID3_Tag::Iterator *it = tag.CreateIterator();
222 ID3_Frame *frame = Q_NULLPTR;
224 while (it && (frame = it->GetNext())) {
225 const ID3_FrameID
id = frame->GetID();
234 if (s.contains(QLatin1Char(
'/'))) {
235 int i = s.indexOf(QLatin1Char(
'/'));
236 cd = s.left(i).toInt();
237 cds = s.mid(i + 1).toInt();
250 if (s.contains(QLatin1Char(
'/'))) {
251 int i = s.indexOf(QLatin1Char(
'/'));
252 track = s.left(i).toInt();
253 tracks = s.mid(i + 1).toInt();
269 char *lang = ID3_GetString(frame, ID3FN_LANGUAGE);
271 s =
_(
"[") +
_(lang) +
_(
"] ") + s;
272 ID3_FreeString(lang);
277 s = info.
get(property).toString() +
_(
" / ") + s;
278 info.
set(property, QVariant(s));
287 info.
set(property, QVariant(s));
294 const double rate = info.
rate();
296 const double ms = s.toDouble(&ok) + 0.5;
297 if (ok && (rate > 0)) {
300 (rate * ms) / 1000.0);
307 if (!creation_date.isValid()) {
311 case ID3FID_RECORDINGDATES:
316 QDate::fromString(s, Qt::ISODate);
320 unsigned int ddmm = s.toUInt();
326 case ID3FID_ORIGYEAR:
335 if (creation_time.isValid()) {
339 creation_time = QTime::fromString(
_(
"hhmm"));
352 s = info.
get(property).toString() +
_(
" / ") + s;
353 info.
set(property, QVariant(s));
364 qWarning(
"unsupported ID3 tag: %d, descr: '%s', text: '%s'",
365 id, frame->GetDescription(),
DBG(s));
374 if (!creation_date.isValid()) {
376 creation_date = QDate(year, month, day);
378 if (creation_date.isValid() && creation_time.isValid()) {
380 QDateTime dt(creation_date, creation_time);
382 _(
"yyyy-MM-ddTHH:mm:ss")));
383 }
else if (creation_date.isValid()) {
387 }
else if (year > 0) {
389 creation_date = QDate(year, 1, 1);
402 char *text = ID3_GetString(frame, ID3FN_TEXT);
403 if (text && strlen(text)) {
405 ID3_FreeString(text);
413 qDebug(
"MP3Decoder::open()");
416 if (
m_source) qWarning(
"MP3Decoder::open(), already open !");
419 if (src.isSequential())
return false;
420 if (!src.open(QIODevice::ReadOnly)) {
421 qWarning(
"unable to open source in read-only mode!");
428 tag.Link(adapter, static_cast<flags_t>(ID3TT_ALL));
432 if (tag.GetSpec() != ID3V2_UNKNOWN) {
435 qDebug(
"HasLyrics = %d", tag.HasLyrics());
436 qDebug(
"HasV1Tag = %d", tag.HasV1Tag());
437 qDebug(
"HasV2Tag = %d", tag.HasV2Tag());
443 const Mp3_Headerinfo *mp3hdr = tag.GetMp3HeaderInfo();
446 i18n(
"The opened file is no MPEG file or it is damaged.\n" 447 "No header information has been found."));
478 return (decoder) ? decoder->
fillInput(stream) : MAD_FLOW_STOP;
483 struct mad_header
const *header,
494 struct mad_frame *frame)
499 decoder->
handleError(data, stream, frame) : MAD_FLOW_BREAK;
504 struct mad_stream *stream,
struct mad_frame *)
506 if (
m_failures >= 2)
return MAD_FLOW_CONTINUE;
507 if (stream->error == MAD_ERROR_NONE)
return MAD_FLOW_CONTINUE;
510 switch (stream->error) {
511 case MAD_ERROR_BUFLEN:
512 case MAD_ERROR_BUFPTR:
513 case MAD_ERROR_NOMEM:
514 error = i18n(
"Out of memory");
516 case MAD_ERROR_BADCRC:
517 error = i18n(
"Checksum error");
519 case MAD_ERROR_LOSTSYNC:
520 error = i18n(
"Synchronization lost");
522 case MAD_ERROR_BADLAYER:
523 case MAD_ERROR_BADBITRATE:
524 case MAD_ERROR_BADSAMPLERATE:
525 case MAD_ERROR_BADEMPHASIS:
526 case MAD_ERROR_BADBITALLOC:
527 case MAD_ERROR_BADSCALEFACTOR:
528 case MAD_ERROR_BADFRAMELEN:
529 case MAD_ERROR_BADBIGVALUES:
530 case MAD_ERROR_BADBLOCKTYPE:
531 case MAD_ERROR_BADSCFSI:
532 case MAD_ERROR_BADDATAPTR:
533 case MAD_ERROR_BADPART3LEN:
534 case MAD_ERROR_BADHUFFTABLE:
535 case MAD_ERROR_BADHUFFDATA:
536 case MAD_ERROR_BADSTEREO:
537 error = i18n(
"File contains invalid data");
540 QString err_hex = QString::number(
541 static_cast<int>(stream->error), 16).toUpper();
542 error = i18n(
"Unknown error 0x%1. Damaged file?", err_hex);
545 long unsigned int pos = stream->this_frame -
m_buffer;
547 error = i18n(
"An error occurred while decoding the file:\n'%1',\n" 548 "at position %2.", error, pos);
552 error +
_(
"\n") + i18n(
"Do you still want to continue?"));
553 if (result != KMessageBox::Continue)
return MAD_FLOW_BREAK;
557 i18n(
"Do you want to continue and ignore all following errors?"));
559 if (result != KMessageBox::Yes)
return MAD_FLOW_BREAK;
562 return MAD_FLOW_CONTINUE;
569 if (!
m_source)
return MAD_FLOW_STOP;
575 size_t rest = stream->bufend - stream->next_frame;
576 if (rest) memmove(
m_buffer, stream->next_frame, rest);
586 if (!bytes_to_read)
return MAD_FLOW_STOP;
590 if (bytes_to_read) size +=
m_source->read(
591 reinterpret_cast<char *>(
m_buffer) + rest, bytes_to_read);
592 if (!size)
return MAD_FLOW_STOP;
595 mad_stream_buffer(stream,
m_buffer, size);
597 return MAD_FLOW_CONTINUE;
606 mad_fixed_t error[3];
616 static inline quint32
prng(quint32 state)
618 return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
629 unsigned int scalebits;
630 mad_fixed_t output, mask, random;
644 output = sample + mad_fixed_t(1L << (MAD_F_FRACBITS + 1 - bits - 1));
646 scalebits = MAD_F_FRACBITS + 1 - bits;
647 mask = mad_fixed_t(1L << scalebits) - 1;
650 random =
static_cast<mad_fixed_t
>(
prng(dither->
random));
651 output += (random & mask) - (dither->
random & mask);
658 if (sample > MAX) sample = MAX;
659 }
else if (output < MIN) {
661 if (sample < MIN) sample = MIN;
668 dither->
error[0] = sample - output;
671 return output >> scalebits;
676 struct mad_header
const *,
struct mad_pcm *pcm)
684 for (
unsigned int track = 0; track < tracks; ++track) {
685 unsigned int nsamples = pcm->length;
686 mad_fixed_t
const *p = pcm->samples[track];
687 unsigned int ofs = 0;
692 static_cast<mad_fixed_t>(*p++), &dither));
693 buffer[ofs++] =
static_cast<sample_t>(sample);
695 *(*m_dest)[track] << buffer;
698 return MAD_FLOW_CONTINUE;
714 struct mad_decoder decoder;
715 mad_decoder_init(&decoder,
this,
724 int result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
727 mad_decoder_finish(&decoder);
729 return (result == 0);
bool contains(const FileProperty property) const
ID3_PropertyMap m_property_map
virtual unsigned int tracks() const Q_DECL_OVERRIDE
QString parseId3Frame2String(const ID3_Frame *frame)
virtual bool open(QWidget *widget, QIODevice &source)
static QString name(int id, bool localized)
static qint32 audio_linear_dither(unsigned int bits, mad_fixed_t sample, Kwave::audio_dither *dither)
static quint32 prng(quint32 state)
static enum mad_flow _error_adapter(void *data, struct mad_stream *stream, struct mad_frame *frame)
QVariant get(FileProperty key) const
static int sorry(QWidget *widget, QString message, QString caption=QString())
static enum mad_flow _output_adapter(void *data, struct mad_header const *header, struct mad_pcm *pcm)
void set(FileProperty key, const QVariant &value)
void setRate(double rate)
QString Q_DECL_EXPORT string2date(const QString &s)
enum mad_flow handleError(void *data, struct mad_stream *stream, struct mad_frame *frame)
void setLength(sample_index_t length)
virtual bool decode(QWidget *widget, Kwave::MultiWriter &dst)
void setTracks(unsigned int tracks)
virtual Kwave::MetaDataList & metaData()
#define REGISTER_MIME_TYPES
static int warningYesNo(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
enum mad_flow processOutput(void *data, struct mad_header const *header, struct mad_pcm *pcm)
Kwave::MultiWriter * m_dest
static int warningContinueCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonContinue=QString(), const QString buttonCancel=QString(), const QString &dontAskAgainName=QString())
void setBits(unsigned int bits)
QWidget * m_parent_widget
static enum mad_flow _input_adapter(void *data, struct mad_stream *stream)
#define REGISTER_COMPRESSION_TYPES
bool parseID3Tags(ID3_Tag &tag)
Encoding encoding(const ID3_FrameID id) const
bool parseMp3Header(const Mp3_Headerinfo &header, QWidget *widget)
Kwave::FileProperty property(const ID3_FrameID id) const
static int fromID3(const QString &tag)
enum mad_flow fillInput(struct mad_stream *stream)
virtual Kwave::Decoder * instance()