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"
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
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
|
<File
|
||||||
RelativePath=".\src\Dialog_About.cpp"
|
RelativePath=".\src\Dialog_About.cpp"
|
||||||
>
|
>
|
||||||
@ -374,6 +390,10 @@
|
|||||||
RelativePath=".\src\Model_Settings.cpp"
|
RelativePath=".\src\Model_Settings.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\Registry_Decoder.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\Thread_FileAnalyzer.cpp"
|
RelativePath=".\src\Thread_FileAnalyzer.cpp"
|
||||||
>
|
>
|
||||||
@ -394,6 +414,10 @@
|
|||||||
RelativePath=".\src\Thread_Process.cpp"
|
RelativePath=".\src\Thread_Process.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\Tool_Abstract.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
@ -404,6 +428,44 @@
|
|||||||
RelativePath=".\src\Config.h"
|
RelativePath=".\src\Config.h"
|
||||||
>
|
>
|
||||||
</File>
|
</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
|
<File
|
||||||
RelativePath=".\src\Dialog_About.h"
|
RelativePath=".\src\Dialog_About.h"
|
||||||
>
|
>
|
||||||
@ -617,7 +679,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
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""
|
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
@ -627,7 +689,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
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""
|
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
@ -637,7 +699,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
Description="MOC "$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
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""
|
Outputs=""$(SolutionDir)tmp\MOC_$(SafeInputName).cpp""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
@ -904,6 +966,10 @@
|
|||||||
RelativePath=".\src\Model_Settings.h"
|
RelativePath=".\src\Model_Settings.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\src\Registry_Decoder.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\Resource.h"
|
RelativePath=".\src\Resource.h"
|
||||||
>
|
>
|
||||||
@ -1082,12 +1148,50 @@
|
|||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</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>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Generated Files"
|
Name="Generated Files"
|
||||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
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}"
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\tmp\MOC_Decoder_Abstract.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\tmp\MOC_Dialog_About.cpp"
|
RelativePath=".\tmp\MOC_Dialog_About.cpp"
|
||||||
>
|
>
|
||||||
@ -1164,6 +1268,10 @@
|
|||||||
RelativePath=".\tmp\MOC_Thread_Process.cpp"
|
RelativePath=".\tmp\MOC_Thread_Process.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\tmp\MOC_Tool_Abstract.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\tmp\RCC_Icons.cpp"
|
RelativePath=".\tmp\RCC_Icons.cpp"
|
||||||
>
|
>
|
||||||
@ -1477,7 +1585,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
Description="UIC "$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
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""
|
Outputs=""$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
@ -1487,7 +1595,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
Description="UIC "$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
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""
|
Outputs=""$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
@ -1497,7 +1605,7 @@
|
|||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
Description="UIC "$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
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""
|
Outputs=""$(SolutionDir)tmp\UIC_$(SafeInputName).h""
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
|
@ -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 105
|
#define VER_LAMEXP_BUILD 110
|
||||||
#define VER_LAMEXP_SUFFIX TechPreview
|
#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_Settings.h"
|
||||||
#include "Model_FileList.h"
|
#include "Model_FileList.h"
|
||||||
#include "Model_FileSystem.h"
|
#include "Model_FileSystem.h"
|
||||||
#include "Encoder_MP3.h"
|
|
||||||
|
|
||||||
//Qt includes
|
//Qt includes
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
@ -21,57 +21,10 @@
|
|||||||
|
|
||||||
#include "Encoder_Abstract.h"
|
#include "Encoder_Abstract.h"
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QMutexLocker>
|
|
||||||
#include <QLibrary>
|
|
||||||
#include <Windows.h>
|
#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)
|
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_configBitrate = 0;
|
||||||
m_configRCMode = 0;
|
m_configRCMode = 0;
|
||||||
}
|
}
|
||||||
@ -86,57 +39,3 @@ AbstractEncoder::~AbstractEncoder(void)
|
|||||||
|
|
||||||
void AbstractEncoder::setBitrate(int bitrate) { m_configBitrate = max(0, bitrate); }
|
void AbstractEncoder::setBitrate(int bitrate) { m_configBitrate = max(0, bitrate); }
|
||||||
void AbstractEncoder::setRCMode(int mode) { m_configRCMode = max(0, mode); }
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include "Tool_Abstract.h"
|
||||||
#include "Model_AudioFile.h"
|
#include "Model_AudioFile.h"
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class QProcess;
|
class QProcess;
|
||||||
class QStringList;
|
class QStringList;
|
||||||
class QMutex;
|
class QMutex;
|
||||||
|
|
||||||
class AbstractEncoder : public QObject
|
class AbstractEncoder : public AbstractTool
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -38,7 +37,7 @@ public:
|
|||||||
~AbstractEncoder(void);
|
~AbstractEncoder(void);
|
||||||
|
|
||||||
//Internal encoder API
|
//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 bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion) = 0;
|
||||||
virtual QString extension(void) = 0;
|
virtual QString extension(void) = 0;
|
||||||
|
|
||||||
@ -46,19 +45,7 @@ public:
|
|||||||
void setBitrate(int bitrate);
|
void setBitrate(int bitrate);
|
||||||
void setRCMode(int mode);
|
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:
|
protected:
|
||||||
int m_configBitrate;
|
int m_configBitrate;
|
||||||
int m_configRCMode;
|
int m_configRCMode;
|
||||||
|
|
||||||
private:
|
|
||||||
static QMutex *m_mutex_startProcess;
|
|
||||||
static void *m_handle_jobObject;
|
|
||||||
};
|
};
|
||||||
|
@ -27,11 +27,11 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QDir>
|
#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()))
|
#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())
|
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;
|
QProcess process;
|
||||||
const QString baseName = QFileInfo(outputFile).fileName();
|
|
||||||
QStringList args;
|
QStringList args;
|
||||||
|
|
||||||
args << "--nohist";
|
args << "--nohist";
|
||||||
@ -69,17 +68,17 @@ bool MP3Encoder::encode(const AudioFileModel &sourceFile, const QString &outputF
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sourceFile.fileName().isEmpty()) args << (IS_UNICODE(sourceFile.fileName()) ? "--uTitle" : "--lTitle") << sourceFile.fileName();
|
if(!metaInfo.fileName().isEmpty()) args << (IS_UNICODE(metaInfo.fileName()) ? "--uTitle" : "--lTitle") << metaInfo.fileName();
|
||||||
if(!sourceFile.fileArtist().isEmpty()) args << (IS_UNICODE(sourceFile.fileArtist()) ? "--uArtist" : "--lArtist") << sourceFile.fileArtist();
|
if(!metaInfo.fileArtist().isEmpty()) args << (IS_UNICODE(metaInfo.fileArtist()) ? "--uArtist" : "--lArtist") << metaInfo.fileArtist();
|
||||||
if(!sourceFile.fileAlbum().isEmpty()) args << (IS_UNICODE(sourceFile.fileAlbum()) ? "--uAlbum" : "--lAlbum") << sourceFile.fileAlbum();
|
if(!metaInfo.fileAlbum().isEmpty()) args << (IS_UNICODE(metaInfo.fileAlbum()) ? "--uAlbum" : "--lAlbum") << metaInfo.fileAlbum();
|
||||||
if(!sourceFile.fileGenre().isEmpty()) args << (IS_UNICODE(sourceFile.fileGenre()) ? "--uGenre" : "--lGenre") << sourceFile.fileGenre();
|
if(!metaInfo.fileGenre().isEmpty()) args << (IS_UNICODE(metaInfo.fileGenre()) ? "--uGenre" : "--lGenre") << metaInfo.fileGenre();
|
||||||
if(!sourceFile.fileComment().isEmpty()) args << (IS_UNICODE(sourceFile.fileComment()) ? "--uComment" : "--lComment") << sourceFile.fileComment();
|
if(!metaInfo.fileComment().isEmpty()) args << (IS_UNICODE(metaInfo.fileComment()) ? "--uComment" : "--lComment") << metaInfo.fileComment();
|
||||||
if(sourceFile.fileYear()) args << "--ty" << QString::number(sourceFile.fileYear());
|
if(metaInfo.fileYear()) args << "--ty" << QString::number(metaInfo.fileYear());
|
||||||
if(sourceFile.filePosition()) args << "--tn" << QString::number(sourceFile.filePosition());
|
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 << "--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);
|
args << QDir::toNativeSeparators(outputFile);
|
||||||
|
|
||||||
if(!startProcess(process, m_binary, args))
|
if(!startProcess(process, m_binary, args))
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
MP3Encoder(void);
|
MP3Encoder(void);
|
||||||
~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 bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
|
||||||
virtual QString extension(void);
|
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;
|
QProcess process;
|
||||||
QStringList args;
|
QStringList args;
|
||||||
@ -68,18 +68,18 @@ bool VorbisEncoder::encode(const AudioFileModel &sourceFile, const QString &outp
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!sourceFile.fileName().isEmpty()) args << "-t" << sourceFile.fileName();
|
if(!metaInfo.fileName().isEmpty()) args << "-t" << metaInfo.fileName();
|
||||||
if(!sourceFile.fileArtist().isEmpty()) args << "-a" << sourceFile.fileArtist();
|
if(!metaInfo.fileArtist().isEmpty()) args << "-a" << metaInfo.fileArtist();
|
||||||
if(!sourceFile.fileAlbum().isEmpty()) args << "-l" << sourceFile.fileAlbum();
|
if(!metaInfo.fileAlbum().isEmpty()) args << "-l" << metaInfo.fileAlbum();
|
||||||
if(!sourceFile.fileGenre().isEmpty()) args << "-G" << sourceFile.fileGenre();
|
if(!metaInfo.fileGenre().isEmpty()) args << "-G" << metaInfo.fileGenre();
|
||||||
if(!sourceFile.fileComment().isEmpty()) args << "-c" << QString("comment=%1").arg(sourceFile.fileComment());
|
if(!metaInfo.fileComment().isEmpty()) args << "-c" << QString("comment=%1").arg(metaInfo.fileComment());
|
||||||
if(sourceFile.fileYear()) args << "-d" << QString::number(sourceFile.fileYear());
|
if(metaInfo.fileYear()) args << "-d" << QString::number(metaInfo.fileYear());
|
||||||
if(sourceFile.filePosition()) args << "-N" << QString::number(sourceFile.filePosition());
|
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 << "--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 << "-o" << QDir::toNativeSeparators(outputFile);
|
||||||
args << QDir::toNativeSeparators(sourceFile.filePath());
|
args << QDir::toNativeSeparators(sourceFile);
|
||||||
|
|
||||||
if(!startProcess(process, binary, args))
|
if(!startProcess(process, binary, args))
|
||||||
{
|
{
|
||||||
|
@ -33,7 +33,7 @@ public:
|
|||||||
VorbisEncoder(void);
|
VorbisEncoder(void);
|
||||||
~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 bool isFormatSupported(const QString &containerType, const QString &containerProfile, const QString &formatType, const QString &formatProfile, const QString &formatVersion);
|
||||||
virtual QString extension(void);
|
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_AudioFile.h"
|
||||||
#include "Model_Progress.h"
|
#include "Model_Progress.h"
|
||||||
#include "Encoder_Abstract.h"
|
#include "Encoder_Abstract.h"
|
||||||
|
#include "Decoder_Abstract.h"
|
||||||
|
#include "Registry_Decoder.h"
|
||||||
#include "Model_Settings.h"
|
#include "Model_Settings.h"
|
||||||
|
|
||||||
#include <QUuid>
|
#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(statusUpdated(int)), this, SLOT(handleUpdate(int)), Qt::DirectConnection);
|
||||||
connect(m_encoder, SIGNAL(messageLogged(QString)), this, SLOT(handleMessage(QString)), Qt::DirectConnection);
|
connect(m_encoder, SIGNAL(messageLogged(QString)), this, SLOT(handleMessage(QString)), Qt::DirectConnection);
|
||||||
|
|
||||||
|
m_currentStep = UnknownStep;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessThread::~ProcessThread(void)
|
ProcessThread::~ProcessThread(void)
|
||||||
{
|
{
|
||||||
|
while(!m_tempFiles.isEmpty())
|
||||||
|
{
|
||||||
|
QFile::remove(m_tempFiles.takeFirst());
|
||||||
|
}
|
||||||
|
|
||||||
LAMEXP_DELETE(m_encoder);
|
LAMEXP_DELETE(m_encoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,10 +92,12 @@ void ProcessThread::run()
|
|||||||
void ProcessThread::processFile()
|
void ProcessThread::processFile()
|
||||||
{
|
{
|
||||||
m_aborted = false;
|
m_aborted = false;
|
||||||
|
bool bSuccess = true;
|
||||||
|
|
||||||
qDebug("Process thread %s has started.", m_jobId.toString().toLatin1().constData());
|
qDebug("Process thread %s has started.", m_jobId.toString().toLatin1().constData());
|
||||||
emit processStateInitialized(m_jobId, QFileInfo(m_audioFile.filePath()).fileName(), "Starting...", ProgressModel::JobRunning);
|
emit processStateInitialized(m_jobId, QFileInfo(m_audioFile.filePath()).fileName(), "Starting...", ProgressModel::JobRunning);
|
||||||
|
|
||||||
|
//Generate output file name
|
||||||
QString outFileName = generateOutFileName();
|
QString outFileName = generateOutFileName();
|
||||||
if(outFileName.isEmpty())
|
if(outFileName.isEmpty())
|
||||||
{
|
{
|
||||||
@ -96,22 +106,53 @@ void ProcessThread::processFile()
|
|||||||
return;
|
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()))
|
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()));
|
m_currentStep = DecodingStep;
|
||||||
emit processStateChanged(m_jobId, "Unsupported!", ProgressModel::JobFailed);
|
AbstractDecoder *decoder = DecoderRegistry::lookup(m_audioFile.formatContainerType(), m_audioFile.formatContainerProfile(), m_audioFile.formatAudioType(), m_audioFile.formatAudioProfile(), m_audioFile.formatAudioVersion());
|
||||||
emit processStateFinished(m_jobId, outFileName, false);
|
|
||||||
return;
|
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)
|
if(bSuccess)
|
||||||
{
|
{
|
||||||
QFileInfo fileInfo(outFileName);
|
QFileInfo fileInfo(outFileName);
|
||||||
bSuccess = fileInfo.exists() && fileInfo.isFile() && (fileInfo.size() > 0);
|
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 processStateChanged(m_jobId, (bSuccess ? "Done." : (m_aborted ? "Aborted!" : "Failed!")), (bSuccess ? ProgressModel::JobComplete : ProgressModel::JobFailed));
|
||||||
emit processStateFinished(m_jobId, outFileName, bSuccess);
|
emit processStateFinished(m_jobId, outFileName, bSuccess);
|
||||||
|
|
||||||
@ -124,7 +165,15 @@ void ProcessThread::processFile()
|
|||||||
|
|
||||||
void ProcessThread::handleUpdate(int progress)
|
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)
|
void ProcessThread::handleMessage(const QString &line)
|
||||||
@ -200,6 +249,26 @@ QString ProcessThread::generateOutFileName(void)
|
|||||||
return outFileName;
|
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
|
// EVENTS
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
#include "Model_AudioFile.h"
|
#include "Model_AudioFile.h"
|
||||||
#include "Encoder_Abstract.h"
|
#include "Encoder_Abstract.h"
|
||||||
@ -53,14 +54,25 @@ signals:
|
|||||||
void processMessageLogged(const QUuid &jobId, const QString &line);
|
void processMessageLogged(const QUuid &jobId, const QString &line);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum ProcessStep
|
||||||
|
{
|
||||||
|
DecodingStep = 0,
|
||||||
|
FilteringStep = 1,
|
||||||
|
EncodingStep = 2,
|
||||||
|
UnknownStep = 3
|
||||||
|
};
|
||||||
|
|
||||||
void processFile();
|
void processFile();
|
||||||
QString generateOutFileName(void);
|
QString generateOutFileName(void);
|
||||||
|
QString generateTempFileName(void);
|
||||||
|
|
||||||
const QUuid m_jobId;
|
const QUuid m_jobId;
|
||||||
AudioFileModel m_audioFile;
|
AudioFileModel m_audioFile;
|
||||||
AbstractEncoder *m_encoder;
|
AbstractEncoder *m_encoder;
|
||||||
const QString m_outputDirectory;
|
const QString m_outputDirectory;
|
||||||
volatile bool m_aborted;
|
volatile bool m_aborted;
|
||||||
|
ProcessStep m_currentStep;
|
||||||
|
QStringList m_tempFiles;
|
||||||
|
|
||||||
static QMutex *m_mutex_genFileName;
|
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