Audacity 3.2.0
ExportFFmpegDialogs.cpp
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 ExportFFmpegDialogs.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******************************************************************//***************************************************************//***************************************************************//***************************************************************//***************************************************************//***************************************************************//*******************************************************************/
43
44
45#include "ExportFFmpegDialogs.h"
46
47#include "../FFmpeg.h"
48#include "FFmpegFunctions.h"
49
50#include <wx/app.h>
51#include <wx/checkbox.h>
52#include <wx/choice.h>
53#include <wx/intl.h>
54#include <wx/timer.h>
55#include <wx/string.h>
56#include <wx/textctrl.h>
57#include <wx/listbox.h>
58#include <wx/window.h>
59#include <wx/spinctrl.h>
60#include <wx/combobox.h>
61#include <wx/stattext.h>
62
63#include "../widgets/FileDialog/FileDialog.h"
64
65#include "Mix.h"
66#include "../Tags.h"
67#include "../widgets/AudacityMessageBox.h"
68#include "../widgets/HelpSystem.h"
69
70#include "Export.h"
71#include "FFmpeg.h"
72
73#if defined(USE_FFMPEG)
74
79#define FFMPEG_EXPORT_CTRL_ID_ENTRIES \
80 FFMPEG_EXPORT_CTRL_ID_FIRST_ENTRY(FEFirstID, 20000), \
81 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEFormatID), \
82 FFMPEG_EXPORT_CTRL_ID_ENTRY(FECodecID), \
83 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEBitrateID), \
84 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEQualityID), \
85 FFMPEG_EXPORT_CTRL_ID_ENTRY(FESampleRateID), \
86 FFMPEG_EXPORT_CTRL_ID_ENTRY(FELanguageID), \
87 FFMPEG_EXPORT_CTRL_ID_ENTRY(FETagID), \
88 FFMPEG_EXPORT_CTRL_ID_ENTRY(FECutoffID), \
89 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEFrameSizeID), \
90 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEBufSizeID), \
91 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEProfileID), \
92 FFMPEG_EXPORT_CTRL_ID_ENTRY(FECompLevelID), \
93 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEUseLPCID), \
94 FFMPEG_EXPORT_CTRL_ID_ENTRY(FELPCCoeffsID), \
95 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEMinPredID), \
96 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEMaxPredID), \
97 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEPredOrderID), \
98 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEMinPartOrderID), \
99 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEMaxPartOrderID), \
100 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEMuxRateID), \
101 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEPacketSizeID), \
102 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEBitReservoirID), \
103 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEVariableBlockLenID), \
104 FFMPEG_EXPORT_CTRL_ID_ENTRY(FELastID), \
105 \
106 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEFormatLabelID), \
107 FFMPEG_EXPORT_CTRL_ID_ENTRY(FECodecLabelID), \
108 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEFormatNameID), \
109 FFMPEG_EXPORT_CTRL_ID_ENTRY(FECodecNameID), \
110 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEPresetID), \
111 FFMPEG_EXPORT_CTRL_ID_ENTRY(FESavePresetID), \
112 FFMPEG_EXPORT_CTRL_ID_ENTRY(FELoadPresetID), \
113 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEDeletePresetID), \
114 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEAllFormatsID), \
115 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEAllCodecsID), \
116 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEImportPresetsID), \
117 FFMPEG_EXPORT_CTRL_ID_ENTRY(FEExportPresetsID) \
118
119// First the enumeration
120#define FFMPEG_EXPORT_CTRL_ID_FIRST_ENTRY(name, num) name = num
121#define FFMPEG_EXPORT_CTRL_ID_ENTRY(name) name
122
126
127// Now the string representations
128#undef FFMPEG_EXPORT_CTRL_ID_FIRST_ENTRY
129#define FFMPEG_EXPORT_CTRL_ID_FIRST_ENTRY(name, num) wxT(#name)
130#undef FFMPEG_EXPORT_CTRL_ID_ENTRY
131#define FFMPEG_EXPORT_CTRL_ID_ENTRY(name) wxT(#name)
132static const wxChar *FFmpegExportCtrlIDNames[] = {
134};
135
136#undef FFMPEG_EXPORT_CTRL_ID_ENTRIES
137#undef FFMPEG_EXPORT_CTRL_ID_ENTRY
138#undef FFMPEG_EXPORT_CTRL_ID_FIRST_ENTRY
139
140//----------------------------------------------------------------------------
141// ExportFFmpegAC3Options Class
142//----------------------------------------------------------------------------
143
144namespace
145{
146
147// i18n-hint kbps abbreviates "thousands of bits per second"
148inline TranslatableString n_kbps(int n) { return XO("%d kbps").Format( n ); }
149
151 n_kbps( 32 ),
152 n_kbps( 40 ),
153 n_kbps( 48 ),
154 n_kbps( 56 ),
155 n_kbps( 64 ),
156 n_kbps( 80 ),
157 n_kbps( 96 ),
158 n_kbps( 112 ),
159 n_kbps( 128 ),
160 n_kbps( 160 ),
161 n_kbps( 192 ),
162 n_kbps( 224 ),
163 n_kbps( 256 ),
164 n_kbps( 320 ),
165 n_kbps( 384 ),
166 n_kbps( 448 ),
167 n_kbps( 512 ),
168 n_kbps( 576 ),
169 n_kbps( 640 ),
170};
171
172const std::vector< int > AC3BitRateValues{
173 32000,
174 40000,
175 48000,
176 56000,
177 64000,
178 80000,
179 96000,
180 112000,
181 128000,
182 160000,
183 192000,
184 224000,
185 256000,
186 320000,
187 384000,
188 448000,
189 512000,
190 576000,
191 640000,
192};
193
194}
195
196const int ExportFFmpegAC3Options::iAC3SampleRates[] = { 32000, 44100, 48000, 0 };
197
199: wxPanelWrapper(parent, wxID_ANY)
200{
203
205}
206
208{
210}
211
215{
216 IntSetting Setting{ L"/FileFormats/AC3BitRate", 160000 };
217
218 S.StartVerticalLay();
219 {
220 S.StartHorizontalLay(wxCENTER);
221 {
222 S.StartMultiColumn(2, wxCENTER);
223 {
224 S.TieNumberAsChoice(
226 }
227 S.EndMultiColumn();
228 }
229 S.EndHorizontalLay();
230 }
231 S.EndVerticalLay();
232}
233
237{
238 return true;
239}
240
244{
247
248 gPrefs->Flush();
249
250 return true;
251}
252
253//----------------------------------------------------------------------------
254// ExportFFmpegAACOptions Class
255//----------------------------------------------------------------------------
256
258: wxPanelWrapper(parent, wxID_ANY)
259{
262
264}
265
267{
269}
270
274{
275 S.StartVerticalLay();
276 {
277 S.StartHorizontalLay(wxEXPAND);
278 {
279 S.SetSizerProportion(1);
280 S.StartMultiColumn(2, wxCENTER);
281 {
282 S.SetStretchyCol(1);
283 S.TieSpinCtrl(
284 XXO("Quality (kbps):"),
285 {wxT("/FileFormats/AACQuality"), 160}, 320, 98);
286 }
287 S.EndMultiColumn();
288 }
289 S.EndHorizontalLay();
290 }
291 S.EndVerticalLay();
292}
293
297{
298 return true;
299}
300
304{
307
308 gPrefs->Flush();
309
310 return true;
311}
312
313//----------------------------------------------------------------------------
314// ExportFFmpegAMRNBOptions Class
315//----------------------------------------------------------------------------
316
317namespace {
318
319// i18n-hint kbps abbreviates "thousands of bits per second"
320inline TranslatableString f_kbps( double d ) { return XO("%.2f kbps").Format( d ); }
321
325{
326 f_kbps( 4.75 ),
327 f_kbps( 5.15 ),
328 f_kbps( 5.90 ),
329 f_kbps( 6.70 ),
330 f_kbps( 7.40 ),
331 f_kbps( 7.95 ),
332 f_kbps( 10.20 ),
333 f_kbps( 12.20 ),
334};
335
336const std::vector< int > AMRNBBitRateValues
337{
338 4750,
339 5150,
340 5900,
341 6700,
342 7400,
343 7950,
344 10200,
345 12200,
346};
347
348}
349
351: wxPanelWrapper(parent, wxID_ANY)
352{
355
357}
358
360{
362}
363
367{
368 IntSetting Setting{ L"/FileFormats/AMRNBBitRate", 12200 };
369 S.StartVerticalLay();
370 {
371 S.StartHorizontalLay(wxCENTER);
372 {
373 S.StartMultiColumn(2, wxCENTER);
374 {
375 S.TieNumberAsChoice(XXO("Bit Rate:"), Setting,
377 }
378 S.EndMultiColumn();
379 }
380 S.EndHorizontalLay();
381 }
382 S.EndVerticalLay();
383}
384
388{
389 return true;
390}
391
395{
398
399 gPrefs->Flush();
400
401 return true;
402}
403
404//----------------------------------------------------------------------------
405// ExportFFmpegOPUSOptions Class
406//----------------------------------------------------------------------------
407
408namespace {
409
412 {
413 wxT("/FileFormats/OPUSBitrate"),
414 {
415 ByColumns,
416 {
417 n_kbps( 6 ),
418 n_kbps( 8 ),
419 n_kbps( 16 ),
420 n_kbps( 24 ),
421 n_kbps( 32 ),
422 n_kbps( 40 ),
423 n_kbps( 48 ),
424 n_kbps( 64 ),
425 n_kbps( 80 ),
426 n_kbps( 96 ),
427 n_kbps( 128 ),
428 n_kbps( 160 ),
429 n_kbps( 192 ),
430 n_kbps( 256 ),
431 },
432 {
433 wxT("6000"),
434 wxT("8000"),
435 wxT("16000"),
436 wxT("24000"),
437 wxT("32000"),
438 wxT("40000"),
439 wxT("48000"),
440 wxT("64000"),
441 wxT("80000"),
442 wxT("96000"),
443 wxT("128000"),
444 wxT("160000"),
445 wxT("192000"),
446 wxT("256000"),
447 }
448 },
449 7 // "128 kbps"
450 };
451
453 {
454 wxT("/FileFormats/OPUSCompression"),
455 {
456 ByColumns,
457 {
458 XO("0"),
459 XO("1"),
460 XO("2"),
461 XO("3"),
462 XO("4"),
463 XO("5"),
464 XO("6"),
465 XO("7"),
466 XO("8"),
467 XO("9"),
468 XO("10"),
469 },
470 {
471 wxT("0"),
472 wxT("1"),
473 wxT("2"),
474 wxT("3"),
475 wxT("4"),
476 wxT("5"),
477 wxT("6"),
478 wxT("7"),
479 wxT("8"),
480 wxT("9"),
481 wxT("10"),
482 }
483 },
484 10 // "10"
485 };
486
487
489 {
490 wxT("/FileFormats/OPUSVbrMode"),
491 {
492 ByColumns,
493 {
494 XO("Off"),
495 XO("On"),
496 XO("Constrained"),
497 },
498 {
499 wxT("off"),
500 wxT("on"),
501 wxT("constrained"),
502 }
503 },
504 1 // "On"
505 };
506
508 {
509 wxT("/FileFormats/OPUSApplication"),
510 {
511 ByColumns,
512 {
513 XO("VOIP"),
514 XO("Audio"),
515 XO("Low Delay"),
516 },
517 {
518 wxT("voip"),
519 wxT("audio"),
520 wxT("lowdelay"),
521 }
522 },
523 1 // "Audio"
524 };
525
527 {
528 wxT("/FileFormats/OPUSFrameDuration"),
529 {
530 ByColumns,
531 {
532 XO("2.5 ms"),
533 XO("5 ms"),
534 XO("10 ms"),
535 XO("20 ms"),
536 XO("40 ms"),
537 XO("60 ms"),
538 },
539 {
540 wxT("2.5"),
541 wxT("5"),
542 wxT("10"),
543 wxT("20"),
544 wxT("40"),
545 wxT("60"),
546 }
547 },
548 3 // "20"
549 };
550
552 {
553 wxT("/FileFormats/OPUSCutoff"),
554 {
555 ByColumns,
556 {
557 XO("Disabled"),
558 XO("Narrowband"),
559 XO("Mediumband"),
560 XO("Wideband"),
561 XO("Super Wideband"),
562 XO("Fullband"),
563 },
564 {
565 wxT("0"),
566 wxT("4000"),
567 wxT("6000"),
568 wxT("8000"),
569 wxT("12000"),
570 wxT("20000"),
571 }
572 },
573 0 // "Disabled"
574 };
575}
576
578: wxPanelWrapper(parent, wxID_ANY)
579{
582
584}
585
587{
589}
590
594{
595 S.SetSizerProportion(1);
596 S.SetBorder(4);
597 S.StartVerticalLay();
598 {
599 S.StartHorizontalLay(wxCENTER);
600 {
601 S.StartMultiColumn(2, wxCENTER);
602 {
603 S.StartMultiColumn(2, wxCENTER);
604 {
605 S.TieChoice(
606 XXO("Bit Rate:"),
608
609 S.TieChoice(
610 XXO("Compression"),
612
613 S.TieChoice(
614 XXO("Frame Duration:"),
616 }
617 S.EndMultiColumn();
618
619 S.StartMultiColumn(2, wxCENTER);
620 {
621 S.TieChoice(
622 XXO("Vbr Mode:"),
624
625 S.TieChoice(
626 XXO("Application:"),
628
629 S.TieChoice(
630 XXO("Cutoff:"),
631 OPUSCutoff);
632
633 }
634 S.EndMultiColumn();
635 }
636 S.EndMultiColumn();
637 }
638 S.EndHorizontalLay();
639 }
640 S.EndVerticalLay();
641}
642
646{
647 return true;
648}
649
653{
656
657 gPrefs->Flush();
658
659 return true;
660}
661
662//----------------------------------------------------------------------------
663// ExportFFmpegWMAOptions Class
664//----------------------------------------------------------------------------
665
667{ 8000, 11025, 16000, 22050, 44100, 0};
668
669namespace {
670
673{
674 n_kbps(24),
675 n_kbps(32),
676 n_kbps(40),
677 n_kbps(48),
678 n_kbps(64),
679 n_kbps(80),
680 n_kbps(96),
681 n_kbps(128),
682 n_kbps(160),
683 n_kbps(192),
684 n_kbps(256),
685 n_kbps(320),
686};
687
688const std::vector< int > WMABitRateValues{
689 24000,
690 32000,
691 40000,
692 48000,
693 64000,
694 80000,
695 96000,
696 128000,
697 160000,
698 192000,
699 256000,
700 320000,
701};
702
703}
704
706: wxPanelWrapper(parent, wxID_ANY)
707{
710
712}
713
715{
717}
718
722{
723 IntSetting Setting{ L"/FileFormats/WMABitRate", 128000 };
724 S.StartVerticalLay();
725 {
726 S.StartHorizontalLay(wxCENTER);
727 {
728 S.StartMultiColumn(2, wxCENTER);
729 {
730 S.TieNumberAsChoice(XXO("Bit Rate:"),
732 }
733 S.EndMultiColumn();
734 }
735 S.EndHorizontalLay();
736 }
737 S.EndVerticalLay();
738}
739
743{
744 return true;
745}
746
750{
753
754 gPrefs->Flush();
755
756 return true;
757}
758
759//----------------------------------------------------------------------------
760// ExportFFmpegCustomOptions Class
761//----------------------------------------------------------------------------
762
763#define OpenID 9000
764
768
770: wxPanelWrapper(parent, wxID_ANY),
771 mFormat(NULL),
772 mCodec(NULL)
773{
775 PopulateOrExchange(S);
776
777 TransferDataToWindow();
778}
779
781{
783}
784
788{
789 S.StartHorizontalLay(wxCENTER);
790 {
791 S.StartVerticalLay(wxCENTER, 0);
792 {
793 S.Id(OpenID).AddButton(XXO("Open custom FFmpeg format options"));
794 S.StartMultiColumn(2, wxCENTER);
795 {
796 S.AddPrompt(XXO("Current Format:"));
797 mFormat = S.Style(wxTE_READONLY).AddTextBox({}, wxT(""), 25);
798 S.AddPrompt(XXO("Current Codec:"));
799 mCodec = S.Style(wxTE_READONLY).AddTextBox({}, wxT(""), 25);
800 }
801 S.EndMultiColumn();
802 }
803 S.EndHorizontalLay();
804 }
805 S.EndHorizontalLay();
806}
807
811{
812 if (mFormat)
813 {
814 mFormat->SetValue(gPrefs->Read(wxT("/FileFormats/FFmpegFormat"), wxT("")));
815 mCodec->SetValue(gPrefs->Read(wxT("/FileFormats/FFmpegCodec"), wxT("")));
816 }
817 return true;
818}
819
823{
824 return true;
825}
826
829void ExportFFmpegCustomOptions::OnOpen(wxCommandEvent & WXUNUSED(evt))
830{
831 // Show "Locate FFmpeg" dialog
832 auto ffmpeg = FFmpegFunctions::Load();
833 if (!ffmpeg)
834 {
836 if (!LoadFFmpeg(true))
837 {
838 return;
839 }
840 }
841
842#ifdef __WXMAC__
843 // Bug 2077 Must be a parent window on OSX or we will appear behind.
844 auto pWin = wxGetTopLevelParent( this );
845#else
846 // Use GetTopWindow on windows as there is no hWnd with top level parent.
847 auto pWin = wxTheApp->GetTopWindow();
848#endif
849
850 ExportFFmpegOptions od(pWin);
851 od.ShowModal();
852
854}
855
857{
858 mControlState.resize(FELastID - FEFirstID);
859}
860
862{
863}
864
866{
867 mPreset = NULL;
868 mAbortImport = false;
869
870 XMLFileReader xmlfile;
871 wxFileName xmlFileName(FileNames::DataDir(), wxT("ffmpeg_presets.xml"));
872 xmlfile.Parse(this,xmlFileName.GetFullPath());
873}
874
876{
877 // We're in a destructor! Don't let exceptions out!
878 GuardedCall( [&] {
879 wxFileName xmlFileName{ FileNames::DataDir(), wxT("ffmpeg_presets.xml") };
880 XMLFileWriter writer{
881 xmlFileName.GetFullPath(), XO("Error Saving FFmpeg Presets") };
882 WriteXMLHeader(writer);
883 WriteXML(writer);
884 writer.Commit();
885 } );
886}
887
888void FFmpegPresets::ImportPresets(wxString &filename)
889{
890 mPreset = NULL;
891 mAbortImport = false;
892
893 FFmpegPresetMap savePresets = mPresets;
894
895 XMLFileReader xmlfile;
896 bool success = xmlfile.Parse(this,filename);
897 if (!success || mAbortImport) {
898 mPresets = savePresets;
899 }
900}
901
902void FFmpegPresets::ExportPresets(wxString &filename)
903{
904 GuardedCall( [&] {
905 XMLFileWriter writer{ filename, XO("Error Saving FFmpeg Presets") };
906 WriteXMLHeader(writer);
907 WriteXML(writer);
908 writer.Commit();
909 } );
910}
911
912void FFmpegPresets::GetPresetList(wxArrayString &list)
913{
914 list.clear();
915 FFmpegPresetMap::iterator iter;
916 for (iter = mPresets.begin(); iter != mPresets.end(); ++iter)
917 {
918 list.push_back(iter->second.mPresetName);
919 }
920
921 std::sort( list.begin(), list.end() );
922}
923
925{
926 FFmpegPresetMap::iterator iter = mPresets.find(name);
927 if (iter != mPresets.end())
928 {
929 mPresets.erase(iter);
930 }
931}
932
934{
935 FFmpegPresetMap::iterator iter = mPresets.find(name);
936 if (iter != mPresets.end())
937 {
938 return &iter->second;
939 }
940
941 return NULL;
942}
943
944// return false if overwrite was not allowed.
946{
948 if (preset)
949 {
950 auto query = XO("Overwrite preset '%s'?").Format(name);
951 int action = AudacityMessageBox(
952 query,
953 XO("Confirm Overwrite"),
954 wxYES_NO | wxCENTRE);
955 if (action == wxNO) return false;
956 }
957 return true;
958}
959
960
962{
963 wxString format;
964 wxString codec;
966
967 {
968 wxWindow *wnd;
969 wxListBox *lb;
970
971 wnd = dynamic_cast<wxWindow*>(parent)->FindWindowById(FEFormatID,parent);
972 lb = dynamic_cast<wxListBox*>(wnd);
973 if (lb->GetSelection() < 0)
974 {
975 AudacityMessageBox( XO("Please select format before saving a profile") );
976 return false;
977 }
978 format = lb->GetStringSelection();
979
980 wnd = dynamic_cast<wxWindow*>(parent)->FindWindowById(FECodecID,parent);
981 lb = dynamic_cast<wxListBox*>(wnd);
982 if (lb->GetSelection() < 0)
983 {
984 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
985 AudacityMessageBox( XO("Please select codec before saving a profile") );
986 return false;
987 }
988 codec = lb->GetStringSelection();
989 }
990
991 preset = &mPresets[name];
992 preset->mPresetName = name;
993
994 wxSpinCtrl *sc;
995 wxTextCtrl *tc;
996 wxCheckBox *cb;
997 wxChoice *ch;
998
999 for (int id = FEFirstID; id < FELastID; id++)
1000 {
1001 wxWindow *wnd = dynamic_cast<wxWindow*>(parent)->FindWindowById(id,parent);
1002 if (wnd != NULL)
1003 {
1004 switch(id)
1005 {
1006 case FEFormatID:
1007 preset->mControlState[id - FEFirstID] = format;
1008 break;
1009 case FECodecID:
1010 preset->mControlState[id - FEFirstID] = codec;
1011 break;
1012 // Spin control
1013 case FEBitrateID:
1014 case FEQualityID:
1015 case FESampleRateID:
1016 case FECutoffID:
1017 case FEFrameSizeID:
1018 case FEBufSizeID:
1019 case FECompLevelID:
1020 case FELPCCoeffsID:
1021 case FEMinPredID:
1022 case FEMaxPredID:
1023 case FEMinPartOrderID:
1024 case FEMaxPartOrderID:
1025 case FEMuxRateID:
1026 case FEPacketSizeID:
1027 sc = dynamic_cast<wxSpinCtrl*>(wnd);
1028 preset->mControlState[id - FEFirstID] = wxString::Format(wxT("%d"),sc->GetValue());
1029 break;
1030 // Text control
1031 case FELanguageID:
1032 case FETagID:
1033 tc = dynamic_cast<wxTextCtrl*>(wnd);
1034 preset->mControlState[id - FEFirstID] = tc->GetValue();
1035 break;
1036 // Choice
1037 case FEProfileID:
1038 case FEPredOrderID:
1039 ch = dynamic_cast<wxChoice*>(wnd);
1040 preset->mControlState[id - FEFirstID] = wxString::Format(wxT("%d"),ch->GetSelection());
1041 break;
1042 // Check box
1043 case FEUseLPCID:
1044 case FEBitReservoirID:
1045 case FEVariableBlockLenID:
1046 cb = dynamic_cast<wxCheckBox*>(wnd);
1047 preset->mControlState[id - FEFirstID] = wxString::Format(wxT("%d"),cb->GetValue());
1048 break;
1049 }
1050 }
1051 }
1052 return true;
1053}
1054
1056{
1058 if (!preset)
1059 {
1060 AudacityMessageBox( XO("Preset '%s' does not exist." ).Format(name));
1061 return;
1062 }
1063
1064 wxListBox *lb;
1065 wxSpinCtrl *sc;
1066 wxTextCtrl *tc;
1067 wxCheckBox *cb;
1068 wxChoice *ch;
1069
1070 for (int id = FEFirstID; id < FELastID; id++)
1071 {
1072 wxWindow *wnd = parent->FindWindowById(id,parent);
1073 if (wnd != NULL)
1074 {
1075 wxString readstr;
1076 long readlong;
1077 bool readbool;
1078 switch(id)
1079 {
1080 // Listbox
1081 case FEFormatID:
1082 case FECodecID:
1083 lb = dynamic_cast<wxListBox*>(wnd);
1084 readstr = preset->mControlState[id - FEFirstID];
1085 readlong = lb->FindString(readstr);
1086 if (readlong > -1) lb->Select(readlong);
1087 break;
1088 // Spin control
1089 case FEBitrateID:
1090 case FEQualityID:
1091 case FESampleRateID:
1092 case FECutoffID:
1093 case FEFrameSizeID:
1094 case FEBufSizeID:
1095 case FECompLevelID:
1096 case FELPCCoeffsID:
1097 case FEMinPredID:
1098 case FEMaxPredID:
1099 case FEMinPartOrderID:
1100 case FEMaxPartOrderID:
1101 case FEMuxRateID:
1102 case FEPacketSizeID:
1103 sc = dynamic_cast<wxSpinCtrl*>(wnd);
1104 preset->mControlState[id - FEFirstID].ToLong(&readlong);
1105 sc->SetValue(readlong);
1106 break;
1107 // Text control
1108 case FELanguageID:
1109 case FETagID:
1110 tc = dynamic_cast<wxTextCtrl*>(wnd);
1111 tc->SetValue(preset->mControlState[id - FEFirstID]);
1112 break;
1113 // Choice
1114 case FEProfileID:
1115 case FEPredOrderID:
1116 ch = dynamic_cast<wxChoice*>(wnd);
1117 preset->mControlState[id - FEFirstID].ToLong(&readlong);
1118 if (readlong > -1) ch->Select(readlong);
1119 break;
1120 // Check box
1121 case FEUseLPCID:
1122 case FEBitReservoirID:
1123 case FEVariableBlockLenID:
1124 cb = dynamic_cast<wxCheckBox*>(wnd);
1125 preset->mControlState[id - FEFirstID].ToLong(&readlong);
1126 if (readlong) readbool = true; else readbool = false;
1127 cb->SetValue(readbool);
1128 break;
1129 }
1130 }
1131 }
1132}
1133
1134bool FFmpegPresets::HandleXMLTag(const std::string_view& tag, const AttributesList &attrs)
1135{
1136 if (mAbortImport)
1137 {
1138 return false;
1139 }
1140
1141 if (tag == "ffmpeg_presets")
1142 {
1143 return true;
1144 }
1145
1146 if (tag == "preset")
1147 {
1148 for (auto pair : attrs)
1149 {
1150 auto attr = pair.first;
1151 auto value = pair.second;
1152
1153 if (attr == "name")
1154 {
1155 wxString strValue = value.ToWString();
1156 mPreset = FindPreset(strValue);
1157
1158 if (mPreset)
1159 {
1160 auto query = XO("Replace preset '%s'?").Format( strValue );
1161 int action = AudacityMessageBox(
1162 query,
1163 XO("Confirm Overwrite"),
1164 wxYES_NO | wxCANCEL | wxCENTRE);
1165 if (action == wxCANCEL)
1166 {
1167 mAbortImport = true;
1168 return false;
1169 }
1170 if (action == wxNO)
1171 {
1172 mPreset = NULL;
1173 return false;
1174 }
1175 *mPreset = FFmpegPreset();
1176 }
1177 else
1178 {
1179 mPreset = &mPresets[strValue];
1180 }
1181
1182 mPreset->mPresetName = strValue;
1183 }
1184 }
1185 return true;
1186 }
1187
1188 if (tag == "setctrlstate" && mPreset)
1189 {
1190 long id = -1;
1191 for (auto pair : attrs)
1192 {
1193 auto attr = pair.first;
1194 auto value = pair.second;
1195
1196 if (attr == "id")
1197 {
1198 for (long i = FEFirstID; i < FELastID; i++)
1199 if (!wxStrcmp(FFmpegExportCtrlIDNames[i - FEFirstID], value.ToWString()))
1200 id = i;
1201 }
1202 else if (attr == "state")
1203 {
1204 if (id > FEFirstID && id < FELastID)
1205 mPreset->mControlState[id - FEFirstID] = value.ToWString();
1206 }
1207 }
1208 return true;
1209 }
1210
1211 return false;
1212}
1213
1215{
1216 if (mAbortImport)
1217 {
1218 return NULL;
1219 }
1220
1221 if (tag == "preset")
1222 {
1223 return this;
1224 }
1225 else if (tag == "setctrlstate")
1226 {
1227 return this;
1228 }
1229 return NULL;
1230}
1231
1233// may throw
1234{
1235 xmlFile.Write(wxT("<?xml "));
1236 xmlFile.Write(wxT("version=\"1.0\" "));
1237 xmlFile.Write(wxT("standalone=\"no\" "));
1238 xmlFile.Write(wxT("?>\n"));
1239
1240 wxString dtdName = wxT("-//audacityffmpegpreset-1.0.0//DTD//EN");
1241 wxString dtdURI =
1242 wxT("http://audacity.sourceforge.net/xml/audacityffmpegpreset-1.0.0.dtd");
1243
1244 xmlFile.Write(wxT("<!DOCTYPE "));
1245 xmlFile.Write(wxT("project "));
1246 xmlFile.Write(wxT("PUBLIC "));
1247 xmlFile.Write(wxT("\"-//audacityffmpegpreset-1.0.0//DTD//EN\" "));
1248 xmlFile.Write(wxT("\"http://audacity.sourceforge.net/xml/audacityffmpegpreset-1.0.0.dtd\" "));
1249 xmlFile.Write(wxT(">\n"));
1250}
1251
1253// may throw
1254{
1255 xmlFile.StartTag(wxT("ffmpeg_presets"));
1256 xmlFile.WriteAttr(wxT("version"),wxT("1.0"));
1257 FFmpegPresetMap::const_iterator iter;
1258 for (iter = mPresets.begin(); iter != mPresets.end(); ++iter)
1259 {
1260 auto preset = &iter->second;
1261 xmlFile.StartTag(wxT("preset"));
1262 xmlFile.WriteAttr(wxT("name"),preset->mPresetName);
1263 for (long i = FEFirstID + 1; i < FELastID; i++)
1264 {
1265 xmlFile.StartTag(wxT("setctrlstate"));
1266 xmlFile.WriteAttr(wxT("id"),wxString(FFmpegExportCtrlIDNames[i - FEFirstID]));
1267 xmlFile.WriteAttr(wxT("state"),preset->mControlState[i - FEFirstID]);
1268 xmlFile.EndTag(wxT("setctrlstate"));
1269 }
1270 xmlFile.EndTag(wxT("preset"));
1271 }
1272 xmlFile.EndTag(wxT("ffmpeg_presets"));
1273}
1274
1275//----------------------------------------------------------------------------
1276// ExportFFmpegOptions Class
1277//----------------------------------------------------------------------------
1278
1279BEGIN_EVENT_TABLE(ExportFFmpegOptions, wxDialogWrapper)
1282 EVT_LISTBOX(FEFormatID,ExportFFmpegOptions::OnFormatList)
1283 EVT_LISTBOX(FECodecID,ExportFFmpegOptions::OnCodecList)
1292
1293
1295CompatibilityEntry ExportFFmpegOptions::CompatibilityList[] =
1296{
1297 { wxT("adts"), AUDACITY_AV_CODEC_ID_AAC },
1298
1300 { wxT("aiff"), AUDACITY_AV_CODEC_ID_PCM_S8 },
1305 { wxT("aiff"), AUDACITY_AV_CODEC_ID_MACE3 },
1306 { wxT("aiff"), AUDACITY_AV_CODEC_ID_MACE6 },
1307 { wxT("aiff"), AUDACITY_AV_CODEC_ID_GSM },
1311 { wxT("aiff"), AUDACITY_AV_CODEC_ID_QDM2 },
1312
1313 { wxT("amr"), AUDACITY_AV_CODEC_ID_AMR_NB },
1314 { wxT("amr"), AUDACITY_AV_CODEC_ID_AMR_WB },
1315
1317 { wxT("asf"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1327 { wxT("asf"), AUDACITY_AV_CODEC_ID_GSM_MS },
1329 //{ wxT("asf"), AUDACITY_AV_CODEC_ID_MP2 }, Bug 59
1330 { wxT("asf"), AUDACITY_AV_CODEC_ID_MP3 },
1331#if LIBAVCODEC_VERSION_MAJOR < 58
1333#endif
1334 { wxT("asf"), AUDACITY_AV_CODEC_ID_AAC },
1335 { wxT("asf"), AUDACITY_AV_CODEC_ID_WMAV1 },
1336 { wxT("asf"), AUDACITY_AV_CODEC_ID_WMAV2 },
1337 { wxT("asf"), AUDACITY_AV_CODEC_ID_WMAPRO },
1339 { wxT("asf"), AUDACITY_AV_CODEC_ID_ATRAC3 },
1340 { wxT("asf"), AUDACITY_AV_CODEC_ID_IMC },
1341 { wxT("asf"), AUDACITY_AV_CODEC_ID_AC3 },
1342 { wxT("asf"), AUDACITY_AV_CODEC_ID_DTS },
1343 { wxT("asf"), AUDACITY_AV_CODEC_ID_FLAC },
1345 { wxT("asf"), AUDACITY_AV_CODEC_ID_VORBIS },
1346
1351
1353 { wxT("avi"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1363 { wxT("avi"), AUDACITY_AV_CODEC_ID_GSM_MS },
1365 // { wxT("avi"), AUDACITY_AV_CODEC_ID_MP2 }, //Bug 59
1366 { wxT("avi"), AUDACITY_AV_CODEC_ID_MP3 },
1367#if LIBAVCODEC_VERSION_MAJOR < 58
1369#endif
1370 { wxT("avi"), AUDACITY_AV_CODEC_ID_AAC },
1371 { wxT("avi"), AUDACITY_AV_CODEC_ID_WMAV1 },
1372 { wxT("avi"), AUDACITY_AV_CODEC_ID_WMAV2 },
1373 { wxT("avi"), AUDACITY_AV_CODEC_ID_WMAPRO },
1375 { wxT("avi"), AUDACITY_AV_CODEC_ID_ATRAC3 },
1376 { wxT("avi"), AUDACITY_AV_CODEC_ID_IMC },
1377 { wxT("avi"), AUDACITY_AV_CODEC_ID_AC3 },
1378 { wxT("avi"), AUDACITY_AV_CODEC_ID_DTS },
1379 { wxT("avi"), AUDACITY_AV_CODEC_ID_FLAC },
1381 { wxT("avi"), AUDACITY_AV_CODEC_ID_VORBIS },
1382
1383 { wxT("crc"), AUDACITY_AV_CODEC_ID_NONE },
1384
1386
1387 { wxT("ffm"), AUDACITY_AV_CODEC_ID_NONE },
1388
1389 { wxT("flv"), AUDACITY_AV_CODEC_ID_MP3 },
1390 { wxT("flv"), AUDACITY_AV_CODEC_ID_PCM_S8 },
1394 { wxT("flv"), AUDACITY_AV_CODEC_ID_AAC },
1396
1397 { wxT("framecrc"), AUDACITY_AV_CODEC_ID_NONE },
1398
1400
1401 { wxT("matroska"), AUDACITY_AV_CODEC_ID_PCM_S16LE },
1402 { wxT("matroska"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1403 { wxT("matroska"), AUDACITY_AV_CODEC_ID_PCM_S24LE },
1404 { wxT("matroska"), AUDACITY_AV_CODEC_ID_PCM_S32LE },
1405 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ADPCM_MS },
1406 { wxT("matroska"), AUDACITY_AV_CODEC_ID_PCM_ALAW },
1407 { wxT("matroska"), AUDACITY_AV_CODEC_ID_PCM_MULAW },
1408 { wxT("matroska"), AUDACITY_AV_CODEC_ID_WMAVOICE },
1409 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ADPCM_IMA_WAV },
1410 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ADPCM_YAMAHA },
1411 { wxT("matroska"), AUDACITY_AV_CODEC_ID_TRUESPEECH },
1412 { wxT("matroska"), AUDACITY_AV_CODEC_ID_GSM_MS },
1413 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ADPCM_G726 },
1414 // { wxT("matroska"), AUDACITY_AV_CODEC_ID_MP2 }, // Bug 59
1415 { wxT("matroska"), AUDACITY_AV_CODEC_ID_MP3 },
1416#if LIBAVCODEC_VERSION_MAJOR < 58
1417 { wxT("matroska"), AUDACITY_AV_CODEC_ID_VOXWARE },
1418#endif
1419 { wxT("matroska"), AUDACITY_AV_CODEC_ID_AAC },
1420 { wxT("matroska"), AUDACITY_AV_CODEC_ID_WMAV1 },
1421 { wxT("matroska"), AUDACITY_AV_CODEC_ID_WMAV2 },
1422 { wxT("matroska"), AUDACITY_AV_CODEC_ID_WMAPRO },
1423 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ADPCM_CT },
1424 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ATRAC3 },
1425 { wxT("matroska"), AUDACITY_AV_CODEC_ID_IMC },
1426 { wxT("matroska"), AUDACITY_AV_CODEC_ID_AC3 },
1427 { wxT("matroska"), AUDACITY_AV_CODEC_ID_DTS },
1428 { wxT("matroska"), AUDACITY_AV_CODEC_ID_FLAC },
1429 { wxT("matroska"), AUDACITY_AV_CODEC_ID_ADPCM_SWF },
1430 { wxT("matroska"), AUDACITY_AV_CODEC_ID_VORBIS },
1431
1433
1434 { wxT("mov"), AUDACITY_AV_CODEC_ID_PCM_S32BE }, //mov
1440 { wxT("mov"), AUDACITY_AV_CODEC_ID_PCM_S8 },
1441 { wxT("mov"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1445 { wxT("mov"), AUDACITY_AV_CODEC_ID_MACE3 },
1446 { wxT("mov"), AUDACITY_AV_CODEC_ID_MACE6 },
1447 { wxT("mov"), AUDACITY_AV_CODEC_ID_MP3 },
1448 { wxT("mov"), AUDACITY_AV_CODEC_ID_AAC },
1449 { wxT("mov"), AUDACITY_AV_CODEC_ID_AMR_NB },
1450 { wxT("mov"), AUDACITY_AV_CODEC_ID_AMR_WB },
1451 { wxT("mov"), AUDACITY_AV_CODEC_ID_GSM },
1452 { wxT("mov"), AUDACITY_AV_CODEC_ID_ALAC },
1453 { wxT("mov"), AUDACITY_AV_CODEC_ID_QCELP },
1454 { wxT("mov"), AUDACITY_AV_CODEC_ID_QDM2 },
1456 { wxT("mov"), AUDACITY_AV_CODEC_ID_WMAV2 },
1457 { wxT("mov"), AUDACITY_AV_CODEC_ID_ALAC },
1458
1459 { wxT("mp4"), AUDACITY_AV_CODEC_ID_AAC },
1460 { wxT("mp4"), AUDACITY_AV_CODEC_ID_QCELP },
1461 { wxT("mp4"), AUDACITY_AV_CODEC_ID_MP3 },
1462 { wxT("mp4"), AUDACITY_AV_CODEC_ID_VORBIS },
1463
1464 { wxT("psp"), AUDACITY_AV_CODEC_ID_AAC },
1465 { wxT("psp"), AUDACITY_AV_CODEC_ID_QCELP },
1466 { wxT("psp"), AUDACITY_AV_CODEC_ID_MP3 },
1467 { wxT("psp"), AUDACITY_AV_CODEC_ID_VORBIS },
1468
1469 { wxT("ipod"), AUDACITY_AV_CODEC_ID_AAC },
1470 { wxT("ipod"), AUDACITY_AV_CODEC_ID_QCELP },
1471 { wxT("ipod"), AUDACITY_AV_CODEC_ID_MP3 },
1472 { wxT("ipod"), AUDACITY_AV_CODEC_ID_VORBIS },
1473
1474 { wxT("3gp"), AUDACITY_AV_CODEC_ID_AAC },
1475 { wxT("3gp"), AUDACITY_AV_CODEC_ID_AMR_NB },
1476 { wxT("3gp"), AUDACITY_AV_CODEC_ID_AMR_WB },
1477
1478 { wxT("3g2"), AUDACITY_AV_CODEC_ID_AAC },
1479 { wxT("3g2"), AUDACITY_AV_CODEC_ID_AMR_NB },
1480 { wxT("3g2"), AUDACITY_AV_CODEC_ID_AMR_WB },
1481
1482 { wxT("mp3"), AUDACITY_AV_CODEC_ID_MP3 },
1483
1484 { wxT("mpeg"), AUDACITY_AV_CODEC_ID_AC3 },
1485 { wxT("mpeg"), AUDACITY_AV_CODEC_ID_DTS },
1487 //{ wxT("mpeg"), AUDACITY_AV_CODEC_ID_MP2 },// Bug 59
1488
1489 { wxT("vcd"), AUDACITY_AV_CODEC_ID_AC3 },
1490 { wxT("vcd"), AUDACITY_AV_CODEC_ID_DTS },
1492 //{ wxT("vcd"), AUDACITY_AV_CODEC_ID_MP2 },// Bug 59
1493
1494 { wxT("vob"), AUDACITY_AV_CODEC_ID_AC3 },
1495 { wxT("vob"), AUDACITY_AV_CODEC_ID_DTS },
1497 //{ wxT("vob"), AUDACITY_AV_CODEC_ID_MP2 },// Bug 59
1498
1499 { wxT("svcd"), AUDACITY_AV_CODEC_ID_AC3 },
1500 { wxT("svcd"), AUDACITY_AV_CODEC_ID_DTS },
1502 //{ wxT("svcd"), AUDACITY_AV_CODEC_ID_MP2 },// Bug 59
1503
1504 { wxT("dvd"), AUDACITY_AV_CODEC_ID_AC3 },
1505 { wxT("dvd"), AUDACITY_AV_CODEC_ID_DTS },
1507 //{ wxT("dvd"), AUDACITY_AV_CODEC_ID_MP2 },// Bug 59
1508
1510 { wxT("nut"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1520 { wxT("nut"), AUDACITY_AV_CODEC_ID_GSM_MS },
1522 //{ wxT("nut"), AUDACITY_AV_CODEC_ID_MP2 },// Bug 59
1523 { wxT("nut"), AUDACITY_AV_CODEC_ID_MP3 },
1524 #if LIBAVCODEC_VERSION_MAJOR < 58
1526 #endif
1527 { wxT("nut"), AUDACITY_AV_CODEC_ID_AAC },
1528 { wxT("nut"), AUDACITY_AV_CODEC_ID_WMAV1 },
1529 { wxT("nut"), AUDACITY_AV_CODEC_ID_WMAV2 },
1530 { wxT("nut"), AUDACITY_AV_CODEC_ID_WMAPRO },
1532 { wxT("nut"), AUDACITY_AV_CODEC_ID_ATRAC3 },
1533 { wxT("nut"), AUDACITY_AV_CODEC_ID_IMC },
1534 { wxT("nut"), AUDACITY_AV_CODEC_ID_AC3 },
1535 { wxT("nut"), AUDACITY_AV_CODEC_ID_DTS },
1536 { wxT("nut"), AUDACITY_AV_CODEC_ID_FLAC },
1538 { wxT("nut"), AUDACITY_AV_CODEC_ID_VORBIS },
1539
1540 { wxT("ogg"), AUDACITY_AV_CODEC_ID_VORBIS },
1541 { wxT("ogg"), AUDACITY_AV_CODEC_ID_FLAC },
1542
1543 { wxT("ac3"), AUDACITY_AV_CODEC_ID_AC3 },
1544
1545 { wxT("dts"), AUDACITY_AV_CODEC_ID_DTS },
1546
1547 { wxT("flac"), AUDACITY_AV_CODEC_ID_FLAC },
1548
1550
1551 { wxT("rm"), AUDACITY_AV_CODEC_ID_AC3 },
1552
1553 { wxT("swf"), AUDACITY_AV_CODEC_ID_MP3 },
1554
1555 { wxT("avm2"), AUDACITY_AV_CODEC_ID_MP3 },
1556
1557 { wxT("voc"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1558
1560 { wxT("wav"), AUDACITY_AV_CODEC_ID_PCM_U8 },
1570 { wxT("wav"), AUDACITY_AV_CODEC_ID_GSM_MS },
1572 //{ wxT("wav"), AUDACITY_AV_CODEC_ID_MP2 }, Bug 59 - It crashes.
1573 { wxT("wav"), AUDACITY_AV_CODEC_ID_MP3 },
1574#if LIBAVCODEC_VERSION_MAJOR < 58
1576#endif
1577 { wxT("wav"), AUDACITY_AV_CODEC_ID_AAC },
1578 // { wxT("wav"), AUDACITY_AV_CODEC_ID_WMAV1 },
1579 // { wxT("wav"), AUDACITY_AV_CODEC_ID_WMAV2 },
1580 { wxT("wav"), AUDACITY_AV_CODEC_ID_WMAPRO },
1582 { wxT("wav"), AUDACITY_AV_CODEC_ID_ATRAC3 },
1583 { wxT("wav"), AUDACITY_AV_CODEC_ID_IMC },
1584 { wxT("wav"), AUDACITY_AV_CODEC_ID_AC3 },
1585 //{ wxT("wav"), AUDACITY_AV_CODEC_ID_DTS },
1586 { wxT("wav"), AUDACITY_AV_CODEC_ID_FLAC },
1588 { wxT("wav"), AUDACITY_AV_CODEC_ID_VORBIS },
1589
1591};
1592
1594// The FF_PROFILE_* enumeration is defined in the ffmpeg library
1595// PRL: I can't find where this preference is used!
1596ChoiceSetting AACProfiles { wxT("/FileFormats/FFmpegAACProfile"),
1597 {
1598 {wxT("1") /*FF_PROFILE_AAC_LOW*/, XO("LC")},
1599 {wxT("0") /*FF_PROFILE_AAC_MAIN*/, XO("Main")},
1600 // {wxT("2") /*FF_PROFILE_AAC_SSR*/, XO("SSR")}, //SSR is not supported
1601 {wxT("3") /*FF_PROFILE_AAC_LTP*/, XO("LTP")},
1602 },
1603 0, // "1"
1604};
1605
1608{
1609 {FMT_M4A, wxT("M4A"), wxT("m4a"), wxT("ipod"), 48, AV_CANMETA, true, XO("M4A (AAC) Files (FFmpeg)"), AUDACITY_AV_CODEC_ID_AAC, true},
1610 {FMT_AC3, wxT("AC3"), wxT("ac3"), wxT("ac3"), 7, AV_VERSION_INT(0,0,0), false, XO("AC3 Files (FFmpeg)"), AUDACITY_AV_CODEC_ID_AC3, true},
1611 {FMT_AMRNB, wxT("AMRNB"), wxT("amr"), wxT("amr"), 1, AV_VERSION_INT(0,0,0), false, XO("AMR (narrow band) Files (FFmpeg)"), AUDACITY_AV_CODEC_ID_AMR_NB, true},
1612 {FMT_OPUS, wxT("OPUS"), wxT("opus"), wxT("opus"), 255, AV_CANMETA, true, XO("Opus (OggOpus) Files (FFmpeg)"), AUDACITY_AV_CODEC_ID_OPUS, true},
1613 {FMT_WMA2, wxT("WMA"), wxT("wma"), wxT("asf"), 2, AV_VERSION_INT(52,53,0), false, XO("WMA (version 2) Files (FFmpeg)"), AUDACITY_AV_CODEC_ID_WMAV2, true},
1614 {FMT_OTHER, wxT("FFMPEG"), wxT(""), wxT(""), 255, AV_CANMETA, true, XO("Custom FFmpeg Export"), AUDACITY_AV_CODEC_ID_NONE, true}
1615};
1616
1625{
1626 {TRUE,FEQualityID,AUDACITY_AV_CODEC_ID_AAC,"any"},
1627 {TRUE,FEQualityID,AUDACITY_AV_CODEC_ID_MP3,"any"},
1628 {TRUE,FEQualityID,AUDACITY_AV_CODEC_ID_VORBIS,"any"},
1629 {FALSE,FEQualityID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1630
1631 {TRUE,FECutoffID,AUDACITY_AV_CODEC_ID_AC3,"any"},
1632 {TRUE,FECutoffID,AUDACITY_AV_CODEC_ID_AAC,"any"},
1633 {TRUE,FECutoffID,AUDACITY_AV_CODEC_ID_VORBIS,"any"},
1634 {FALSE,FECutoffID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1635
1636 {TRUE,FEFrameSizeID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1637 {FALSE,FEFrameSizeID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1638
1639 {TRUE,FEProfileID,AUDACITY_AV_CODEC_ID_AAC,"any"},
1640 {FALSE,FEProfileID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1641
1642 {TRUE,FECompLevelID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1643 {FALSE,FECompLevelID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1644
1645 {TRUE,FEUseLPCID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1646 {FALSE,FEUseLPCID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1647
1648 {TRUE,FELPCCoeffsID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1649 {FALSE,FELPCCoeffsID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1650
1651 {TRUE,FEMinPredID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1652 {FALSE,FEMinPredID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1653
1654 {TRUE,FEMaxPredID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1655 {FALSE,FEMaxPredID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1656
1657 {TRUE,FEPredOrderID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1658 {FALSE,FEPredOrderID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1659
1660 {TRUE,FEMinPartOrderID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1661 {FALSE,FEMinPartOrderID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1662
1663 {TRUE,FEMaxPartOrderID,AUDACITY_AV_CODEC_ID_FLAC,"any"},
1664 {FALSE,FEMaxPartOrderID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1665
1666 {TRUE,FEMuxRateID,AUDACITY_AV_CODEC_ID_NONE,"mpeg"},
1667 {TRUE,FEMuxRateID,AUDACITY_AV_CODEC_ID_NONE,"vcd"},
1668 {TRUE,FEMuxRateID,AUDACITY_AV_CODEC_ID_NONE,"vob"},
1669 {TRUE,FEMuxRateID,AUDACITY_AV_CODEC_ID_NONE,"svcd"},
1670 {TRUE,FEMuxRateID,AUDACITY_AV_CODEC_ID_NONE,"dvd"},
1671 {FALSE,FEMuxRateID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1672
1673 {TRUE,FEPacketSizeID,AUDACITY_AV_CODEC_ID_NONE,"mpeg"},
1674 {TRUE,FEPacketSizeID,AUDACITY_AV_CODEC_ID_NONE,"vcd"},
1675 {TRUE,FEPacketSizeID,AUDACITY_AV_CODEC_ID_NONE,"vob"},
1676 {TRUE,FEPacketSizeID,AUDACITY_AV_CODEC_ID_NONE,"svcd"},
1677 {TRUE,FEPacketSizeID,AUDACITY_AV_CODEC_ID_NONE,"dvd"},
1678 {FALSE,FEPacketSizeID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1679
1680 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"matroska"},
1681 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"mov"},
1682 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"3gp"},
1683 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"mp4"},
1684 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"psp"},
1685 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"3g2"},
1686 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"ipod"},
1687 {TRUE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"mpegts"},
1688 {FALSE,FELanguageID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1689
1690 {TRUE,FEBitReservoirID,AUDACITY_AV_CODEC_ID_MP3,"any"},
1691 {TRUE,FEBitReservoirID,AUDACITY_AV_CODEC_ID_WMAV1,"any"},
1692 {TRUE,FEBitReservoirID,AUDACITY_AV_CODEC_ID_WMAV2,"any"},
1693 {FALSE,FEBitReservoirID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1694
1695 {TRUE,FEVariableBlockLenID,AUDACITY_AV_CODEC_ID_WMAV1,"any"},
1696 {TRUE,FEVariableBlockLenID,AUDACITY_AV_CODEC_ID_WMAV2,"any"},
1697 {FALSE,FEVariableBlockLenID,AUDACITY_AV_CODEC_ID_NONE,"any"},
1698
1700};
1701
1702namespace {
1703
1706 XO("Estimate"),
1707 XO("2-level"),
1708 XO("4-level"),
1709 XO("8-level"),
1710 XO("Full search"),
1711 XO("Log search"),
1712};
1713
1714}
1715
1716
1717
1719{
1720}
1721
1723: wxDialogWrapper(parent, wxID_ANY,
1724 XO("Configure custom FFmpeg options"))
1725{
1726 SetName();
1729 //FFmpegLibsInst()->LoadLibs(NULL,true); //Loaded at startup or from Prefs now
1730
1731 mPresets = std::make_unique<FFmpegPresets>();
1732 mPresets->GetPresetList(mPresetNames);
1733
1734 if (mFFmpeg)
1735 {
1738
1740
1741 //Select the format that was selected last time this dialog was closed
1742 mFormatList->Select(mFormatList->FindString(gPrefs->Read(wxT("/FileFormats/FFmpegFormat"))));
1744
1745 //Select the codec that was selected last time this dialog was closed
1746 auto codec = mFFmpeg->CreateEncoder(gPrefs->Read(wxT("/FileFormats/FFmpegCodec")).ToUTF8());
1747
1748 if (codec != nullptr)
1749 mCodecList->Select(mCodecList->FindString(wxString::FromUTF8(codec->GetName())));
1750
1751 DoOnCodecList();
1752 }
1753
1754}
1755
1759{
1760 if (!mFFmpeg)
1761 return;
1762
1763 for (auto ofmt : mFFmpeg->GetOutputFormats())
1764 {
1765 // Any audio-capable format has default audio codec.
1766 // If it doesn't, then it doesn't supports any audio codecs
1767 if (ofmt->GetAudioCodec() != AUDACITY_AV_CODEC_ID_NONE)
1768 {
1769 mFormatNames.push_back(wxString::FromUTF8(ofmt->GetName()));
1770 mFormatLongNames.push_back(wxString::Format(wxT("%s - %s"),mFormatNames.back(),wxString::FromUTF8(ofmt->GetLongName())));
1771 }
1772 }
1773 // Show all formats
1776}
1777
1781{
1782 if (!mFFmpeg)
1783 return;
1784 // Enumerate all codecs
1785 std::unique_ptr<AVCodecWrapper> codec;
1786 for (auto codec : mFFmpeg->GetCodecs())
1787 {
1788 // We're only interested in audio and only in encoders
1789 if (codec->IsAudio() && mFFmpeg->av_codec_is_encoder(codec->GetWrappedValue()))
1790 {
1791 // MP2 Codec is broken. Don't allow it.
1792 if( codec->GetId() == mFFmpeg->GetAVCodecID(AUDACITY_AV_CODEC_ID_MP2))
1793 continue;
1794
1795 mCodecNames.push_back(wxString::FromUTF8(codec->GetName()));
1796 mCodecLongNames.push_back(wxString::Format(wxT("%s - %s"),mCodecNames.back(),wxString::FromUTF8(codec->GetLongName())));
1797 }
1798 }
1799 // Show all codecs
1802}
1803
1807{
1808 IntSetting PredictionOrderSetting{ L"/FileFormats/FFmpegPredOrderMethod",
1809 4 }; // defaults to Full search
1810
1811 S.StartVerticalLay(1);
1812 S.StartMultiColumn(1, wxEXPAND);
1813 {
1814 S.SetStretchyRow(3);
1815 S.StartMultiColumn(7, wxEXPAND);
1816 {
1817 S.SetStretchyCol(1);
1818 mPresetCombo = S.Id(FEPresetID).AddCombo(XXO("Preset:"), gPrefs->Read(wxT("/FileFormats/FFmpegPreset"),wxEmptyString), mPresetNames);
1819 S.Id(FELoadPresetID).AddButton(XXO("Load Preset"));
1820 S.Id(FESavePresetID).AddButton(XXO("Save Preset"));
1821 S.Id(FEDeletePresetID).AddButton(XXO("Delete Preset"));
1822 S.Id(FEImportPresetsID).AddButton(XXO("Import Presets"));
1823 S.Id(FEExportPresetsID).AddButton(XXO("Export Presets"));
1824 }
1825 S.EndMultiColumn();
1826 S.StartMultiColumn(4, wxALIGN_LEFT);
1827 {
1828 S.SetStretchyCol(1);
1829 S.SetStretchyCol(3);
1830 S.Id(FEFormatLabelID).AddFixedText(XO("Format:"));
1831 mFormatName = S.Id(FEFormatNameID).AddVariableText( {} );
1832 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
1833 S.Id(FECodecLabelID).AddFixedText(XO("Codec:"));
1834 mCodecName = S.Id(FECodecNameID).AddVariableText( {} );
1835 }
1836 S.EndMultiColumn();
1837 S.AddVariableText(XO(
1838"Not all formats and codecs are compatible. Nor are all option combinations compatible with all codecs."),
1839 false);
1840 S.StartMultiColumn(2, wxEXPAND);
1841 {
1842 S.StartMultiColumn(2, wxEXPAND);
1843 {
1844 S.SetStretchyRow(1);
1845 S.Id(FEAllFormatsID).AddButton(XXO("Show All Formats"));
1846 S.Id(FEAllCodecsID).AddButton(XXO("Show All Codecs"));
1847 mFormatList = S.Id(FEFormatID).AddListBox(mFormatNames);
1848 mFormatList->DeselectAll();
1849 mCodecList = S.Id(FECodecID).AddListBox(mCodecNames);
1850 mCodecList->DeselectAll();
1851 }
1852 S.EndMultiColumn();
1853 S.StartVerticalLay();
1854 {
1855 //S.StartScroller( );
1856 S.SetBorder( 3 );
1857 S.StartStatic(XO("General Options"), 0);
1858 {
1859 S.StartMultiColumn(8, wxEXPAND);
1860 {
1861 S.Id(FELanguageID)
1862 .ToolTip(XO("ISO 639 3-letter language code\nOptional\nempty - automatic"))
1863 .TieTextBox(XXO("Language:"), {wxT("/FileFormats/FFmpegLanguage"), wxEmptyString}, 9);
1864
1865 S.AddSpace( 20,0 );
1866 S.AddVariableText(XO("Bit Reservoir"));
1867 S.Id(FEBitReservoirID).TieCheckBox( {}, {wxT("/FileFormats/FFmpegBitReservoir"), true});
1868
1869 S.AddSpace( 20,0 );
1870 S.AddVariableText(XO("VBL"));
1871 S.Id(FEVariableBlockLenID).TieCheckBox( {}, {wxT("/FileFormats/FFmpegVariableBlockLen"), true});
1872 }
1873 S.EndMultiColumn();
1874 S.StartMultiColumn(4, wxALIGN_LEFT);
1875 {
1876 S.Id(FETagID)
1877 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
1878 .ToolTip(XO("Codec tag (FOURCC)\nOptional\nempty - automatic"))
1879 .TieTextBox(XXO("Tag:"), {wxT("/FileFormats/FFmpegTag"), wxEmptyString}, 4);
1880
1881 S.Id(FEBitrateID)
1882 .ToolTip(XO("Bit Rate (bits/second) - influences the resulting file size and quality\nSome codecs may only accept specific values (128k, 192k, 256k etc)\n0 - automatic\nRecommended - 192000"))
1883 .TieSpinCtrl(XXO("Bit Rate:"), {wxT("/FileFormats/FFmpegBitRate"), 0}, 1000000, 0);
1884
1885 S.Id(FEQualityID)
1886 .ToolTip(XO("Overall quality, used differently by different codecs\nRequired for vorbis\n0 - automatic\n-1 - off (use bitrate instead)"))
1887 .TieSpinCtrl(XXO("Quality:"), {wxT("/FileFormats/FFmpegQuality"), 0}, 500, -1);
1888
1889 S.Id(FESampleRateID)
1890 .ToolTip(XO("Sample rate (Hz)\n0 - don't change sample rate"))
1891 .TieSpinCtrl(XXO("Sample Rate:"), {wxT("/FileFormats/FFmpegSampleRate"), 0}, 200000, 0);
1892
1893 S.Id(FECutoffID)
1894 .ToolTip(XO("Audio cutoff bandwidth (Hz)\nOptional\n0 - automatic"))
1895 .TieSpinCtrl(XXO("Cutoff:"), {wxT("/FileFormats/FFmpegCutOff"), 0}, 10000000, 0);
1896
1897 // PRL: As commented elsewhere, this preference does nothing
1898 S.Id(FEProfileID)
1899 .ToolTip(XO("AAC Profile\nLow Complexity - default\nMost players won't play anything other than LC"))
1900 .MinSize( { 100, -1 } )
1901 .TieChoice(XXO("Profile:"), AACProfiles);
1902 }
1903 S.EndMultiColumn();
1904 }
1905 S.EndStatic();
1906 S.StartStatic(XO("FLAC options"),0);
1907 {
1908 S.StartMultiColumn(4, wxALIGN_LEFT);
1909 {
1910 S
1911 .ToolTip(XO("Compression level\nRequired for FLAC\n-1 - automatic\nmin - 0 (fast encoding, large output file)\nmax - 10 (slow encoding, small output file)"))
1912 .Id(FECompLevelID).TieSpinCtrl(XXO("Compression:"), {wxT("/FileFormats/FFmpegCompLevel"), 0}, 10, -1);
1913
1914 S.Id(FEFrameSizeID)
1915 .ToolTip(XO("Frame size\nOptional\n0 - default\nmin - 16\nmax - 65535"))
1916 .TieSpinCtrl(XXO("Frame:"), {wxT("/FileFormats/FFmpegFrameSize"), 0}, 65535, 0);
1917
1918 S.Id(FELPCCoeffsID)
1919 .ToolTip(XO("LPC coefficients precision\nOptional\n0 - default\nmin - 1\nmax - 15"))
1920 .TieSpinCtrl(XXO("LPC"), {wxT("/FileFormats/FFmpegLPCCoefPrec"), 0}, 15, 0);
1921
1922 S.Id(FEPredOrderID)
1923 .ToolTip(XO("Prediction Order Method\nEstimate - fastest, lower compression\nLog search - slowest, best compression\nFull search - default"))
1924 .MinSize( { 100, -1 } )
1925 .TieNumberAsChoice(
1926 XXO("PdO Method:"),
1927 PredictionOrderSetting,
1929 );
1930
1931 S.Id(FEMinPredID)
1932 .ToolTip(XO("Minimal prediction order\nOptional\n-1 - default\nmin - 0\nmax - 32 (with LPC) or 4 (without LPC)"))
1933 .TieSpinCtrl(XXO("Min. PdO"), {wxT("/FileFormats/FFmpegMinPredOrder"), -1}, 32, -1);
1934
1935 S.Id(FEMaxPredID)
1936 .ToolTip(XO("Maximal prediction order\nOptional\n-1 - default\nmin - 0\nmax - 32 (with LPC) or 4 (without LPC)"))
1937 .TieSpinCtrl(XXO("Max. PdO"), {wxT("/FileFormats/FFmpegMaxPredOrder"), -1}, 32, -1);
1938
1939 S.Id(FEMinPartOrderID)
1940 .ToolTip(XO("Minimal partition order\nOptional\n-1 - default\nmin - 0\nmax - 8"))
1941 .TieSpinCtrl(XXO("Min. PtO"), {wxT("/FileFormats/FFmpegMinPartOrder"), -1}, 8, -1);
1942
1943 S.Id(FEMaxPartOrderID)
1944 .ToolTip(XO("Maximal partition order\nOptional\n-1 - default\nmin - 0\nmax - 8"))
1945 .TieSpinCtrl(XXO("Max. PtO"), {wxT("/FileFormats/FFmpegMaxPartOrder"), -1}, 8, -1);
1946
1947 /* i18n-hint: Abbreviates "Linear Predictive Coding",
1948 but this text needs to be kept very short */
1949 S.AddVariableText(XO("Use LPC"));
1950 // PRL: This preference is not used anywhere!
1951 S.Id(FEUseLPCID).TieCheckBox( {}, {wxT("/FileFormats/FFmpegUseLPC"), true});
1952 }
1953 S.EndMultiColumn();
1954 }
1955 S.EndStatic();
1956 S.StartStatic(XO("MPEG container options"),0);
1957 {
1958 S.StartMultiColumn(4, wxALIGN_LEFT);
1959 {
1960 S.Id(FEMuxRateID)
1961 .ToolTip(XO("Maximum bit rate of the multiplexed stream\nOptional\n0 - default"))
1962 /* i18n-hint: 'mux' is short for multiplexor, a device that selects between several inputs
1963 'Mux Rate' is a parameter that has some bearing on compression ratio for MPEG
1964 it has a hard to predict effect on the degree of compression */
1965 .TieSpinCtrl(XXO("Mux Rate:"), {wxT("/FileFormats/FFmpegMuxRate"), 0}, 10000000, 0);
1966
1967 S.Id(FEPacketSizeID)
1968 /* i18n-hint: 'Packet Size' is a parameter that has some bearing on compression ratio for MPEG
1969 compression. It measures how big a chunk of audio is compressed in one piece. */
1970 .ToolTip(XO("Packet size\nOptional\n0 - default"))
1971 /* i18n-hint: 'Packet Size' is a parameter that has some bearing on compression ratio for MPEG
1972 compression. It measures how big a chunk of audio is compressed in one piece. */
1973 .TieSpinCtrl(XXO("Packet Size:"), {wxT("/FileFormats/FFmpegPacketSize"), 0}, 10000000, 0);
1974 }
1975 S.EndMultiColumn();
1976 }
1977 S.EndStatic();
1978 //S.EndScroller();
1979 S.SetBorder( 5 );
1980 S.AddStandardButtons(eOkButton | eCancelButton | eHelpButton );
1981 }
1982 S.EndVerticalLay();
1983 }
1984 S.EndMultiColumn();
1985 }
1986 S.EndMultiColumn();
1987 S.EndVerticalLay();
1988
1989 Layout();
1990 Fit();
1991 SetMinSize(GetSize());
1992 Center();
1993
1994 return;
1995}
1996
1999void ExportFFmpegOptions::FindSelectedFormat(wxString **name, wxString **longname)
2000{
2001 // Get current selection
2002 wxArrayInt selections;
2003 int n = mFormatList->GetSelections(selections);
2004 if (n <= 0) return;
2005
2006 // Get selected format short name
2007 wxString selfmt = mFormatList->GetString(selections[0]);
2008
2009 // Find its index
2010 int nFormat = make_iterator_range( mFormatNames ).index( selfmt );
2011 if (nFormat == wxNOT_FOUND) return;
2012
2013 // Return short name and description
2014 if (name != NULL) *name = &mFormatNames[nFormat];
2015 if (longname != NULL) *longname = &mFormatLongNames[nFormat];
2016 return;
2017}
2020void ExportFFmpegOptions::FindSelectedCodec(wxString **name, wxString **longname)
2021{
2022 // Get current selection
2023 wxArrayInt selections;
2024 int n = mCodecList->GetSelections(selections);
2025 if (n <= 0) return;
2026
2027 // Get selected codec short name
2028 wxString selcdc = mCodecList->GetString(selections[0]);
2029
2030 // Find its index
2031 int nCodec = make_iterator_range( mCodecNames ).index( selcdc );
2032 if (nCodec == wxNOT_FOUND) return;
2033
2034 // Return short name and description
2035 if (name != NULL) *name = &mCodecNames[nCodec];
2036 if (longname != NULL) *longname = &mCodecLongNames[nCodec];
2037}
2038
2042{
2043 const auto ffmpegId = mFFmpeg->GetAVCodecID(id);
2044
2045 // By default assume that id is not in the list
2046 int index = -1;
2047 // By default no codecs are compatible (yet)
2048 mShownCodecNames.clear();
2049 mShownCodecLongNames.clear();
2050 // Clear the listbox
2051 mCodecList->Clear();
2052 // Zero - format is not found at all
2053 int found = 0;
2054 wxString str(fmt);
2055 for (int i = 0; CompatibilityList[i].fmt != NULL; i++)
2056 {
2057 if (str == CompatibilityList[i].fmt)
2058 {
2059 // Format is found in the list
2060 found = 1;
2061 if (CompatibilityList[i].codec.value == AUDACITY_AV_CODEC_ID_NONE)
2062 {
2063 // Format is found in the list and it is compatible with AUDACITY_AV_CODEC_ID_NONE (means that it is compatible to anything)
2064 found = 2;
2065 break;
2066 }
2067 // Find the codec, that is claimed to be compatible
2068 std::unique_ptr<AVCodecWrapper> codec = mFFmpeg->CreateEncoder(mFFmpeg->GetAVCodecID(CompatibilityList[i].codec));
2069 // If it exists, is audio and has encoder
2070 if (codec != NULL && codec->IsAudio() && mFFmpeg->av_codec_is_encoder(codec->GetWrappedValue()))
2071 {
2072 // If it was selected - remember its NEW index
2073 if ((ffmpegId >= 0) && codec->GetId() == ffmpegId)
2074 index = mShownCodecNames.size();
2075
2076 mShownCodecNames.push_back(wxString::FromUTF8(codec->GetName()));
2077 mShownCodecLongNames.push_back(wxString::Format(wxT("%s - %s"),mShownCodecNames.back(),wxString::FromUTF8(codec->GetLongName())));
2078 }
2079 }
2080 }
2081 // All codecs are compatible with this format
2082 if (found == 2)
2083 {
2084 std::unique_ptr<AVCodecWrapper> codec;
2085 for (auto codec : mFFmpeg->GetCodecs())
2086 {
2087 if (codec->IsAudio() && mFFmpeg->av_codec_is_encoder(codec->GetWrappedValue()))
2088 {
2089 // MP2 is broken.
2090 if( codec->GetId() == mFFmpeg->GetAVCodecID(AUDACITY_AV_CODEC_ID_MP2) )
2091 continue;
2092
2094 .contains( wxString::FromUTF8(codec->GetName()) ) )
2095 {
2096 if ((ffmpegId >= 0) && codec->GetId() == ffmpegId)
2097 index = mShownCodecNames.size();
2098
2099 mShownCodecNames.push_back(wxString::FromUTF8(codec->GetName()));
2100 mShownCodecLongNames.push_back(wxString::Format(wxT("%s - %s"),mShownCodecNames.back(),wxString::FromUTF8(codec->GetLongName())));
2101 }
2102 }
2103 }
2104 }
2105 // Format is not found - find format in libavformat and add its default audio codec
2106 // This allows us to provide limited support for NEW formats without modifying the compatibility list
2107 else if (found == 0)
2108 {
2109 wxCharBuffer buf = str.ToUTF8();
2110 auto format = mFFmpeg->GuessOutputFormat(buf, nullptr, nullptr);
2111
2112 if (format != nullptr)
2113 {
2114 auto codec = mFFmpeg->CreateEncoder(format->GetAudioCodec());
2115
2116 if (
2117 codec != nullptr && codec->IsAudio() && mFFmpeg->av_codec_is_encoder(codec->GetWrappedValue()))
2118 {
2119 if ((ffmpegId >= 0) && codec->GetId() == ffmpegId)
2120 index = mShownCodecNames.size();
2121
2122 mShownCodecNames.push_back(wxString::FromUTF8(codec->GetName()));
2123 mShownCodecLongNames.push_back(wxString::Format(wxT("%s - %s"),mShownCodecNames.back(),wxString::FromUTF8(codec->GetLongName())));
2124 }
2125 }
2126 }
2127 // Show NEW codec list
2129
2130 return index;
2131}
2132
2136 AudacityAVCodecID id, wxString* selfmt)
2137{
2138 int index = -1;
2139 mShownFormatNames.clear();
2140 mShownFormatLongNames.clear();
2141 mFormatList->Clear();
2142
2143 wxArrayString FromList;
2144 // Find all formats compatible to this codec in compatibility list
2145 for (int i = 0; CompatibilityList[i].fmt != NULL; i++)
2146 {
2147 if (CompatibilityList[i].codec == id || (CompatibilityList[i].codec.value == AUDACITY_AV_CODEC_ID_NONE) )
2148 {
2149 if ((selfmt != NULL) && (*selfmt == CompatibilityList[i].fmt)) index = mShownFormatNames.size();
2150 FromList.push_back(CompatibilityList[i].fmt);
2151 mShownFormatNames.push_back(CompatibilityList[i].fmt);
2152 auto tofmt = mFFmpeg->GuessOutputFormat(
2153 wxString(CompatibilityList[i].fmt).ToUTF8(), nullptr, nullptr);
2154
2155 if (tofmt != NULL)
2156 {
2157 mShownFormatLongNames.push_back(wxString::Format(
2158 wxT("%s - %s"), CompatibilityList[i].fmt,
2159 wxString::FromUTF8(tofmt->GetLongName())));
2160 }
2161 }
2162 }
2163 bool found = false;
2164 if (selfmt != NULL)
2165 {
2166 for (int i = 0; CompatibilityList[i].fmt != NULL; i++)
2167 {
2168 if (*selfmt == CompatibilityList[i].fmt)
2169 {
2170 found = true;
2171 break;
2172 }
2173 }
2174 }
2175 // Format was in the compatibility list
2176 if (found)
2177 {
2178 // Find all formats which have this codec as default and which are not in the list yet and add them too
2179 for (auto ofmt : mFFmpeg->GetOutputFormats())
2180 {
2181 if (ofmt->GetAudioCodec() == mFFmpeg->GetAVCodecID(id))
2182 {
2183 wxString ofmtname = wxString::FromUTF8(ofmt->GetName());
2184 found = false;
2185 for (unsigned int i = 0; i < FromList.size(); i++)
2186 {
2187 if (ofmtname == FromList[i])
2188 {
2189 found = true;
2190 break;
2191 }
2192 }
2193 if (!found)
2194 {
2195 if ((selfmt != NULL) &&
2196 (*selfmt == wxString::FromUTF8(ofmt->GetName())))
2197 index = mShownFormatNames.size();
2198
2199 mShownFormatNames.push_back(wxString::FromUTF8(ofmt->GetName()));
2200
2201 mShownFormatLongNames.push_back(wxString::Format(
2202 wxT("%s - %s"), mShownFormatNames.back(),
2203 wxString::FromUTF8(ofmt->GetLongName())));
2204 }
2205 }
2206 }
2207 }
2209 return index;
2210}
2211
2214void ExportFFmpegOptions::OnDeletePreset(wxCommandEvent& WXUNUSED(event))
2215{
2216 wxComboBox *preset = dynamic_cast<wxComboBox*>(FindWindowById(FEPresetID,this));
2217 wxString presetname = preset->GetValue();
2218 if (presetname.empty())
2219 {
2220 AudacityMessageBox( XO("You can't delete a preset without name") );
2221 return;
2222 }
2223
2224 auto query = XO("Delete preset '%s'?").Format( presetname );
2225 int action = AudacityMessageBox(
2226 query,
2227 XO("Confirm Deletion"),
2228 wxYES_NO | wxCENTRE);
2229 if (action == wxNO) return;
2230
2231 mPresets->DeletePreset(presetname);
2232 long index = preset->FindString(presetname);
2233 preset->SetValue(wxEmptyString);
2234 preset->Delete(index);
2235 mPresetNames.erase(
2236 std::find( mPresetNames.begin(), mPresetNames.end(), presetname )
2237 );
2238}
2239
2242void ExportFFmpegOptions::OnSavePreset(wxCommandEvent& WXUNUSED(event))
2243{ const bool kCheckForOverwrite = true;
2244 SavePreset(kCheckForOverwrite);
2245}
2246
2247// Return false if failed to save.
2248bool ExportFFmpegOptions::SavePreset(bool bCheckForOverwrite)
2249{
2250 wxComboBox *preset = dynamic_cast<wxComboBox*>(FindWindowById(FEPresetID,this));
2251 wxString name = preset->GetValue();
2252 if (name.empty())
2253 {
2254 AudacityMessageBox( XO("You can't save a preset without a name") );
2255 return false;
2256 }
2257 if( bCheckForOverwrite && !mPresets->OverwriteIsOk(name))
2258 return false;
2259 if( !mPresets->SavePreset(this,name) )
2260 return false;
2261 int index = mPresetNames.Index(name,false);
2262 if (index == -1)
2263 {
2264 mPresetNames.push_back(name);
2265 mPresetCombo->Clear();
2266 mPresetCombo->Append(mPresetNames);
2267 mPresetCombo->Select(mPresetNames.Index(name,false));
2268 }
2269 return true;
2270}
2271
2274void ExportFFmpegOptions::OnLoadPreset(wxCommandEvent& WXUNUSED(event))
2275{
2276 wxComboBox *preset = dynamic_cast<wxComboBox*>(FindWindowById(FEPresetID,this));
2277 wxString presetname = preset->GetValue();
2278
2281 mFormatList->Clear();
2282 mFormatList->Append(mFormatNames);
2283
2286 mCodecList->Clear();
2287 mCodecList->Append(mCodecNames);
2288
2289 mPresets->LoadPreset(this,presetname);
2290
2292 DoOnCodecList();
2293}
2294
2296{
2297 static const FileNames::FileTypes result{
2299 return result;
2300};
2301
2304void ExportFFmpegOptions::OnImportPresets(wxCommandEvent& WXUNUSED(event))
2305{
2306 wxString path;
2307 FileDialogWrapper dlg(this,
2308 XO("Select xml file with presets to import"),
2309 gPrefs->Read(wxT("/FileFormats/FFmpegPresetDir")),
2310 wxEmptyString,
2311 FileTypes(),
2312 wxFD_OPEN);
2313 if (dlg.ShowModal() == wxID_CANCEL) return;
2314 path = dlg.GetPath();
2315 mPresets->ImportPresets(path);
2316 mPresets->GetPresetList(mPresetNames);
2317 mPresetCombo->Clear();
2318 mPresetCombo->Append(mPresetNames);
2319}
2320
2323void ExportFFmpegOptions::OnExportPresets(wxCommandEvent& WXUNUSED(event))
2324{
2325 const bool kCheckForOverwrite = true;
2326 // Bug 1180 save any pending preset before exporting the lot.
2327 // If saving fails, don't try to export.
2328 if( !SavePreset(!kCheckForOverwrite) )
2329 return;
2330
2331 wxArrayString presets;
2332 mPresets->GetPresetList( presets);
2333 if( presets.Count() < 1)
2334 {
2335 AudacityMessageBox( XO("No presets to export") );
2336 return;
2337 }
2338
2339 wxString path;
2340 FileDialogWrapper dlg(this,
2341 XO("Select xml file to export presets into"),
2342 gPrefs->Read(wxT("/FileFormats/FFmpegPresetDir")),
2343 wxEmptyString,
2344 FileTypes(),
2345 wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
2346 if (dlg.ShowModal() == wxID_CANCEL) return;
2347 path = dlg.GetPath();
2348 mPresets->ExportPresets(path);
2349}
2350
2353void ExportFFmpegOptions::OnAllFormats(wxCommandEvent& WXUNUSED(event))
2354{
2357 mFormatList->Clear();
2358 mFormatList->Append(mFormatNames);
2359}
2360
2363void ExportFFmpegOptions::OnAllCodecs(wxCommandEvent& WXUNUSED(event))
2364{
2367 mCodecList->Clear();
2368 mCodecList->Append(mCodecNames);
2369}
2370
2379{
2380 wxString *selcdc = nullptr;
2381 wxString* selcdclong = nullptr;
2382
2383 FindSelectedCodec(&selcdc, &selcdclong);
2384
2385 if (selcdc == nullptr)
2386 return false; // unrecognised codec. Treated as OK
2387
2388 auto cdc = mFFmpeg->CreateEncoder(selcdc->ToUTF8());
2389
2390 if (cdc == nullptr)
2391 return false; // unrecognised codec. Treated as OK
2392
2393 wxString* selfmt = nullptr;
2394 wxString* selfmtlong = nullptr;
2395
2396 FindSelectedFormat(&selfmt, &selfmtlong);
2397
2398 if (selfmt == nullptr)
2399 return false; // unrecognised format; Treated as OK
2400
2401 // This is intended to test for illegal combinations.
2402 // However, the list updating now seems to be working correctly
2403 // making it impossible to select illegal combinations
2404 bool bFound = false;
2405 for (int i = 0; CompatibilityList[i].fmt != NULL; i++)
2406 {
2407 if (*selfmt == CompatibilityList[i].fmt)
2408 {
2409 if (CompatibilityList[i].codec == mFFmpeg->GetAudacityCodecID(cdc->GetId()) || (CompatibilityList[i].codec == AUDACITY_AV_CODEC_ID_NONE) ){
2410 bFound = true;
2411 break;
2412 }
2413 }
2414 }
2415
2416 // We can put extra code in here, to disallow combinations
2417 // We could also test for illegal parameters, and deliver
2418 // custom error messages in that case.
2419 // The below would make AAC codec disallowed.
2420 //if( cdc->id == AUDACITY_AV_CODEC_ID_AAC)
2421 // bFound = false;
2422
2423 // Valid combination was found, so no reporting.
2424 if( bFound )
2425 return false;
2426
2428 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
2429 XO("Format %s is not compatible with codec %s.")
2430 .Format( *selfmt, *selcdc ),
2431 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
2432 XO("Incompatible format and codec"));
2433
2434 return true;
2435}
2436
2437
2438
2440{
2441 int handled = -1;
2442 for (int i = 0; apptable[i].control != 0; i++)
2443 {
2444 if (apptable[i].control != handled)
2445 {
2446 bool codec = false;
2447 bool format = false;
2448 if (apptable[i].codec == AUDACITY_AV_CODEC_ID_NONE)
2449 {
2450 codec = true;
2451 }
2452 else if (
2453 cdc != NULL &&
2454 apptable[i].codec == mFFmpeg->GetAudacityCodecID(cdc->GetId()))
2455 {
2456 codec = true;
2457 }
2458
2459 if (wxString::FromUTF8(apptable[i].format) == wxT("any")) format = true;
2460 else if (selfmt != NULL &&
2461 *selfmt == wxString::FromUTF8(apptable[i].format)) format = true;
2462 if (codec && format)
2463 {
2464 handled = apptable[i].control;
2465 wxWindow *item = FindWindowById(apptable[i].control,this);
2466 if (item != NULL) item->Enable(apptable[i].enable);
2467 }
2468 }
2469 }
2470}
2471
2473{
2474 wxString *selfmt = NULL;
2475 wxString *selfmtlong = NULL;
2476 FindSelectedFormat(&selfmt, &selfmtlong);
2477 if (selfmt == NULL)
2478 {
2479 return;
2480 }
2481
2482 wxString *selcdc = NULL;
2483 wxString *selcdclong = NULL;
2484 FindSelectedCodec(&selcdc, &selcdclong);
2485
2486 auto fmt = mFFmpeg->GuessOutputFormat(selfmt->ToUTF8(),NULL,NULL);
2487 if (fmt == NULL)
2488 {
2489 //This shouldn't really happen
2490 mFormatName->SetLabel(wxString(_("Failed to guess format")));
2491 return;
2492 }
2493 mFormatName->SetLabel(wxString::Format(wxT("%s"), *selfmtlong));
2494
2496
2497 if (selcdc != nullptr)
2498 {
2499 auto cdc = mFFmpeg->CreateEncoder(selcdc->ToUTF8());
2500
2501 if (cdc != nullptr)
2502 {
2503 selcdcid = mFFmpeg->GetAudacityCodecID(cdc->GetId());
2504 }
2505 }
2506 int newselcdc =
2507 FetchCompatibleCodecList(*selfmt, selcdcid);
2508
2509 if (newselcdc >= 0) mCodecList->Select(newselcdc);
2510
2511 std::unique_ptr<AVCodecWrapper> cdc;
2512
2513 if (selcdc != nullptr)
2514 cdc = mFFmpeg->CreateEncoder(selcdc->ToUTF8());
2515
2516 EnableDisableControls(cdc.get(), selfmt);
2517 Layout();
2518 Fit();
2519 return;
2520}
2521
2523{
2524 wxString *selcdc = nullptr;
2525 wxString* selcdclong = nullptr;
2526
2527 FindSelectedCodec(&selcdc, &selcdclong);
2528
2529 if (selcdc == nullptr)
2530 {
2531 return;
2532 }
2533
2534 wxString* selfmt = nullptr;
2535 wxString* selfmtlong = nullptr;
2536
2537 FindSelectedFormat(&selfmt, &selfmtlong);
2538
2539 auto cdc = mFFmpeg->CreateEncoder(selcdc->ToUTF8());
2540 if (cdc == nullptr)
2541 {
2542 //This shouldn't really happen
2543 /* i18n-hint: "codec" is short for a "coder-decoder" algorithm */
2544 mCodecName->SetLabel(wxString(_("Failed to find the codec")));
2545 return;
2546 }
2547
2548 mCodecName->SetLabel(wxString::Format(wxT("[%d] %s"), (int) mFFmpeg->GetAudacityCodecID(cdc->GetId()).value, *selcdclong));
2549
2550 if (selfmt != nullptr)
2551 {
2552 auto fmt = mFFmpeg->GuessOutputFormat(selfmt->ToUTF8(), nullptr, nullptr);
2553 if (fmt == nullptr)
2554 {
2555 selfmt = nullptr;
2556 selfmtlong = nullptr;
2557 }
2558 }
2559
2560 int newselfmt = FetchCompatibleFormatList(
2561 mFFmpeg->GetAudacityCodecID(cdc->GetId()), selfmt);
2562
2563 if (newselfmt >= 0)
2564 mFormatList->Select(newselfmt);
2565
2566 EnableDisableControls(cdc.get(), selfmt);
2567 Layout();
2568 Fit();
2569 return;
2570}
2571
2574void ExportFFmpegOptions::OnFormatList(wxCommandEvent& WXUNUSED(event))
2575{
2577}
2578
2581void ExportFFmpegOptions::OnCodecList(wxCommandEvent& WXUNUSED(event))
2582{
2583 DoOnCodecList();
2584}
2585
2586
2589void ExportFFmpegOptions::OnOK(wxCommandEvent& WXUNUSED(event))
2590{
2592 return;
2593
2594 int selcdc = mCodecList->GetSelection();
2595 int selfmt = mFormatList->GetSelection();
2596 if (selcdc > -1) gPrefs->Write(wxT("/FileFormats/FFmpegCodec"),mCodecList->GetString(selcdc));
2597 if (selfmt > -1) gPrefs->Write(wxT("/FileFormats/FFmpegFormat"),mFormatList->GetString(selfmt));
2598 gPrefs->Flush();
2599
2602
2603 gPrefs->Flush();
2604
2605 EndModal(wxID_OK);
2606
2607 return;
2608}
2609
2610void ExportFFmpegOptions::OnGetURL(wxCommandEvent & WXUNUSED(event))
2611{
2612 HelpSystem::ShowHelp(this, L"Custom_FFmpeg_Export_Options");
2613}
2614
2615
2616#endif
@ AUDACITY_AV_CODEC_ID_GSM_MS
Definition: AVCodecID.h:324
@ AUDACITY_AV_CODEC_ID_IMC
Definition: AVCodecID.h:321
@ AUDACITY_AV_CODEC_ID_QCELP
Definition: AVCodecID.h:318
@ AUDACITY_AV_CODEC_ID_PCM_S16BE
Definition: AVCodecID.h:218
@ AUDACITY_AV_CODEC_ID_ADPCM_G726
Definition: AVCodecID.h:261
@ AUDACITY_AV_CODEC_ID_OPUS
Definition: AVCodecID.h:363
@ AUDACITY_AV_CODEC_ID_ADPCM_IMA_QT
Definition: AVCodecID.h:250
@ AUDACITY_AV_CODEC_ID_QDM2
Definition: AVCodecID.h:313
@ AUDACITY_AV_CODEC_ID_PCM_S24LE
Definition: AVCodecID.h:229
@ AUDACITY_AV_CODEC_ID_ADPCM_YAMAHA
Definition: AVCodecID.h:264
@ AUDACITY_AV_CODEC_ID_AC3
Definition: AVCodecID.h:297
@ AUDACITY_AV_CODEC_ID_MACE3
Definition: AVCodecID.h:303
@ AUDACITY_AV_CODEC_ID_PCM_MULAW
Definition: AVCodecID.h:223
@ AUDACITY_AV_CODEC_ID_PCM_S8
Definition: AVCodecID.h:221
@ AUDACITY_AV_CODEC_ID_VORBIS
Definition: AVCodecID.h:299
@ AUDACITY_AV_CODEC_ID_DVAUDIO
Definition: AVCodecID.h:300
@ AUDACITY_AV_CODEC_ID_PCM_S32BE
Definition: AVCodecID.h:226
@ AUDACITY_AV_CODEC_ID_DTS
Definition: AVCodecID.h:298
@ AUDACITY_AV_CODEC_ID_ALAC
Definition: AVCodecID.h:310
@ AUDACITY_AV_CODEC_ID_PCM_S16LE
Definition: AVCodecID.h:217
@ AUDACITY_AV_CODEC_ID_PCM_S32LE
Definition: AVCodecID.h:225
@ AUDACITY_AV_CODEC_ID_FLAC
Definition: AVCodecID.h:306
@ AUDACITY_AV_CODEC_ID_PCM_ALAW
Definition: AVCodecID.h:224
@ AUDACITY_AV_CODEC_ID_WMAV1
Definition: AVCodecID.h:301
@ AUDACITY_AV_CODEC_ID_NONE
Definition: AVCodecID.h:14
@ AUDACITY_AV_CODEC_ID_ADPCM_SWF
Definition: AVCodecID.h:263
@ AUDACITY_AV_CODEC_ID_VOXWARE
Definition: AVCodecID.h:326
@ AUDACITY_AV_CODEC_ID_NELLYMOSER
Definition: AVCodecID.h:328
@ AUDACITY_AV_CODEC_ID_GSM
Definition: AVCodecID.h:312
@ AUDACITY_AV_CODEC_ID_PCM_U8
Definition: AVCodecID.h:222
@ AUDACITY_AV_CODEC_ID_ROQ_DPCM
Definition: AVCodecID.h:290
@ AUDACITY_AV_CODEC_ID_TRUESPEECH
Definition: AVCodecID.h:315
@ AUDACITY_AV_CODEC_ID_MP2
Definition: AVCodecID.h:294
@ AUDACITY_AV_CODEC_ID_WMAPRO
Definition: AVCodecID.h:332
@ AUDACITY_AV_CODEC_ID_WMAV2
Definition: AVCodecID.h:302
@ AUDACITY_AV_CODEC_ID_AMR_NB
Definition: AVCodecID.h:286
@ AUDACITY_AV_CODEC_ID_MP3
Definition: AVCodecID.h:295
@ AUDACITY_AV_CODEC_ID_PCM_S24BE
Definition: AVCodecID.h:230
@ AUDACITY_AV_CODEC_ID_ATRAC3
Definition: AVCodecID.h:325
@ AUDACITY_AV_CODEC_ID_ADPCM_MS
Definition: AVCodecID.h:256
@ AUDACITY_AV_CODEC_ID_AMR_WB
Definition: AVCodecID.h:287
@ AUDACITY_AV_CODEC_ID_AAC
Definition: AVCodecID.h:296
@ AUDACITY_AV_CODEC_ID_ADPCM_IMA_WAV
Definition: AVCodecID.h:251
@ AUDACITY_AV_CODEC_ID_MACE6
Definition: AVCodecID.h:304
@ AUDACITY_AV_CODEC_ID_WMAVOICE
Definition: AVCodecID.h:331
@ AUDACITY_AV_CODEC_ID_ADPCM_CT
Definition: AVCodecID.h:262
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)
END_EVENT_TABLE()
#define str(a)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
Definition: Distortion.cpp:82
static const FileNames::FileTypes & FileTypes()
#define FFMPEG_EXPORT_CTRL_ID_ENTRIES
FFmpegExportCtrlID
static const wxChar * FFmpegExportCtrlIDNames[]
ChoiceSetting AACProfiles
AAC profiles.
#define OpenID
#define AV_CANMETA
std::unordered_map< wxString, FFmpegPreset > FFmpegPresetMap
@ FMT_OPUS
@ FMT_M4A
@ FMT_OTHER
@ FMT_AC3
@ FMT_WMA2
@ FMT_AMRNB
TranslatableString n_kbps(int n)
Definition: ExportMP3.cpp:130
int format
Definition: ExportPCM.cpp:56
bool FindFFmpegLibs(wxWindow *parent)
Definition: FFmpeg.cpp:310
bool LoadFFmpeg(bool showerror)
Definition: FFmpeg.cpp:46
#define AV_VERSION_INT(a, b, c)
Definition: FFmpegTypes.h:77
#define XXO(s)
Definition: Internat.h:44
#define XO(s)
Definition: Internat.h:31
#define _(s)
Definition: Internat.h:75
IteratorRange< Iterator > make_iterator_range(const Iterator &i1, const Iterator &i2)
Definition: MemoryX.h:431
FileConfig * gPrefs
Definition: Prefs.cpp:71
ByColumns_t ByColumns
Definition: Prefs.cpp:474
EffectReverbSettings preset
Definition: Reverb.cpp:46
@ eIsCreatingFromPrefs
Definition: ShuttleGui.h:48
@ eIsSavingToPrefs
Definition: ShuttleGui.h:49
@ eOkButton
Definition: ShuttleGui.h:597
@ eCancelButton
Definition: ShuttleGui.h:598
@ eHelpButton
Definition: ShuttleGui.h:601
#define S(N)
Definition: ToChars.cpp:64
std::vector< TranslatableString > TranslatableStrings
std::vector< Attribute > AttributesList
Definition: XMLTagHandler.h:40
virtual AVCodecIDFwd GetId() const noexcept=0
bool TransferDataToWindow() override
bool TransferDataFromWindow() override
ExportFFmpegAACOptions(wxWindow *parent, int format)
void PopulateOrExchange(ShuttleGui &S)
static const int iAC3SampleRates[]
ExportFFmpegAC3Options(wxWindow *parent, int format)
bool TransferDataToWindow() override
bool TransferDataFromWindow() override
void PopulateOrExchange(ShuttleGui &S)
ExportFFmpegAMRNBOptions(wxWindow *parent, int format)
void PopulateOrExchange(ShuttleGui &S)
bool TransferDataFromWindow() override
void OnOpen(wxCommandEvent &evt)
void PopulateOrExchange(ShuttleGui &S)
bool TransferDataToWindow() override
bool TransferDataFromWindow() override
ExportFFmpegOPUSOptions(wxWindow *parent, int format)
void PopulateOrExchange(ShuttleGui &S)
Custom FFmpeg export dialog.
void OnExportPresets(wxCommandEvent &event)
void OnSavePreset(wxCommandEvent &event)
void OnImportPresets(wxCommandEvent &event)
void FindSelectedCodec(wxString **name, wxString **longname)
Finds the codec currently selected and returns its name and description.
wxArrayStringEx mCodecNames
void OnDeletePreset(wxCommandEvent &event)
wxArrayString mShownFormatLongNames
void FetchCodecList()
Retrieves codec list from libavcodec.
static CompatibilityEntry CompatibilityList[]
std::unique_ptr< FFmpegPresets > mPresets
int FetchCompatibleFormatList(AudacityAVCodecID id, wxString *selfmt)
void OnCodecList(wxCommandEvent &event)
void PopulateOrExchange(ShuttleGui &S)
void FindSelectedFormat(wxString **name, wxString **longname)
Finds the format currently selected and returns its name and description.
void OnLoadPreset(wxCommandEvent &event)
wxArrayStringEx mFormatNames
wxArrayString mShownCodecLongNames
wxArrayString mShownCodecNames
int FetchCompatibleCodecList(const wxChar *fmt, AudacityAVCodecID id)
wxArrayString mCodecLongNames
void OnFormatList(wxCommandEvent &event)
void OnAllFormats(wxCommandEvent &event)
wxStaticText * mFormatName
void OnOK(wxCommandEvent &event)
ExportFFmpegOptions(wxWindow *parent)
void OnAllCodecs(wxCommandEvent &event)
bool SavePreset(bool bCheckForOverwrite)
void FetchFormatList()
Retrieves format list from libavformat.
static ExposedFormat fmts[]
List of export types.
static ApplicableFor apptable[]
wxArrayString mShownFormatNames
void OnGetURL(wxCommandEvent &event)
wxArrayStringEx mPresetNames
void EnableDisableControls(AVCodecWrapper *cdc, wxString *selfmt)
std::shared_ptr< FFmpegFunctions > mFFmpeg
wxArrayString mFormatLongNames
bool TransferDataFromWindow() override
void PopulateOrExchange(ShuttleGui &S)
bool TransferDataToWindow() override
static const int iWMASampleRates[]
ExportFFmpegWMAOptions(wxWindow *parent, int format)
wxArrayString mControlState
void LoadPreset(ExportFFmpegOptions *parent, wxString &name)
FFmpegPresetMap mPresets
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
bool HandleXMLTag(const std::string_view &tag, const AttributesList &attrs) override
void WriteXMLHeader(XMLWriter &xmlFile) const
void GetPresetList(wxArrayString &list)
void WriteXML(XMLWriter &xmlFile) const
void ExportPresets(wxString &filename)
FFmpegPreset * FindPreset(wxString &name)
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
virtual wxString GetPath() const
virtual int ShowModal()
FILES_API const FileType XMLFiles
Definition: FileNames.h:74
std::vector< FileType > FileTypes
Definition: FileNames.h:76
FILES_API const FileType AllFiles
Definition: FileNames.h:71
Abstract base class used in importing a file.
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:239
Specialization of Setting for int.
Definition: Prefs.h:349
Definition: Prefs.h:173
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:628
Holds a msgid for the translation catalog; may also bind format arguments.
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:85
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:26
FILES_API FilePath DataDir()
Audacity user data directory.
const TranslatableStrings PredictionOrderMethodNames
Prediction order method - names.
ChoiceSetting OPUSBitrate
Bit Rates supported by OPUS encoder. Setting bit rate to other values will not result in different fi...
const TranslatableStrings WMABitRateNames
Bit Rates supported by WMA encoder. Setting bit rate to other values will not result in different fil...
std::string ToUTF8(const std::wstring &wstr)
Entry for the Applicability table.
int control
control ID
Describes format-codec compatibility.
const wxChar * fmt
format, recognizable by guess_format()
AudacityAVCodecID codec
codec ID
Describes export type.
static std::shared_ptr< FFmpegFunctions > Load(bool fromUserPathOnly=false)