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