Audacity  2.2.2
Import.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  Import.cpp
6 
7  Dominic Mazzoni
8 
9 *******************************************************************//***************************************************************//***************************************************************//******************************************************************/
35 
36 
37 
38 #include "../Audacity.h"
39 #include "Import.h"
40 
41 #include <algorithm>
42 #include "ImportPlugin.h"
43 
44 #include <wx/textctrl.h>
45 #include <wx/string.h>
46 #include <wx/intl.h>
47 #include <wx/log.h>
48 #include <wx/sizer.h> //for wxBoxSizer
49 #include <wx/listimpl.cpp>
50 #include "../ShuttleGui.h"
51 #include "../Project.h"
52 
53 #include "ImportPCM.h"
54 #include "ImportMP3.h"
55 #include "ImportOGG.h"
56 #include "ImportQT.h"
57 #include "ImportRaw.h"
58 #include "ImportLOF.h"
59 #include "ImportFLAC.h"
60 #include "ImportFFmpeg.h"
61 #include "ImportGStreamer.h"
62 #include "../Prefs.h"
63 
64 // ============================================================================
65 //
66 // Return reference to singleton
67 //
68 // (Thread-safe...no active threading during construction or after destruction)
69 // ============================================================================
72 {
73  return mInstance;
74 }
75 
77 {
78 }
79 
81 {
82 }
83 
85 {
89 
90  // build the list of import plugin and/or unusableImporters.
91  // order is significant. If none match, they will all be tried
92  // in the order defined here.
98 
99  #if defined(USE_FFMPEG)
101  #endif
102  #ifdef USE_QUICKTIME
104  #endif
105  #if defined(USE_GSTREAMER)
107  #endif
108 
109  ReadImportItems();
110 
111  return true;
112 }
113 
115 {
119 
120  return true;
121 }
122 
124 {
125  for(const auto &importPlugin : mImportPluginList)
126  {
127 #ifdef __AUDACITY_OLD_STD__
128  formatList->push_back(Format{importPlugin->GetPluginFormatDescription(),
129  importPlugin->GetSupportedExtensions()});
130 #else
131  formatList->emplace_back(importPlugin->GetPluginFormatDescription(),
132  importPlugin->GetSupportedExtensions());
133 #endif
134  }
135 }
136 
137 void Importer::StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod)
138 {
139  wxStringTokenizer toker;
140 
141  for (toker.SetString(str, delims, mod);
142  toker.HasMoreTokens(); list.Add (toker.GetNextToken()));
143 }
144 
146 {
147  int item_counter = 0;
148  wxStringTokenizer toker;
149  wxString item_name;
150  wxString item_value;
151 
153  /* Rule string format is:
154  * extension1:extension2:extension3\mime_type1:mime_type2:mime_type3|filter1:filter2:filter3\unusedfilter1:unusedfilter2
155  * backslashes are escaped and unescaped internally
156  */
157  for (item_counter = 0; true; item_counter++)
158  {
159  wxString condition, filters, used_filters, unused_filters = wxEmptyString, extensions, mime_types = wxEmptyString;
160  item_name.Printf (wxT("/ExtImportItems/Item%d"), item_counter);
161  /* Break at first non-existent item */
162  if (!gPrefs->Read(item_name, &item_value))
163  break;
164 
165  toker.SetString(item_value, wxT("|"), wxTOKEN_RET_EMPTY_ALL);
166  /* Break at first broken item */
167  if (toker.CountTokens() != 2)
168  break;
169 
170  auto new_item = make_movable<ExtImportItem>();
171 
172  /* First token is the filtering condition, second - the filter list */
173  condition = toker.GetNextToken();
174  filters = toker.GetNextToken();
175 
176  /* Condition token consists of extension list and mime type list
177  * mime type list can be omitted entirely (complete with '\' separator)*/
178  toker.SetString(condition, wxT("\\"), wxTOKEN_RET_EMPTY_ALL);
179  extensions = toker.GetNextToken();
180  if (toker.HasMoreTokens())
181  mime_types = toker.GetNextToken();
182 
183  wxString delims(wxT(":"));
184  StringToList (extensions, delims, new_item->extensions);
185 
186  if (mime_types != wxEmptyString)
187  StringToList (mime_types, delims, new_item->mime_types);
188 
189  /* Filter token consists of used and unused filter lists */
190  toker.SetString(filters, wxT("\\"), wxTOKEN_RET_EMPTY_ALL);
191  used_filters = toker.GetNextToken();
192  if (toker.HasMoreTokens())
193  unused_filters = toker.GetNextToken();
194 
195  StringToList (used_filters, delims, new_item->filters);
196 
197  if (unused_filters != wxEmptyString)
198  {
199  /* Filters are stored in one list, but the position at which
200  * unused filters start is remembered
201  */
202  new_item->divider = new_item->filters.Count();
203  StringToList (unused_filters, delims, new_item->filters);
204  }
205  else
206  new_item->divider = -1;
207 
208  /* Find corresponding filter object for each filter ID */
209  for (size_t i = 0; i < new_item->filters.Count(); i++)
210  {
211  bool found = false;
212  for (const auto &importPlugin : mImportPluginList)
213  {
214  if (importPlugin->GetPluginStringID().Cmp(new_item->filters[i]) == 0)
215  {
216  new_item->filter_objects.push_back(importPlugin.get());
217  found = true;
218  break;
219  }
220  }
221  /* IDs that do not have corresponding filters, will be shown as-is */
222  if (!found)
223  new_item->filter_objects.push_back(nullptr);
224  }
225  /* Find all filter objects that are not present in the filter list */
226  for (const auto &importPlugin : mImportPluginList)
227  {
228  bool found = false;
229  for (size_t i = 0; i < new_item->filter_objects.size(); i++)
230  {
231  if (importPlugin.get() == new_item->filter_objects[i])
232  {
233  found = true;
234  break;
235  }
236  }
237  /* Add these filters at the bottom of used filter list */
238  if (!found)
239  {
240  int index = new_item->divider;
241  if (new_item->divider < 0)
242  index = new_item->filters.Count();
243  new_item->filters.Insert(importPlugin->GetPluginStringID(),index);
244  new_item->filter_objects.insert(
245  new_item->filter_objects.begin() + index, importPlugin.get());
246  if (new_item->divider >= 0)
247  new_item->divider++;
248  }
249  }
250  this->mExtImportItems.push_back( std::move(new_item) );
251  }
252 }
253 
255 {
256  size_t i;
257  wxString val, name;
258  for (i = 0; i < this->mExtImportItems.size(); i++)
259  {
260  ExtImportItem *item = mExtImportItems[i].get();
261  val.Clear();
262 
263  for (size_t j = 0; j < item->extensions.Count(); j++)
264  {
265  val.Append (item->extensions[j]);
266  if (j < item->extensions.Count() - 1)
267  val.Append (wxT(":"));
268  }
269  val.Append (wxT("\\"));
270  for (size_t j = 0; j < item->mime_types.Count(); j++)
271  {
272  val.Append (item->mime_types[j]);
273  if (j < item->mime_types.Count() - 1)
274  val.Append (wxT(":"));
275  }
276  val.Append (wxT("|"));
277  for (size_t j = 0; j < item->filters.Count() && ((int) j < item->divider || item->divider < 0); j++)
278  {
279  val.Append (item->filters[j]);
280  if (j < item->filters.Count() - 1 && ((int) j < item->divider - 1 || item->divider < 0))
281  val.Append (wxT(":"));
282  }
283  if (item->divider >= 0)
284  {
285  val.Append (wxT("\\"));
286  for (size_t j = item->divider; j < item->filters.Count(); j++)
287  {
288  val.Append (item->filters[j]);
289  if (j < item->filters.Count() - 1)
290  val.Append (wxT(":"));
291  }
292  }
293  name.Printf (wxT("/ExtImportItems/Item%d"), (int)i);
294  gPrefs->Write (name, val);
295  gPrefs->Flush();
296  }
297  /* If we used to have more items than we have now, DELETE the excess items.
298  We just keep deleting items and incrementing until we find there aren't any
299  more to DELETE.*/
300  i = this->mExtImportItems.size();
301  do {
302  name.Printf (wxT("/ExtImportItems/Item%d"), (int)i);
303  // No item to DELETE? Then it's time to finish.
304  if (!gPrefs->Read(name, &val))
305  break;
306  // Failure to DELETE probably means a read-only config file.
307  // no point continuing.
308  // TODO: Possibly report (once).
309  if( !gPrefs->DeleteEntry (name, false))
310  break;
311  i++;
312  } while( true );
313 }
314 
316 {
317  auto new_item = make_movable<ExtImportItem>();
318  new_item->extensions.Add(wxT("*"));
319  new_item->mime_types.Add(wxT("*"));
320 
321  for (const auto &importPlugin : mImportPluginList)
322  {
323  new_item->filters.Add (importPlugin->GetPluginStringID());
324  new_item->filter_objects.push_back(importPlugin.get());
325  }
326  new_item->divider = -1;
327  return new_item;
328 }
329 
330 bool Importer::IsMidi(const wxString &fName)
331 {
332  const auto extension = fName.AfterLast(wxT('.'));
333  return
334  extension.IsSameAs(wxT("gro"), false) ||
335  extension.IsSameAs(wxT("midi"), false) ||
336  extension.IsSameAs(wxT("mid"), false);
337 }
338 
339 // returns number of tracks imported
340 bool Importer::Import(const wxString &fName,
341  TrackFactory *trackFactory,
342  TrackHolders &tracks,
343  Tags *tags,
344  wxString &errorMessage)
345 {
347  auto cleanup = valueRestorer( pProj->mbBusyImporting, true );
348 
349  wxString extension = fName.AfterLast(wxT('.'));
350 
351  // Always refuse to import MIDI, even though the FFmpeg plugin pretends to know how (but makes very bad renderings)
352 #ifdef USE_MIDI
353  // MIDI files must be imported, not opened
354  if (IsMidi(fName)) {
355  errorMessage.Printf(_("\"%s\" \nis a MIDI file, not an audio file. \nAudacity cannot open this type of file for playing, but you can\nedit it by clicking File > Import > MIDI."), fName);
356  return false;
357  }
358 #endif
359 
360  using ImportPluginPtrs = std::vector< ImportPlugin* >;
361 
362  // This list is used to call plugins in correct order
363  ImportPluginPtrs importPlugins;
364 
365  // This list is used to remember plugins that should have been compatible with the file.
366  ImportPluginPtrs compatiblePlugins;
367 
368  // If user explicitly selected a filter,
369  // then we should try importing via corresponding plugin first
370  wxString type = gPrefs->Read(wxT("/LastOpenType"),wxT(""));
371 
372  // Not implemented (yet?)
373  wxString mime_type = wxT("*");
374 
375  // First, add user-selected filter
376  bool usersSelectionOverrides;
377  gPrefs->Read(wxT("/ExtendedImport/OverrideExtendedImportByOpenFileDialogChoice"), &usersSelectionOverrides, false);
378 
379  wxLogDebug(wxT("LastOpenType is %s"),type);
380  wxLogDebug(wxT("OverrideExtendedImportByOpenFileDialogChoice is %i"),usersSelectionOverrides);
381 
382  if (usersSelectionOverrides)
383  {
384  for (const auto &plugin : mImportPluginList)
385  {
386  if (plugin->GetPluginFormatDescription().CompareTo(type) == 0)
387  {
388  // This plugin corresponds to user-selected filter, try it first.
389  wxLogDebug(wxT("Inserting %s"),plugin->GetPluginStringID());
390  importPlugins.insert(importPlugins.begin(), plugin.get());
391  }
392  }
393  }
394 
395  wxLogMessage(wxT("File name is %s"), fName);
396  wxLogMessage(wxT("Mime type is %s"), mime_type.Lower());
397 
398  for (const auto &uItem : mExtImportItems)
399  {
400  ExtImportItem *item = uItem.get();
401  bool matches_ext = false, matches_mime = false;
402  wxLogDebug(wxT("Testing extensions"));
403  for (size_t j = 0; j < item->extensions.Count(); j++)
404  {
405  wxLogDebug(wxT("%s"), item->extensions[j].Lower());
406  if (wxMatchWild (item->extensions[j].Lower(),fName.Lower(), false))
407  {
408  wxLogDebug(wxT("Match!"));
409  matches_ext = true;
410  break;
411  }
412  }
413  if (item->extensions.Count() == 0)
414  {
415  wxLogDebug(wxT("Match! (empty list)"));
416  matches_ext = true;
417  }
418  if (matches_ext)
419  wxLogDebug(wxT("Testing mime types"));
420  else
421  wxLogDebug(wxT("Not testing mime types"));
422  for (size_t j = 0; matches_ext && j < item->mime_types.Count(); j++)
423  {
424  if (wxMatchWild (item->mime_types[j].Lower(),mime_type.Lower(), false))
425  {
426  wxLogDebug(wxT("Match!"));
427  matches_mime = true;
428  break;
429  }
430  }
431  if (item->mime_types.Count() == 0)
432  {
433  wxLogDebug(wxT("Match! (empty list)"));
434  matches_mime = true;
435  }
436  if (matches_ext && matches_mime)
437  {
438  wxLogDebug(wxT("Complete match!"));
439  for (size_t j = 0; j < item->filter_objects.size() && (item->divider < 0 || (int) j < item->divider); j++)
440  {
441  // the filter_object can be NULL if a suitable importer was not found
442  // this happens when we recompile with --without-ffmpeg and there
443  // is still ffmpeg in prefs from previous --with-ffmpeg builds
444  if (!(item->filter_objects[j]))
445  continue;
446  wxLogDebug(wxT("Inserting %s"),item->filter_objects[j]->GetPluginStringID());
447  importPlugins.push_back(item->filter_objects[j]);
448  }
449  }
450  }
451 
452  // Add all plugins that support the extension
453 
454  // Here we rely on the fact that the first plugin in mImportPluginList is libsndfile.
455  // We want to save this for later insertion ahead of libmad, if libmad supports the extension.
456  // The order of plugins in mImportPluginList is determined by the Importer constructor alone and
457  // is not changed by user selection overrides or any other mechanism, but we include an assert
458  // in case subsequent code revisions to the constructor should break this assumption that
459  // libsndfile is first.
460  ImportPlugin *libsndfilePlugin = mImportPluginList.begin()->get();
461  wxASSERT(libsndfilePlugin->GetPluginStringID().IsSameAs(wxT("libsndfile")));
462 
463  for (const auto &plugin : mImportPluginList)
464  {
465  // Make sure its not already in the list
466  if (importPlugins.end() ==
467  std::find(importPlugins.begin(), importPlugins.end(), plugin.get()))
468  {
469  if (plugin->SupportsExtension(extension))
470  {
471  // If libmad is accidentally fed a wav file which has been incorrectly
472  // given an .mp3 extension then it can choke on the contents and crash.
473  // To avoid this, put libsndfile ahead of libmad in the lists created for
474  // mp3 files, or for any of the extensions supported by libmad.
475  // A genuine .mp3 file will first fail an attempted import with libsndfile
476  // but then get processed as desired by libmad.
477  // But a wav file which bears an incorrect .mp3 extension will be successfully
478  // processed by libsndfile and thus avoid being submitted to libmad.
479  if (plugin->GetPluginStringID().IsSameAs(wxT("libmad")))
480  {
481  // Make sure libsndfile is not already in the list
482  if (importPlugins.end() ==
483  std::find(importPlugins.begin(), importPlugins.end(), libsndfilePlugin))
484  {
485  wxLogDebug(wxT("Appending %s"),libsndfilePlugin->GetPluginStringID());
486  importPlugins.push_back(libsndfilePlugin);
487  }
488  }
489  wxLogDebug(wxT("Appending %s"),plugin->GetPluginStringID());
490  importPlugins.push_back(plugin.get());
491  }
492  }
493  }
494 
495  // Add remaining plugins, except for libmad, which should not be used as a fallback for anything.
496  // Otherwise, if FFmpeg (libav) has not been installed, libmad will still be there near the
497  // end of the preference list importPlugins, where it will claim success importing FFmpeg file
498  // formats unsuitable for it, and produce distorted results.
499  for (const auto &plugin : mImportPluginList)
500  {
501  if (!(plugin->GetPluginStringID().IsSameAs(wxT("libmad"))))
502  {
503  // Make sure its not already in the list
504  if (importPlugins.end() ==
505  std::find(importPlugins.begin(), importPlugins.end(), plugin.get()))
506  {
507  wxLogDebug(wxT("Appending %s"),plugin->GetPluginStringID());
508  importPlugins.push_back(plugin.get());
509  }
510  }
511  }
512 
513  // Try the import plugins, in the permuted sequences just determined
514  for (const auto plugin : importPlugins)
515  {
516  // Try to open the file with this plugin (probe it)
517  wxLogMessage(wxT("Opening with %s"),plugin->GetPluginStringID());
518  auto inFile = plugin->Open(fName);
519  if ( (inFile != NULL) && (inFile->GetStreamCount() > 0) )
520  {
521  wxLogMessage(wxT("Open(%s) succeeded"), fName);
522  // File has more than one stream - display stream selector
523  if (inFile->GetStreamCount() > 1)
524  {
525  ImportStreamDialog ImportDlg(inFile.get(), NULL, -1, _("Select stream(s) to import"));
526 
527  if (ImportDlg.ShowModal() == wxID_CANCEL)
528  {
529  return false;
530  }
531  }
532  // One stream - import it by default
533  else
534  inFile->SetStreamUsage(0,TRUE);
535 
536  auto res = inFile->Import(trackFactory, tracks, tags);
537 
539  {
540  // LOF ("list-of-files") has different semantics
541  if (extension.IsSameAs(wxT("lof"), false))
542  {
543  return true;
544  }
545 
546  if (tracks.size() > 0)
547  {
548  // success!
549  return true;
550  }
551  }
552 
554  {
555  return false;
556  }
557 
558  // We could exit here since we had a match on the file extension,
559  // but there may be another plug-in that can import the file and
560  // that may recognize the extension, so we allow the loop to
561  // continue.
562  }
563  }
564  wxLogError(wxT("Importer::Import: Opening failed."));
565 
566  // None of our plugins can handle this file. It might be that
567  // Audacity supports this format, but support was not compiled in.
568  // If so, notify the user of this fact
569  for (const auto &unusableImportPlugin : mUnusableImportPluginList)
570  {
571  if( unusableImportPlugin->SupportsExtension(extension) )
572  {
573  errorMessage.Printf(_("This version of Audacity was not compiled with %s support."),
574  unusableImportPlugin->
575  GetPluginFormatDescription());
576  return false;
577  }
578  }
579 
580  /* warnings for unsupported data types */
581 
582  if (compatiblePlugins.empty())
583  {
584  // if someone has sent us a .cda file, send them away
585  if (extension.IsSameAs(wxT("cda"), false)) {
586  /* i18n-hint: %s will be the filename */
587  errorMessage.Printf(_("\"%s\" is an audio CD track. \nAudacity cannot open audio CDs directly. \nExtract (rip) the CD tracks to an audio format that \nAudacity can import, such as WAV or AIFF."), fName);
588  return false;
589  }
590 
591  // playlist type files
592  if ((extension.IsSameAs(wxT("m3u"), false))||(extension.IsSameAs(wxT("ram"), false))||(extension.IsSameAs(wxT("pls"), false))) {
593  errorMessage.Printf(_("\"%s\" is a playlist file. \nAudacity cannot open this file because it only contains links to other files. \nYou may be able to open it in a text editor and download the actual audio files."), fName);
594  return false;
595  }
596  //WMA files of various forms
597  if ((extension.IsSameAs(wxT("wma"), false))||(extension.IsSameAs(wxT("asf"), false))) {
598  errorMessage.Printf(_("\"%s\" is a Windows Media Audio file. \nAudacity cannot open this type of file due to patent restrictions. \nYou need to convert it to a supported audio format, such as WAV or AIFF."), fName);
599  return false;
600  }
601  //AAC files of various forms (probably not encrypted)
602  if ((extension.IsSameAs(wxT("aac"), false))||(extension.IsSameAs(wxT("m4a"), false))||(extension.IsSameAs(wxT("m4r"), false))||(extension.IsSameAs(wxT("mp4"), false))) {
603  errorMessage.Printf(_("\"%s\" is an Advanced Audio Coding file. \nAudacity cannot open this type of file. \nYou need to convert it to a supported audio format, such as WAV or AIFF."), fName);
604  return false;
605  }
606  // encrypted itunes files
607  if ((extension.IsSameAs(wxT("m4p"), false))) {
608  errorMessage.Printf(_("\"%s\" is an encrypted audio file. \nThese typically are from an online music store. \nAudacity cannot open this type of file due to the encryption. \nTry recording the file into Audacity, or burn it to audio CD then \nextract the CD track to a supported audio format such as WAV or AIFF."), fName);
609  return false;
610  }
611  // Real Inc. files of various sorts
612  if ((extension.IsSameAs(wxT("ra"), false))||(extension.IsSameAs(wxT("rm"), false))||(extension.IsSameAs(wxT("rpm"), false))) {
613  errorMessage.Printf(_("\"%s\" is a RealPlayer media file. \nAudacity cannot open this proprietary format. \nYou need to convert it to a supported audio format, such as WAV or AIFF."), fName);
614  return false;
615  }
616 
617  // Other notes-based formats
618  if ((extension.IsSameAs(wxT("kar"), false))||(extension.IsSameAs(wxT("mod"), false))||(extension.IsSameAs(wxT("rmi"), false))) {
619  errorMessage.Printf(_("\"%s\" is a notes-based file, not an audio file. \nAudacity cannot open this type of file. \nTry converting it to an audio file such as WAV or AIFF and \nthen import it, or record it into Audacity."), fName);
620  return false;
621  }
622 
623  // MusePack files
624  if ((extension.IsSameAs(wxT("mp+"), false))||(extension.IsSameAs(wxT("mpc"), false))||(extension.IsSameAs(wxT("mpp"), false))) {
625  errorMessage.Printf(_("\"%s\" is a Musepack audio file. \nAudacity cannot open this type of file. \nIf you think it might be an mp3 file, rename it to end with \".mp3\" \nand try importing it again. Otherwise you need to convert it to a supported audio \nformat, such as WAV or AIFF."), fName);
626  return false;
627  }
628 
629  // WavPack files
630  if ((extension.IsSameAs(wxT("wv"), false))||(extension.IsSameAs(wxT("wvc"), false))) {
631  errorMessage.Printf(_("\"%s\" is a Wavpack audio file. \nAudacity cannot open this type of file. \nYou need to convert it to a supported audio format, such as WAV or AIFF."), fName);
632  return false;
633  }
634 
635  // AC3 files
636  if ((extension.IsSameAs(wxT("ac3"), false))) {
637  errorMessage.Printf(_("\"%s\" is a Dolby Digital audio file. \nAudacity cannot currently open this type of file. \nYou need to convert it to a supported audio format, such as WAV or AIFF."), fName);
638  return false;
639  }
640 
641  // Speex files
642  if ((extension.IsSameAs(wxT("spx"), false))) {
643  errorMessage.Printf(_("\"%s\" is an Ogg Speex audio file. \nAudacity cannot currently open this type of file. \nYou need to convert it to a supported audio format, such as WAV or AIFF."), fName);
644  return false;
645  }
646 
647  // Video files of various forms
648  if ((extension.IsSameAs(wxT("mpg"), false))||(extension.IsSameAs(wxT("mpeg"), false))||(extension.IsSameAs(wxT("avi"), false))||(extension.IsSameAs(wxT("wmv"), false))||(extension.IsSameAs(wxT("rv"), false))) {
649  errorMessage.Printf(_("\"%s\" is a video file. \nAudacity cannot currently open this type of file. \nYou need to extract the audio to a supported format, such as WAV or AIFF."), fName);
650  return false;
651  }
652 
653  // Audacity project
654  if (extension.IsSameAs(wxT("aup"), false)) {
655  errorMessage.Printf(_("\"%s\" is an Audacity Project file. \nUse the 'File > Open' command to open Audacity Projects."), fName);
656  return false;
657  }
658 
659  // we were not able to recognize the file type
660  errorMessage.Printf(_("Audacity did not recognize the type of the file '%s'.\nTry installing FFmpeg. For uncompressed files, also try File > Import > Raw Data."),fName);
661  }
662  else
663  {
664  // We DO have a plugin for this file, but import failed.
665  wxString pluglist;
666 
667  for (const auto &plugin : compatiblePlugins)
668  {
669  if (pluglist.empty())
670  pluglist = plugin->GetPluginFormatDescription();
671  else
672  pluglist = wxString::Format( _("%s, %s"),
673  pluglist, plugin->GetPluginFormatDescription() );
674  }
675 
676  errorMessage.Printf(_("Audacity recognized the type of the file '%s'.\nImporters supposedly supporting such files are:\n%s,\nbut none of them understood this file format."),fName, pluglist);
677  }
678 
679  return false;
680 }
681 
682 //-------------------------------------------------------------------------
683 // ImportStreamDialog
684 //-------------------------------------------------------------------------
685 
686 BEGIN_EVENT_TABLE( ImportStreamDialog, wxDialogWrapper )
687  EVT_BUTTON( wxID_OK, ImportStreamDialog::OnOk )
688  EVT_BUTTON( wxID_CANCEL, ImportStreamDialog::OnCancel )
690 
691 ImportStreamDialog::ImportStreamDialog( ImportFileHandle *_mFile, wxWindow *parent, wxWindowID id, const wxString &title,
692  const wxPoint &position, const wxSize& size, long style ):
693 wxDialogWrapper( parent, id, title, position, size, style | wxRESIZE_BORDER )
694 {
695  SetName(GetTitle());
696 
697  mFile = _mFile;
698  scount = mFile->GetStreamCount();
699  for (wxInt32 i = 0; i < scount; i++)
700  mFile->SetStreamUsage(i, FALSE);
701 
702  wxBoxSizer *vertSizer;
703  {
704  auto uVertSizer = std::make_unique<wxBoxSizer>(wxVERTICAL);
705  vertSizer = uVertSizer.get();
706 
707  auto choices = mFile->GetStreamInfo();
708  StreamList = safenew wxListBox(this, -1, wxDefaultPosition, wxDefaultSize, choices, wxLB_EXTENDED | wxLB_ALWAYS_SB);
709 
710  vertSizer->Add(StreamList, 1, wxEXPAND | wxALIGN_LEFT | wxALL, 5);
711 
712  vertSizer->Add(CreateStdButtonSizer(this, eCancelButton | eOkButton).release(), 0, wxEXPAND);
713 
714  SetAutoLayout(true);
715 
716  SetSizer(uVertSizer.release());
717  }
718 
719  vertSizer->Fit( this );
720 
721  SetSize( 400, 200 );
722 }
723 
725 {
726 
727 }
728 
729 void ImportStreamDialog::OnOk(wxCommandEvent & WXUNUSED(event))
730 {
731  wxArrayInt selitems;
732  int sels = StreamList->GetSelections(selitems);
733  for (wxInt32 i = 0; i < sels; i++)
734  mFile->SetStreamUsage(selitems[i],TRUE);
735  EndModal( wxID_OK );
736 }
737 
738 void ImportStreamDialog::OnCancel(wxCommandEvent & WXUNUSED(event))
739 {
740  EndModal( wxID_CANCEL );
741 }
742 
void OnCancel(wxCommandEvent &event)
Definition: Import.cpp:738
std::unique_ptr< wxSizer > CreateStdButtonSizer(wxWindow *parent, long buttons, wxWindow *extra)
Class which actulaly imports the auido, using functions defined in ImportPCM.cpp, ImportMP3...
Definition: Import.h:88
An ImportFileHandle for data.
Definition: ImportPlugin.h:119
std::unique_ptr< T > movable_ptr
Definition: MemoryX.h:713
static Importer mInstance
Definition: Import.h:149
void GetFLACImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
Definition: ImportFLAC.cpp:60
wxArrayString filters
Definition: Import.h:59
virtual void SetStreamUsage(wxInt32 StreamID, bool Use)=0
Abstract base class used in importing a file.
Definition: Import.h:32
ExtImportItems mExtImportItems
Definition: Import.h:151
void GetFFmpegImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
static bool IsMidi(const wxString &fName)
Definition: Import.cpp:330
Importer()
Definition: Import.cpp:76
bool Initialize()
Definition: Import.cpp:84
void StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod=wxTOKEN_RET_EMPTY_ALL)
Definition: Import.cpp:137
bool Import(const wxString &fName, TrackFactory *trackFactory, TrackHolders &tracks, Tags *tags, wxString &errorMessage)
Definition: Import.cpp:340
void GetGStreamerImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
#define safenew
Definition: Audacity.h:223
Used to create a WaveTrack, or a LabelTrack.. Implementation of the functions of this class are dispe...
Definition: Track.h:850
void GetSupportedImportFormats(FormatList *formatList)
Definition: Import.cpp:123
bool mbBusyImporting
Definition: Project.h:692
AudacityProject provides the main window, with tools and tracks contained within it.
Definition: Project.h:158
void ReadImportItems()
Definition: Import.cpp:145
wxFileConfig * gPrefs
Definition: Prefs.cpp:72
void OnOk(wxCommandEvent &event)
Definition: Import.cpp:729
void GetQTImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
Definition: ImportQT.cpp:36
ImportPluginList mImportPluginList
Definition: Import.h:152
void WriteImportItems()
Definition: Import.cpp:254
virtual ~ImportStreamDialog()
Definition: Import.cpp:724
void GetPCMImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &WXUNUSED(unusableImportPluginList))
Definition: ImportPCM.cpp:116
~Importer()
Definition: Import.cpp:80
wxArrayString mime_types
Definition: Import.h:85
The interface that all file import "plugins" (if you want to call them that) must implement...
void GetLOFImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &WXUNUSED(unusableImportPluginList))
Definition: ImportLOF.cpp:171
std::vector< movable_ptr< ExtImportItem > > ExtImportItems
Definition: Import.h:47
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
ID3 Tags (for MP3)
Definition: Tags.h:72
Base class for FlacImportPlugin, LOFImportPlugin, MP3ImportPlugin, OggImportPlugin and PCMImportPlugi...
Definition: ImportPlugin.h:73
_("Move Track &Down")+wxT("\t")+(GetActiveProject() -> GetCommandManager() ->GetKeyFromName(wxT("TrackMoveDown"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveTopID, _("Move Track to &Top")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveTop"))), OnMoveTrack) POPUP_MENU_ITEM(OnMoveBottomID, _("Move Track to &Bottom")+wxT("\t")+(GetActiveProject() ->GetCommandManager() ->GetKeyFromName(wxT("TrackMoveBottom"))), OnMoveTrack) void TrackMenuTable::OnSetName(wxCommandEvent &)
UnusableImportPluginList mUnusableImportPluginList
Definition: Import.h:153
void GetOGGImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
Definition: ImportOGG.cpp:58
ValueRestorer< T > valueRestorer(T &var)
Definition: MemoryX.h:875
void GetMP3ImportPlugin(ImportPluginList &importPluginList, UnusableImportPluginList &unusableImportPluginList)
Definition: ImportMP3.cpp:60
const wxChar * name
Definition: Distortion.cpp:94
AUDACITY_DLL_API AudacityProject * GetActiveProject()
Definition: Project.cpp:300
wxListBox * StreamList
Definition: Import.h:174
An UnusableImportPlugin list.
An ImportPlugin list.
wxArrayString extensions
Definition: Import.h:79
std::vector< ImportPlugin * > filter_objects
Definition: Import.h:73
movable_ptr< ExtImportItem > CreateDefaultImportItem()
Definition: Import.cpp:315
END_EVENT_TABLE()
virtual wxString GetPluginStringID()=0
static Importer & Get()
Definition: Import.cpp:71
std::vector< std::unique_ptr< WaveTrack >> TrackHolders
Definition: ImportRaw.h:42
int divider
Definition: Import.h:68
ImportFileHandle * mFile
Definition: Import.h:172
std::vector< Format > FormatList
Definition: Import.h:46
bool Terminate()
Definition: Import.cpp:114