OSDN Git Service

Updated CA certificates file for cURL.
[lamexp/LameXP.git] / src / Encoder_MAC.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2022 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU GENERAL PUBLIC LICENSE as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version; always including the non-optional
9 // LAMEXP GNU GENERAL PUBLIC LICENSE ADDENDUM. See "License.txt" file!
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include "Encoder_MAC.h"
24
25 #include "Global.h"
26 #include "Model_Settings.h"
27
28 #include <QProcess>
29 #include <QDir>
30
31 #define APPEND_TAG(NAME, VALUE) do \
32 { \
33         if (!buffer.isEmpty()) buffer += L1C('|'); \
34         buffer += QString("%1=%2").arg((NAME), (VALUE)); \
35 } \
36 while(0)
37
38 ///////////////////////////////////////////////////////////////////////////////
39 // Encoder Info
40 ///////////////////////////////////////////////////////////////////////////////
41
42 class MACEncoderInfo : public AbstractEncoderInfo
43 {
44         virtual bool isModeSupported(int mode) const
45         {
46                 switch(mode)
47                 {
48                 case SettingsModel::VBRMode:
49                         return true;
50                         break;
51                 case SettingsModel::ABRMode:
52                 case SettingsModel::CBRMode:
53                         return false;
54                         break;
55                 default:
56                         MUTILS_THROW("Bad RC mode specified!");
57                 }
58         }
59
60         virtual int valueCount(int mode) const
61         {
62                 switch(mode)
63                 {
64                 case SettingsModel::VBRMode:
65                         return 5;
66                         break;
67                 case SettingsModel::ABRMode:
68                 case SettingsModel::CBRMode:
69                         return -1;
70                         break;
71                 default:
72                         MUTILS_THROW("Bad RC mode specified!");
73                 }
74         }
75
76         virtual int valueAt(int mode, int index) const
77         {
78                 switch(mode)
79                 {
80                 case SettingsModel::VBRMode:
81                         return qBound(0, index + 1, 8);
82                         break;
83                 case SettingsModel::ABRMode:
84                 case SettingsModel::CBRMode:
85                         return -1;
86                         break;
87                 default:
88                         MUTILS_THROW("Bad RC mode specified!");
89                 }
90         }
91
92         virtual int valueType(int mode) const
93         {
94                 switch(mode)
95                 {
96                 case SettingsModel::VBRMode:
97                         return TYPE_COMPRESSION_LEVEL;
98                         break;
99                 case SettingsModel::ABRMode:
100                 case SettingsModel::CBRMode:
101                         return -1;
102                         break;
103                 default:
104                         MUTILS_THROW("Bad RC mode specified!");
105                 }
106         }
107
108         virtual const char *description(void) const
109         {
110                 static const char* s_description = "Monkey's Audio (MAC)";
111                 return s_description;
112         }
113
114         virtual const char *extension(void) const
115         {
116                 static const char* s_extension = "ape";
117                 return s_extension;
118         }
119
120         virtual bool isResamplingSupported(void) const
121         {
122                 return false;
123         }
124 }
125 static const g_macEncoderInfo;
126
127 ///////////////////////////////////////////////////////////////////////////////
128 // Encoder implementation
129 ///////////////////////////////////////////////////////////////////////////////
130
131 MACEncoder::MACEncoder(void)
132 :
133         m_binary(lamexp_tools_lookup(L1S("mac.exe")))
134 {
135         if (m_binary.isEmpty())
136         {
137                 MUTILS_THROW("Error initializing MAC encoder. Tool 'mac.exe' is not registred!");
138         }
139 }
140
141 MACEncoder::~MACEncoder(void)
142 {
143 }
144
145 bool MACEncoder::encode(const QString &sourceFile, const AudioFileModel_MetaInfo &metaInfo, const unsigned int /*duration*/, const unsigned int /*channels*/, const QString &outputFile, QAtomicInt &abortFlag)
146 {
147         QProcess process;
148         QStringList args;
149         
150         const QString baseName = QFileInfo(outputFile).fileName();
151
152         args << QDir::toNativeSeparators(sourceFile);
153         args << QDir::toNativeSeparators(outputFile);
154
155         switch(m_configRCMode)
156         {
157         case SettingsModel::VBRMode:
158                 args << QString().sprintf("-c%d", (m_configBitrate + 1) * 1000);
159                 break;
160         default:
161                 MUTILS_THROW("Bad rate-control mode!");
162                 break;
163         }
164
165         if (!metaInfo.empty(true))
166         {
167                 const QString apeTagsData = createApeTags(metaInfo);
168                 if (!apeTagsData.isEmpty())
169                 {
170                         args << "-t" << apeTagsData;
171                 }
172         }
173
174         if(!startProcess(process, m_binary, args))
175         {
176                 return false;
177         }
178
179         int prevProgress = -1;
180         QRegExp regExp(L1S("Progress: (\\d+).(\\d+)%"));
181
182         const result_t result = awaitProcess(process, abortFlag, [this, &prevProgress, &regExp](const QString &text)
183         {
184                 if (regExp.lastIndexIn(text) >= 0)
185                 {
186                         qint32 newProgress;
187                         if (MUtils::regexp_parse_int32(regExp, newProgress))
188                         {
189                                 if (newProgress > prevProgress)
190                                 {
191                                         emit statusUpdated(newProgress);
192                                         prevProgress = NEXT_PROGRESS(newProgress);
193                                 }
194                         }
195                         return true;
196                 }
197                 return false;
198         });
199
200         return (result == RESULT_SUCCESS);
201 }
202
203 bool MACEncoder::isFormatSupported(const QString &containerType, const QString& /*containerProfile*/, const QString &formatType, const QString& /*formatProfile*/, const QString& /*formatVersion*/)
204 {
205         if(containerType.compare(L1S("Wave"), Qt::CaseInsensitive) == 0)
206         {
207                 if(formatType.compare(L1S("PCM"), Qt::CaseInsensitive) == 0)
208                 {
209                         return true;
210                 }
211         }
212
213         return false;
214 }
215
216 const AbstractEncoderInfo *MACEncoder::getEncoderInfo(void)
217 {
218         return &g_macEncoderInfo;
219 }
220
221 QString MACEncoder::createApeTags(const AudioFileModel_MetaInfo &metaInfo)
222 {
223         QString buffer;
224
225         if (!metaInfo.title().isEmpty())   APPEND_TAG(L1S("Title"),   cleanTag(metaInfo.title()));
226         if (!metaInfo.artist().isEmpty())  APPEND_TAG(L1S("Artist"),  cleanTag(metaInfo.artist()));
227         if (!metaInfo.album().isEmpty())   APPEND_TAG(L1S("Album"),   cleanTag(metaInfo.album()));
228         if (!metaInfo.genre().isEmpty())   APPEND_TAG(L1S("Genre"),   cleanTag(metaInfo.genre()));
229         if (!metaInfo.comment().isEmpty()) APPEND_TAG(L1S("Comment"), cleanTag(metaInfo.comment()));
230         if (metaInfo.year())               APPEND_TAG(L1S("Year"),    QString::number(metaInfo.year()));
231         if (metaInfo.position())           APPEND_TAG(L1S("Track"),   QString::number(metaInfo.position()));
232
233         return buffer;
234 }