41#include <unordered_set>
69 mResult = ImportResult::Error;
71 return mListener->OnImportFileOpened(importFileHandle);
78 mListener->OnImportProgress(progress);
85 mListener->OnImportResult(result);
136 , mpPlugin{
std::move( pPlugin ) }
143 std::unique_ptr<ImportPlugin> pPlugin,
161 std::unique_ptr<UnusableImportPlugin> pPlugin )
176 { {
wxT(
""),
wxT(
"AUP,PCM,OGG,FLAC,MP3,LOF,WavPack,FFmpeg") } }
181 static struct MyVisitor final :
Visitor {
220 {
XO(
"All supported files"), {} },
225 fileTypes.push_back( extraType );
230 l.emplace_back(importPlugin->GetPluginFormatDescription(),
231 importPlugin->GetSupportedExtensions());
235 extraExtensions.
insert(extraExtensions.end(),
239 using ExtensionSet = std::unordered_set< FileExtension >;
242 ExtensionSet allSet{ allList.begin(), allList.end() }, newSet;
243 for (
const auto &
format : l ) {
246 for (
const auto &extension :
format.extensions ) {
247 if ( newSet.insert( extension ).second )
248 newList.push_back( extension );
249 if ( allSet.insert( extension ).second )
250 allList.push_back( extension );
252 fileTypes.push_back( {
format.description, newList } );
255 fileTypes[1].extensions = allList;
281 wxString defaultValue;
282 if ( !fileTypes.empty() )
283 defaultValue = fileTypes[0].description.Translation();
285 wxString type =
gPrefs->
Read(
wxT(
"/DefaultOpenType"), defaultValue);
287 auto begin = fileTypes.begin();
288 auto index = std::distance(
290 std::find_if(
begin, fileTypes.end(),
292 return fileType.description.Translation() == type; } ) );
293 return (index == fileTypes.size()) ? 0 : index;
298 wxStringTokenizer toker;
300 for (toker.SetString(
str, delims, mod);
301 toker.HasMoreTokens(); list.push_back(toker.GetNextToken()));
306 int item_counter = 0;
307 wxStringTokenizer toker;
316 for (item_counter = 0;
true; item_counter++)
318 wxString condition, filters, used_filters, unused_filters, extensions, mime_types;
319 item_name.Printf (
wxT(
"/ExtImportItems/Item%d"), item_counter);
324 toker.SetString(item_value,
wxT(
"|"), wxTOKEN_RET_EMPTY_ALL);
326 if (toker.CountTokens() != 2)
329 auto new_item = std::make_unique<ExtImportItem>();
332 condition = toker.GetNextToken();
333 filters = toker.GetNextToken();
337 toker.SetString(condition,
wxT(
"\\"), wxTOKEN_RET_EMPTY_ALL);
338 extensions = toker.GetNextToken();
339 if (toker.HasMoreTokens())
340 mime_types = toker.GetNextToken();
342 wxString delims(
wxT(
":"));
343 StringToList (extensions, delims, new_item->extensions);
345 if (!mime_types.empty())
346 StringToList (mime_types, delims, new_item->mime_types);
349 toker.SetString(filters,
wxT(
"\\"), wxTOKEN_RET_EMPTY_ALL);
350 used_filters = toker.GetNextToken();
351 if (toker.HasMoreTokens())
352 unused_filters = toker.GetNextToken();
356 if (!unused_filters.empty())
361 new_item->divider = new_item->filters.size();
362 StringToList (unused_filters, delims, new_item->filters);
365 new_item->divider = -1;
368 for (
size_t i = 0; i < new_item->filters.size(); i++)
373 if (importPlugin->GetPluginStringID() == new_item->filters[i])
375 new_item->filter_objects.push_back(importPlugin);
382 new_item->filter_objects.push_back(
nullptr);
388 for (
size_t i = 0; i < new_item->filter_objects.size(); i++)
390 if (importPlugin == new_item->filter_objects[i])
399 int index = new_item->divider;
400 if (new_item->divider < 0)
401 index = new_item->filters.size();
402 new_item->filters.insert(
403 new_item->filters.begin() + index,
404 importPlugin->GetPluginStringID());
405 new_item->filter_objects.insert(
406 new_item->filter_objects.begin() + index, importPlugin);
407 if (new_item->divider >= 0)
424 for (
size_t j = 0; j < item->
extensions.size(); j++)
427 if (j < item->extensions.size() - 1)
428 val.Append (
wxT(
":"));
430 val.Append (
wxT(
"\\"));
431 for (
size_t j = 0; j < item->
mime_types.size(); j++)
434 if (j < item->mime_types.size() - 1)
435 val.Append (
wxT(
":"));
437 val.Append (
wxT(
"|"));
438 for (
size_t j = 0; j < item->
filters.size() && ((
int) j < item->divider || item->
divider < 0); j++)
441 if (j < item->filters.size() - 1 && ((
int) j < item->divider - 1 || item->
divider < 0))
442 val.Append (
wxT(
":"));
446 val.Append (
wxT(
"\\"));
447 for (
size_t j = item->
divider; j < item->filters.size(); j++)
450 if (j < item->filters.size() - 1)
451 val.Append (
wxT(
":"));
454 name.Printf (
wxT(
"/ExtImportItems/Item%d"), (
int)i);
463 name.Printf (
wxT(
"/ExtImportItems/Item%d"), (
int)i);
478 auto new_item = std::make_unique<ExtImportItem>();
479 new_item->extensions.push_back(
wxT(
"*"));
480 new_item->mime_types.push_back(
wxT(
"*"));
484 new_item->filters.push_back(importPlugin->GetPluginStringID());
485 new_item->filter_objects.push_back(importPlugin);
487 new_item->divider = -1;
510"\"%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.")
517 if (wxFileName(fName).GetExt() ==
wxT(
"doc")) {
519 XO(
"\"%s\" \nis a not an audio file. \nAudacity cannot open this type of file.")
524 using ImportPluginPtrs = std::vector< ImportPlugin* >;
527 ImportPluginPtrs importPlugins;
530 ImportPluginPtrs compatiblePlugins;
533 wxString mime_type =
wxT(
"*");
536 bool usersSelectionOverrides;
537 gPrefs->
Read(
wxT(
"/ExtendedImport/OverrideExtendedImportByOpenFileDialogChoice"), &usersSelectionOverrides,
false);
539 if (usersSelectionOverrides)
545 wxLogDebug(
wxT(
"LastOpenType is %s"),type);
546 wxLogDebug(
wxT(
"OverrideExtendedImportByOpenFileDialogChoice is %i"),usersSelectionOverrides);
550 if (plugin->GetPluginFormatDescription().Translation() == type )
553 wxLogDebug(
wxT(
"Inserting %s"),plugin->GetPluginStringID());
554 importPlugins.insert(importPlugins.begin(), plugin);
559 wxLogMessage(
wxT(
"File name is %s"), fName);
560 wxLogMessage(
wxT(
"Mime type is %s"), mime_type.Lower());
565 bool matches_ext =
false, matches_mime =
false;
566 wxLogDebug(
wxT(
"Testing extensions"));
567 for (
size_t j = 0; j < item->
extensions.size(); j++)
570 if (wxMatchWild (item->
extensions[j].Lower(),fName.Lower(),
false))
572 wxLogDebug(
wxT(
"Match!"));
579 wxLogDebug(
wxT(
"Match! (empty list)"));
583 wxLogDebug(
wxT(
"Testing mime types"));
585 wxLogDebug(
wxT(
"Not testing mime types"));
586 for (
size_t j = 0; matches_ext && j < item->
mime_types.size(); j++)
588 if (wxMatchWild (item->
mime_types[j].Lower(),mime_type.Lower(),
false))
590 wxLogDebug(
wxT(
"Match!"));
597 wxLogDebug(
wxT(
"Match! (empty list)"));
600 if (matches_ext && matches_mime)
602 wxLogDebug(
wxT(
"Complete match!"));
603 for (
size_t j = 0; j < item->
filter_objects.size() && (item->
divider < 0 || (
int) j < item->divider); j++)
620 if (importPlugins.end() ==
621 std::find(importPlugins.begin(), importPlugins.end(), plugin))
623 if (plugin->SupportsExtension(extension))
625 wxLogDebug(
wxT(
"Appending %s"),plugin->GetPluginStringID());
626 importPlugins.push_back(plugin);
635 if (importPlugins.end() ==
636 std::find(importPlugins.begin(), importPlugins.end(), plugin))
638 wxLogDebug(
wxT(
"Appending %s"),plugin->GetPluginStringID());
639 importPlugins.push_back(plugin);
643 ImportProgressResultProxy importResultProxy(importProgressListener);
646 for (
const auto plugin : importPlugins)
649 wxLogMessage(
wxT(
"Opening with %s"),plugin->GetPluginStringID());
650 auto inFile = plugin->Open(fName, pProj);
651 if ( (inFile != NULL) && (inFile->GetStreamCount() > 0) )
653 wxLogMessage(
wxT(
"Open(%s) succeeded"), fName);
654 if(!importResultProxy.OnImportFileOpened(*inFile))
657 inFile->Import(importResultProxy, trackFactory,
tracks, tags);
658 const auto importResult = importResultProxy.GetResult();
663 if (extension.IsSameAs(
wxT(
"lof"),
false))
669 if (extension.IsSameAs(
wxT(
"aup"),
false))
675 auto iter = std::remove_if(
tracks.begin(),
end,
676 [](
auto &pList){ return pList->empty(); });
697 wxLogError(
wxT(
"Importer::Import: Opening failed."));
704 if( unusableImportPlugin->SupportsExtension(extension) )
706 errorMessage =
XO(
"This version of Audacity was not compiled with %s support.")
707 .Format( unusableImportPlugin->GetPluginFormatDescription() );
714 if (compatiblePlugins.empty())
717 if (extension.IsSameAs(
wxT(
"cda"),
false)) {
720"\"%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.")
726 if ((extension.IsSameAs(
wxT(
"m3u"),
false))||(extension.IsSameAs(
wxT(
"ram"),
false))||(extension.IsSameAs(
wxT(
"pls"),
false))) {
729"\"%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.")
734 if ((extension.IsSameAs(
wxT(
"wma"),
false))||(extension.IsSameAs(
wxT(
"asf"),
false))) {
737"\"%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.")
742 if ((extension.IsSameAs(
wxT(
"aac"),
false))||(extension.IsSameAs(
wxT(
"m4a"),
false))||(extension.IsSameAs(
wxT(
"m4r"),
false))||(extension.IsSameAs(
wxT(
"mp4"),
false))) {
745"\"%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.")
750 if ((extension.IsSameAs(
wxT(
"m4p"),
false))) {
753"\"%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.")
758 if ((extension.IsSameAs(
wxT(
"ra"),
false))||(extension.IsSameAs(
wxT(
"rm"),
false))||(extension.IsSameAs(
wxT(
"rpm"),
false))) {
761"\"%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.")
767 if ((extension.IsSameAs(
wxT(
"kar"),
false))||(extension.IsSameAs(
wxT(
"mod"),
false))||(extension.IsSameAs(
wxT(
"rmi"),
false))) {
770"\"%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.")
776 if ((extension.IsSameAs(
wxT(
"mp+"),
false))||(extension.IsSameAs(
wxT(
"mpc"),
false))||(extension.IsSameAs(
wxT(
"mpp"),
false))) {
779"\"%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.")
785 if ((extension.IsSameAs(
wxT(
"wv"),
false))||(extension.IsSameAs(
wxT(
"wvc"),
false))) {
788"\"%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.")
794 if ((extension.IsSameAs(
wxT(
"ac3"),
false))) {
797"\"%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.")
803 if ((extension.IsSameAs(
wxT(
"spx"),
false))) {
806"\"%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.")
812 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))) {
815"\"%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.")
820 if( !wxFileExists(fName)){
821 errorMessage =
XO(
"File \"%s\" not found.").Format( fName );
828 auto message = importPlugin->FailureHint();
829 if (!message.empty()) {
830 extraMessages += message;
837"Audacity did not recognize the type of the file '%s'.\n\n%sFor uncompressed files, also try File > Import > Raw Data.")
838 .Format( fName, extraMessages );
845 for (
const auto &plugin : compatiblePlugins)
847 if (pluglist.
empty())
848 pluglist = plugin->GetPluginFormatDescription();
850 pluglist =
XO(
"%s, %s")
851 .Format( pluglist, plugin->GetPluginFormatDescription() );
856"Audacity recognized the type of the file '%s'.\nImporters supposedly supporting such files are:\n%s,\nbut none of them understood this file format.")
857 .Format( fName, pluglist );
const TranslatableString name
wxString FileExtension
File extension, not including any leading dot.
BoolSetting NewImportingSession
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....
std::vector< std::shared_ptr< TrackList > > TrackHolders
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
audacity::BasicSettings * gPrefs
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
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.
Base class for FlacImportFileHandle, LOFImportFileHandle, MP3ImportFileHandle, OggImportFileHandle an...
Interface used to report on import state and progress.
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)
bool Import(AudacityProject &project, const FilePath &fName, ImportProgressListener *importProgressListener, WaveTrackFactory *trackFactory, TrackHolders &tracks, Tags *tags, TranslatableString &errorMessage)
static void SetLastOpenType(const FileNames::FileType &type)
static UnusableImportPluginList & sUnusableImportPluginList()
ExtImportItems mExtImportItems
FileNames::FileTypes GetFileTypes(const FileNames::FileType &extraType={})
std::unique_ptr< ExtImportItem > CreateDefaultImportItem()
static size_t SelectDefaultOpenType(const FileNames::FileTypes &fileTypes)
static void SetDefaultOpenType(const FileNames::FileType &type)
static ImportPluginList & sImportPluginList()
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...
ImportResult GetResult() const noexcept
ImportProgressResultProxy(ImportProgressListener *listener)
bool OnImportFileOpened(ImportFileHandle &importFileHandle) override
void OnImportResult(ImportResult result) override
Used to report on import result for file handle passed as argument to OnImportFileOpened.
void OnImportProgress(double progress) override
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
bool DeleteEntry(const wxString &key)
Deletes specified entry if exists.
virtual bool Read(const wxString &key, bool *value) const =0
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 GroupItemBase *pRegistry)
static const auto PathStart
TranslatableString description
FileExtensions extensions
static Registry::GroupItemBase & Registry()
ImporterItem(const Identifier &id, std::unique_ptr< ImportPlugin > pPlugin)
RegisteredImportPlugin(const Identifier &id, std::unique_ptr< ImportPlugin >, const Registry::Placement &placement={ wxEmptyString, {} })
RegisteredUnusableImportPlugin(std::unique_ptr< UnusableImportPlugin >)
Common abstract base class for items that group other items.
Common abstract base class for items that are not groups.