40#include <unordered_set>
68 mResult = ImportResult::Error;
70 return mListener->OnImportFileOpened(importFileHandle);
77 mListener->OnImportProgress(progress);
84 mListener->OnImportResult(result);
135 , mpPlugin{
std::move( pPlugin ) }
142 std::unique_ptr<ImportPlugin> pPlugin,
160 std::unique_ptr<UnusableImportPlugin> pPlugin )
177 { {
wxT(
""),
wxT(
"AUP,PCM,OGG,FLAC,MP3,LOF,WavPack,portsmf,FFmpeg") } }
182 static std::once_flag
flag;
183 std::call_once(
flag, []{
214 {
XO(
"All supported files"), {} },
219 fileTypes.push_back( extraType );
224 l.emplace_back(importPlugin->GetPluginFormatDescription(),
225 importPlugin->GetSupportedExtensions());
229 extraExtensions.
insert(extraExtensions.end(),
233 using ExtensionSet = std::unordered_set< FileExtension >;
236 ExtensionSet allSet{ allList.begin(), allList.end() }, newSet;
237 for (
const auto &
format : l ) {
240 for (
const auto &extension :
format.extensions ) {
241 if ( newSet.insert( extension ).second )
242 newList.push_back( extension );
243 if ( allSet.insert( extension ).second )
244 allList.push_back( extension );
246 fileTypes.push_back( {
format.description, newList } );
249 fileTypes[1].extensions = allList;
275 wxString defaultValue;
276 if ( !fileTypes.empty() )
277 defaultValue = fileTypes[0].description.Translation();
279 wxString type =
gPrefs->
Read(
wxT(
"/DefaultOpenType"), defaultValue);
281 auto begin = fileTypes.begin();
282 auto index = std::distance(
284 std::find_if(
begin, fileTypes.end(),
286 return fileType.description.Translation() == type; } ) );
287 return (index == fileTypes.size()) ? 0 : index;
292 wxStringTokenizer toker;
294 for (toker.SetString(
str, delims, mod);
295 toker.HasMoreTokens(); list.push_back(toker.GetNextToken()));
300 int item_counter = 0;
301 wxStringTokenizer toker;
310 for (item_counter = 0;
true; item_counter++)
312 wxString condition, filters, used_filters, unused_filters, extensions, mime_types;
313 item_name.Printf (
wxT(
"/ExtImportItems/Item%d"), item_counter);
318 toker.SetString(item_value,
wxT(
"|"), wxTOKEN_RET_EMPTY_ALL);
320 if (toker.CountTokens() != 2)
323 auto new_item = std::make_unique<ExtImportItem>();
326 condition = toker.GetNextToken();
327 filters = toker.GetNextToken();
331 toker.SetString(condition,
wxT(
"\\"), wxTOKEN_RET_EMPTY_ALL);
332 extensions = toker.GetNextToken();
333 if (toker.HasMoreTokens())
334 mime_types = toker.GetNextToken();
336 wxString delims(
wxT(
":"));
337 StringToList (extensions, delims, new_item->extensions);
339 if (!mime_types.empty())
340 StringToList (mime_types, delims, new_item->mime_types);
343 toker.SetString(filters,
wxT(
"\\"), wxTOKEN_RET_EMPTY_ALL);
344 used_filters = toker.GetNextToken();
345 if (toker.HasMoreTokens())
346 unused_filters = toker.GetNextToken();
350 if (!unused_filters.empty())
355 new_item->divider = new_item->filters.size();
356 StringToList (unused_filters, delims, new_item->filters);
359 new_item->divider = -1;
362 for (
size_t i = 0; i < new_item->filters.size(); i++)
367 if (importPlugin->GetPluginStringID() == new_item->filters[i])
369 new_item->filter_objects.push_back(importPlugin);
376 new_item->filter_objects.push_back(
nullptr);
382 for (
size_t i = 0; i < new_item->filter_objects.size(); i++)
384 if (importPlugin == new_item->filter_objects[i])
393 int index = new_item->divider;
394 if (new_item->divider < 0)
395 index = new_item->filters.size();
396 new_item->filters.insert(
397 new_item->filters.begin() + index,
398 importPlugin->GetPluginStringID());
399 new_item->filter_objects.insert(
400 new_item->filter_objects.begin() + index, importPlugin);
401 if (new_item->divider >= 0)
418 for (
size_t j = 0; j < item->
extensions.size(); j++)
421 if (j < item->extensions.size() - 1)
422 val.Append (
wxT(
":"));
424 val.Append (
wxT(
"\\"));
425 for (
size_t j = 0; j < item->
mime_types.size(); j++)
428 if (j < item->mime_types.size() - 1)
429 val.Append (
wxT(
":"));
431 val.Append (
wxT(
"|"));
432 for (
size_t j = 0; j < item->
filters.size() && ((
int) j < item->divider || item->
divider < 0); j++)
435 if (j < item->filters.size() - 1 && ((
int) j < item->divider - 1 || item->
divider < 0))
436 val.Append (
wxT(
":"));
440 val.Append (
wxT(
"\\"));
441 for (
size_t j = item->
divider; j < item->filters.size(); j++)
444 if (j < item->filters.size() - 1)
445 val.Append (
wxT(
":"));
448 name.Printf (
wxT(
"/ExtImportItems/Item%d"), (
int)i);
457 name.Printf (
wxT(
"/ExtImportItems/Item%d"), (
int)i);
472 auto new_item = std::make_unique<ExtImportItem>();
473 new_item->extensions.push_back(
wxT(
"*"));
474 new_item->mime_types.push_back(
wxT(
"*"));
478 new_item->filters.push_back(importPlugin->GetPluginStringID());
479 new_item->filter_objects.push_back(importPlugin);
481 new_item->divider = -1;
490 std::optional<LibFileFormats::AcidizerTags>& outAcidTags,
499 if (wxFileName(fName).GetExt() ==
wxT(
"doc")) {
501 XO(
"\"%s\" \nis a not an audio file. \nAudacity cannot open this type of file.")
506 using ImportPluginPtrs = std::vector< ImportPlugin* >;
509 ImportPluginPtrs importPlugins;
512 ImportPluginPtrs compatiblePlugins;
515 wxString mime_type =
wxT(
"*");
518 bool usersSelectionOverrides;
519 gPrefs->
Read(
wxT(
"/ExtendedImport/OverrideExtendedImportByOpenFileDialogChoice"), &usersSelectionOverrides,
false);
521 if (usersSelectionOverrides)
527 wxLogDebug(
wxT(
"LastOpenType is %s"),type);
528 wxLogDebug(
wxT(
"OverrideExtendedImportByOpenFileDialogChoice is %i"),usersSelectionOverrides);
532 if (plugin->GetPluginFormatDescription().Translation() == type )
535 wxLogDebug(
wxT(
"Inserting %s"),plugin->GetPluginStringID());
536 importPlugins.insert(importPlugins.begin(), plugin);
541 wxLogMessage(
wxT(
"File name is %s"), fName);
542 wxLogMessage(
wxT(
"Mime type is %s"), mime_type.Lower());
547 bool matches_ext =
false, matches_mime =
false;
548 wxLogDebug(
wxT(
"Testing extensions"));
549 for (
size_t j = 0; j < item->
extensions.size(); j++)
552 if (wxMatchWild (item->
extensions[j].Lower(),fName.Lower(),
false))
554 wxLogDebug(
wxT(
"Match!"));
561 wxLogDebug(
wxT(
"Match! (empty list)"));
565 wxLogDebug(
wxT(
"Testing mime types"));
567 wxLogDebug(
wxT(
"Not testing mime types"));
568 for (
size_t j = 0; matches_ext && j < item->
mime_types.size(); j++)
570 if (wxMatchWild (item->
mime_types[j].Lower(),mime_type.Lower(),
false))
572 wxLogDebug(
wxT(
"Match!"));
579 wxLogDebug(
wxT(
"Match! (empty list)"));
582 if (matches_ext && matches_mime)
584 wxLogDebug(
wxT(
"Complete match!"));
585 for (
size_t j = 0; j < item->
filter_objects.size() && (item->
divider < 0 || (
int) j < item->divider); j++)
602 if (importPlugins.end() ==
603 std::find(importPlugins.begin(), importPlugins.end(), plugin))
605 if (plugin->SupportsExtension(extension))
607 wxLogDebug(
wxT(
"Appending %s"),plugin->GetPluginStringID());
608 importPlugins.push_back(plugin);
617 if (importPlugins.end() ==
618 std::find(importPlugins.begin(), importPlugins.end(), plugin))
620 wxLogDebug(
wxT(
"Appending %s"),plugin->GetPluginStringID());
621 importPlugins.push_back(plugin);
625 ImportProgressResultProxy importResultProxy(importProgressListener);
628 for (
const auto plugin : importPlugins)
631 wxLogMessage(
wxT(
"Opening with %s"),plugin->GetPluginStringID());
632 auto inFile = plugin->Open(fName, pProj);
633 if ( (inFile != NULL) && (inFile->GetStreamCount() > 0) )
635 wxLogMessage(
wxT(
"Open(%s) succeeded"), fName);
636 if(!importResultProxy.OnImportFileOpened(*inFile))
640 importResultProxy, trackFactory,
tracks, tags, outAcidTags);
641 const auto importResult = importResultProxy.GetResult();
646 if (extension.IsSameAs(
wxT(
"lof"),
false))
652 if (extension.IsSameAs(
wxT(
"aup"),
false))
658 auto iter = std::remove_if(
tracks.begin(),
end,
659 [](
auto &pList){ return pList->empty(); });
680 wxLogError(
wxT(
"Importer::Import: Opening failed."));
687 if( unusableImportPlugin->SupportsExtension(extension) )
689 errorMessage =
XO(
"This version of Audacity was not compiled with %s support.")
690 .Format( unusableImportPlugin->GetPluginFormatDescription() );
697 if (compatiblePlugins.empty())
700 if (extension.IsSameAs(
wxT(
"cda"),
false)) {
703"\"%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.")
709 if ((extension.IsSameAs(
wxT(
"m3u"),
false))||(extension.IsSameAs(
wxT(
"ram"),
false))||(extension.IsSameAs(
wxT(
"pls"),
false))) {
712"\"%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.")
717 if ((extension.IsSameAs(
wxT(
"wma"),
false))||(extension.IsSameAs(
wxT(
"asf"),
false))) {
720"\"%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.")
725 if ((extension.IsSameAs(
wxT(
"aac"),
false))||(extension.IsSameAs(
wxT(
"m4a"),
false))||(extension.IsSameAs(
wxT(
"m4r"),
false))||(extension.IsSameAs(
wxT(
"mp4"),
false))) {
728"\"%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.")
733 if ((extension.IsSameAs(
wxT(
"m4p"),
false))) {
736"\"%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.")
741 if ((extension.IsSameAs(
wxT(
"ra"),
false))||(extension.IsSameAs(
wxT(
"rm"),
false))||(extension.IsSameAs(
wxT(
"rpm"),
false))) {
744"\"%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.")
750 if ((extension.IsSameAs(
wxT(
"kar"),
false))||(extension.IsSameAs(
wxT(
"mod"),
false))||(extension.IsSameAs(
wxT(
"rmi"),
false))) {
753"\"%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.")
759 if ((extension.IsSameAs(
wxT(
"mp+"),
false))||(extension.IsSameAs(
wxT(
"mpc"),
false))||(extension.IsSameAs(
wxT(
"mpp"),
false))) {
762"\"%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.")
768 if ((extension.IsSameAs(
wxT(
"wv"),
false))||(extension.IsSameAs(
wxT(
"wvc"),
false))) {
771"\"%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.")
777 if ((extension.IsSameAs(
wxT(
"ac3"),
false))) {
780"\"%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.")
786 if ((extension.IsSameAs(
wxT(
"spx"),
false))) {
789"\"%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.")
795 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))) {
798"\"%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.")
803 if( !wxFileExists(fName)){
804 errorMessage =
XO(
"File \"%s\" not found.").Format( fName );
811 auto message = importPlugin->FailureHint();
812 if (!message.empty()) {
813 extraMessages += message;
820"Audacity did not recognize the type of the file '%s'.\n\n%sFor uncompressed files, also try File > Import > Raw Data.")
821 .Format( fName, extraMessages );
828 for (
const auto &plugin : compatiblePlugins)
830 if (pluglist.
empty())
831 pluglist = plugin->GetPluginFormatDescription();
833 pluglist =
XO(
"%s, %s")
834 .Format( pluglist, plugin->GetPluginFormatDescription() );
839"Audacity recognized the type of the file '%s'.\nImporters supposedly supporting such files are:\n%s,\nbut none of them understood this file format.")
840 .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.
Singleton class which actually imports the audio, using ImportPlugin objects that are registered by m...
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, ImportProgressListener *importProgressListener, WaveTrackFactory *trackFactory, TrackHolders &tracks, Tags *tags, std::optional< LibFileFormats::AcidizerTags > &outAcidTags, 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()
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)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
void Visit(const Visitors &visitors, const GroupItem< RegistryTraits > *pTopItem, const GroupItem< RegistryTraits > *pRegistry={}, typename RegistryTraits::ComputedItemContextType &computedItemContext=RegistryTraits::ComputedItemContextType::Instance)
static const auto PathStart
TranslatableString description
FileExtensions extensions
ImporterItem(const Identifier &id, std::unique_ptr< ImportPlugin > pPlugin)
std::unique_ptr< ImportPlugin > mpPlugin
static Registry::GroupItem< Traits > & Registry()
RegisteredImportPlugin(const Identifier &id, std::unique_ptr< ImportPlugin >, const Registry::Placement &placement={ wxEmptyString, {} })
RegisteredUnusableImportPlugin(std::unique_ptr< UnusableImportPlugin >)