Audacity  3.0.3
FFmpeg.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3 Audacity: A Digital Audio Editor
4 
5 FFmpeg.cpp
6 
7 Audacity(R) is copyright (c) 1999-2009 Audacity Team.
8 License: GPL v2. See License.txt.
9 
10 ******************************************************************//*******************************************************************/
16 
17 // Store function pointers here when including FFmpeg.h
18 #define DEFINE_FFMPEG_POINTERS
19 
20 
21 #include "FFmpeg.h"
22 
23 #include "FileNames.h"
24 #include "SelectFile.h"
25 #include "widgets/HelpSystem.h"
27 
28 #include <wx/checkbox.h>
29 #include <wx/dynlib.h>
30 #include <wx/file.h>
31 #include <wx/log.h>
32 #include <wx/textctrl.h>
33 
34 #if !defined(USE_FFMPEG)
38 {
39  return XO("FFmpeg support not compiled in");
40 }
41 
42 #else
43 
44 static BoolSetting FFmpegEnabled{ L"/FFmpeg/Enabled", false };
45 
46 bool LoadFFmpeg(bool showerror)
47 {
48  auto ffmpeg = FFmpegFunctions::Load();
49 
50  if (!ffmpeg)
51  {
52  FFmpegEnabled.Write(false);
53  gPrefs->Flush();
54  return false;
55  }
56  else
57  {
58  FFmpegEnabled.Write(true);
59  gPrefs->Flush();
60  return true;
61  }
62 }
63 
66 {
67  bool enabled = FFmpegEnabled.Read();
68  // 'false' means that no errors should be shown whatsoever
69  if (!LoadFFmpeg(false))
70  {
71  if (enabled)
72  {
74 "FFmpeg was configured in Preferences and successfully loaded before, \
75 \nbut this time Audacity failed to load it at startup. \
76 \n\nYou may want to go back to Preferences > Libraries and re-configure it."),
77  XO("FFmpeg startup failed"));
78  }
79  }
80 }
81 
83 {
84  auto ffmpeg = FFmpegFunctions::Load();
85 
86  if (ffmpeg)
87  {
88  return Verbatim(
89  wxString::Format(
90  wxT("F(%d.%d.%d),C(%d.%d.%d),U(%d.%d.%d)"),
91  ffmpeg->AVFormatVersion.Major, ffmpeg->AVFormatVersion.Minor, ffmpeg->AVFormatVersion.Micro,
92  ffmpeg->AVCodecVersion.Major, ffmpeg->AVCodecVersion.Minor, ffmpeg->AVCodecVersion.Micro,
93  ffmpeg->AVUtilVersion.Major, ffmpeg->AVUtilVersion.Minor, ffmpeg->AVUtilVersion.Micro
94  ));
95  }
96 
97  return XO("FFmpeg library not found");
98 }
99 
100 /*******************************************************/
101 
103 
104 //----------------------------------------------------------------------------
105 // FindFFmpegDialog
106 //----------------------------------------------------------------------------
107 
108 #define ID_FFMPEG_BROWSE 5000
109 #define ID_FFMPEG_DLOAD 5001
110 
112 class FindFFmpegDialog final : public wxDialogWrapper
113 {
114 public:
115 
116  FindFFmpegDialog(wxWindow *parent, const wxString &path, const wxString &name)
117  : wxDialogWrapper(parent, wxID_ANY, XO("Locate FFmpeg"))
118  , mName(name)
119  , mFullPath(path, name)
120  {
121  SetName();
122 
123  ShuttleGui S(this, eIsCreating);
125  }
126 
128  {
129  S.SetBorder(10);
130  S.StartVerticalLay(true);
131  {
132  S.AddTitle(
133  XO(
134 "Audacity needs the file '%s' to import and export audio via FFmpeg.")
135  .Format( mName ) );
136 
137  S.SetBorder(3);
138  S.StartHorizontalLay(wxALIGN_LEFT, true);
139  {
140  S.AddTitle( XO("Location of '%s':").Format( mName ) );
141  }
142  S.EndHorizontalLay();
143 
144  S.StartMultiColumn(2, wxEXPAND);
145  S.SetStretchyCol(0);
146  {
147  if (mFullPath.GetFullPath().empty())
148  {
149  mPathText = S.AddTextBox(
150  {},
151  XO("To find '%s', click here -->")
152  .Format(mName)
153  .Translation(),
154  0);
155  }
156  else
157  {
158  mPathText = S.AddTextBox({}, mFullPath.GetFullPath(), 0);
159  }
160 
161  S.Id(ID_FFMPEG_BROWSE).AddButton(XXO("Browse..."), wxALIGN_RIGHT);
162  S.AddVariableText(
163  XO("To get a free copy of FFmpeg, click here -->"), true);
164  S.Id(ID_FFMPEG_DLOAD).AddButton(XXO("Download"), wxALIGN_RIGHT);
165  }
166  S.EndMultiColumn();
167 
168  S.AddStandardButtons();
169  }
170  S.EndVerticalLay();
171 
172  Layout();
173  Fit();
174  SetMinSize(GetSize());
175  Center();
176 
177  return;
178  }
179 
180  void OnBrowse(wxCommandEvent & WXUNUSED(event))
181  {
182  static const FileNames::FileTypes types = {
183 # if defined(__WXMSW__)
184  { XO("Only avformat.dll"), { wxT("avformat-*.dll") } },
185 # elif defined(__WXMAC__)
186  { XO("Only ffmpeg.*.dylib"), { wxT("ffmpeg.*.dylib") } },
187 # else
188  { XO("Only libavformat.so"), { wxT("libavformat.so.*") } },
189 # endif
192  };
193 
194  UpdatePath();
195 
196  /* i18n-hint: It's asking for the location of a file, for
197  example, "Where is lame_enc.dll?" - you could translate
198  "Where would I find the file '%s'?" instead if you want. */
199  auto question = XO("Where is '%s'?").Format( mName );
200 
201  wxString path = SelectFile(
202  FileNames::Operation::_None,
203  question,
204  mFullPath.GetPath(),
205  mFullPath.GetFullName(),
206  wxT(""),
207  types,
208  wxFD_OPEN | wxRESIZE_BORDER,
209  this);
210 
211  if (!path.empty())
212  {
213  mFullPath = path;
214  mPathText->SetValue(path);
215  }
216  }
217 
218  void OnDownload(wxCommandEvent & WXUNUSED(event))
219  {
220  HelpSystem::ShowHelp(this, L"FAQ:Installing_the_FFmpeg_Import_Export_Library");
221  }
222 
223  void UpdatePath()
224  {
225  mFullPath = mPathText->GetValue();
226  }
227 
228  wxString GetLibPath()
229  {
230  UpdatePath();
231  return mFullPath.GetFullPath();
232  }
233 
234 private:
235  wxString mName;
236  wxFileName mFullPath;
237 
238  wxTextCtrl *mPathText;
239 
240  DECLARE_EVENT_TABLE()
241 };
242 
243 BEGIN_EVENT_TABLE(FindFFmpegDialog, wxDialogWrapper)
247 
248 
249 //----------------------------------------------------------------------------
250 // FFmpegNotFoundDialog
251 //----------------------------------------------------------------------------
252 
254  : wxDialogWrapper(parent, wxID_ANY, XO("FFmpeg not found"))
255 {
256  SetName();
257  ShuttleGui S(this, eIsCreating);
258  PopulateOrExchange(S);
259 }
260 
262 {
263  wxString text;
264 
265  S.SetBorder(10);
266  S.StartVerticalLay(true);
267  {
268  S.AddFixedText(XO(
269 "Audacity attempted to use FFmpeg to import an audio file,\n\
270 but the libraries were not found.\n\n\
271 To use FFmpeg import, go to Edit > Preferences > Libraries\n\
272 to download or locate the FFmpeg libraries."
273  ));
274 
275  mDontShow = S
276  .AddCheckBox(XXO("Do not show this warning again"),
278 
280  }
281  S.EndVerticalLay();
282 
283  Layout();
284  Fit();
285  SetMinSize(GetSize());
286  Center();
287 
288  return;
289 }
290 
291 void FFmpegNotFoundDialog::OnOk(wxCommandEvent & WXUNUSED(event))
292 {
293  if (mDontShow->GetValue())
294  {
296  gPrefs->Flush();
297  }
298  this->EndModal(0);
299 }
300 
301 BEGIN_EVENT_TABLE(FFmpegNotFoundDialog, wxDialogWrapper)
304 
305 
306 bool FindFFmpegLibs(wxWindow* parent)
307 {
308  wxString path;
309 
310 #if defined(__WXMSW__)
311  const wxString name = wxT("avformat-*.dll");
312 #elif defined(__WXMAC__)
313  const wxString name = wxT("ffmpeg.*.64bit.dylib");
314 #else
315  const wxString name = wxT("libavformat.so.*");
316 #endif
317 
318  wxLogMessage(wxT("Looking for FFmpeg libraries..."));
319 
320  auto searchPaths = FFmpegFunctions::GetSearchPaths();
321 
322  if (!searchPaths.empty())
323  path = searchPaths.front();
324 
325  FindFFmpegDialog fd(parent, path, name);
326 
327  if (fd.ShowModal() == wxID_CANCEL) {
328  wxLogMessage(wxT("User canceled the dialog. Failed to find FFmpeg libraries."));
329  return false;
330  }
331 
332  path = fd.GetLibPath();
333 
334  wxLogMessage(wxT("User-specified path = '%s'"), path);
335 
336  if (!::wxFileExists(path)) {
337  wxLogError(wxT("User-specified file does not exist. Failed to find FFmpeg libraries."));
338  return false;
339  }
340 
341  wxLogMessage(wxT("User-specified FFmpeg file exists. Success."));
342 
343  AVFormatPath.Write(path);
344  gPrefs->Flush();
345 
346  return true;
347 }
348 
349 BoolSetting FFmpegNotFoundDontShow{ L"/FFmpeg/NotFoundDontShow", false };
350 
351 #endif //USE_FFMPEG
FindFFmpegDialog::FindFFmpegDialog
FindFFmpegDialog(wxWindow *parent, const wxString &path, const wxString &name)
Definition: FFmpeg.cpp:116
EVT_BUTTON
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
TranslatableString
Holds a msgid for the translation catalog; may also bind format arguments.
Definition: TranslatableString.h:32
FindFFmpegDialog::GetLibPath
wxString GetLibPath()
Definition: FFmpeg.cpp:228
FindFFmpegDialog::UpdatePath
void UpdatePath()
Definition: FFmpeg.cpp:223
eIsCreating
@ eIsCreating
Definition: ShuttleGui.h:38
ShuttleGuiBase::StartVerticalLay
void StartVerticalLay(int iProp=1)
Definition: ShuttleGui.cpp:1184
ShuttleGuiBase::AddCheckBox
wxCheckBox * AddCheckBox(const TranslatableString &Prompt, bool Selected)
Definition: ShuttleGui.cpp:309
AudacityMessageBox
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
Definition: AudacityMessageBox.cpp:17
HelpSystem.h
ShuttleGuiBase::AddTitle
void AddTitle(const TranslatableString &Prompt, int wrapWidth=0)
Centred text string.
Definition: ShuttleGui.cpp:281
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:70
FFmpeg.h
FindFFmpegDialog::OnDownload
void OnDownload(wxCommandEvent &WXUNUSED(event))
Definition: FFmpeg.cpp:218
SelectFile
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
Definition: SelectFile.cpp:17
Setting::Write
bool Write(const T &value)
Write value to config and return true if successful.
Definition: Prefs.h:172
Format
Abstract base class used in importing a file.
BoolSetting
This specialization of Setting for bool adds a Toggle method to negate the saved value.
Definition: Prefs.h:204
XO
#define XO(s)
Definition: Internat.h:31
ShuttleGuiBase::EndMultiColumn
void EndMultiColumn()
Definition: ShuttleGui.cpp:1238
FileNames::AllFiles
FILES_API const FileType AllFiles
Definition: FileNames.h:71
HelpSystem::ShowHelp
static void ShowHelp(wxWindow *parent, const FilePath &localFileName, const URLString &remoteURL, bool bModal=false, bool alwaysDefaultBrowser=false)
Definition: HelpSystem.cpp:237
ShuttleGui::Id
ShuttleGui & Id(int id)
Definition: ShuttleGui.cpp:2274
Setting::Read
bool Read(T *pVar) const
overload of Read returning a boolean that is true if the value was previously defined *‍/
Definition: Prefs.h:128
LoadFFmpeg
bool LoadFFmpeg(bool showerror)
Definition: FFmpeg.cpp:46
FindFFmpegDialog::mFullPath
wxFileName mFullPath
Definition: FFmpeg.cpp:236
XXO
#define XXO(s)
Definition: Internat.h:44
ShuttleGuiBase::EndHorizontalLay
void EndHorizontalLay()
Definition: ShuttleGui.cpp:1177
ShuttleGuiBase::StartHorizontalLay
void StartHorizontalLay(int PositionFlags=wxALIGN_CENTRE, int iProp=1)
Definition: ShuttleGui.cpp:1167
ShuttleGuiBase::AddTextBox
wxTextCtrl * AddTextBox(const TranslatableString &Caption, const wxString &Value, const int nChars)
Definition: ShuttleGui.cpp:638
ShuttleGuiBase::StartMultiColumn
void StartMultiColumn(int nCols, int PositionFlags=wxALIGN_LEFT)
Definition: ShuttleGui.cpp:1229
ShuttleGuiBase::EndVerticalLay
void EndVerticalLay()
Definition: ShuttleGui.cpp:1203
FindFFmpegDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: FFmpeg.cpp:127
GetFFmpegVersion
TranslatableString GetFFmpegVersion()
Definition: FFmpeg.cpp:82
ShuttleGuiBase::AddFixedText
void AddFixedText(const TranslatableString &Str, bool bCenter=false, int wrapWidth=0)
Definition: ShuttleGui.cpp:440
FFmpegEnabled
static BoolSetting FFmpegEnabled
Definition: FFmpeg.cpp:44
FFmpegNotFoundDontShow
BoolSetting FFmpegNotFoundDontShow
Definition: FFmpeg.cpp:349
FFmpegNotFoundDialog
Definition: FFmpeg.h:57
name
const TranslatableString name
Definition: Distortion.cpp:98
SelectFile.h
FindFFmpegDialog::mPathText
wxTextCtrl * mPathText
Definition: FFmpeg.cpp:238
FindFFmpegLibs
bool FindFFmpegLibs(wxWindow *parent)
Definition: FFmpeg.cpp:306
FindFFmpegDialog::mName
wxString mName
Definition: FFmpeg.cpp:235
ShuttleGuiBase::AddButton
wxButton * AddButton(const TranslatableString &Text, int PositionFlags=wxALIGN_CENTRE, bool setDefault=false)
Definition: ShuttleGui.cpp:360
wxDialogWrapper
Definition: wxPanelWrapper.h:81
FileConfig::Flush
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
Definition: FileConfig.cpp:143
eOkButton
@ eOkButton
Definition: ShuttleGui.h:600
FFmpegNotFoundDialog::mDontShow
wxCheckBox * mDontShow
Definition: FFmpeg.h:68
FindFFmpegDialog::OnBrowse
void OnBrowse(wxCommandEvent &WXUNUSED(event))
Definition: FFmpeg.cpp:180
ID_FFMPEG_DLOAD
#define ID_FFMPEG_DLOAD
Definition: FFmpeg.cpp:109
FileNames::DynamicLibraries
FILES_API const FileType DynamicLibraries
Definition: FileNames.h:73
AVFormatPath
StringSetting AVFormatPath
Definition: FFmpegFunctions.cpp:296
FFmpegFunctions::Load
static std::shared_ptr< FFmpegFunctions > Load()
Definition: FFmpegFunctions.cpp:262
FileNames.h
FFmpegFunctions::GetSearchPaths
static std::vector< wxString > GetSearchPaths()
Definition: FFmpegFunctions.cpp:298
AudacityMessageBox.h
FFmpegNotFoundDialog::PopulateOrExchange
void PopulateOrExchange(ShuttleGui &S)
Definition: FFmpeg.cpp:261
Verbatim
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Definition: TranslatableString.h:321
ID_FFMPEG_BROWSE
#define ID_FFMPEG_BROWSE
Definition: FFmpeg.cpp:108
ShuttleGui::AddStandardButtons
void AddStandardButtons(long buttons=eOkButton|eCancelButton, wxWindow *extra=NULL)
Definition: ShuttleGui.cpp:2444
FileNames::FileTypes
std::vector< FileType > FileTypes
Definition: FileNames.h:76
FFmpegStartup
void FFmpegStartup()
Definition: FFmpeg.cpp:65
ShuttleGuiBase::SetBorder
void SetBorder(int Border)
Definition: ShuttleGui.h:489
wxDialogWrapper::SetName
void SetName()
Definition: wxPanelWrapper.cpp:81
ShuttleGuiBase::AddVariableText
wxStaticText * AddVariableText(const TranslatableString &Str, bool bCenter=false, int PositionFlags=0, int wrapWidth=0)
Definition: ShuttleGui.cpp:463
ShuttleGuiBase::SetStretchyCol
void SetStretchyCol(int i)
Used to modify an already placed FlexGridSizer to make a column stretchy.
Definition: ShuttleGui.cpp:202
END_EVENT_TABLE
END_EVENT_TABLE()
FindFFmpegDialog
Allows user to locate libav* libraries.
Definition: FFmpeg.cpp:113
FFmpegNotFoundDialog::OnOk
void OnOk(wxCommandEvent &WXUNUSED(event))
Definition: FFmpeg.cpp:291
ShuttleGui
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Definition: ShuttleGui.h:631