44#include <unordered_set>
46#include <wx/textctrl.h>
47#include <wx/listbox.h>
101 , mpPlugin{
std::move( pPlugin ) }
108 std::unique_ptr<ImportPlugin> pPlugin,
126 std::unique_ptr<UnusableImportPlugin> pPlugin )
141 { {
wxT(
""),
wxT(
"AUP,PCM,OGG,FLAC,MP3,LOF,WavPack,FFmpeg") } }
146 static struct MyVisitor final :
Visitor {
185 {
XO(
"All supported files"), {} },
190 fileTypes.push_back( extraType );
195 l.emplace_back(importPlugin->GetPluginFormatDescription(),
196 importPlugin->GetSupportedExtensions());
200 extraExtensions.
insert(extraExtensions.end(),
204 using ExtensionSet = std::unordered_set< FileExtension >;
207 ExtensionSet allSet{ allList.begin(), allList.end() }, newSet;
208 for (
const auto &
format : l ) {
211 for (
const auto &extension :
format.extensions ) {
212 if ( newSet.insert( extension ).second )
213 newList.push_back( extension );
214 if ( allSet.insert( extension ).second )
215 allList.push_back( extension );
217 fileTypes.push_back( {
format.description, newList } );
220 fileTypes[1].extensions = allList;
246 wxString defaultValue;
247 if ( !fileTypes.empty() )
248 defaultValue = fileTypes[0].description.Translation();
250 wxString type =
gPrefs->Read(
wxT(
"/DefaultOpenType"), defaultValue);
252 auto begin = fileTypes.begin();
253 auto index = std::distance(
255 std::find_if(
begin, fileTypes.end(),
257 return fileType.description.Translation() == type; } ) );
258 return (index == fileTypes.size()) ? 0 : index;
263 wxStringTokenizer toker;
265 for (toker.SetString(
str, delims, mod);
266 toker.HasMoreTokens(); list.push_back(toker.GetNextToken()));
271 int item_counter = 0;
272 wxStringTokenizer toker;
281 for (item_counter = 0;
true; item_counter++)
283 wxString condition, filters, used_filters, unused_filters, extensions, mime_types;
284 item_name.Printf (
wxT(
"/ExtImportItems/Item%d"), item_counter);
286 if (!
gPrefs->Read(item_name, &item_value))
289 toker.SetString(item_value,
wxT(
"|"), wxTOKEN_RET_EMPTY_ALL);
291 if (toker.CountTokens() != 2)
294 auto new_item = std::make_unique<ExtImportItem>();
297 condition = toker.GetNextToken();
298 filters = toker.GetNextToken();
302 toker.SetString(condition,
wxT(
"\\"), wxTOKEN_RET_EMPTY_ALL);
303 extensions = toker.GetNextToken();
304 if (toker.HasMoreTokens())
305 mime_types = toker.GetNextToken();
307 wxString delims(
wxT(
":"));
308 StringToList (extensions, delims, new_item->extensions);
310 if (!mime_types.empty())
311 StringToList (mime_types, delims, new_item->mime_types);
314 toker.SetString(filters,
wxT(
"\\"), wxTOKEN_RET_EMPTY_ALL);
315 used_filters = toker.GetNextToken();
316 if (toker.HasMoreTokens())
317 unused_filters = toker.GetNextToken();
321 if (!unused_filters.empty())
326 new_item->divider = new_item->filters.size();
327 StringToList (unused_filters, delims, new_item->filters);
330 new_item->divider = -1;
333 for (
size_t i = 0; i < new_item->filters.size(); i++)
338 if (importPlugin->GetPluginStringID() == new_item->filters[i])
340 new_item->filter_objects.push_back(importPlugin);
347 new_item->filter_objects.push_back(
nullptr);
353 for (
size_t i = 0; i < new_item->filter_objects.size(); i++)
355 if (importPlugin == new_item->filter_objects[i])
364 int index = new_item->divider;
365 if (new_item->divider < 0)
366 index = new_item->filters.size();
367 new_item->filters.insert(
368 new_item->filters.begin() + index,
369 importPlugin->GetPluginStringID());
370 new_item->filter_objects.insert(
371 new_item->filter_objects.begin() + index, importPlugin);
372 if (new_item->divider >= 0)
389 for (
size_t j = 0; j < item->
extensions.size(); j++)
392 if (j < item->extensions.size() - 1)
393 val.Append (
wxT(
":"));
395 val.Append (
wxT(
"\\"));
396 for (
size_t j = 0; j < item->
mime_types.size(); j++)
399 if (j < item->mime_types.size() - 1)
400 val.Append (
wxT(
":"));
402 val.Append (
wxT(
"|"));
403 for (
size_t j = 0; j < item->
filters.size() && ((
int) j < item->divider || item->
divider < 0); j++)
406 if (j < item->filters.size() - 1 && ((
int) j < item->divider - 1 || item->
divider < 0))
407 val.Append (
wxT(
":"));
411 val.Append (
wxT(
"\\"));
412 for (
size_t j = item->
divider; j < item->filters.size(); j++)
415 if (j < item->filters.size() - 1)
416 val.Append (
wxT(
":"));
419 name.Printf (
wxT(
"/ExtImportItems/Item%d"), (
int)i);
428 name.Printf (
wxT(
"/ExtImportItems/Item%d"), (
int)i);
443 auto new_item = std::make_unique<ExtImportItem>();
444 new_item->extensions.push_back(
wxT(
"*"));
445 new_item->mime_types.push_back(
wxT(
"*"));
449 new_item->filters.push_back(importPlugin->GetPluginStringID());
450 new_item->filter_objects.push_back(importPlugin);
452 new_item->divider = -1;
474"\"%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.")
481 if (wxFileName(fName).GetExt() ==
wxT(
"doc")) {
483 XO(
"\"%s\" \nis a not an audio file. \nAudacity cannot open this type of file.")
488 using ImportPluginPtrs = std::vector< ImportPlugin* >;
491 ImportPluginPtrs importPlugins;
494 ImportPluginPtrs compatiblePlugins;
497 wxString mime_type =
wxT(
"*");
500 bool usersSelectionOverrides;
501 gPrefs->Read(
wxT(
"/ExtendedImport/OverrideExtendedImportByOpenFileDialogChoice"), &usersSelectionOverrides,
false);
503 if (usersSelectionOverrides)
507 wxString type =
gPrefs->Read(
wxT(
"/LastOpenType"),
wxT(
""));
509 wxLogDebug(
wxT(
"LastOpenType is %s"),type);
510 wxLogDebug(
wxT(
"OverrideExtendedImportByOpenFileDialogChoice is %i"),usersSelectionOverrides);
514 if (plugin->GetPluginFormatDescription().Translation() == type )
517 wxLogDebug(
wxT(
"Inserting %s"),plugin->GetPluginStringID());
518 importPlugins.insert(importPlugins.begin(), plugin);
523 wxLogMessage(
wxT(
"File name is %s"), fName);
524 wxLogMessage(
wxT(
"Mime type is %s"), mime_type.Lower());
529 bool matches_ext =
false, matches_mime =
false;
530 wxLogDebug(
wxT(
"Testing extensions"));
531 for (
size_t j = 0; j < item->
extensions.size(); j++)
534 if (wxMatchWild (item->
extensions[j].Lower(),fName.Lower(),
false))
536 wxLogDebug(
wxT(
"Match!"));
543 wxLogDebug(
wxT(
"Match! (empty list)"));
547 wxLogDebug(
wxT(
"Testing mime types"));
549 wxLogDebug(
wxT(
"Not testing mime types"));
550 for (
size_t j = 0; matches_ext && j < item->
mime_types.size(); j++)
552 if (wxMatchWild (item->
mime_types[j].Lower(),mime_type.Lower(),
false))
554 wxLogDebug(
wxT(
"Match!"));
561 wxLogDebug(
wxT(
"Match! (empty list)"));
564 if (matches_ext && matches_mime)
566 wxLogDebug(
wxT(
"Complete match!"));
567 for (
size_t j = 0; j < item->
filter_objects.size() && (item->
divider < 0 || (
int) j < item->divider); j++)
584 if (importPlugins.end() ==
585 std::find(importPlugins.begin(), importPlugins.end(), plugin))
587 if (plugin->SupportsExtension(extension))
589 wxLogDebug(
wxT(
"Appending %s"),plugin->GetPluginStringID());
590 importPlugins.push_back(plugin);
599 if (importPlugins.end() ==
600 std::find(importPlugins.begin(), importPlugins.end(), plugin))
602 wxLogDebug(
wxT(
"Appending %s"),plugin->GetPluginStringID());
603 importPlugins.push_back(plugin);
608 for (
const auto plugin : importPlugins)
611 wxLogMessage(
wxT(
"Opening with %s"),plugin->GetPluginStringID());
612 auto inFile = plugin->Open(fName, pProj);
613 if ( (inFile != NULL) && (inFile->GetStreamCount() > 0) )
615 wxLogMessage(
wxT(
"Open(%s) succeeded"), fName);
617 if (inFile->GetStreamCount() > 1)
621 if (ImportDlg.ShowModal() == wxID_CANCEL)
628 inFile->SetStreamUsage(0,TRUE);
630 auto res = inFile->Import(trackFactory, tracks, tags);
635 if (extension.IsSameAs(
wxT(
"lof"),
false))
641 if (extension.IsSameAs(
wxT(
"aup"),
false))
646 auto end = tracks.end();
647 auto iter = std::remove_if( tracks.begin(),
end,
648 std::mem_fn( &NewChannelGroup::empty ) );
653 tracks.erase( iter,
end );
655 if (tracks.size() > 0)
671 wxLogError(
wxT(
"Importer::Import: Opening failed."));
678 if( unusableImportPlugin->SupportsExtension(extension) )
680 errorMessage =
XO(
"This version of Audacity was not compiled with %s support.")
681 .Format( unusableImportPlugin->GetPluginFormatDescription() );
688 if (compatiblePlugins.empty())
691 if (extension.IsSameAs(
wxT(
"cda"),
false)) {
694"\"%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.")
700 if ((extension.IsSameAs(
wxT(
"m3u"),
false))||(extension.IsSameAs(
wxT(
"ram"),
false))||(extension.IsSameAs(
wxT(
"pls"),
false))) {
703"\"%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.")
708 if ((extension.IsSameAs(
wxT(
"wma"),
false))||(extension.IsSameAs(
wxT(
"asf"),
false))) {
711"\"%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.")
716 if ((extension.IsSameAs(
wxT(
"aac"),
false))||(extension.IsSameAs(
wxT(
"m4a"),
false))||(extension.IsSameAs(
wxT(
"m4r"),
false))||(extension.IsSameAs(
wxT(
"mp4"),
false))) {
719"\"%s\" is an Advanced Audio Coding file.\nWithout the optional FFmpeg library, Audacity cannot open this type of file.\nOtherwise, you need to convert it to a supported audio format, such as WAV or AIFF.")
724 if ((extension.IsSameAs(
wxT(
"m4p"),
false))) {
727"\"%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.")
732 if ((extension.IsSameAs(
wxT(
"ra"),
false))||(extension.IsSameAs(
wxT(
"rm"),
false))||(extension.IsSameAs(
wxT(
"rpm"),
false))) {
735"\"%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.")
741 if ((extension.IsSameAs(
wxT(
"kar"),
false))||(extension.IsSameAs(
wxT(
"mod"),
false))||(extension.IsSameAs(
wxT(
"rmi"),
false))) {
744"\"%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.")
750 if ((extension.IsSameAs(
wxT(
"mp+"),
false))||(extension.IsSameAs(
wxT(
"mpc"),
false))||(extension.IsSameAs(
wxT(
"mpp"),
false))) {
753"\"%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.")
759 if ((extension.IsSameAs(
wxT(
"wv"),
false))||(extension.IsSameAs(
wxT(
"wvc"),
false))) {
762"\"%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.")
768 if ((extension.IsSameAs(
wxT(
"ac3"),
false))) {
771"\"%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.")
777 if ((extension.IsSameAs(
wxT(
"spx"),
false))) {
780"\"%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.")
786 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))) {
789"\"%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.")
794 if( !wxFileExists(fName)){
795 errorMessage =
XO(
"File \"%s\" not found.").Format( fName );
802 auto message = importPlugin->FailureHint();
803 if (!message.empty()) {
804 extraMessages += message;
811"Audacity did not recognize the type of the file '%s'.\n\n%sFor uncompressed files, also try File > Import > Raw Data.")
812 .Format( fName, extraMessages );
819 for (
const auto &plugin : compatiblePlugins)
821 if (pluglist.
empty())
822 pluglist = plugin->GetPluginFormatDescription();
824 pluglist =
XO(
"%s, %s")
825 .Format( pluglist, plugin->GetPluginFormatDescription() );
830"Audacity recognized the type of the file '%s'.\nImporters supposedly supporting such files are:\n%s,\nbut none of them understood this file format.")
831 .Format( fName, pluglist );
847 const wxPoint &position, const wxSize&
size,
long style ):
853 scount = mFile->GetStreamCount();
854 for (wxInt32 i = 0; i < scount; i++)
855 mFile->SetStreamUsage(i, FALSE);
864 .Position(wxEXPAND | wxALIGN_LEFT | wxALL)
865 .Style(wxLB_EXTENDED | wxLB_ALWAYS_SB)
867 transform_container<wxArrayStringEx>(
868 mFile->GetStreamInfo(),
871 S.AddStandardButtons();
875 GetSizer()->Fit(
this );
888 int sels = StreamList->GetSelections(selitems);
889 for (wxInt32 i = 0; i < sels; i++)
890 mFile->SetStreamUsage(selitems[i],TRUE);
896 EndModal( wxID_CANCEL );
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
const TranslatableString name
wxString FileExtension
File extension, not including any leading dot.
BoolSetting NewImportingSession
std::vector< std::shared_ptr< WaveTrack > > NewChannelGroup
std::vector< std::vector< std::shared_ptr< WaveTrack > > > TrackHolders
std::vector< std::unique_ptr< ExtImportItem > > ExtImportItems
std::vector< std::unique_ptr< UnusableImportPlugin > > UnusableImportPluginList
std::vector< ImportPlugin * > ImportPluginList
The interface that all file import "plugins" (if you want to call them that) must implement....
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
auto Visit(Visitor &&vis, Variant &&var)
Mimic some of std::visit, for the case of one visitor only.
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
This specialization of Setting for bool adds a Toggle method to negate the saved value.
std::vector< ImportPlugin * > filter_objects
virtual bool DeleteEntry(const wxString &key, bool bDeleteGroupIfEmpty=true) wxOVERRIDE
virtual bool Flush(bool bCurrentOnly=false) wxOVERRIDE
std::vector< FileType > FileTypes
FILES_API const FileType AllFiles
FILES_API const FileType AudacityProjects
An explicitly nonlocalized string, not meant for the user to see.
An ImportFileHandle for data.
void OnOk(wxCommandEvent &event)
virtual ~ImportStreamDialog()
void OnCancel(wxCommandEvent &event)
Class which actually imports the auido, using functions defined in ImportPCM.cpp, ImportMP3_*....
static Importer mInstance
void StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod=wxTOKEN_RET_EMPTY_ALL)
static void SetLastOpenType(const FileNames::FileType &type)
static UnusableImportPluginList & sUnusableImportPluginList()
ExtImportItems mExtImportItems
FileNames::FileTypes GetFileTypes(const FileNames::FileType &extraType={})
bool Import(AudacityProject &project, const FilePath &fName, WaveTrackFactory *trackFactory, TrackHolders &tracks, Tags *tags, TranslatableString &errorMessage)
std::unique_ptr< ExtImportItem > CreateDefaultImportItem()
static size_t SelectDefaultOpenType(const FileNames::FileTypes &fileTypes)
static void SetDefaultOpenType(const FileNames::FileType &type)
static ImportPluginList & sImportPluginList()
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
Holds a msgid for the translation catalog; may also bind format arguments.
wxString Translation() const
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
iterator insert(const_iterator pos, std::initializer_list< T > items)
FILES_API bool IsMidi(const FilePath &fName)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItem *pRegistry)
static const auto PathStart
TranslatableString description
FileExtensions extensions
ImporterItem(const Identifier &id, std::unique_ptr< ImportPlugin > pPlugin)
static Registry::GroupItem & Registry()
RegisteredImportPlugin(const Identifier &id, std::unique_ptr< ImportPlugin >, const Registry::Placement &placement={ wxEmptyString, {} })
RegisteredUnusableImportPlugin(std::unique_ptr< UnusableImportPlugin >)