void AnalyzeTask::run_ex(void) { int fileType = fileTypeNormal; QString currentFile = QDir::fromNativeSeparators(m_inputFile); qDebug("Analyzing: %s", MUTILS_UTF8(currentFile)); AudioFileModel file = analyzeFile(currentFile, &fileType); if(*m_abortFlag) { qWarning("Operation cancelled by user!"); return; } switch(fileType) { case fileTypeDenied: qWarning("Cannot access file for reading, skipping!"); break; case fileTypeCDDA: qWarning("Dummy CDDA file detected, skipping!"); break; default: if(file.metaInfo().title().isEmpty() || file.techInfo().containerType().isEmpty() || file.techInfo().audioType().isEmpty()) { fileType = fileTypeUnknown; if(!QFileInfo(currentFile).suffix().compare("cue", Qt::CaseInsensitive)) { qWarning("Cue Sheet file detected, skipping!"); fileType = fileTypeCueSheet; } else if(!QFileInfo(currentFile).suffix().compare("avs", Qt::CaseInsensitive)) { qDebug("Found a potential Avisynth script, investigating..."); if(analyzeAvisynthFile(currentFile, file)) { fileType = fileTypeNormal; } else { qDebug("Rejected Avisynth file: %s", MUTILS_UTF8(file.filePath())); } } else { qDebug("Rejected file of unknown type: %s", MUTILS_UTF8(file.filePath())); } } break; } //Emit the file now! emit fileAnalyzed(m_taskId, fileType, file); }
void AnalyzeTask::parseProperty(const QString &value, const MI_propertyId_t propertyIdx, AudioFileModel &audioFile, QString &coverMimeType) { #if MUTILS_DEBUG qDebug("Property #%d = \"%s\"", propertyIdx, MUTILS_UTF8(value.left(24))); #endif switch (propertyIdx) { case propertyId_container: audioFile.techInfo().setContainerType(value); return; case propertyId_container_profile: audioFile.techInfo().setContainerProfile(value); return; case propertyId_duration: SET_OPTIONAL(double, parseFloat(value, _tmp), audioFile.techInfo().setDuration(qRound(_tmp))); return; case propertyId_title: audioFile.metaInfo().setTitle(value); return; case propertyId_artist: audioFile.metaInfo().setArtist(value); return; case propertyId_album: audioFile.metaInfo().setAlbum(value); return; case propertyId_genre: audioFile.metaInfo().setGenre(value); return; case propertyId_released_date: SET_OPTIONAL(quint32, parseYear(value, _tmp), audioFile.metaInfo().setYear(_tmp)); return; case propertyId_track_position: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.metaInfo().setPosition(_tmp)); return; case propertyId_comment: audioFile.metaInfo().setComment(value); return; case propertyId_format: audioFile.techInfo().setAudioType(value); return; case propertyId_format_version: audioFile.techInfo().setAudioVersion(value); return; case propertyId_format_profile: audioFile.techInfo().setAudioProfile(value); return; case propertyId_channel_s_: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioChannels(_tmp)); return; case propertyId_samplingrate: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioSamplerate(_tmp)); return; case propertyId_bitdepth: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioBitdepth(_tmp)); return; case propertyId_bitrate: SET_OPTIONAL(quint32, parseUnsigned(value, _tmp), audioFile.techInfo().setAudioBitrate(DIV_RND(_tmp, 1000U))); return; case propertyId_bitrate_mode: SET_OPTIONAL(quint32, parseRCMode(value, _tmp), audioFile.techInfo().setAudioBitrateMode(_tmp)); return; case propertyId_encoded_library: audioFile.techInfo().setAudioEncodeLib(cleanAsciiStr(value)); return; case propertyId_cover_mime: coverMimeType = value; return; case propertyId_cover_data: retrieveCover(audioFile, coverMimeType, value); return; default: MUTILS_THROW_FMT("Invalid property ID: %d", propertyIdx); } }
bool AnalyzeTask::analyzeAvisynthFile(const QString &filePath, AudioFileModel &info) { QProcess process; MUtils::init_process(process, QFileInfo(m_avs2wavBin).absolutePath()); process.start(m_avs2wavBin, QStringList() << QDir::toNativeSeparators(filePath) << "?"); if(!process.waitForStarted()) { qWarning("AVS2WAV process failed to create!"); qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData()); process.kill(); process.waitForFinished(-1); return false; } bool bInfoHeaderFound = false; while(process.state() != QProcess::NotRunning) { if(MUTILS_BOOLIFY(m_abortFlag)) { process.kill(); qWarning("Process was aborted on user request!"); break; } if(!process.waitForReadyRead()) { if(process.state() == QProcess::Running) { qWarning("AVS2WAV time out. Killing process and skipping file!"); process.kill(); process.waitForFinished(-1); return false; } } while(process.canReadLine()) { const QString line = QString::fromUtf8(process.readLine().constData()).simplified(); if(!line.isEmpty()) { if(bInfoHeaderFound) { const qint32 index = line.indexOf(':'); if (index > 0) { const QString key = line.left(index).trimmed(); const QString val = line.mid(index + 1).trimmed(); if (!(key.isEmpty() || val.isEmpty())) { switch (m_avisynthIdx.value(key.toLower(), MI_propertyId_t(-1))) { case propertyId_duration: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setDuration(_tmp)); break; case propertyId_samplingrate: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setAudioSamplerate(_tmp)); break; case propertyId_channel_s_: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setAudioChannels(_tmp)); break; case propertyId_bitdepth: SET_OPTIONAL(quint32, parseUnsigned(val, _tmp), info.techInfo().setAudioBitdepth(_tmp)); break; } } } } else { if(line.contains("[Audio Info]", Qt::CaseInsensitive)) { info.techInfo().setAudioType("Avisynth"); info.techInfo().setContainerType("Avisynth"); bInfoHeaderFound = true; } } } } } process.waitForFinished(); if(process.state() != QProcess::NotRunning) { process.kill(); process.waitForFinished(-1); } //Check exit code switch(process.exitCode()) { case 0: qDebug("Avisynth script was analyzed successfully."); return true; break; case -5: qWarning("It appears that Avisynth is not installed on the system!"); return false; break; default: qWarning("Failed to open the Avisynth script, bad AVS file?"); return false; break; } }
bool AnalyzeTask::analyzeAvisynthFile(const QString &filePath, AudioFileModel &info) { QProcess process; MUtils::init_process(process, QFileInfo(m_avs2wavBin).absolutePath()); process.start(m_avs2wavBin, QStringList() << QDir::toNativeSeparators(filePath) << "?"); if(!process.waitForStarted()) { qWarning("AVS2WAV process failed to create!"); qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData()); process.kill(); process.waitForFinished(-1); return false; } bool bInfoHeaderFound = false; while(process.state() != QProcess::NotRunning) { if(*m_abortFlag) { process.kill(); qWarning("Process was aborted on user request!"); break; } if(!process.waitForReadyRead()) { if(process.state() == QProcess::Running) { qWarning("AVS2WAV time out. Killing process and skipping file!"); process.kill(); process.waitForFinished(-1); return false; } } QByteArray data; while(process.canReadLine()) { QString line = QString::fromUtf8(process.readLine().constData()).simplified(); if(!line.isEmpty()) { int index = line.indexOf(':'); if(index > 0) { QString key = line.left(index).trimmed(); QString val = line.mid(index+1).trimmed(); if(bInfoHeaderFound && !key.isEmpty() && !val.isEmpty()) { if(key.compare("TotalSeconds", Qt::CaseInsensitive) == 0) { bool ok = false; unsigned int duration = val.toUInt(&ok); if(ok) info.techInfo().setDuration(duration); } if(key.compare("SamplesPerSec", Qt::CaseInsensitive) == 0) { bool ok = false; unsigned int samplerate = val.toUInt(&ok); if(ok) info.techInfo().setAudioSamplerate (samplerate); } if(key.compare("Channels", Qt::CaseInsensitive) == 0) { bool ok = false; unsigned int channels = val.toUInt(&ok); if(ok) info.techInfo().setAudioChannels(channels); } if(key.compare("BitsPerSample", Qt::CaseInsensitive) == 0) { bool ok = false; unsigned int bitdepth = val.toUInt(&ok); if(ok) info.techInfo().setAudioBitdepth(bitdepth); } } } else { if(line.contains("[Audio Info]", Qt::CaseInsensitive)) { info.techInfo().setAudioType("Avisynth"); info.techInfo().setContainerType("Avisynth"); bInfoHeaderFound = true; } } } } } process.waitForFinished(); if(process.state() != QProcess::NotRunning) { process.kill(); process.waitForFinished(-1); } //Check exit code switch(process.exitCode()) { case 0: qDebug("Avisynth script was analyzed successfully."); return true; break; case -5: qWarning("It appears that Avisynth is not installed on the system!"); return false; break; default: qWarning("Failed to open the Avisynth script, bad AVS file?"); return false; break; } }
void AnalyzeTask::updateInfo(AudioFileModel &audioFile, bool &skipNext, QPair<quint32, quint32> &id_val, quint32 &coverType, QByteArray &coverData, const QString &key, const QString &value) { //qWarning("'%s' -> '%s'", MUTILS_UTF8(key), MUTILS_UTF8(value)); /*New Stream*/ if(IS_KEY("Gen_ID") || IS_KEY("Aud_ID")) { if(value.isEmpty()) { skipNext = false; } else { //We ignore all ID's, except for the lowest one! bool ok = false; unsigned int id = value.toUInt(&ok); if(ok) { if(IS_KEY("Gen_ID")) { id_val.first = qMin(id_val.first, id); skipNext = (id > id_val.first); } if(IS_KEY("Aud_ID")) { id_val.second = qMin(id_val.second, id); skipNext = (id > id_val.second); } } else { skipNext = true; } } if(skipNext) { qWarning("Skipping info for non-primary stream!"); } return; } /*Skip or empty?*/ if((skipNext) || value.isEmpty()) { return; } /*Playlist file?*/ if(IS_KEY("Aud_Source")) { skipNext = true; audioFile.techInfo().setContainerType(QString()); audioFile.techInfo().setAudioType(QString()); qWarning("Skipping info for playlist file!"); return; } /*General Section*/ if(IS_SEC("Gen")) { if(IS_KEY("Gen_Format")) { audioFile.techInfo().setContainerType(value); } else if(IS_KEY("Gen_Format_Profile")) { audioFile.techInfo().setContainerProfile(value); } else if(IS_KEY("Gen_Title") || IS_KEY("Gen_Track")) { audioFile.metaInfo().setTitle(value); } else if(IS_KEY("Gen_Duration")) { unsigned int tmp = parseDuration(value); if(tmp > 0) audioFile.techInfo().setDuration(tmp); } else if(IS_KEY("Gen_Artist") || IS_KEY("Gen_Performer")) { audioFile.metaInfo().setArtist(value); } else if(IS_KEY("Gen_Album")) { audioFile.metaInfo().setAlbum(value); } else if(IS_KEY("Gen_Genre")) { audioFile.metaInfo().setGenre(value); } else if(IS_KEY("Gen_Released_Date") || IS_KEY("Gen_Recorded_Date")) { unsigned int tmp = parseYear(value); if(tmp > 0) audioFile.metaInfo().setYear(tmp); } else if(IS_KEY("Gen_Comment")) { audioFile.metaInfo().setComment(value); } else if(IS_KEY("Gen_Track/Position")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.metaInfo().setPosition(tmp); } else if(IS_KEY("Gen_Cover") || IS_KEY("Gen_Cover_Type")) { if(coverType == UINT_MAX) { coverType = 0; } } else if(IS_KEY("Gen_Cover_Mime")) { QString temp = FIRST_TOK(value); for (quint32 i = 0; MIME_TYPES[i].type; i++) { if (temp.compare(QString::fromLatin1(MIME_TYPES[i].type), Qt::CaseInsensitive) == 0) { coverType = i; break; } } } else if(IS_KEY("Gen_Cover_Data")) { if(!coverData.isEmpty()) coverData.clear(); coverData.append(QByteArray::fromBase64(FIRST_TOK(value).toLatin1())); } else { qWarning("Unknown key '%s' with value '%s' found!", MUTILS_UTF8(key), MUTILS_UTF8(value)); } return; } /*Audio Section*/ if(IS_SEC("Aud")) { if(IS_KEY("Aud_Format")) { audioFile.techInfo().setAudioType(value); } else if(IS_KEY("Aud_Format_Profile")) { audioFile.techInfo().setAudioProfile(value); } else if(IS_KEY("Aud_Format_Version")) { audioFile.techInfo().setAudioVersion(value); } else if(IS_KEY("Aud_Channel(s)")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioChannels(tmp); } else if(IS_KEY("Aud_SamplingRate")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioSamplerate(tmp); } else if(IS_KEY("Aud_BitDepth")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioBitdepth(tmp); } else if(IS_KEY("Aud_Duration")) { unsigned int tmp = parseDuration(value); if(tmp > 0) audioFile.techInfo().setDuration(tmp); } else if(IS_KEY("Aud_BitRate")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioBitrate(tmp/1000); } else if(IS_KEY("Aud_BitRate_Mode")) { if(!value.compare("CBR", Qt::CaseInsensitive)) audioFile.techInfo().setAudioBitrateMode(AudioFileModel::BitrateModeConstant); if(!value.compare("VBR", Qt::CaseInsensitive)) audioFile.techInfo().setAudioBitrateMode(AudioFileModel::BitrateModeVariable); } else if(IS_KEY("Aud_Encoded_Library")) { audioFile.techInfo().setAudioEncodeLib(value); } else { qWarning("Unknown key '%s' with value '%s' found!", MUTILS_UTF8(key), MUTILS_UTF8(value)); } return; } /*Section not recognized*/ qWarning("Unknown section: %s", MUTILS_UTF8(key)); }
void AnalyzeTask::updateInfo(AudioFileModel &audioFile, bool *skipNext, unsigned int *id_val, cover_t *coverType, QByteArray *coverData, const QString &key, const QString &value) { //qWarning("'%s' -> '%s'", QUTF8(key), QUTF8(value)); /*New Stream*/ if(IS_KEY("Gen_ID") || IS_KEY("Aud_ID")) { if(value.isEmpty()) { *skipNext = false; } else { //We ignore all ID's, except for the lowest one! bool ok = false; unsigned int id = value.toUInt(&ok); if(ok) { if(IS_KEY("Gen_ID")) { id_val[0] = qMin(id_val[0], id); *skipNext = (id > id_val[0]); } if(IS_KEY("Aud_ID")) { id_val[1] = qMin(id_val[1], id); *skipNext = (id > id_val[1]); } } else { *skipNext = true; } } if(*skipNext) { qWarning("Skipping info for non-primary stream!"); } return; } /*Skip or empty?*/ if((*skipNext) || value.isEmpty()) { return; } /*Playlist file?*/ if(IS_KEY("Aud_Source")) { *skipNext = true; audioFile.techInfo().setContainerType(QString()); audioFile.techInfo().setAudioType(QString()); qWarning("Skipping info for playlist file!"); return; } /*General Section*/ if(IS_SEC("Gen")) { if(IS_KEY("Gen_Format")) { audioFile.techInfo().setContainerType(value); } else if(IS_KEY("Gen_Format_Profile")) { audioFile.techInfo().setContainerProfile(value); } else if(IS_KEY("Gen_Title") || IS_KEY("Gen_Track")) { audioFile.metaInfo().setTitle(value); } else if(IS_KEY("Gen_Duration")) { unsigned int tmp = parseDuration(value); if(tmp > 0) audioFile.techInfo().setDuration(tmp); } else if(IS_KEY("Gen_Artist") || IS_KEY("Gen_Performer")) { audioFile.metaInfo().setArtist(value); } else if(IS_KEY("Gen_Album")) { audioFile.metaInfo().setAlbum(value); } else if(IS_KEY("Gen_Genre")) { audioFile.metaInfo().setGenre(value); } else if(IS_KEY("Gen_Released_Date") || IS_KEY("Gen_Recorded_Date")) { unsigned int tmp = parseYear(value); if(tmp > 0) audioFile.metaInfo().setYear(tmp); } else if(IS_KEY("Gen_Comment")) { audioFile.metaInfo().setComment(value); } else if(IS_KEY("Gen_Track/Position")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.metaInfo().setPosition(tmp); } else if(IS_KEY("Gen_Cover") || IS_KEY("Gen_Cover_Type")) { if(*coverType == coverNone) { *coverType = coverJpeg; } } else if(IS_KEY("Gen_Cover_Mime")) { QString temp = FIRST_TOK(value); if(!temp.compare("image/jpeg", Qt::CaseInsensitive)) *coverType = coverJpeg; else if(!temp.compare("image/png", Qt::CaseInsensitive)) *coverType = coverPng; else if(!temp.compare("image/gif", Qt::CaseInsensitive)) *coverType = coverGif; } else if(IS_KEY("Gen_Cover_Data")) { if(!coverData->isEmpty()) coverData->clear(); coverData->append(QByteArray::fromBase64(FIRST_TOK(value).toLatin1())); } else { qWarning("Unknown key '%s' with value '%s' found!", QUTF8(key), QUTF8(value)); } return; } /*Audio Section*/ if(IS_SEC("Aud")) { if(IS_KEY("Aud_Format")) { audioFile.techInfo().setAudioType(value); } else if(IS_KEY("Aud_Format_Profile")) { audioFile.techInfo().setAudioProfile(value); } else if(IS_KEY("Aud_Format_Version")) { audioFile.techInfo().setAudioVersion(value); } else if(IS_KEY("Aud_Channel(s)")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioChannels(tmp); } else if(IS_KEY("Aud_SamplingRate")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioSamplerate(tmp); } else if(IS_KEY("Aud_BitDepth")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioBitdepth(tmp); } else if(IS_KEY("Aud_Duration")) { unsigned int tmp = parseDuration(value); if(tmp > 0) audioFile.techInfo().setDuration(tmp); } else if(IS_KEY("Aud_BitRate")) { bool ok = false; unsigned int tmp = value.toUInt(&ok); if(ok) audioFile.techInfo().setAudioBitrate(tmp/1000); } else if(IS_KEY("Aud_BitRate_Mode")) { if(!value.compare("CBR", Qt::CaseInsensitive)) audioFile.techInfo().setAudioBitrateMode(AudioFileModel::BitrateModeConstant); if(!value.compare("VBR", Qt::CaseInsensitive)) audioFile.techInfo().setAudioBitrateMode(AudioFileModel::BitrateModeVariable); } else if(IS_KEY("Aud_Encoded_Library")) { audioFile.techInfo().setAudioEncodeLib(value); } else { qWarning("Unknown key '%s' with value '%s' found!", QUTF8(key), QUTF8(value)); } return; } /*Section not recognized*/ qWarning("Unknown section: %s", QUTF8(key)); }