Audacity 3.2.0
FFmpegPresets.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 FFmpegPresets.cpp
6
7 Audacity(R) is copyright (c) 1999-2010 Audacity Team.
8 License: GPL v2 or later. See License.txt.
9
10 LRN
11
12 Vitaly Sverchinsky split from ExportFFmpegDialogs.cpp
13
14**********************************************************************/
15
16#include "FFmpegPresets.h"
17
18#include <wx/spinctrl.h>
19#include <wx/listbox.h>
20#include <wx/checkbox.h>
21#include <wx/choice.h>
22#include <wx/textctrl.h>
23
24#include "FFmpegDefines.h"
25#include "ExportFFmpegOptions.h"
26
27#include "XMLFileReader.h"
28#include "AudacityMessageBox.h"
29
30
32{
33 mControlState.resize(FELastID - FEFirstID);
34}
35
37{
38}
39
41{
42 mPreset = NULL;
43 mAbortImport = false;
44
45 XMLFileReader xmlfile;
46 wxFileName xmlFileName(FileNames::DataDir(), wxT("ffmpeg_presets.xml"));
47 xmlfile.Parse(this,xmlFileName.GetFullPath());
48}
49
51{
52 // We're in a destructor! Don't let exceptions out!
53 GuardedCall( [&] {
54 wxFileName xmlFileName{ FileNames::DataDir(), wxT("ffmpeg_presets.xml") };
55 XMLFileWriter writer{
56 xmlFileName.GetFullPath(), XO("Error Saving FFmpeg Presets") };
57 WriteXMLHeader(writer);
58 WriteXML(writer);
59 writer.Commit();
60 } );
61}
62
63void FFmpegPresets::ImportPresets(wxString &filename)
64{
65 mPreset = NULL;
66 mAbortImport = false;
67
68 FFmpegPresetMap savePresets = mPresets;
69
70 XMLFileReader xmlfile;
71 bool success = xmlfile.Parse(this,filename);
72 if (!success || mAbortImport) {
73 mPresets = savePresets;
74 }
75}
76
77void FFmpegPresets::ExportPresets(wxString &filename)
78{
79 GuardedCall( [&] {
80 XMLFileWriter writer{ filename, XO("Error Saving FFmpeg Presets") };
81 WriteXMLHeader(writer);
82 WriteXML(writer);
83 writer.Commit();
84 } );
85}
86
87void FFmpegPresets::GetPresetList(wxArrayString &list)
88{
89 list.clear();
90 FFmpegPresetMap::iterator iter;
91 for (iter = mPresets.begin(); iter != mPresets.end(); ++iter)
92 {
93 list.push_back(iter->second.mPresetName);
94 }
95
96 std::sort( list.begin(), list.end() );
97}
98
100{
101 FFmpegPresetMap::iterator iter = mPresets.find(name);
102 if (iter != mPresets.end())
103 {
104 mPresets.erase(iter);
105 }
106}
107
109{
110 FFmpegPresetMap::iterator iter = mPresets.find(name);
111 if (iter != mPresets.end())
112 {
113 return &iter->second;
114 }
115
116 return NULL;
117}
118
119// return false if overwrite was not allowed.
121{
123 if (preset)
124 {
125 auto query = XO("Overwrite preset '%s'?").Format(name);
126 int action = AudacityMessageBox(
127 query,
128 XO("Confirm Overwrite"),
129 wxYES_NO | wxCENTRE);
130 if (action == wxNO) return false;
131 }
132 return true;
133}
134
135
137{
138 wxString format;
139 wxString codec;
141
142 {
143 wxWindow *wnd;
144 wxListBox *lb;
145
146 wnd = dynamic_cast<wxWindow*>(parent)->FindWindowById(FEFormatID,parent);
147 lb = dynamic_cast<wxListBox*>(wnd);
148 if (lb->GetSelection() < 0)
149 {
150 AudacityMessageBox( XO("Please select format before saving a profile") );
151 return false;
152 }
153 format = lb->GetStringSelection();
154
155 wnd = dynamic_cast<wxWindow*>(parent)->FindWindowById(FECodecID,parent);
156 lb = dynamic_cast<wxListBox*>(wnd);
157 if (lb->GetSelection() < 0)
158 {
159 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
160 AudacityMessageBox( XO("Please select codec before saving a profile") );
161 return false;
162 }
163 codec = lb->GetStringSelection();
164 }
165
166 preset = &mPresets[name];
167 preset->mPresetName = name;
168
169 wxSpinCtrl *sc;
170 wxTextCtrl *tc;
171 wxCheckBox *cb;
172 wxChoice *ch;
173
174 for (int id = FEFirstID; id < FELastID; id++)
175 {
176 wxWindow *wnd = dynamic_cast<wxWindow*>(parent)->FindWindowById(id,parent);
177 if (wnd != NULL)
178 {
179 switch(id)
180 {
181 case FEFormatID:
182 preset->mControlState[id - FEFirstID] = format;
183 break;
184 case FECodecID:
185 preset->mControlState[id - FEFirstID] = codec;
186 break;
187 // Spin control
188 case FEBitrateID:
189 case FEQualityID:
190 case FESampleRateID:
191 case FECutoffID:
192 case FEFrameSizeID:
193 case FEBufSizeID:
194 case FECompLevelID:
195 case FELPCCoeffsID:
196 case FEMinPredID:
197 case FEMaxPredID:
198 case FEMinPartOrderID:
199 case FEMaxPartOrderID:
200 case FEMuxRateID:
201 case FEPacketSizeID:
202 sc = dynamic_cast<wxSpinCtrl*>(wnd);
203 preset->mControlState[id - FEFirstID] = wxString::Format(wxT("%d"),sc->GetValue());
204 break;
205 // Text control
206 case FELanguageID:
207 case FETagID:
208 tc = dynamic_cast<wxTextCtrl*>(wnd);
209 preset->mControlState[id - FEFirstID] = tc->GetValue();
210 break;
211 // Choice
212 case FEProfileID:
213 case FEPredOrderID:
214 ch = dynamic_cast<wxChoice*>(wnd);
215 preset->mControlState[id - FEFirstID] = wxString::Format(wxT("%d"),ch->GetSelection());
216 break;
217 // Check box
218 case FEUseLPCID:
219 case FEBitReservoirID:
220 case FEVariableBlockLenID:
221 cb = dynamic_cast<wxCheckBox*>(wnd);
222 preset->mControlState[id - FEFirstID] = wxString::Format(wxT("%d"),cb->GetValue());
223 break;
224 }
225 }
226 }
227 return true;
228}
229
231{
233 if (!preset)
234 {
235 AudacityMessageBox( XO("Preset '%s' does not exist." ).Format(name));
236 return;
237 }
238
239 wxListBox *lb;
240 wxSpinCtrl *sc;
241 wxTextCtrl *tc;
242 wxCheckBox *cb;
243 wxChoice *ch;
244
245 for (int id = FEFirstID; id < FELastID; id++)
246 {
247 wxWindow *wnd = parent->FindWindowById(id,parent);
248 if (wnd != NULL)
249 {
250 wxString readstr;
251 long readlong;
252 bool readbool;
253 switch(id)
254 {
255 // Listbox
256 case FEFormatID:
257 case FECodecID:
258 lb = dynamic_cast<wxListBox*>(wnd);
259 readstr = preset->mControlState[id - FEFirstID];
260 readlong = lb->FindString(readstr);
261 if (readlong > -1) lb->Select(readlong);
262 break;
263 // Spin control
264 case FEBitrateID:
265 case FEQualityID:
266 case FESampleRateID:
267 case FECutoffID:
268 case FEFrameSizeID:
269 case FEBufSizeID:
270 case FECompLevelID:
271 case FELPCCoeffsID:
272 case FEMinPredID:
273 case FEMaxPredID:
274 case FEMinPartOrderID:
275 case FEMaxPartOrderID:
276 case FEMuxRateID:
277 case FEPacketSizeID:
278 sc = dynamic_cast<wxSpinCtrl*>(wnd);
279 preset->mControlState[id - FEFirstID].ToLong(&readlong);
280 sc->SetValue(readlong);
281 break;
282 // Text control
283 case FELanguageID:
284 case FETagID:
285 tc = dynamic_cast<wxTextCtrl*>(wnd);
286 tc->SetValue(preset->mControlState[id - FEFirstID]);
287 break;
288 // Choice
289 case FEProfileID:
290 case FEPredOrderID:
291 ch = dynamic_cast<wxChoice*>(wnd);
292 preset->mControlState[id - FEFirstID].ToLong(&readlong);
293 if (readlong > -1) ch->Select(readlong);
294 break;
295 // Check box
296 case FEUseLPCID:
297 case FEBitReservoirID:
298 case FEVariableBlockLenID:
299 cb = dynamic_cast<wxCheckBox*>(wnd);
300 preset->mControlState[id - FEFirstID].ToLong(&readlong);
301 if (readlong) readbool = true; else readbool = false;
302 cb->SetValue(readbool);
303 break;
304 }
305 }
306 }
307}
308
309bool FFmpegPresets::HandleXMLTag(const std::string_view& tag, const AttributesList &attrs)
310{
311 if (mAbortImport)
312 {
313 return false;
314 }
315
316 if (tag == "ffmpeg_presets")
317 {
318 return true;
319 }
320
321 if (tag == "preset")
322 {
323 for (auto pair : attrs)
324 {
325 auto attr = pair.first;
326 auto value = pair.second;
327
328 if (attr == "name")
329 {
330 wxString strValue = value.ToWString();
331 mPreset = FindPreset(strValue);
332
333 if (mPreset)
334 {
335 auto query = XO("Replace preset '%s'?").Format( strValue );
336 int action = AudacityMessageBox(
337 query,
338 XO("Confirm Overwrite"),
339 wxYES_NO | wxCANCEL | wxCENTRE);
340 if (action == wxCANCEL)
341 {
342 mAbortImport = true;
343 return false;
344 }
345 if (action == wxNO)
346 {
347 mPreset = NULL;
348 return false;
349 }
351 }
352 else
353 {
354 mPreset = &mPresets[strValue];
355 }
356
357 mPreset->mPresetName = strValue;
358 }
359 }
360 return true;
361 }
362
363 if (tag == "setctrlstate" && mPreset)
364 {
365 long id = -1;
366 for (auto pair : attrs)
367 {
368 auto attr = pair.first;
369 auto value = pair.second;
370
371 if (attr == "id")
372 {
373 for (long i = FEFirstID; i < FELastID; i++)
374 if (!wxStrcmp(FFmpegExportCtrlIDNames[i - FEFirstID], value.ToWString()))
375 id = i;
376 }
377 else if (attr == "state")
378 {
379 if (id > FEFirstID && id < FELastID)
380 mPreset->mControlState[id - FEFirstID] = value.ToWString();
381 }
382 }
383 return true;
384 }
385
386 return false;
387}
388
389XMLTagHandler *FFmpegPresets::HandleXMLChild(const std::string_view& tag)
390{
391 if (mAbortImport)
392 {
393 return NULL;
394 }
395
396 if (tag == "preset")
397 {
398 return this;
399 }
400 else if (tag == "setctrlstate")
401 {
402 return this;
403 }
404 return NULL;
405}
406
408// may throw
409{
410 xmlFile.Write(wxT("<?xml "));
411 xmlFile.Write(wxT("version=\"1.0\" "));
412 xmlFile.Write(wxT("standalone=\"no\" "));
413 xmlFile.Write(wxT("?>\n"));
414
415 wxString dtdName = wxT("-//audacityffmpegpreset-1.0.0//DTD//EN");
416 wxString dtdURI =
417 wxT("http://audacity.sourceforge.net/xml/audacityffmpegpreset-1.0.0.dtd");
418
419 xmlFile.Write(wxT("<!DOCTYPE "));
420 xmlFile.Write(wxT("project "));
421 xmlFile.Write(wxT("PUBLIC "));
422 xmlFile.Write(wxT("\"-//audacityffmpegpreset-1.0.0//DTD//EN\" "));
423 xmlFile.Write(wxT("\"http://audacity.sourceforge.net/xml/audacityffmpegpreset-1.0.0.dtd\" "));
424 xmlFile.Write(wxT(">\n"));
425}
426
428// may throw
429{
430 xmlFile.StartTag(wxT("ffmpeg_presets"));
431 xmlFile.WriteAttr(wxT("version"),wxT("1.0"));
432 FFmpegPresetMap::const_iterator iter;
433 for (iter = mPresets.begin(); iter != mPresets.end(); ++iter)
434 {
435 auto preset = &iter->second;
436 xmlFile.StartTag(wxT("preset"));
437 xmlFile.WriteAttr(wxT("name"),preset->mPresetName);
438 for (long i = FEFirstID + 1; i < FELastID; i++)
439 {
440 xmlFile.StartTag(wxT("setctrlstate"));
441 xmlFile.WriteAttr(wxT("id"),wxString(FFmpegExportCtrlIDNames[i - FEFirstID]));
442 xmlFile.WriteAttr(wxT("state"),preset->mControlState[i - FEFirstID]);
443 xmlFile.EndTag(wxT("setctrlstate"));
444 }
445 xmlFile.EndTag(wxT("preset"));
446 }
447 xmlFile.EndTag(wxT("ffmpeg_presets"));
448}
wxT("CloseDown"))
R GuardedCall(const F1 &body, const F2 &handler=F2::Default(), F3 delayedHandler=DefaultDelayedHandlerAction) noexcept(noexcept(handler(std::declval< AudacityException * >())) &&noexcept(handler(nullptr)) &&noexcept(std::function< void(AudacityException *)>{std::move(delayedHandler)}))
Execute some code on any thread; catch any AudacityException; enqueue error report on the main thread...
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
static const wxChar * FFmpegExportCtrlIDNames[]
Definition: FFmpegDefines.h:79
std::unordered_map< wxString, FFmpegPreset > FFmpegPresetMap
Definition: FFmpegPresets.h:31
XO("Cut/Copy/Paste")
ReverbSettings preset
Definition: ReverbBase.cpp:25
wxString name
Definition: TagsEditor.cpp:166
std::vector< Attribute > AttributesList
Definition: XMLTagHandler.h:40
Custom FFmpeg export dialog.
wxArrayString mControlState
Definition: FFmpegPresets.h:28
wxString mPresetName
Definition: FFmpegPresets.h:27
void LoadPreset(ExportFFmpegOptions *parent, wxString &name)
FFmpegPresetMap mPresets
Definition: FFmpegPresets.h:58
bool SavePreset(ExportFFmpegOptions *parent, wxString &name)
void ImportPresets(wxString &filename)
bool OverwriteIsOk(wxString &name)
XMLTagHandler * HandleXMLChild(const std::string_view &tag) override
void DeletePreset(wxString &name)
FFmpegPreset * mPreset
Definition: FFmpegPresets.h:59
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
~FFmpegPresets() override
void WriteXMLHeader(XMLWriter &xmlFile) const
void GetPresetList(wxArrayString &list)
void WriteXML(XMLWriter &xmlFile) const
void ExportPresets(wxString &filename)
FFmpegPreset * FindPreset(wxString &name)
Abstract base class used in importing a file.
Reads a file and passes the results through an XMLTagHandler.
Definition: XMLFileReader.h:19
bool Parse(XMLTagHandler *baseHandler, const FilePath &fname)
Wrapper to output XML data to files.
Definition: XMLWriter.h:84
This class is an interface which should be implemented by classes which wish to be able to load and s...
Definition: XMLTagHandler.h:42
Base class for XMLFileWriter and XMLStringWriter that provides the general functionality for creating...
Definition: XMLWriter.h:25
FILES_API FilePath DataDir()
Audacity user data directory.