Added support for dedicated decoders. Only Vorbis and MP3 so far.
This commit is contained in:
parent
c77efc9bdf
commit
6eb959e406
120
LameXP.vcproj
120
LameXP.vcproj
@ -290,6 +290,22 @@
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\Decoder_Abstract.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Decoder_MP3.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Decoder_MP3.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Decoder_Vorbis.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Dialog_About.cpp"
|
||||
>
|
||||
@ -374,6 +390,10 @@
|
||||
RelativePath=".\src\Model_Settings.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Registry_Decoder.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Thread_FileAnalyzer.cpp"
|
||||
>
|
||||
@ -394,6 +414,10 @@
|
||||
RelativePath=".\src\Thread_Process.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Tool_Abstract.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
@ -404,6 +428,44 @@
|
||||
RelativePath=".\src\Config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Decoder_Abstract.h"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Static|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Decoder_Vorbis.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Dialog_About.h"
|
||||
>
|
||||
@ -617,7 +679,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)"
"
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
@ -627,7 +689,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)"
"
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
@ -637,7 +699,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)"
"
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
@ -904,6 +966,10 @@
|
||||
RelativePath=".\src\Model_Settings.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Registry_Decoder.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Resource.h"
|
||||
>
|
||||
@ -1082,12 +1148,50 @@
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Tool_Abstract.h"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release_Static|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
CommandLine=""$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp" "$(InputPath)""
|
||||
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Generated Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\tmp\MOC_Decoder_Abstract.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tmp\MOC_Dialog_About.cpp"
|
||||
>
|
||||
@ -1164,6 +1268,10 @@
|
||||
RelativePath=".\tmp\MOC_Thread_Process.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tmp\MOC_Tool_Abstract.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tmp\RCC_Icons.cpp"
|
||||
>
|
||||
@ -1477,7 +1585,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="UIC "$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||
CommandLine=""$(QTDIR)\bin\uic.exe" -o "$(SolutionDir)tmp\UIC_$(SafeInputName).h" "$(InputPath)""
|
||||
CommandLine=""$(QTDIR)\bin\uic.exe" -o "$(SolutionDir)tmp\UIC_$(SafeInputName).h" "$(InputPath)"
"
|
||||
Outputs=""$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
@ -1487,7 +1595,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="UIC "$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||
CommandLine=""$(QTDIR)\bin\uic.exe" -o "$(SolutionDir)tmp\UIC_$(SafeInputName).h" "$(InputPath)""
|
||||
CommandLine=""$(QTDIR)\bin\uic.exe" -o "$(SolutionDir)tmp\UIC_$(SafeInputName).h" "$(InputPath)"
"
|
||||
Outputs=""$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
@ -1497,7 +1605,7 @@
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
Description="UIC "$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||
CommandLine=""$(QTDIR)\bin\uic.exe" -o "$(SolutionDir)tmp\UIC_$(SafeInputName).h" "$(InputPath)""
|
||||
CommandLine=""$(QTDIR)\bin\uic.exe" -o "$(SolutionDir)tmp\UIC_$(SafeInputName).h" "$(InputPath)"
"
|
||||
Outputs=""$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
|
@ -25,7 +25,7 @@
|
||||
#define VER_LAMEXP_MAJOR 4
|
||||
#define VER_LAMEXP_MINOR_HI 0
|
||||
#define VER_LAMEXP_MINOR_LO 0
|
||||
#define VER_LAMEXP_BUILD 105
|
||||
#define VER_LAMEXP_BUILD 110
|
||||
#define VER_LAMEXP_SUFFIX TechPreview
|
||||
|
||||
/*
|
||||
|
39
src/Decoder_Abstract.cpp
Normal file
39
src/Decoder_Abstract.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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_Abstract.h"
|
||||
|
||||
AbstractDecoder::AbstractDecoder(void)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractDecoder::~AbstractDecoder(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Default implementation
|
||||
*/
|
||||
|
||||
bool AbstractDecoder::isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion)
|
||||
{
|
||||
return false;
|
||||
}
|
37
src/Decoder_Abstract.h
Normal file
37
src/Decoder_Abstract.h
Normal file
@ -0,0 +1,37 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 "Tool_Abstract.h"
|
||||
|
||||
class AbstractDecoder : public AbstractTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AbstractDecoder(void);
|
||||
~AbstractDecoder(void);
|
||||
|
||||
//Internal decoder API
|
||||
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);
|
||||
};
|
142
src/Decoder_MP3.cpp
Normal file
142
src/Decoder_MP3.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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_MP3.h"
|
||||
|
||||
#include "Global.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#include <QRegExp>
|
||||
|
||||
MP3Decoder::MP3Decoder(void)
|
||||
:
|
||||
m_binary(lamexp_lookup_tool("mpg123.exe"))
|
||||
{
|
||||
if(m_binary.isEmpty())
|
||||
{
|
||||
throw "Error initializing MPG123 decoder. Tool 'oggdec.exe' is not registred!";
|
||||
}
|
||||
}
|
||||
|
||||
MP3Decoder::~MP3Decoder(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool MP3Decoder::decode(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag)
|
||||
{
|
||||
QProcess process;
|
||||
QStringList args;
|
||||
|
||||
args << "-v" << "-w" << QDir::toNativeSeparators(outputFile);
|
||||
args << QDir::toNativeSeparators(sourceFile);
|
||||
|
||||
if(!startProcess(process, m_binary, args))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bTimeout = false;
|
||||
bool bAborted = false;
|
||||
|
||||
QRegExp regExp("\\s+Time:\\s+(\\d+):(\\d+)\\.(\\d+)\\s+\\[(\\d+):(\\d+)\\.(\\d+)\\],");
|
||||
|
||||
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("mpg123 process timed out <-- killing!");
|
||||
bTimeout = true;
|
||||
break;
|
||||
}
|
||||
while(process.bytesAvailable() > 0)
|
||||
{
|
||||
QByteArray line = process.readLine();
|
||||
QString text = QString::fromUtf8(line.constData()).simplified();
|
||||
if(regExp.lastIndexIn(text) >= 0)
|
||||
{
|
||||
int values[6];
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
bool ok = false;
|
||||
int temp = regExp.cap(i+1).toInt(&ok);
|
||||
values[i] = (ok ? temp : 0);
|
||||
}
|
||||
int timeDone = (60 * values[0]) + values[1];
|
||||
int timeLeft = (60 * values[3]) + values[4];
|
||||
if(timeDone > 0 || timeLeft > 0)
|
||||
{
|
||||
statusUpdated(static_cast<int>((static_cast<double>(timeDone) / static_cast<double>(timeDone + timeLeft)) * 100.0));
|
||||
}
|
||||
}
|
||||
else 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()));
|
||||
|
||||
if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MP3Decoder::isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion)
|
||||
{
|
||||
if(containerType.compare("MPEG Audio", Qt::CaseInsensitive) == 0 || containerType.compare("Wave", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
if(formatType.compare("MPEG Audio", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
if(formatProfile.compare("Layer 3", Qt::CaseInsensitive) == 0 || formatProfile.compare("Layer 2", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
if(formatVersion.compare("Version 1", Qt::CaseInsensitive) == 0 || formatVersion.compare("Version 2", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
37
src/Decoder_MP3.h
Normal file
37
src/Decoder_MP3.h
Normal file
@ -0,0 +1,37 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 MP3Decoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
MP3Decoder(void);
|
||||
~MP3Decoder(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);
|
||||
|
||||
private:
|
||||
const QString m_binary;
|
||||
};
|
126
src/Decoder_Vorbis.cpp
Normal file
126
src/Decoder_Vorbis.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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_Vorbis.h"
|
||||
|
||||
#include "Global.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
#include <QRegExp>
|
||||
|
||||
VorbisDecoder::VorbisDecoder(void)
|
||||
:
|
||||
m_binary(lamexp_lookup_tool("oggdec.exe"))
|
||||
{
|
||||
if(m_binary.isEmpty())
|
||||
{
|
||||
throw "Error initializing Vorbis decoder. Tool 'oggdec.exe' is not registred!";
|
||||
}
|
||||
}
|
||||
|
||||
VorbisDecoder::~VorbisDecoder(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool VorbisDecoder::decode(const QString &sourceFile, const QString &outputFile, volatile bool *abortFlag)
|
||||
{
|
||||
QProcess process;
|
||||
QStringList args;
|
||||
|
||||
args << "-w" << pathToShort(QDir::toNativeSeparators(outputFile));
|
||||
args << pathToShort(QDir::toNativeSeparators(sourceFile));
|
||||
|
||||
if(!startProcess(process, m_binary, args))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bTimeout = false;
|
||||
bool bAborted = false;
|
||||
|
||||
QRegExp regExp(" (\\d+)% decoded.");
|
||||
|
||||
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("OggDec process timed out <-- killing!");
|
||||
bTimeout = true;
|
||||
break;
|
||||
}
|
||||
while(process.bytesAvailable() > 0)
|
||||
{
|
||||
QByteArray line = process.readLine();
|
||||
QString text = QString::fromUtf8(line.constData()).simplified();
|
||||
if(regExp.lastIndexIn(text) >= 0)
|
||||
{
|
||||
bool ok = false;
|
||||
int progress = regExp.cap(1).toInt(&ok);
|
||||
if(ok) emit statusUpdated(progress);
|
||||
}
|
||||
else 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()));
|
||||
|
||||
if(bTimeout || bAborted || process.exitStatus() != QProcess::NormalExit || QFileInfo(outputFile).size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VorbisDecoder::isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion)
|
||||
{
|
||||
if(containerType.compare("OGG", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
if(formatType.compare("Vorbis", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
37
src/Decoder_Vorbis.h
Normal file
37
src/Decoder_Vorbis.h
Normal file
@ -0,0 +1,37 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 VorbisDecoder : public AbstractDecoder
|
||||
{
|
||||
public:
|
||||
VorbisDecoder(void);
|
||||
~VorbisDecoder(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);
|
||||
|
||||
private:
|
||||
const QString m_binary;
|
||||
};
|
@ -34,7 +34,6 @@
|
||||
#include "Model_Settings.h"
|
||||
#include "Model_FileList.h"
|
||||
#include "Model_FileSystem.h"
|
||||
#include "Encoder_MP3.h"
|
||||
|
||||
//Qt includes
|
||||
#include <QMessageBox>
|
||||
|
@ -21,57 +21,10 @@
|
||||
|
||||
#include "Encoder_Abstract.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QProcess>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QLibrary>
|
||||
#include <Windows.h>
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
QMutex *AbstractEncoder::m_mutex_startProcess = NULL;
|
||||
HANDLE AbstractEncoder::m_handle_jobObject = NULL;
|
||||
|
||||
AbstractEncoder::AbstractEncoder(void)
|
||||
{
|
||||
typedef HANDLE (WINAPI *CreateJobObjectFun)(__in_opt LPSECURITY_ATTRIBUTES lpJobAttributes, __in_opt LPCSTR lpName);
|
||||
typedef BOOL (WINAPI *SetInformationJobObjectFun)(__in HANDLE hJob, __in JOBOBJECTINFOCLASS JobObjectInformationClass, __in_bcount(cbJobObjectInformationLength) LPVOID lpJobObjectInformation, __in DWORD cbJobObjectInformationLength);
|
||||
|
||||
static CreateJobObjectFun CreateJobObjectPtr = NULL;
|
||||
static SetInformationJobObjectFun SetInformationJobObjectPtr = NULL;
|
||||
|
||||
if(!m_mutex_startProcess)
|
||||
{
|
||||
m_mutex_startProcess = new QMutex();
|
||||
}
|
||||
|
||||
if(!m_handle_jobObject)
|
||||
{
|
||||
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
|
||||
{
|
||||
QLibrary Kernel32Lib("kernel32.dll");
|
||||
CreateJobObjectPtr = (CreateJobObjectFun) Kernel32Lib.resolve("CreateJobObjectA");
|
||||
SetInformationJobObjectPtr = (SetInformationJobObjectFun) Kernel32Lib.resolve("SetInformationJobObject");
|
||||
}
|
||||
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
|
||||
{
|
||||
m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
|
||||
if(m_handle_jobObject == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_handle_jobObject = NULL;
|
||||
}
|
||||
if(m_handle_jobObject)
|
||||
{
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
|
||||
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
|
||||
SetInformationJobObjectPtr(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_configBitrate = 0;
|
||||
m_configRCMode = 0;
|
||||
}
|
||||
@ -86,57 +39,3 @@ AbstractEncoder::~AbstractEncoder(void)
|
||||
|
||||
void AbstractEncoder::setBitrate(int bitrate) { m_configBitrate = max(0, bitrate); }
|
||||
void AbstractEncoder::setRCMode(int mode) { m_configRCMode = max(0, mode); }
|
||||
|
||||
/*
|
||||
* Auxiliary functions
|
||||
*/
|
||||
|
||||
bool AbstractEncoder::startProcess(QProcess &process, const QString &program, const QStringList &args)
|
||||
{
|
||||
typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE hProcess);
|
||||
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
|
||||
|
||||
QMutexLocker lock(m_mutex_startProcess);
|
||||
|
||||
emit messageLogged(commandline2string(program, args) + "\n");
|
||||
|
||||
if(!AssignProcessToJobObjectPtr)
|
||||
{
|
||||
QLibrary Kernel32Lib("kernel32.dll");
|
||||
AssignProcessToJobObjectPtr = (AssignProcessToJobObjectFun) Kernel32Lib.resolve("AssignProcessToJobObject");
|
||||
}
|
||||
|
||||
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||
process.setReadChannel(QProcess::StandardOutput);
|
||||
process.start(program, args);
|
||||
|
||||
if(process.waitForStarted())
|
||||
{
|
||||
|
||||
if(AssignProcessToJobObjectPtr)
|
||||
{
|
||||
AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);
|
||||
}
|
||||
if(!SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS))
|
||||
{
|
||||
SetPriorityClass(process.pid()->hProcess, IDLE_PRIORITY_CLASS);
|
||||
}
|
||||
lock.unlock();
|
||||
emit statusUpdated(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QString AbstractEncoder::commandline2string(const QString &program, const QStringList &arguments)
|
||||
{
|
||||
QString commandline = (program.contains(' ') ? QString("\"%1\"").arg(program) : program);
|
||||
|
||||
for(int i = 0; i < arguments.count(); i++)
|
||||
{
|
||||
commandline += (arguments.at(i).contains(' ') ? QString(" \"%1\"").arg(arguments.at(i)) : QString(" %1").arg(arguments.at(i)));
|
||||
}
|
||||
|
||||
return commandline;
|
||||
}
|
||||
|
@ -21,15 +21,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tool_Abstract.h"
|
||||
#include "Model_AudioFile.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QProcess;
|
||||
class QStringList;
|
||||
class QMutex;
|
||||
|
||||
class AbstractEncoder : public QObject
|
||||
class AbstractEncoder : public AbstractTool
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -38,7 +37,7 @@ public:
|
||||
~AbstractEncoder(void);
|
||||
|
||||
//Internal encoder API
|
||||
virtual bool encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag) = 0;
|
||||
virtual bool encode(const QString &sourceFile, const AudioFileModel &metaInfo, const QString &outputFile, volatile bool *abortFlag) = 0;
|
||||
virtual bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion) = 0;
|
||||
virtual QString extension(void) = 0;
|
||||
|
||||
@ -46,19 +45,7 @@ public:
|
||||
void setBitrate(int bitrate);
|
||||
void setRCMode(int mode);
|
||||
|
||||
//Auxiliary functions
|
||||
bool startProcess(QProcess &process, const QString &program, const QStringList &args);
|
||||
static QString commandline2string(const QString &program, const QStringList &arguments);
|
||||
|
||||
signals:
|
||||
void statusUpdated(int progress);
|
||||
void messageLogged(const QString &line);
|
||||
|
||||
protected:
|
||||
int m_configBitrate;
|
||||
int m_configRCMode;
|
||||
|
||||
private:
|
||||
static QMutex *m_mutex_startProcess;
|
||||
static void *m_handle_jobObject;
|
||||
};
|
||||
|
@ -27,11 +27,11 @@
|
||||
#include <QProcess>
|
||||
#include <QDir>
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define IS_UNICODE(STR) (qstricmp(STR.toUtf8().constData(), QString::fromLocal8Bit(STR.toLocal8Bit()).toUtf8().constData()))
|
||||
|
||||
MP3Encoder::MP3Encoder(void) : m_binary(lamexp_lookup_tool("lame.exe"))
|
||||
MP3Encoder::MP3Encoder(void)
|
||||
:
|
||||
m_binary(lamexp_lookup_tool("lame.exe"))
|
||||
{
|
||||
if(m_binary.isEmpty())
|
||||
{
|
||||
@ -43,10 +43,9 @@ MP3Encoder::~MP3Encoder(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag)
|
||||
bool MP3Encoder::encode(const QString &sourceFile, const AudioFileModel &metaInfo, const QString &outputFile, volatile bool *abortFlag)
|
||||
{
|
||||
QProcess process;
|
||||
const QString baseName = QFileInfo(outputFile).fileName();
|
||||
QStringList args;
|
||||
|
||||
args << "--nohist";
|
||||
@ -69,17 +68,17 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF
|
||||
break;
|
||||
}
|
||||
|
||||
if(!sourceFile.fileName().isEmpty()) args << (IS_UNICODE(sourceFile.fileName()) ? "--uTitle" : "--lTitle") << sourceFile.fileName();
|
||||
if(!sourceFile.fileArtist().isEmpty()) args << (IS_UNICODE(sourceFile.fileArtist()) ? "--uArtist" : "--lArtist") << sourceFile.fileArtist();
|
||||
if(!sourceFile.fileAlbum().isEmpty()) args << (IS_UNICODE(sourceFile.fileAlbum()) ? "--uAlbum" : "--lAlbum") << sourceFile.fileAlbum();
|
||||
if(!sourceFile.fileGenre().isEmpty()) args << (IS_UNICODE(sourceFile.fileGenre()) ? "--uGenre" : "--lGenre") << sourceFile.fileGenre();
|
||||
if(!sourceFile.fileComment().isEmpty()) args << (IS_UNICODE(sourceFile.fileComment()) ? "--uComment" : "--lComment") << sourceFile.fileComment();
|
||||
if(sourceFile.fileYear()) args << "--ty" << QString::number(sourceFile.fileYear());
|
||||
if(sourceFile.filePosition()) args << "--tn" << QString::number(sourceFile.filePosition());
|
||||
if(!metaInfo.fileName().isEmpty()) args << (IS_UNICODE(metaInfo.fileName()) ? "--uTitle" : "--lTitle") << metaInfo.fileName();
|
||||
if(!metaInfo.fileArtist().isEmpty()) args << (IS_UNICODE(metaInfo.fileArtist()) ? "--uArtist" : "--lArtist") << metaInfo.fileArtist();
|
||||
if(!metaInfo.fileAlbum().isEmpty()) args << (IS_UNICODE(metaInfo.fileAlbum()) ? "--uAlbum" : "--lAlbum") << metaInfo.fileAlbum();
|
||||
if(!metaInfo.fileGenre().isEmpty()) args << (IS_UNICODE(metaInfo.fileGenre()) ? "--uGenre" : "--lGenre") << metaInfo.fileGenre();
|
||||
if(!metaInfo.fileComment().isEmpty()) args << (IS_UNICODE(metaInfo.fileComment()) ? "--uComment" : "--lComment") << metaInfo.fileComment();
|
||||
if(metaInfo.fileYear()) args << "--ty" << QString::number(metaInfo.fileYear());
|
||||
if(metaInfo.filePosition()) args << "--tn" << QString::number(metaInfo.filePosition());
|
||||
|
||||
//args << "--tv" << QString().sprintf("Encoder=LameXP v%d.%02d.%04d [%s]", lamexp_version_major(), lamexp_version_minor(), lamexp_version_build(), lamexp_version_release());
|
||||
|
||||
args << QDir::toNativeSeparators(sourceFile.filePath());
|
||||
args << QDir::toNativeSeparators(sourceFile);
|
||||
args << QDir::toNativeSeparators(outputFile);
|
||||
|
||||
if(!startProcess(process, m_binary, args))
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
MP3Encoder(void);
|
||||
~MP3Encoder(void);
|
||||
|
||||
virtual bool encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag);
|
||||
virtual bool encode(const QString &sourceFile, const AudioFileModel &metaInfo, const QString &outputFile, volatile bool *abortFlag);
|
||||
virtual bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
|
||||
virtual QString extension(void);
|
||||
|
||||
|
@ -47,7 +47,7 @@ VorbisEncoder::~VorbisEncoder(void)
|
||||
{
|
||||
}
|
||||
|
||||
bool VorbisEncoder::encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag)
|
||||
bool VorbisEncoder::encode(const QString &sourceFile, const AudioFileModel &metaInfo, const QString &outputFile, volatile bool *abortFlag)
|
||||
{
|
||||
QProcess process;
|
||||
QStringList args;
|
||||
@ -68,18 +68,18 @@ bool VorbisEncoder::encode(const AudioFileModel &sourceFile, const QString &outp
|
||||
break;
|
||||
}
|
||||
|
||||
if(!sourceFile.fileName().isEmpty()) args << "-t" << sourceFile.fileName();
|
||||
if(!sourceFile.fileArtist().isEmpty()) args << "-a" << sourceFile.fileArtist();
|
||||
if(!sourceFile.fileAlbum().isEmpty()) args << "-l" << sourceFile.fileAlbum();
|
||||
if(!sourceFile.fileGenre().isEmpty()) args << "-G" << sourceFile.fileGenre();
|
||||
if(!sourceFile.fileComment().isEmpty()) args << "-c" << QString("comment=%1").arg(sourceFile.fileComment());
|
||||
if(sourceFile.fileYear()) args << "-d" << QString::number(sourceFile.fileYear());
|
||||
if(sourceFile.filePosition()) args << "-N" << QString::number(sourceFile.filePosition());
|
||||
if(!metaInfo.fileName().isEmpty()) args << "-t" << metaInfo.fileName();
|
||||
if(!metaInfo.fileArtist().isEmpty()) args << "-a" << metaInfo.fileArtist();
|
||||
if(!metaInfo.fileAlbum().isEmpty()) args << "-l" << metaInfo.fileAlbum();
|
||||
if(!metaInfo.fileGenre().isEmpty()) args << "-G" << metaInfo.fileGenre();
|
||||
if(!metaInfo.fileComment().isEmpty()) args << "-c" << QString("comment=%1").arg(metaInfo.fileComment());
|
||||
if(metaInfo.fileYear()) args << "-d" << QString::number(metaInfo.fileYear());
|
||||
if(metaInfo.filePosition()) args << "-N" << QString::number(metaInfo.filePosition());
|
||||
|
||||
//args << "--tv" << QString().sprintf("Encoder=LameXP v%d.%02d.%04d [%s]", lamexp_version_major(), lamexp_version_minor(), lamexp_version_build(), lamexp_version_release());
|
||||
|
||||
args << "-o" << QDir::toNativeSeparators(outputFile);
|
||||
args << QDir::toNativeSeparators(sourceFile.filePath());
|
||||
args << QDir::toNativeSeparators(sourceFile);
|
||||
|
||||
if(!startProcess(process, binary, args))
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
VorbisEncoder(void);
|
||||
~VorbisEncoder(void);
|
||||
|
||||
virtual bool encode(const AudioFileModel &sourceFile, const QString &outputFile, volatile bool *abortFlag);
|
||||
virtual bool encode(const QString &sourceFile, const AudioFileModel &metaInfo, const QString &outputFile, volatile bool *abortFlag);
|
||||
virtual bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
|
||||
virtual QString extension(void);
|
||||
|
||||
|
38
src/Registry_Decoder.cpp
Normal file
38
src/Registry_Decoder.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 "Registry_Decoder.h"
|
||||
|
||||
#include "Decoder_Abstract.h"
|
||||
#include "Decoder_MP3.h"
|
||||
#include "Decoder_Vorbis.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#define PROBE_DECODER(DEC) if(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)
|
||||
{
|
||||
PROBE_DECODER(MP3Decoder);
|
||||
PROBE_DECODER(VorbisDecoder);
|
||||
return NULL;
|
||||
}
|
||||
|
31
src/Registry_Decoder.h
Normal file
31
src/Registry_Decoder.h
Normal file
@ -0,0 +1,31 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
|
||||
class QString;
|
||||
class AbstractDecoder;
|
||||
|
||||
class DecoderRegistry
|
||||
{
|
||||
public:
|
||||
static AbstractDecoder *lookup(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
|
||||
};
|
@ -25,7 +25,8 @@
|
||||
#include "Model_AudioFile.h"
|
||||
#include "Model_Progress.h"
|
||||
#include "Encoder_Abstract.h"
|
||||
|
||||
#include "Decoder_Abstract.h"
|
||||
#include "Registry_Decoder.h"
|
||||
#include "Model_Settings.h"
|
||||
|
||||
#include <QUuid>
|
||||
@ -58,10 +59,17 @@ ProcessThread::ProcessThread(const AudioFileModel &audioFile, const QString &out
|
||||
|
||||
connect(m_encoder, SIGNAL(statusUpdated(int)), this, SLOT(handleUpdate(int)), Qt::DirectConnection);
|
||||
connect(m_encoder, SIGNAL(messageLogged(QString)), this, SLOT(handleMessage(QString)), Qt::DirectConnection);
|
||||
|
||||
m_currentStep = UnknownStep;
|
||||
}
|
||||
|
||||
ProcessThread::~ProcessThread(void)
|
||||
{
|
||||
while(!m_tempFiles.isEmpty())
|
||||
{
|
||||
QFile::remove(m_tempFiles.takeFirst());
|
||||
}
|
||||
|
||||
LAMEXP_DELETE(m_encoder);
|
||||
}
|
||||
|
||||
@ -84,10 +92,12 @@ void ProcessThread::run()
|
||||
void ProcessThread::processFile()
|
||||
{
|
||||
m_aborted = false;
|
||||
bool bSuccess = true;
|
||||
|
||||
qDebug("Process thread %s has started.", m_jobId.toString().toLatin1().constData());
|
||||
emit processStateInitialized(m_jobId, QFileInfo(m_audioFile.filePath()).fileName(), "Starting...", ProgressModel::JobRunning);
|
||||
|
||||
//Generate output file name
|
||||
QString outFileName = generateOutFileName();
|
||||
if(outFileName.isEmpty())
|
||||
{
|
||||
@ -96,22 +106,53 @@ void ProcessThread::processFile()
|
||||
return;
|
||||
}
|
||||
|
||||
QString sourceFile = m_audioFile.filePath();
|
||||
|
||||
//Decode source file
|
||||
if(!m_encoder->isFormatSupported(m_audioFile.formatContainerType(), m_audioFile.formatContainerProfile(), m_audioFile.formatAudioType(), m_audioFile.formatAudioProfile(), m_audioFile.formatAudioVersion()))
|
||||
{
|
||||
handleMessage(QString("The format of this file is NOT supported:\n%1\n\nContainer Format:\t%2\nAudio Format:\t%3").arg(m_audioFile.filePath(), m_audioFile.formatContainerInfo(), m_audioFile.formatAudioCompressInfo()));
|
||||
emit processStateChanged(m_jobId, "Unsupported!", ProgressModel::JobFailed);
|
||||
emit processStateFinished(m_jobId, outFileName, false);
|
||||
return;
|
||||
m_currentStep = DecodingStep;
|
||||
AbstractDecoder *decoder = DecoderRegistry::lookup(m_audioFile.formatContainerType(), m_audioFile.formatContainerProfile(), m_audioFile.formatAudioType(), m_audioFile.formatAudioProfile(), m_audioFile.formatAudioVersion());
|
||||
|
||||
if(decoder)
|
||||
{
|
||||
QString tempFile = generateTempFileName();
|
||||
|
||||
connect(decoder, SIGNAL(statusUpdated(int)), this, SLOT(handleUpdate(int)), Qt::DirectConnection);
|
||||
connect(decoder, SIGNAL(messageLogged(QString)), this, SLOT(handleMessage(QString)), Qt::DirectConnection);
|
||||
|
||||
bSuccess = decoder->decode(sourceFile, tempFile, &m_aborted);
|
||||
|
||||
if(bSuccess)
|
||||
{
|
||||
sourceFile = tempFile;
|
||||
handleMessage("\n-------------------------------\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
handleMessage(QString("The format of this file is NOT supported:\n%1\n\nContainer Format:\t%2\nAudio Format:\t%3").arg(m_audioFile.filePath(), m_audioFile.formatContainerInfo(), m_audioFile.formatAudioCompressInfo()));
|
||||
emit processStateChanged(m_jobId, "Unsupported!", ProgressModel::JobFailed);
|
||||
emit processStateFinished(m_jobId, outFileName, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool bSuccess = m_encoder->encode(m_audioFile, outFileName, &m_aborted);
|
||||
//Encode audio file
|
||||
if(bSuccess)
|
||||
{
|
||||
m_currentStep = EncodingStep;
|
||||
bSuccess = m_encoder->encode(sourceFile, m_audioFile, outFileName, &m_aborted);
|
||||
}
|
||||
|
||||
//Make sure output file exists
|
||||
if(bSuccess)
|
||||
{
|
||||
QFileInfo fileInfo(outFileName);
|
||||
bSuccess = fileInfo.exists() && fileInfo.isFile() && (fileInfo.size() > 0);
|
||||
}
|
||||
|
||||
//Report result
|
||||
emit processStateChanged(m_jobId, (bSuccess ? "Done." : (m_aborted ? "Aborted!" : "Failed!")), (bSuccess ? ProgressModel::JobComplete : ProgressModel::JobFailed));
|
||||
emit processStateFinished(m_jobId, outFileName, bSuccess);
|
||||
|
||||
@ -124,7 +165,15 @@ void ProcessThread::processFile()
|
||||
|
||||
void ProcessThread::handleUpdate(int progress)
|
||||
{
|
||||
emit processStateChanged(m_jobId, QString("Encoding (%1%)").arg(QString::number(progress)), ProgressModel::JobRunning);
|
||||
switch(m_currentStep)
|
||||
{
|
||||
case EncodingStep:
|
||||
emit processStateChanged(m_jobId, QString("Encoding (%1%)").arg(QString::number(progress)), ProgressModel::JobRunning);
|
||||
break;
|
||||
case DecodingStep:
|
||||
emit processStateChanged(m_jobId, QString("Decoding (%1%)").arg(QString::number(progress)), ProgressModel::JobRunning);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessThread::handleMessage(const QString &line)
|
||||
@ -200,6 +249,26 @@ QString ProcessThread::generateOutFileName(void)
|
||||
return outFileName;
|
||||
}
|
||||
|
||||
QString ProcessThread::generateTempFileName(void)
|
||||
{
|
||||
QMutexLocker lock(m_mutex_genFileName);
|
||||
QString tempFileName = QString("%1/%2.wav").arg(QDir::tempPath(), QUuid::createUuid().toString());
|
||||
|
||||
while(QFileInfo(tempFileName).exists())
|
||||
{
|
||||
tempFileName = QString("%1/%2.wav").arg(QDir::tempPath(), QUuid::createUuid().toString());
|
||||
}
|
||||
|
||||
QFile file(tempFileName);
|
||||
if(file.open(QFile::ReadWrite))
|
||||
{
|
||||
file.close();
|
||||
}
|
||||
|
||||
m_tempFiles << tempFileName;
|
||||
return tempFileName;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// EVENTS
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include <QThread>
|
||||
#include <QUuid>
|
||||
#include <QStringList>
|
||||
|
||||
#include "Model_AudioFile.h"
|
||||
#include "Encoder_Abstract.h"
|
||||
@ -53,14 +54,25 @@ signals:
|
||||
void processMessageLogged(const QUuid &jobId, const QString &line);
|
||||
|
||||
private:
|
||||
enum ProcessStep
|
||||
{
|
||||
DecodingStep = 0,
|
||||
FilteringStep = 1,
|
||||
EncodingStep = 2,
|
||||
UnknownStep = 3
|
||||
};
|
||||
|
||||
void processFile();
|
||||
QString generateOutFileName(void);
|
||||
QString generateTempFileName(void);
|
||||
|
||||
const QUuid m_jobId;
|
||||
AudioFileModel m_audioFile;
|
||||
AbstractEncoder *m_encoder;
|
||||
const QString m_outputDirectory;
|
||||
volatile bool m_aborted;
|
||||
ProcessStep m_currentStep;
|
||||
QStringList m_tempFiles;
|
||||
|
||||
static QMutex *m_mutex_genFileName;
|
||||
};
|
||||
|
167
src/Tool_Abstract.cpp
Normal file
167
src/Tool_Abstract.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 "Tool_Abstract.h"
|
||||
|
||||
#include <QProcess>
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QLibrary>
|
||||
#include <Windows.h>
|
||||
|
||||
/*
|
||||
* Win32 API definitions
|
||||
*/
|
||||
typedef HANDLE (WINAPI *CreateJobObjectFun)(__in_opt LPSECURITY_ATTRIBUTES lpJobAttributes, __in_opt LPCSTR lpName);
|
||||
typedef BOOL (WINAPI *SetInformationJobObjectFun)(__in HANDLE hJob, __in JOBOBJECTINFOCLASS JobObjectInformationClass, __in_bcount(cbJobObjectInformationLength) LPVOID lpJobObjectInformation, __in DWORD cbJobObjectInformationLength);
|
||||
typedef BOOL (WINAPI *AssignProcessToJobObjectFun)(__in HANDLE hJob, __in HANDLE hProcess);
|
||||
|
||||
/*
|
||||
* Static vars
|
||||
*/
|
||||
QMutex *AbstractTool::m_mutex_startProcess = NULL;
|
||||
HANDLE AbstractTool::m_handle_jobObject = NULL;
|
||||
|
||||
/*
|
||||
* Constructor
|
||||
*/
|
||||
AbstractTool::AbstractTool(void)
|
||||
{
|
||||
static CreateJobObjectFun CreateJobObjectPtr = NULL;
|
||||
static SetInformationJobObjectFun SetInformationJobObjectPtr = NULL;
|
||||
|
||||
if(!m_mutex_startProcess)
|
||||
{
|
||||
m_mutex_startProcess = new QMutex();
|
||||
}
|
||||
|
||||
if(!m_handle_jobObject)
|
||||
{
|
||||
if(!CreateJobObjectPtr || !SetInformationJobObjectPtr)
|
||||
{
|
||||
QLibrary Kernel32Lib("kernel32.dll");
|
||||
CreateJobObjectPtr = (CreateJobObjectFun) Kernel32Lib.resolve("CreateJobObjectA");
|
||||
SetInformationJobObjectPtr = (SetInformationJobObjectFun) Kernel32Lib.resolve("SetInformationJobObject");
|
||||
}
|
||||
if(CreateJobObjectPtr && SetInformationJobObjectPtr)
|
||||
{
|
||||
m_handle_jobObject = CreateJobObjectPtr(NULL, NULL);
|
||||
if(m_handle_jobObject == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
m_handle_jobObject = NULL;
|
||||
}
|
||||
if(m_handle_jobObject)
|
||||
{
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
|
||||
memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
|
||||
SetInformationJobObjectPtr(m_handle_jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Destructor
|
||||
*/
|
||||
AbstractTool::~AbstractTool(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize and launch process object
|
||||
*/
|
||||
bool AbstractTool::startProcess(QProcess &process, const QString &program, const QStringList &args)
|
||||
{
|
||||
static AssignProcessToJobObjectFun AssignProcessToJobObjectPtr = NULL;
|
||||
|
||||
QMutexLocker lock(m_mutex_startProcess);
|
||||
|
||||
emit messageLogged(commandline2string(program, args) + "\n");
|
||||
|
||||
if(!AssignProcessToJobObjectPtr)
|
||||
{
|
||||
QLibrary Kernel32Lib("kernel32.dll");
|
||||
AssignProcessToJobObjectPtr = (AssignProcessToJobObjectFun) Kernel32Lib.resolve("AssignProcessToJobObject");
|
||||
}
|
||||
|
||||
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||
process.setReadChannel(QProcess::StandardOutput);
|
||||
process.start(program, args);
|
||||
|
||||
if(process.waitForStarted())
|
||||
{
|
||||
|
||||
if(AssignProcessToJobObjectPtr)
|
||||
{
|
||||
AssignProcessToJobObjectPtr(m_handle_jobObject, process.pid()->hProcess);
|
||||
}
|
||||
if(!SetPriorityClass(process.pid()->hProcess, BELOW_NORMAL_PRIORITY_CLASS))
|
||||
{
|
||||
SetPriorityClass(process.pid()->hProcess, IDLE_PRIORITY_CLASS);
|
||||
}
|
||||
lock.unlock();
|
||||
emit statusUpdated(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert program arguments to single string
|
||||
*/
|
||||
QString AbstractTool::commandline2string(const QString &program, const QStringList &arguments)
|
||||
{
|
||||
QString commandline = (program.contains(' ') ? QString("\"%1\"").arg(program) : program);
|
||||
|
||||
for(int i = 0; i < arguments.count(); i++)
|
||||
{
|
||||
commandline += (arguments.at(i).contains(' ') ? QString(" \"%1\"").arg(arguments.at(i)) : QString(" %1").arg(arguments.at(i)));
|
||||
}
|
||||
|
||||
return commandline;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert long path to short path
|
||||
*/
|
||||
QString AbstractTool::pathToShort(const QString &longPath)
|
||||
{
|
||||
QString shortPath;
|
||||
DWORD buffSize = GetShortPathNameW(reinterpret_cast<const wchar_t*>(longPath.utf16()), NULL, NULL);
|
||||
|
||||
if(buffSize > 0)
|
||||
{
|
||||
wchar_t *buffer = new wchar_t[buffSize];
|
||||
DWORD result = GetShortPathNameW(reinterpret_cast<const wchar_t*>(longPath.utf16()), buffer, buffSize);
|
||||
|
||||
if(result > 0 && result < buffSize)
|
||||
{
|
||||
shortPath = QString::fromUtf16(reinterpret_cast<const unsigned short*>(buffer));
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
return (shortPath.isEmpty() ? longPath : shortPath);
|
||||
}
|
||||
|
48
src/Tool_Abstract.h
Normal file
48
src/Tool_Abstract.h
Normal file
@ -0,0 +1,48 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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 <QObject>
|
||||
|
||||
class QMutex;
|
||||
class QProcess;
|
||||
|
||||
class AbstractTool : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AbstractTool(void);
|
||||
~AbstractTool(void);
|
||||
|
||||
bool startProcess(QProcess &process, const QString &program, const QStringList &args);
|
||||
static QString commandline2string(const QString &program, const QStringList &arguments);
|
||||
static QString AbstractTool::pathToShort(const QString &longPath);
|
||||
|
||||
signals:
|
||||
void statusUpdated(int progress);
|
||||
void messageLogged(const QString &line);
|
||||
|
||||
private:
|
||||
static QMutex *m_mutex_startProcess;
|
||||
static void *m_handle_jobObject;
|
||||
};
|
Loading…
Reference in New Issue
Block a user