Beispiel #1
0
static int lamexp_main(int &argc, char **argv)
{
	int iResult = -1;
	int iShutdown = SHUTDOWN_FLAG_NONE;

	//Print logo
	lamexp_print_logo();

	//Get CLI arguments
	const MUtils::OS::ArgumentMap &arguments = MUtils::OS::arguments();

	//Enumerate CLI arguments
	if(!arguments.isEmpty())
	{
		qDebug("Command-Line Arguments:");
		foreach(const QString &key, arguments.uniqueKeys())
		{
			foreach(const QString &val, arguments.values(key))
			{
				if(!val.isEmpty())
				{
					qDebug("--%s = \"%s\"", MUTILS_UTF8(key), MUTILS_UTF8(val));
					continue;
				}
				qDebug("--%s", MUTILS_UTF8(key));
			}
		}
		qDebug(" ");
	}
void AnalyzeTask::parseFileInfo(QXmlStreamReader &xmlStream, AudioFileModel &audioFile)
{
	QSet<MI_trackType_t> tracksProcessed;
	MI_trackType_t trackType;
	while (findNextElement(QLatin1String("Track"), xmlStream))
	{
		const QString typeString = findAttribute(QLatin1String("Type"), xmlStream.attributes());
		if ((trackType = m_trackTypes.value(typeString.toLower(), MI_trackType_t(-1))) != MI_trackType_t(-1))
		{
			if (!tracksProcessed.contains(trackType))
			{
				tracksProcessed << trackType;
				parseTrackInfo(xmlStream, trackType, audioFile);
			}
			else
			{
				qWarning("Skipping non-primary '%s' track!", MUTILS_UTF8(typeString));
				xmlStream.skipCurrentElement();
			}
		}
		else
		{
			qWarning("Skipping unsupported '%s' track!", MUTILS_UTF8(typeString));
			xmlStream.skipCurrentElement();
		}
	}
}
Beispiel #3
0
static __forceinline void doWriteOutput(QFile &outFile, const QResource *const resource)
{
	for(int i = 0; i < 64; i++)
	{
		if(outFile.open(QIODevice::WriteOnly))
		{
			break;
		}
		if(i == 0)
		{
			qWarning("Failed to open file on first attemp, retrying...");
		}
		Sleep(25);
	}
	
	//Write data to file
	if(outFile.isOpen() && outFile.isWritable())
	{
		if(outFile.write(reinterpret_cast<const char*>(resource->data()), resource->size()) != resource->size())
		{
			QFile::remove(QFileInfo(outFile).canonicalFilePath());
			MUTILS_THROW_FMT("File '%s' could not be written!", MUTILS_UTF8(QFileInfo(outFile).fileName()));
		}
	}
	else
	{
		MUTILS_THROW_FMT("File '%s' could not be created!", MUTILS_UTF8(QFileInfo(outFile).fileName()));
	}

	//Close file after it has been written
	outFile.close();
}
void InitializationThread::selfTest(void)
{
	const unsigned int cpu[4] = {CPU_TYPE_X86_GEN, CPU_TYPE_X86_SSE, CPU_TYPE_X64_GEN, CPU_TYPE_X64_SSE};

	LockedFile::selfTest();

	for(size_t k = 0; k < 4; k++)
	{
		qDebug("[TEST]");
		switch(cpu[k])
		{
			PRINT_CPU_TYPE(CPU_TYPE_X86_GEN); break;
			PRINT_CPU_TYPE(CPU_TYPE_X86_SSE); break;
			PRINT_CPU_TYPE(CPU_TYPE_X64_GEN); break;
			PRINT_CPU_TYPE(CPU_TYPE_X64_SSE); break;
			default: MUTILS_THROW("CPU support undefined!");
		}
		unsigned int n = 0;
		for(int i = 0; true; i++)
		{
			if(!(g_lamexp_tools[i].pcName || g_lamexp_tools[i].pcHash  || g_lamexp_tools[i].uiVersion))
			{
				break;
			}
			else if(g_lamexp_tools[i].pcName && g_lamexp_tools[i].pcHash && g_lamexp_tools[i].uiVersion)
			{
				const QString toolName = QString::fromLatin1(g_lamexp_tools[i].pcName);
				const QByteArray expectedHash = QByteArray(g_lamexp_tools[i].pcHash);
				if(g_lamexp_tools[i].uiCpuType & cpu[k])
				{
					qDebug("%02i -> %s", ++n, MUTILS_UTF8(toolName));
					QFile resource(QString(":/tools/%1").arg(toolName));
					if(!resource.open(QIODevice::ReadOnly))
					{
						qFatal("The resource for \"%s\" could not be opened!", MUTILS_UTF8(toolName));
						break;
					}
					QByteArray hash = LockedFile::fileHash(resource);
					if(hash.isNull() || _stricmp(hash.constData(), expectedHash.constData()))
					{
						qFatal("Hash check for tool \"%s\" has failed!", MUTILS_UTF8(toolName));
						break;
					}
					resource.close();
				}
			}
			else
			{
				qFatal("Inconsistent checksum data detected. Take care!");
			}
		}
		if(n != EXPECTED_TOOL_COUNT)
		{
			qFatal("Tool count mismatch for CPU type %u !!!", cpu[k]);
		}
		qDebug("Done.\n");
	}
}
Beispiel #5
0
QString SettingsModel::defaultLanguage(void) const
{
	QMutexLocker lock(&m_defaultLangLock);

	//Default already initialized?
	if(!m_defaultLanguage.isNull())
	{
		return *m_defaultLanguage;
	}

	//Detect system langauge
	QLocale systemLanguage= QLocale::system();
	qDebug("[Locale]");
	qDebug("Language: %s (%d)", MUTILS_UTF8(QLocale::languageToString(systemLanguage.language())), systemLanguage.language());
	qDebug("Country is: %s (%d)", MUTILS_UTF8(QLocale::countryToString(systemLanguage.country())), systemLanguage.country());
	qDebug("Script is: %s (%d)\n", MUTILS_UTF8(QLocale::scriptToString(systemLanguage.script())), systemLanguage.script());

	//Check if we can use the default translation
	if(systemLanguage.language() == QLocale::English /*|| systemLanguage.language() == QLocale::C*/)
	{
		m_defaultLanguage.reset(new QString(MUtils::Translation::DEFAULT_LANGID));
		return MUtils::Translation::DEFAULT_LANGID;
	}

	QStringList languages;
	if(MUtils::Translation::enumerate(languages) > 0)
	{
		//Try to find a suitable translation for the user's system language *and* country
		for(QStringList::ConstIterator iter = languages.constBegin(); iter != languages.constEnd(); iter++)
		{
			if(MUtils::Translation::get_sysid(*iter) == systemLanguage.language())
			{
				if(MUtils::Translation::get_country(*iter) == systemLanguage.country())
				{
					m_defaultLanguage.reset(new QString(*iter));
					return (*iter);
				}
			}
		}

		//Try to find a suitable translation for the user's system language
		for(QStringList::ConstIterator iter = languages.constBegin(); iter != languages.constEnd(); iter++)
		{
			if(MUtils::Translation::get_sysid(*iter) == systemLanguage.language())
			{
				m_defaultLanguage.reset(new QString(*iter));
				return (*iter);
			}
		}
	}

	//Fall back to the default translation
	m_defaultLanguage.reset(new QString(MUtils::Translation::DEFAULT_LANGID));
	return MUtils::Translation::DEFAULT_LANGID;
}
void AnalyzeTask::run_ex(void)
{
	int fileType = fileTypeNormal;
	QString currentFile = QDir::fromNativeSeparators(m_inputFile);
	qDebug("Analyzing: %s", MUTILS_UTF8(currentFile));
	
	AudioFileModel fileInfo(currentFile);
	analyzeFile(currentFile, fileInfo, &fileType);

	if(MUTILS_BOOLIFY(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(fileInfo.metaInfo().title().isEmpty() || fileInfo.techInfo().containerType().isEmpty() || fileInfo.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, fileInfo))
				{
					fileType = fileTypeNormal;
				}
				else
				{
					qDebug("Rejected Avisynth file: %s", MUTILS_UTF8(fileInfo.filePath()));
				}
			}
			else
			{
				qDebug("Rejected file of unknown type: %s", MUTILS_UTF8(fileInfo.filePath()));
			}
		}
		break;
	}

	//Emit the file now!
	emit fileAnalyzed(m_taskId, fileType, fileInfo);
}
Beispiel #7
0
CueSplitter::CueSplitter(const QString &outputDir, const QString &baseName, CueSheetModel *model, const QList<AudioFileModel> &inputFilesInfo)
:
	m_model(model),
	m_outputDir(outputDir),
	m_baseName(baseName),
	m_soxBin(lamexp_tools_lookup("sox.exe"))
{
	if(m_soxBin.isEmpty())
	{
		qFatal("Invalid path to SoX binary. Tool not initialized properly.");
	}

	m_decompressedFiles.clear();
	m_tempFiles.clear();

	qDebug("\n[CueSplitter]");

	int nInputFiles = inputFilesInfo.count();
	for(int i = 0; i < nInputFiles; i++)
	{
		m_inputFilesInfo.insert(inputFilesInfo[i].filePath(), inputFilesInfo[i]);
		qDebug("File %02d: <%s>", i, MUTILS_UTF8(inputFilesInfo[i].filePath()));
	}
	
	qDebug("All input files added.");
	m_bSuccess = false;
}
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);
	}
}
Beispiel #9
0
void CueSplitter::run()
{
	m_bSuccess = false;
	m_bAborted = false;
	m_abortFlag = false;
	m_nTracksSuccess = 0;
	m_nTracksSkipped = 0;
	m_decompressedFiles.clear();
	m_activeFile.clear();
	
	if(!QDir(m_outputDir).exists())
	{
		qWarning("Output directory \"%s\" does not exist!", MUTILS_UTF8(m_outputDir));
		return;
	}
	
	QStringList inputFileList = m_inputFilesInfo.keys();
	int nInputFiles = inputFileList.count();
	
	emit progressMaxChanged(nInputFiles);
	emit progressValChanged(0);

	//Decompress all input files
	for(int i = 0; i < nInputFiles; i++)
	{
		const AudioFileModel_TechInfo &inputFileInfo = m_inputFilesInfo[inputFileList.at(i)].techInfo();
		if(inputFileInfo.containerType().compare("Wave", Qt::CaseInsensitive) || inputFileInfo.audioType().compare("PCM", Qt::CaseInsensitive))
		{
			AbstractDecoder *decoder = DecoderRegistry::lookup(inputFileInfo.containerType(), inputFileInfo.containerProfile(), inputFileInfo.audioType(), inputFileInfo.audioProfile(), inputFileInfo.audioVersion());
			if(decoder)
			{
				m_activeFile = shortName(QFileInfo(inputFileList.at(i)).fileName());
				
				emit fileSelected(m_activeFile);
				emit progressValChanged(i+1);
				
				QString tempFile = QString("%1/~%2.wav").arg(m_outputDir, MUtils::rand_str());
				connect(decoder, SIGNAL(statusUpdated(int)), this, SLOT(handleUpdate(int)), Qt::DirectConnection);
				
				if(decoder->decode(inputFileList.at(i), tempFile, &m_abortFlag))
				{
					m_decompressedFiles.insert(inputFileList.at(i), tempFile);
					m_tempFiles.append(tempFile);
				}
				else
				{
					qWarning("Failed to decompress file: <%s>", inputFileList.at(i).toLatin1().constData());
					MUtils::remove_file(tempFile);
				}
				
				m_activeFile.clear();
				MUTILS_DELETE(decoder);
			}
			else
			{
				qWarning("Unsupported input file: <%s>", inputFileList.at(i).toLatin1().constData());
			}
		}
Beispiel #10
0
static __forceinline void doLockFile(HANDLE &fileHandle, const QString &filePath, QFile *const outFile)
{
	bool success = false;
	fileHandle = INVALID_HANDLE_VALUE;

	//Try to open the file!
	for(int i = 0; i < 64; i++)
	{
		const HANDLE hTemp = CreateFileW(MUTILS_WCHR(QDir::toNativeSeparators(filePath)), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
		if(VALID_HANDLE(hTemp))
		{
			PROTECT_HANDLE(fileHandle = hTemp, true);
			break; /*file opened successfully*/
		}
		if(i == 0)
		{
			qWarning("Failed to open file on first attemp, retrying...");
		}
		Sleep(1);
	}
	
	//Now try to actually lock the file!
	if (VALID_HANDLE(fileHandle))
	{
		for (int i = 0; i < 64; i++)
		{
			LARGE_INTEGER fileSize;
			if (GetFileSizeEx(fileHandle, &fileSize))
			{
				OVERLAPPED overlapped = { 0U, 0U, 0U, 0U, 0U };
				if (LockFileEx(fileHandle, LOCKFILE_FAIL_IMMEDIATELY, 0, fileSize.LowPart, fileSize.HighPart, &overlapped))
				{
					success = true;
					break; /*file locked successfully*/
				}
				Sleep(1);
			}
			if (i == 0)
			{
				qWarning("Failed to lock file on first attemp, retrying...");
			}
		}
	}

	//Locked successfully?
	if(!success)
	{
		CLOSE_HANDLE(fileHandle);
		if(outFile)
		{
			QFile::remove(QFileInfo(*outFile).canonicalFilePath());
		}
		MUTILS_THROW_FMT("File '%s' could not be locked!", MUTILS_UTF8(QFileInfo(filePath).fileName()));
	}
}
Beispiel #11
0
static __forceinline void doValidateFileExists(const QString &filePath)
{
	QFileInfo existingFileInfo(filePath);
	existingFileInfo.setCaching(false);
	
	//Make sure the file exists, before we try to lock it
	if((!existingFileInfo.exists()) || (!existingFileInfo.isFile()) || filePath.isEmpty())
	{
		MUTILS_THROW_FMT("File '%s' does not exist!", MUTILS_UTF8(filePath));
	}
}
Beispiel #12
0
static __forceinline void doValidateHash(HANDLE &fileHandle, const int &fileDescriptor, const QByteArray &expectedHash, const QString &filePath)
{
	QFile checkFile;

	//Now re-open the file for reading
	if(g_useFileDescrForQFile)
	{
		checkFile.open(fileDescriptor, QIODevice::ReadOnly);
	}
	else
	{
		checkFile.setFileName(filePath);
		for(int i = 0; i < 64; i++)
		{
			if(checkFile.open(QIODevice::ReadOnly)) break;
			if(!i) qWarning("Failed to re-open file on first attemp, retrying...");
			Sleep(100);
		}
	}

	//Opened successfully
	if((!checkFile.isOpen()) || checkFile.peek(1).isEmpty())
	{
		QFile::remove(filePath);
		MUTILS_THROW_FMT("File '%s' could not be read!", MUTILS_UTF8(QFileInfo(filePath).fileName()));
	}

	//Verify file contents
	const QByteArray hash = FileHash::computeHash(checkFile);
	checkFile.close();

	//Compare hashes
	if(hash.isNull() || _stricmp(hash.constData(), expectedHash.constData()))
	{
		qWarning("\nFile checksum error:\n A = %s\n B = %s\n", expectedHash.constData(), hash.constData());
		CLOSE_HANDLE(fileHandle);
		QFile::remove(filePath);
		MUTILS_THROW_FMT("File '%s' is corruputed, take care!", MUTILS_UTF8(QFileInfo(filePath).fileName()));
	}
}
Beispiel #13
0
bool MUtils::Translation::install_translator_from_file(const QString &qmFile)
{
	QWriteLocker writeLock(&g_translation_lock);

	if(g_translation_inst.isNull())
	{
		g_translation_inst.reset(new QTranslator());
	}

	if(qmFile.isEmpty())
	{
		QApplication::removeTranslator(g_translation_inst.data());
		return true;
	}

	const QFileInfo qmFileInfo(qmFile);
	if(!(qmFileInfo.exists() && qmFileInfo.isFile()))
	{
		qWarning("Translation file not found:\n\"%s\"", MUTILS_UTF8(qmFile));
		return false;
	}

	const QString qmPath = QFileInfo(qmFile).canonicalFilePath();
	if(!qmPath.isEmpty())
	{
		QApplication::removeTranslator(g_translation_inst.data());
		if(g_translation_inst->load(qmPath))
		{
			QApplication::installTranslator(g_translation_inst.data());
			return true;
		}
	}

	qWarning("Failed to load translation:\n\"%s\"",  MUTILS_UTF8(qmFile));
	return false;
}
Beispiel #14
0
	inline void flushValues(void)
	{
		QWriteLocker writeLock(&m_cacheLock);

		if(!m_cacheDirty->isEmpty())
		{
			QSet<QString>::ConstIterator iter;
			for(iter = m_cacheDirty->constBegin(); iter != m_cacheDirty->constEnd(); iter++)
			{
				if(m_cache->contains(*iter))
				{
					m_configFile->setValue((*iter), m_cache->value(*iter));
				}
				else
				{
					qWarning("Could not find '%s' in cache, but it has been marked as dirty!", MUTILS_UTF8(*iter));
				}
			}
			m_configFile->sync();
			m_cacheDirty->clear();
		}
	}
Beispiel #15
0
static void lamexp_print_logo(void)
{
	//Print version info
	qDebug("LameXP - Audio Encoder Front-End v%d.%02d %s (Build #%03d)", lamexp_version_major(), lamexp_version_minor(), lamexp_version_release(), lamexp_version_build());
	qDebug("Copyright (c) 2004-%04d LoRd_MuldeR <*****@*****.**>. Some rights reserved.", qMax(MUtils::Version::app_build_date().year(), MUtils::OS::current_date().year()));
	qDebug("Built on %s at %s with %s for Win-%s.\n", MUTILS_UTF8(MUtils::Version::app_build_date().toString(Qt::ISODate)), MUTILS_UTF8(MUtils::Version::app_build_time().toString(Qt::ISODate)), MUtils::Version::compiler_version(), MUtils::Version::compiler_arch());
	
	//print license info
	qDebug("This program is free software: you can redistribute it and/or modify");
	qDebug("it under the terms of the GNU General Public License <http://www.gnu.org/>.");
	qDebug("Note that this program is distributed with ABSOLUTELY NO WARRANTY.\n");

	//Print library version
	qDebug("This application is powerd by MUtils library v%u.%02u (%s, %s).\n", MUtils::Version::lib_version_major(), MUtils::Version::lib_version_minor(), MUTILS_UTF8(MUtils::Version::lib_build_date().toString(Qt::ISODate)), MUTILS_UTF8(MUtils::Version::lib_build_time().toString(Qt::ISODate)));
	
	//Print warning, if this is a "debug" build
	if(MUTILS_DEBUG)
	{
		qWarning("---------------------------------------------------------");
		qWarning("DEBUG BUILD: DO NOT RELEASE THIS BINARY TO THE PUBLIC !!!");
		qWarning("---------------------------------------------------------\n");
	}
}
Beispiel #16
0
bool MUtils::Translation::insert(const QString &langId, const QString &qmFile, const QString &langName, const quint32 &systemId, const quint32 &country)
{
	QWriteLocker writeLockTranslations(&g_translation_lock);

	const QString key = langId.simplified().toLower();
	if(key.isEmpty() || qmFile.isEmpty() || langName.isEmpty() || (systemId < 1))
	{
		return false;
	}

	if(g_translation_data.isNull())
	{
		g_translation_data.reset(new translation_store_t());
	}

	if(g_translation_data->contains(key))
	{
		qWarning("Translation store already contains entry for '%s', going to replace!", MUTILS_UTF8(key));
	}

	g_translation_data->insert(key, MAKE_ENTRY(langName, qmFile, systemId, country));
	return true;
}
Beispiel #17
0
bool PlaylistImporter::parsePlaylist_m3u(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
{
	const QTextCodec *codec = QTextCodec::codecForName("System");
	const bool preferUTF8 = data.fileName().endsWith(".m3u8", Qt::CaseInsensitive);
	bool foundAtLeastOneFile = false;
	
	data.reset();

	while(!data.atEnd())
	{
		QString filePath[3];
		QByteArray line = data.readLine();

		if(preferUTF8)
		{
			filePath[0] = QString(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
			filePath[1] = QString(QDir::fromNativeSeparators(codec->toUnicode(line.constData(), line.size()).trimmed()));
			filePath[2] = QString(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
		}
		else
		{
			filePath[0] = QString(QDir::fromNativeSeparators(codec->toUnicode(line.constData(), line.size()).trimmed()));
			filePath[1] = QString(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
			filePath[2] = QString(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
		}

		for(size_t i = 0; i < 3; i++)
		{
			if(!(filePath[i].isEmpty() || filePath[i].startsWith("#") || filePath[i].contains(QChar(QChar::ReplacementCharacter))))
			{
				QFileInfo filename(filePath[i]);
				filename.setCaching(false);
				fixFilePath(filename, baseDir, rootDir);

				if(filename.exists() && filename.isFile())
				{
					qDebug("Found: \"%s\"", MUTILS_UTF8(filePath[i]));
					if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
					{
						fileList << filename.canonicalFilePath();
					}
					foundAtLeastOneFile = true;
					break;
				}
			}
		}
	}

	//If we did not find any files yet, try UTF-16 now
	if(!foundAtLeastOneFile)
	{
		const char* codecs[2] = {"UTF-16LE", "UTF-16BE"};

		for(size_t i = 0; i < 2; i++)
		{
			QTextStream stream(&data);
			stream.setAutoDetectUnicode(false);
			stream.setCodec(codecs[i]);
			stream.seek(0i64);

			while(!stream.atEnd())
			{
				QString filePath = stream.readLine().trimmed();

				if(!(filePath.isEmpty() || filePath.startsWith("#") || filePath.contains(QChar(QChar::ReplacementCharacter))))
				{
					QFileInfo filename(filePath);
					filename.setCaching(false);
					fixFilePath(filename, baseDir, rootDir);

					if(filename.exists() && filename.isFile())
					{
						if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
						{
							fileList << filename.canonicalFilePath();
						}
						foundAtLeastOneFile = true;
					}
				}
			}

			if(foundAtLeastOneFile) break;
		}
	}

	return foundAtLeastOneFile;
}
bool AvisynthCheckThread::checkAvisynth(QString &basePath, const SysinfoModel *const sysinfo, QFile *&path, const bool &x64)
{
	qDebug("Avisynth %s-Bit support is being tested.", x64 ? "64" : "32");

	//Look for "portable" Avisynth version
	static const char *const ARCH_DIR[] = { "x64", "x86" };
	const QLatin1String archSuffix = QLatin1String(ARCH_DIR[x64 ? 1 : 0]);
	if (ENABLE_PORTABLE_AVS)
	{
		const QString avsPortableDir = QString("%1/extra/Avisynth").arg(QCoreApplication::applicationDirPath());
		if (VALID_DIR(avsPortableDir))
		{
			QFileInfo avsDllFile(QString("%1/%2/avisynth.dll").arg(avsPortableDir, archSuffix)), devilDllFile(QString("%1/%2/devil.dll").arg(avsPortableDir, archSuffix));
			if (avsDllFile.exists() && devilDllFile.exists() && avsDllFile.isFile() && devilDllFile.isFile())
			{
				qWarning("Adding portable Avisynth to PATH environment variable: %s", MUTILS_UTF8(avsPortableDir));
				basePath = avsPortableDir;
			}
		}
	}

	//Get extra paths
	QStringList avisynthExtraPaths;
	if (!basePath.isEmpty())
	{
		avisynthExtraPaths << QString("%1/%2").arg(basePath, archSuffix);
	}

	//Setup process object
	const QStringList output = runProcess(AVS_CHECK_BINARY(sysinfo, x64), QStringList(), &avisynthExtraPaths);

	//Init regular expressions
	QRegExp avsLogo("Avisynth\\s+Checker\\s+(x86|x64)");
	QRegExp avsPath("Avisynth_DLLPath=(.+)");
	QRegExp avsVers("Avisynth_Version=(\\d+)\\.(\\d+)");
	
	//Check for version info
	bool avisynthLogo = false;
	quint32 avisynthVersion[2] = { 0, 0 };
	QString avisynthPath;
	for(QStringList::ConstIterator iter = output.constBegin(); iter != output.constEnd(); iter++)
	{
		if(avisynthLogo)
		{
			if(avsPath.indexIn(*iter) >= 0)
			{
				avisynthPath =  avsPath.cap(1).trimmed();
			}
			else if(avsVers.indexIn(*iter) >= 0)
			{
				quint32 temp[2];
				if(MUtils::regexp_parse_uint32(avsVers, temp, 2))
				{
					avisynthVersion[0] = temp[0];
					avisynthVersion[1] = temp[1];
				}
			}
		}
		else
		{
			if(avsLogo.lastIndexIn(*iter) >= 0)
			{
				avisynthLogo = true;
			}
		}
	}
	
	//Minimum required version found?
	if((avisynthVersion[0] >= 2) && (avisynthVersion[1] >= 50) && (!avisynthPath.isEmpty()))
	{
		Wow64RedirectionDisabler disableWow64Redir;
		path = new QFile(avisynthPath);
		if(!path->open(QIODevice::ReadOnly))
		{
			MUTILS_DELETE(path);
		}
		qDebug("Avisynth was detected successfully (current version: %u.%02u).", avisynthVersion[0], avisynthVersion[1]);
		qDebug("Avisynth DLL path: %s", MUTILS_UTF8(avisynthPath));
		return true;
	}
	
	//Failed to determine version
	qWarning("Failed to determine Avisynth version!");
	return false;
}
double InitializationThread::doInit(const size_t threadCount)
{
	m_bSuccess = false;
	delay();

	//CPU type selection
	unsigned int cpuSupport = 0;
	if((m_cpuFeatures.features & MUtils::CPUFetaures::FLAG_SSE) && (m_cpuFeatures.features & MUtils::CPUFetaures::FLAG_SSE2) && m_cpuFeatures.intel)
	{
		cpuSupport = m_cpuFeatures.x64 ? CPU_TYPE_X64_SSE : CPU_TYPE_X86_SSE;
	}
	else
	{
		cpuSupport = m_cpuFeatures.x64 ? CPU_TYPE_X64_GEN : CPU_TYPE_X86_GEN;
	}

	//Hack to disable x64 on Wine, as x64 binaries won't run under Wine (tested with Wine 1.4 under Ubuntu 12.04 x64)
	if(cpuSupport & CPU_TYPE_X64_ALL)
	{
		if(MUtils::OS::running_on_wine())
		{
			qWarning("Running under Wine on a 64-Bit system. Going to disable all x64 support!\n");
			cpuSupport = (cpuSupport == CPU_TYPE_X64_SSE) ? CPU_TYPE_X86_SSE : CPU_TYPE_X86_GEN;
		}
	}

	//Print selected CPU type
	switch(cpuSupport)
	{
		PRINT_CPU_TYPE(CPU_TYPE_X86_GEN); break;
		PRINT_CPU_TYPE(CPU_TYPE_X86_SSE); break;
		PRINT_CPU_TYPE(CPU_TYPE_X64_GEN); break;
		PRINT_CPU_TYPE(CPU_TYPE_X64_SSE); break;
		default: MUTILS_THROW("CPU support undefined!");
	}

	//Allocate queues
	QQueue<QString> queueToolName;
	QQueue<QString> queueChecksum;
	QQueue<QString> queueVersInfo;
	QQueue<unsigned int> queueVersions;
	QQueue<unsigned int> queueCpuTypes;

	//Init properties
	for(int i = 0; true; i++)
	{
		if(!(g_lamexp_tools[i].pcName || g_lamexp_tools[i].pcHash  || g_lamexp_tools[i].uiVersion))
		{
			break;
		}
		else if(g_lamexp_tools[i].pcName && g_lamexp_tools[i].pcHash && g_lamexp_tools[i].uiVersion)
		{
			queueToolName.enqueue(QString::fromLatin1(g_lamexp_tools[i].pcName));
			queueChecksum.enqueue(QString::fromLatin1(g_lamexp_tools[i].pcHash));
			queueVersInfo.enqueue(QString::fromLatin1(g_lamexp_tools[i].pcVersTag));
			queueCpuTypes.enqueue(g_lamexp_tools[i].uiCpuType);
			queueVersions.enqueue(g_lamexp_tools[i].uiVersion);
		}
		else
		{
			qFatal("Inconsistent checksum data detected. Take care!");
		}
	}

	QDir appDir = QDir(QCoreApplication::applicationDirPath()).canonicalPath();

	QScopedPointer<QThreadPool> pool(new QThreadPool());
	pool->setMaxThreadCount((threadCount > 0) ? threadCount : qBound(2U, cores2threads(m_cpuFeatures.count), EXPECTED_TOOL_COUNT));
	/* qWarning("Using %u threads for extraction.", pool->maxThreadCount()); */

	LockedFile::selfTest();
	ExtractorTask::clearFlags();

	//Start the timer
	QElapsedTimer timeExtractStart;
	timeExtractStart.start();
	
	//Extract all files
	while(!(queueToolName.isEmpty() || queueChecksum.isEmpty() || queueVersInfo.isEmpty() || queueCpuTypes.isEmpty() || queueVersions.isEmpty()))
	{
		const QString toolName = queueToolName.dequeue();
		const QString checksum = queueChecksum.dequeue();
		const QString versInfo = queueVersInfo.dequeue();
		const unsigned int cpuType = queueCpuTypes.dequeue();
		const unsigned int version = queueVersions.dequeue();
			
		const QByteArray toolHash(checksum.toLatin1());
		if(toolHash.size() != 96)
		{
			qFatal("The checksum for \"%s\" has an invalid size!", MUTILS_UTF8(toolName));
			return -1.0;
		}
			
		QResource *resource = new QResource(QString(":/tools/%1").arg(toolName));
		if(!(resource->isValid() && resource->data()))
		{
			MUTILS_DELETE(resource);
			qFatal("The resource for \"%s\" could not be found!", MUTILS_UTF8(toolName));
			return -1.0;
		}
			
		if(cpuType & cpuSupport)
		{
			pool->start(new ExtractorTask(resource, appDir, toolName, toolHash, version, versInfo));
			continue;
		}

		MUTILS_DELETE(resource);
	}

	//Sanity Check
	if(!(queueToolName.isEmpty() && queueChecksum.isEmpty() && queueVersInfo.isEmpty() && queueCpuTypes.isEmpty() && queueVersions.isEmpty()))
	{
		qFatal("Checksum queues *not* empty fater verification completed. Take care!");
	}

	//Wait for extrator threads to finish
	pool->waitForDone();

	//Performance measure
	const double delayExtract = double(timeExtractStart.elapsed()) / 1000.0;
	timeExtractStart.invalidate();

	//Make sure all files were extracted correctly
	if(ExtractorTask::getExcept())
	{
		char errorMsg[BUFF_SIZE];
		if(ExtractorTask::getErrMsg(errorMsg, BUFF_SIZE))
		{
			qFatal("At least one of the required tools could not be initialized:\n%s", errorMsg);
			return -1.0;
		}
		qFatal("At least one of the required tools could not be initialized!");
		return -1.0;
	}

	qDebug("All extracted.\n");

	//Using any custom tools?
	if(ExtractorTask::getCustom())
	{
		qWarning("Warning: Using custom tools, you might encounter unexpected problems!\n");
	}

	//Check delay
	if(delayExtract > g_allowedExtractDelay)
	{
		m_slowIndicator = true;
		qWarning("Extracting tools took %.3f seconds -> probably slow realtime virus scanner.", delayExtract);
		qWarning("Please report performance problems to your anti-virus developer !!!\n");
	}
	else
	{
		qDebug("Extracting the tools took %.3f seconds (OK).\n", delayExtract);
	}

	//Register all translations
	initTranslations();

	//Look for AAC encoders
	InitAacEncTask::clearFlags();
	for(size_t i = 0; g_lamexp_aacenc[i].toolName; i++)
	{
		pool->start(new InitAacEncTask(&(g_lamexp_aacenc[i])));
	}
	pool->waitForDone();

	//Make sure initialization finished correctly
	if(InitAacEncTask::getExcept())
	{
		char errorMsg[BUFF_SIZE];
		if(InitAacEncTask::getErrMsg(errorMsg, BUFF_SIZE))
		{
			qFatal("At least one optional component failed to initialize:\n%s", errorMsg);
			return -1.0;
		}
		qFatal("At least one optional component failed to initialize!");
		return -1.0;
	}

	m_bSuccess = true;
	delay();

	return delayExtract;
}
void InitializationThread::initTranslations(void)
{
	//Search for language files
	const QDir qmDirectory(":/localization");
	const QStringList qmFiles = qmDirectory.entryList(QStringList() << "LameXP_??.qm", QDir::Files, QDir::Name);

	//Make sure we found at least one translation
	if(qmFiles.count() < 1)
	{
		qFatal("Could not find any translation files!");
		return;
	}

	//Initialize variables
	const QString langResTemplate(":/localization/%1.txt");
	QRegExp langIdExp("^LameXP_(\\w\\w)\\.qm$", Qt::CaseInsensitive);

	//Add all available translations
	for(QStringList::ConstIterator iter = qmFiles.constBegin(); iter != qmFiles.constEnd(); iter++)
	{
		const QString langFile = qmDirectory.absoluteFilePath(*iter);
		QString langId, langName;
		unsigned int systemId = 0, country = 0;
		
		if(QFileInfo(langFile).isFile() && (langIdExp.indexIn(*iter) >= 0))
		{
			langId = langIdExp.cap(1).toLower();
			QResource langRes = QResource(langResTemplate.arg(*iter));
			if(langRes.isValid() && langRes.size() > 0)
			{
				QByteArray data = QByteArray::fromRawData(reinterpret_cast<const char*>(langRes.data()), langRes.size());
				QTextStream stream(&data, QIODevice::ReadOnly);
				stream.setAutoDetectUnicode(false); stream.setCodec("UTF-8");

				while(!(stream.atEnd() || (stream.status() != QTextStream::Ok)))
				{
					QStringList langInfo = stream.readLine().simplified().split(",", QString::SkipEmptyParts);
					if(langInfo.count() >= 3)
					{
						systemId = langInfo.at(0).trimmed().toUInt();
						country  = langInfo.at(1).trimmed().toUInt();
						langName = langInfo.at(2).trimmed();
						break;
					}
				}
			}
		}

		if(!(langId.isEmpty() || langName.isEmpty() || (systemId == 0)))
		{
			if(MUtils::Translation::insert(langId, langFile, langName, systemId, country))
			{
				qDebug("Registering translation: %s = %s (%u) [%u]", MUTILS_UTF8(*iter), MUTILS_UTF8(langName), systemId, country);
			}
			else
			{
				qWarning("Failed to register: %s", langFile.toLatin1().constData());
			}
		}
	}

	qDebug("All registered.\n");
}
void InitAacEncTask::initAacEncImpl(const char *const toolName, const char *const fileNames[], const quint32 &toolMinVersion, const quint32 &verDigits, const quint32 &verShift, const char *const verStr, QRegExp &regExpVer, QRegExp &regExpSig)
{
	static const size_t MAX_FILES = 8;
	const QString appPath = QDir(QCoreApplication::applicationDirPath()).canonicalPath();
	
	QFileInfoList fileInfo;
	for(size_t i = 0; fileNames[i] && (fileInfo.count() < MAX_FILES); i++)
	{
		fileInfo.append(QFileInfo(QString("%1/%2").arg(appPath, QString::fromLatin1(fileNames[i]))));
	}
	
	for(QFileInfoList::ConstIterator iter = fileInfo.constBegin(); iter != fileInfo.constEnd(); iter++)
	{
		if(!(iter->exists() && iter->isFile()))
		{
			qDebug("%s encoder binaries not found -> Encoding support will be disabled!\n", toolName);
			return;
		}
		if((iter->suffix().compare("exe", Qt::CaseInsensitive) == 0) && (!MUtils::OS::is_executable_file(iter->canonicalFilePath())))
		{
			qDebug("%s executable is invalid -> %s support will be disabled!\n", MUTILS_UTF8(iter->fileName()), toolName);
			return;
		}
	}

	qDebug("Found %s encoder binary:\n%s\n", toolName, MUTILS_UTF8(fileInfo.first().canonicalFilePath()));

	//Lock the encoder binaries
	QScopedPointer<LockedFile> binaries[MAX_FILES];
	try
	{
		size_t index = 0;
		for(QFileInfoList::ConstIterator iter = fileInfo.constBegin(); iter != fileInfo.constEnd(); iter++)
		{
			binaries[index++].reset(new LockedFile(iter->canonicalFilePath()));
		}
	}
	catch(...)
	{
		qWarning("Failed to get excluive lock to encoder binary -> %s support will be disabled!", toolName);
		return;
	}

	QProcess process;
	MUtils::init_process(process, fileInfo.first().absolutePath());

	process.start(fileInfo.first().canonicalFilePath(), QStringList() << "-help");

	if(!process.waitForStarted())
	{
		qWarning("%s process failed to create!", toolName);
		qWarning("Error message: \"%s\"\n", process.errorString().toLatin1().constData());
		process.kill();
		process.waitForFinished(-1);
		return;
	}

	quint32 toolVersion = 0;
	bool sigFound = regExpSig.isEmpty() ? true : false;

	while(process.state() != QProcess::NotRunning)
	{
		if(!process.waitForReadyRead())
		{
			if(process.state() == QProcess::Running)
			{
				qWarning("%s process time out -> killing!", toolName);
				process.kill();
				process.waitForFinished(-1);
				return;
			}
		}
		while(process.canReadLine())
		{
			QString line = QString::fromUtf8(process.readLine().constData()).simplified();
			if((!sigFound) && regExpSig.lastIndexIn(line) >= 0)
			{
				sigFound = true;
				continue;
			}
			if(sigFound && (regExpVer.lastIndexIn(line) >= 0))
			{
				quint32 tmp[8];
				if(MUtils::regexp_parse_uint32(regExpVer, tmp, qMin(verDigits, 8U)))
				{
					toolVersion = 0;
					for(quint32 i = 0; i < verDigits; i++)
					{
						toolVersion = (toolVersion * verShift) + qBound(0U, tmp[i], (verShift - 1));
					}
				}
			}
		}
	}

	if(toolVersion <= 0)
	{
		qWarning("%s version could not be determined -> Encoding support will be disabled!", toolName);
		return;
	}
	else if(toolVersion < toolMinVersion)
	{
		qWarning("%s version is too much outdated (%s) -> Encoding support will be disabled!", toolName, MUTILS_UTF8(lamexp_version2string(verStr, toolVersion,    "N/A")));
		qWarning("Minimum required %s version currently is: %s\n",                             toolName, MUTILS_UTF8(lamexp_version2string(verStr, toolMinVersion, "N/A")));
		return;
	}

	qDebug("Enabled %s encoder %s.\n", toolName, MUTILS_UTF8(lamexp_version2string(verStr, toolVersion, "N/A")));

	size_t index = 0;
	for(QFileInfoList::ConstIterator iter = fileInfo.constBegin(); iter != fileInfo.constEnd(); iter++)
	{
		lamexp_tools_register(iter->fileName(), binaries[index++].take(), toolVersion);
	}
}
Beispiel #22
0
SettingsModel::SettingsModel(void)
:
	m_configCache(NULL)
{
	QString configPath = "LameXP.ini";
	
	if(!lamexp_version_portable())
	{
		QString dataPath = initDirectory(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
		if(!dataPath.isEmpty())
		{
			configPath = QString("%1/config.ini").arg(QDir(dataPath).canonicalPath());
		}
		else
		{
			qWarning("SettingsModel: DataLocation could not be initialized!");
			dataPath = initDirectory(QDesktopServices::storageLocation(QDesktopServices::HomeLocation));
			if(!dataPath.isEmpty())
			{
				configPath = QString("%1/LameXP.ini").arg(QDir(dataPath).canonicalPath());
			}
		}
	}
	else
	{
		qDebug("LameXP is running in \"portable\" mode -> config in application dir!\n");
		QString appPath = QFileInfo(QApplication::applicationFilePath()).canonicalFilePath();
		if(appPath.isEmpty())
		{
			appPath = QFileInfo(QApplication::applicationFilePath()).absoluteFilePath();
		}
		if(QFileInfo(appPath).exists() && QFileInfo(appPath).isFile())
		{
			configPath = QString("%1/%2.ini").arg(QFileInfo(appPath).absolutePath(), QFileInfo(appPath).completeBaseName());
		}
	}

	//Create settings
	QSettings *configFile = new QSettings(configPath, QSettings::IniFormat);
	const QString groupKey = QString().sprintf("LameXP_%u%02u%05u", lamexp_version_major(), lamexp_version_minor(), lamexp_version_confg());
	QStringList childGroups =configFile->childGroups();

	//Clean-up settings
	while(!childGroups.isEmpty())
	{
		QString current = childGroups.takeFirst();
		QRegExp filter("^LameXP_(\\d+)(\\d\\d)(\\d\\d\\d\\d\\d)$");
		if(filter.indexIn(current) >= 0)
		{
			bool ok = false;
			unsigned int temp = filter.cap(3).toUInt(&ok) + 10;
			if(ok && (temp >= lamexp_version_confg()))
			{
				continue;
			}
		}
		qWarning("Deleting obsolete group from config: %s", MUTILS_UTF8(current));
		REMOVE_GROUP(configFile, current);
	}

	//Setup settings
	configFile->beginGroup(groupKey);
	configFile->setValue(g_settingsId_versionNumber, QApplication::applicationVersion());
	configFile->sync();

	//Create the cache
	m_configCache = new SettingsCache(configFile);
}
const AudioFileModel& AnalyzeTask::parseMediaInfo(const QByteArray &data, AudioFileModel &audioFile)
{
	QXmlStreamReader xmlStream(data);
	bool firstMediaFile = true;

	if (findNextElement(QLatin1String("MediaInfo"), xmlStream))
	{
		const QString versionXml = findAttribute(QLatin1String("Version"),  xmlStream.attributes());
		if (versionXml.isEmpty() || (!checkVersionStr(versionXml, 2U, 0U)))
		{
			qWarning("Invalid file format version property: \"%s\"", MUTILS_UTF8(versionXml));
			return audioFile;
		}
		if (findNextElement(QLatin1String("CreatingLibrary"), xmlStream))
		{
			const QString versionLib = findAttribute(QLatin1String("Version"), xmlStream.attributes());
			const QString identifier = xmlStream.readElementText(QXmlStreamReader::SkipChildElements).simplified();
			if (!STRICMP(identifier, QLatin1String("MediaInfoLib")))
			{
				qWarning("Invalid library identiofier property: \"%s\"", MUTILS_UTF8(identifier));
				return audioFile;
			}
			if (!versionLib.isEmpty())
			{
				if (m_mediaInfoVer != UINT_MAX)
				{
					const quint32 mediaInfoVer = (m_mediaInfoVer > 9999U) ? m_mediaInfoVer / 10U : m_mediaInfoVer;
					if (!checkVersionStr(versionLib, mediaInfoVer / 100U, mediaInfoVer % 100U))
					{
						qWarning("Invalid library version property: \"%s\"", MUTILS_UTF8(versionLib));
						return audioFile;
					}
				}
			}
			else
			{
				qWarning("Library version property not found!");
				return audioFile;
			}
			while (findNextElement(QLatin1String("Media"), xmlStream))
			{
				if (firstMediaFile || audioFile.techInfo().containerType().isEmpty() || audioFile.techInfo().audioType().isEmpty())
				{
					firstMediaFile = false;
					parseFileInfo(xmlStream, audioFile);
				}
				else
				{
					qWarning("Skipping non-primary file!");
					xmlStream.skipCurrentElement();
				}
			}
		}
	}

	if (!(audioFile.techInfo().containerType().isEmpty() || audioFile.techInfo().audioType().isEmpty()))
	{
		if (audioFile.metaInfo().title().isEmpty())
		{
			QString baseName = QFileInfo(audioFile.filePath()).fileName();
			int index;
			if ((index = baseName.lastIndexOf(".")) >= 0)
			{
				baseName = baseName.left(index);
			}
			baseName = baseName.replace("_", " ").simplified();
			if ((index = baseName.lastIndexOf(" - ")) >= 0)
			{
				baseName = baseName.mid(index + 3).trimmed();
			}
			audioFile.metaInfo().setTitle(baseName);
		}
		if ((audioFile.techInfo().audioType().compare("PCM", Qt::CaseInsensitive) == 0) && (audioFile.techInfo().audioProfile().compare("Float", Qt::CaseInsensitive) == 0))
		{
			if (audioFile.techInfo().audioBitdepth() == 32) audioFile.techInfo().setAudioBitdepth(AudioFileModel::BITDEPTH_IEEE_FLOAT32);
		}
	}
	else
	{
		qWarning("Audio file format could *not* be recognized!");
	}

	return audioFile;
}
Beispiel #24
0
static int mixp_main(int &argc, char **argv)
{
	//Print the logo
	qDebug("MediaInfoXP v%u.%02u, built on %s at %s.", mixp_versionMajor, mixp_versionMinor, mixp_buildDate, mixp_buildTime);
	qDebug("Copyright (c) 2004-%s LoRd_MuldeR <*****@*****.**>. Some rights reserved.", &mixp_buildDate[7]);
	qDebug("Built with Qt v%s, running with Qt v%s.\n", QT_VERSION_STR, qVersion());

	//Print library version
	qDebug("This application is powerd by MUtils library v%u.%02u (%s, %s).\n", MUtils::Version::lib_version_major(), MUtils::Version::lib_version_minor(), MUTILS_UTF8(MUtils::Version::lib_build_date().toString(Qt::ISODate)), MUTILS_UTF8(MUtils::Version::lib_build_time().toString(Qt::ISODate)));

	//Create application
	QScopedPointer<QApplication> application(new QApplication(argc, argv));

	//Create IPC
	QScopedPointer<MUtils::IPCChannel> ipcChannel(new MUtils::IPCChannel("mediainfo-xp", qHash(QString("%0@%1").arg(QString::fromLatin1(mixp_buildDate), QString::fromLatin1(mixp_buildTime))), "instance"));
	const int ipcMode = ipcChannel->initialize();
	if((ipcMode != MUtils::IPCChannel::RET_SUCCESS_MASTER) && (ipcMode != MUtils::IPCChannel::RET_SUCCESS_SLAVE))
	{
		qFatal("The IPC initialization has failed!");
		return EXIT_FAILURE;
	}

	//Handle multiple instances
	if(ipcMode == MUtils::IPCChannel::RET_SUCCESS_SLAVE)
	{
		mixp_handle_multi_instance(ipcChannel.data());
		return EXIT_SUCCESS;
	}

	//Get temp folder
	const QString tempFolder =  MUtils::temp_folder();
	qDebug("TEMP folder is:\n%s\n", QDir::toNativeSeparators(tempFolder).toUtf8().constData());

	//Create main window
	QScopedPointer<CMainWindow> mainWindow(new CMainWindow(tempFolder, ipcChannel.data()));
	mainWindow->show();

	//Run application
	const int exit_code = application->exec();
	qDebug("\nTime to say goodbye... (%d)\n", exit_code);

	return exit_code;
}
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));
}