WMA decoding support. Limitations in the WMA decoder we cannot do anything about: WMA decoder doesn't handle Unicode filenames, WMA decoder will deadlock if we more than one instance is running at a time (we use a semaphore to prevent that!) and WMA decoder doesn't output any progress information.

This commit is contained in:
LoRd_MuldeR 2010-12-12 19:25:06 +01:00
parent c931b92a8e
commit 0534264be0
11 changed files with 225 additions and 5 deletions

View File

@ -306,6 +306,10 @@
RelativePath=".\src\Decoder_Vorbis.cpp" RelativePath=".\src\Decoder_Vorbis.cpp"
> >
</File> </File>
<File
RelativePath=".\src\Decoder_WMA.cpp"
>
</File>
<File <File
RelativePath=".\src\Dialog_About.cpp" RelativePath=".\src\Dialog_About.cpp"
> >
@ -482,6 +486,10 @@
RelativePath=".\src\Decoder_Vorbis.h" RelativePath=".\src\Decoder_Vorbis.h"
> >
</File> </File>
<File
RelativePath=".\src\Decoder_WMA.h"
>
</File>
<File <File
RelativePath=".\src\Dialog_About.h" RelativePath=".\src\Dialog_About.h"
> >

View File

@ -118,6 +118,9 @@ VIAddVersionKey "Website" "http://mulder.at.gg/"
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM !define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
!define MUI_STARTMENUPAGE_REGISTRY_KEY "${MyRegPath}" !define MUI_STARTMENUPAGE_REGISTRY_KEY "${MyRegPath}"
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "StartmenuFolder" !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "StartmenuFolder"
!define MUI_LANGDLL_REGISTRY_ROOT HKLM
!define MUI_LANGDLL_REGISTRY_KEY "${MyRegPath}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "SetupLanguage"
!define MUI_STARTMENUPAGE_DEFAULTFOLDER "LameXP v${LAMEXP_VERSION}" !define MUI_STARTMENUPAGE_DEFAULTFOLDER "LameXP v${LAMEXP_VERSION}"
!define MUI_FINISHPAGE_NOAUTOCLOSE !define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_UNFINISHPAGE_NOAUTOCLOSE !define MUI_UNFINISHPAGE_NOAUTOCLOSE
@ -373,11 +376,17 @@ SectionEnd
Section "Uninstall" Section "Uninstall"
!insertmacro PrintProgress "$(LAMEXP_LANG_STATUS_UNINSTALL)" !insertmacro PrintProgress "$(LAMEXP_LANG_STATUS_UNINSTALL)"
IfFileExists "$INSTDIR\LameXP.exe" 0 UnNotInstalled
!insertmacro PrintProgress "$(LAMEXP_LANG_STATUS_CLOSING)"
!insertmacro UAC_AsUser_Call Function un.CloseRunningInstance UAC_SYNCOUTDIR
UnNotInstalled:
Delete /REBOOTOK "$INSTDIR\*.exe" Delete /REBOOTOK "$INSTDIR\*.exe"
Delete /REBOOTOK "$INSTDIR\*.txt" Delete /REBOOTOK "$INSTDIR\*.txt"
RMDir "$INSTDIR" RMDir "$INSTDIR"
!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
StrCmp "$StartMenuFolder" "" NoStartmenuFolder
IfFileExists "$SMPROGRAMS\$StartMenuFolder\*.*" 0 NoStartmenuFolder IfFileExists "$SMPROGRAMS\$StartMenuFolder\*.*" 0 NoStartmenuFolder
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuFolder\*.lnk" Delete /REBOOTOK "$SMPROGRAMS\$StartMenuFolder\*.lnk"
Delete /REBOOTOK "$SMPROGRAMS\$StartMenuFolder\*.url" Delete /REBOOTOK "$SMPROGRAMS\$StartMenuFolder\*.url"
@ -389,6 +398,7 @@ Section "Uninstall"
DeleteRegValue HKLM "${MyRegPath}" "UninstallString" DeleteRegValue HKLM "${MyRegPath}" "UninstallString"
DeleteRegValue HKLM "${MyRegPath}" "DisplayName" DeleteRegValue HKLM "${MyRegPath}" "DisplayName"
DeleteRegValue HKLM "${MyRegPath}" "StartmenuFolder" DeleteRegValue HKLM "${MyRegPath}" "StartmenuFolder"
DeleteRegValue HKLM "${MyRegPath}" "SetupLanguage"
!insertmacro PrintProgress "$(MUI_UNTEXT_FINISH_TITLE)." !insertmacro PrintProgress "$(MUI_UNTEXT_FINISH_TITLE)."
SectionEnd SectionEnd
@ -437,3 +447,8 @@ FunctionEnd
Function CloseRunningInstance Function CloseRunningInstance
nsExec::Exec /TIMEOUT=30000 '"$OUTDIR\LameXP.exe" --force-kill' nsExec::Exec /TIMEOUT=30000 '"$OUTDIR\LameXP.exe" --force-kill'
FunctionEnd FunctionEnd
Function un.CloseRunningInstance
nsExec::Exec /TIMEOUT=30000 '"$OUTDIR\LameXP.exe" --force-kill'
FunctionEnd

View File

@ -17,7 +17,9 @@
<file>icons/calendar.png</file> <file>icons/calendar.png</file>
<file>icons/cancel.png</file> <file>icons/cancel.png</file>
<file>icons/cd.png</file> <file>icons/cd.png</file>
<file>icons/cd_add.png</file>
<file>icons/cd_burn.png</file> <file>icons/cd_burn.png</file>
<file>icons/cd_delete.png</file>
<file>icons/cd_edit.png</file> <file>icons/cd_edit.png</file>
<file>icons/cd_go.png</file> <file>icons/cd_go.png</file>
<file>icons/clock_play.png</file> <file>icons/clock_play.png</file>

View File

@ -25,7 +25,7 @@
#define VER_LAMEXP_MAJOR 4 #define VER_LAMEXP_MAJOR 4
#define VER_LAMEXP_MINOR_HI 0 #define VER_LAMEXP_MINOR_HI 0
#define VER_LAMEXP_MINOR_LO 0 #define VER_LAMEXP_MINOR_LO 0
#define VER_LAMEXP_BUILD 145 #define VER_LAMEXP_BUILD 147
#define VER_LAMEXP_SUFFIX TechPreview #define VER_LAMEXP_SUFFIX TechPreview
/* /*

View File

@ -37,3 +37,8 @@ bool AbstractDecoder::isFormatSupported(const QString &containerType, const QStr
{ {
return false; return false;
} }
bool AbstractDecoder::isDecoderAvailable(void)
{
return true;
}

View File

@ -34,4 +34,6 @@ public:
//Internal decoder API //Internal decoder API
virtual bool decode(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag) = 0; virtual bool decode(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag) = 0;
static bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion); static bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
static bool isDecoderAvailable(void);
}; };

139
src/Decoder_WMA.cpp Normal file
View File

@ -0,0 +1,139 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2010 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////
#include "Decoder_WMA.h"
#include "Global.h"
#include <QDir>
#include <QProcess>
#include <QRegExp>
#include <QSystemSemaphore>
#include <QUuid>
WMADecoder::WMADecoder(void)
:
m_binary(lamexp_lookup_tool("wmawav.exe")),
m_semaphore(new QSystemSemaphore("{84BB780D-67D3-49DC-ADF0-97C795A55D5C}", 1))
{
if(m_binary.isEmpty())
{
throw "Error initializing WMA decoder. Tool 'wmawav.exe' is not registred!";
}
}
WMADecoder::~WMADecoder(void)
{
}
bool WMADecoder::decode(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag)
{
QProcess process;
QStringList args;
args << pathToShort(QDir::toNativeSeparators(sourceFile));
args << pathToShort(QDir::toNativeSeparators(outputFile));
if(!m_semaphore->acquire())
{
emit messageLogged("Failed to acquire the semaphore!");
return false;
}
if(!startProcess(process, m_binary, args))
{
m_semaphore->release();
return false;
}
bool bTimeout = false;
bool bAborted = false;
//The WMA Decoder doesn't actually send any status updates :-[
emit statusUpdated(20 + (QUuid::createUuid().data1 % 80));
while(process.state() != QProcess::NotRunning)
{
if(*abortFlag)
{
process.kill();
bAborted = true;
emit messageLogged("\nABORTED BY USER !!!");
break;
}
process.waitForReadyRead();
if(!process.bytesAvailable() && process.state() == QProcess::Running)
{
process.kill();
qWarning("WmaWav process timed out <-- killing!");
bTimeout = true;
break;
}
while(process.bytesAvailable() > 0)
{
QByteArray line = process.readLine();
QString text = QString::fromUtf8(line.constData()).simplified();
if(!text.isEmpty())
{
emit messageLogged(text);
}
}
}
process.waitForFinished();
if(process.state() != QProcess::NotRunning)
{
process.kill();
process.waitForFinished(-1);
}
emit statusUpdated(100);
emit messageLogged(QString().sprintf("\nExited with code: 0x%04X", process.exitCode()));
m_semaphore->release();
if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit || QFileInfo(outputFile).size() == 0)
{
return false;
}
return true;
}
bool WMADecoder::isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion)
{
if(containerType.compare("Windows Media", Qt::CaseInsensitive) == 0)
{
if(formatType.compare("WMA", Qt::CaseInsensitive) == 0)
{
if(formatVersion.compare("Version 1", Qt::CaseInsensitive) == 0 || formatVersion.compare("Version 2", Qt::CaseInsensitive) == 0 || formatVersion.compare("Version 3", Qt::CaseInsensitive) == 0 || formatProfile.compare("Pro", Qt::CaseInsensitive) == 0 || formatProfile.compare("Lossless", Qt::CaseInsensitive) == 0)
{
return true;
}
}
}
return false;
}
bool WMADecoder::isDecoderAvailable(void)
{
return lamexp_check_tool("wmawav.exe");
}

41
src/Decoder_WMA.h Normal file
View File

@ -0,0 +1,41 @@
///////////////////////////////////////////////////////////////////////////////
// LameXP - Audio Encoder Front-End
// Copyright (C) 2004-2010 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// http://www.gnu.org/licenses/gpl-2.0.txt
///////////////////////////////////////////////////////////////////////////////
#pragma once
#include "Decoder_Abstract.h"
class QSystemSemaphore;
class WMADecoder : public AbstractDecoder
{
public:
WMADecoder(void);
~WMADecoder(void);
virtual bool decode(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag);
static bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
static bool isDecoderAvailable(void);
private:
const QString m_binary;
QSystemSemaphore *m_semaphore;
};

View File

@ -1481,7 +1481,10 @@ void MainWindow::installWMADecoderActionTriggered(bool checked)
QFile::remove(setupFile); QFile::remove(setupFile);
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
QMessageBox::information(this, "WMA Decoder", "The WMA File Decoder has been installed. Please restart LameXP now!"); if(QMessageBox::information(this, "WMA Decoder", "The WMA File Decoder has been installed. Please restart LameXP now!", "Quit LameXP", "Ignore") == 0)
{
QApplication::quit();
}
break; break;
} }
} }

View File

@ -70,7 +70,7 @@
ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, AudioFileModel *metaInfo, SettingsModel *settings, QWidget *parent) ProcessingDialog::ProcessingDialog(FileListModel *fileListModel, AudioFileModel *metaInfo, SettingsModel *settings, QWidget *parent)
: :
QDialog(parent), QDialog(parent),
m_systemTray(new QSystemTrayIcon(QIcon(":/icons/cd.png"), this)), m_systemTray(new QSystemTrayIcon(QIcon(":/icons/cd_go.png"), this)),
m_settings(settings), m_settings(settings),
m_metaInfo(metaInfo) m_metaInfo(metaInfo)
{ {
@ -318,6 +318,7 @@ void ProcessingDialog::doneEncoding(void)
WinSevenTaskbar::setOverlayIcon(this, &QIcon(":/icons/error.png")); WinSevenTaskbar::setOverlayIcon(this, &QIcon(":/icons/error.png"));
SET_PROGRESS_TEXT((m_succeededJobs.count() > 0) ? QString("Process was aborted by the user after %1 file(s)!").arg(QString::number(m_succeededJobs.count())) : "Process was aborted prematurely by the user!"); SET_PROGRESS_TEXT((m_succeededJobs.count() > 0) ? QString("Process was aborted by the user after %1 file(s)!").arg(QString::number(m_succeededJobs.count())) : "Process was aborted prematurely by the user!");
m_systemTray->showMessage("LameXP - Aborted", "Process was aborted by the user.", QSystemTrayIcon::Warning); m_systemTray->showMessage("LameXP - Aborted", "Process was aborted by the user.", QSystemTrayIcon::Warning);
m_systemTray->setIcon(QIcon(":/icons/cd_delete.png"));
QApplication::processEvents(); QApplication::processEvents();
if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABORTED), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC); if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_ABORTED), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
} }
@ -329,7 +330,8 @@ void ProcessingDialog::doneEncoding(void)
WinSevenTaskbar::setTaskbarState(this, WinSevenTaskbar::WinSevenTaskbarErrorState); WinSevenTaskbar::setTaskbarState(this, WinSevenTaskbar::WinSevenTaskbarErrorState);
WinSevenTaskbar::setOverlayIcon(this, &QIcon(":/icons/exclamation.png")); WinSevenTaskbar::setOverlayIcon(this, &QIcon(":/icons/exclamation.png"));
SET_PROGRESS_TEXT(QString("Error: %1 of %2 files failed. Double-click failed items for detailed information!").arg(QString::number(m_failedJobs.count()), QString::number(m_failedJobs.count() + m_succeededJobs.count()))); SET_PROGRESS_TEXT(QString("Error: %1 of %2 files failed. Double-click failed items for detailed information!").arg(QString::number(m_failedJobs.count()), QString::number(m_failedJobs.count() + m_succeededJobs.count())));
m_systemTray->showMessage("LameXP - Error", "At least one file has failed!", QSystemTrayIcon::Critical ); m_systemTray->showMessage("LameXP - Error", "At least one file has failed!", QSystemTrayIcon::Critical);
m_systemTray->setIcon(QIcon(":/icons/cd_delete.png"));
QApplication::processEvents(); QApplication::processEvents();
if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_ERROR), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC); if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_ERROR), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
} }
@ -340,6 +342,7 @@ void ProcessingDialog::doneEncoding(void)
WinSevenTaskbar::setOverlayIcon(this, &QIcon(":/icons/accept.png")); WinSevenTaskbar::setOverlayIcon(this, &QIcon(":/icons/accept.png"));
SET_PROGRESS_TEXT("Alle files completed successfully."); SET_PROGRESS_TEXT("Alle files completed successfully.");
m_systemTray->showMessage("LameXP - Done", "All files completed successfully.", QSystemTrayIcon::Information); m_systemTray->showMessage("LameXP - Done", "All files completed successfully.", QSystemTrayIcon::Information);
m_systemTray->setIcon(QIcon(":/icons/cd_add.png"));
QApplication::processEvents(); QApplication::processEvents();
if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_SUCCESS), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC); if(m_settings->soundsEnabled()) PlaySound(MAKEINTRESOURCE(IDR_WAVE_SUCCESS), GetModuleHandle(NULL), SND_RESOURCE | SND_SYNC);
} }

View File

@ -24,16 +24,18 @@
#include "Decoder_AAC.h" #include "Decoder_AAC.h"
#include "Decoder_MP3.h" #include "Decoder_MP3.h"
#include "Decoder_Vorbis.h" #include "Decoder_Vorbis.h"
#include "Decoder_WMA.h"
#include <QString> #include <QString>
#define PROBE_DECODER(DEC) if(DEC::isFormatSupported(containerType, containerProfile, formatType, formatProfile, formatVersion)) { return new DEC(); } #define PROBE_DECODER(DEC) if(DEC::isDecoderAvailable() && DEC::isFormatSupported(containerType, containerProfile, formatType, formatProfile, formatVersion)) { return new DEC(); }
AbstractDecoder *DecoderRegistry::lookup(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion) AbstractDecoder *DecoderRegistry::lookup(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion)
{ {
PROBE_DECODER(MP3Decoder); PROBE_DECODER(MP3Decoder);
PROBE_DECODER(VorbisDecoder); PROBE_DECODER(VorbisDecoder);
PROBE_DECODER(AACDecoder); PROBE_DECODER(AACDecoder);
PROBE_DECODER(WMADecoder);
return NULL; return NULL;
} }