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()