Audacity 3.2.0
Classes | Public Member Functions | Static Public Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes | List of all members
Importer Class Reference

Class which actually imports the auido, using functions defined in ImportPCM.cpp, ImportMP3_*.cpp, ImportOGG.cpp, ImportRawData.cpp, ImportLOF.cpp, and ImportAUP.cpp. More...

#include <Import.h>

Collaboration diagram for Importer:
[legend]

Classes

struct  ImporterItem
 
struct  RegisteredImportPlugin
 
struct  RegisteredUnusableImportPlugin
 

Public Member Functions

 Importer ()
 
 ~Importer ()
 
 Importer (const Importer &)=delete
 
Importeroperator= (Importer &)=delete
 
bool Initialize ()
 
bool Terminate ()
 
FileNames::FileTypes GetFileTypes (const FileNames::FileType &extraType={})
 
void ReadImportItems ()
 
void WriteImportItems ()
 
void StringToList (wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod=wxTOKEN_RET_EMPTY_ALL)
 
ExtImportItemsGetImportItems ()
 
std::unique_ptr< ExtImportItemCreateDefaultImportItem ()
 
bool Import (AudacityProject &project, const FilePath &fName, ImportProgressListener *importProgressListener, WaveTrackFactory *trackFactory, TrackHolders &tracks, Tags *tags, TranslatableString &errorMessage)
 

Static Public Member Functions

static ImporterGet ()
 
static void SetLastOpenType (const FileNames::FileType &type)
 
static void SetDefaultOpenType (const FileNames::FileType &type)
 
static size_t SelectDefaultOpenType (const FileNames::FileTypes &fileTypes)
 

Static Private Member Functions

static ImportPluginListsImportPluginList ()
 
static UnusableImportPluginListsUnusableImportPluginList ()
 

Private Attributes

ExtImportItems mExtImportItems
 

Static Private Attributes

static Importer mInstance
 

Detailed Description

Class which actually imports the auido, using functions defined in ImportPCM.cpp, ImportMP3_*.cpp, ImportOGG.cpp, ImportRawData.cpp, ImportLOF.cpp, and ImportAUP.cpp.

Definition at line 79 of file Import.h.

Constructor & Destructor Documentation

◆ Importer() [1/2]

Importer::Importer ( )

Definition at line 108 of file Import.cpp.

109{
110}

◆ ~Importer()

Importer::~Importer ( )

Definition at line 112 of file Import.cpp.

113{
114}

◆ Importer() [2/2]

Importer::Importer ( const Importer )
delete

Member Function Documentation

◆ CreateDefaultImportItem()

std::unique_ptr< ExtImportItem > Importer::CreateDefaultImportItem ( )

Allocates NEW ExtImportItem, fills it with default data and returns a pointer to it.

Definition at line 476 of file Import.cpp.

477{
478 auto new_item = std::make_unique<ExtImportItem>();
479 new_item->extensions.push_back(wxT("*"));
480 new_item->mime_types.push_back(wxT("*"));
481
482 for (const auto &importPlugin : sImportPluginList())
483 {
484 new_item->filters.push_back(importPlugin->GetPluginStringID());
485 new_item->filter_objects.push_back(importPlugin);
486 }
487 new_item->divider = -1;
488 return new_item;
489}
wxT("CloseDown"))
static ImportPluginList & sImportPluginList()
Definition: Import.cpp:116

References sImportPluginList(), and wxT().

Referenced by ExtImportPrefs::OnAddRule().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Get()

Importer & Importer::Get ( )
static

◆ GetFileTypes()

FileNames::FileTypes Importer::GetFileTypes ( const FileNames::FileType extraType = {})

Constructs a list of types, for use by file opening dialogs, that includes all supported file types

Definition at line 214 of file Import.cpp.

215{
216 // Construct the filter
217 FileNames::FileTypes fileTypes{
219 // Will fill in the list of extensions later:
220 { XO("All supported files"), {} },
222 };
223
224 if ( !extraType.extensions.empty() )
225 fileTypes.push_back( extraType );
226
228 for(const auto &importPlugin : sImportPluginList())
229 {
230 l.emplace_back(importPlugin->GetPluginFormatDescription(),
231 importPlugin->GetSupportedExtensions());
232 }
233
234 FileExtensions extraExtensions = FileNames::AudacityProjects.extensions;
235 extraExtensions.insert(extraExtensions.end(),
236 extraType.extensions.begin(),
237 extraType.extensions.end());
238
239 using ExtensionSet = std::unordered_set< FileExtension >;
240 FileExtensions allList = FileNames::AudacityProjects.extensions, newList;
241 allList.insert(allList.end(), extraType.extensions.begin(), extraType.extensions.end());
242 ExtensionSet allSet{ allList.begin(), allList.end() }, newSet;
243 for ( const auto &format : l ) {
244 newList.clear();
245 newSet.clear();
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 );
251 }
252 fileTypes.push_back( { format.description, newList } );
253 }
254
255 fileTypes[1].extensions = allList;
256 return fileTypes;
257}
XO("Cut/Copy/Paste")
std::vector< FileType > FileTypes
Definition: FileNames.h:75
FILES_API const FileType AllFiles
Definition: FileNames.h:70
FILES_API const FileType AudacityProjects
Definition: FileNames.h:71
Extend wxArrayString with move operations and construction and insertion fromstd::initializer_list.
iterator insert(const_iterator pos, std::initializer_list< T > items)
FileExtensions extensions
Definition: FileNames.h:61

References FileNames::AllFiles, FileNames::AudacityProjects, FileNames::FileType::extensions, anonymous_namespace{ExportPCM.cpp}::format, wxArrayStringEx::insert(), sImportPluginList(), and XO().

Referenced by ApplyMacroDialog::OnApplyToFiles(), and ProjectFileManager::ShowOpenDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetImportItems()

ExtImportItems & Importer::GetImportItems ( )
inline

Returns a pointer to internal items array. External objects are allowed to change the array contents.

Definition at line 164 of file Import.h.

164{ return mExtImportItems; }
ExtImportItems mExtImportItems
Definition: Import.h:192

Referenced by ExtImportPrefs::DoOnPluginKeyDown(), ExtImportPrefs::DoOnRuleTableSelect(), ExtImportPrefs::OnAddRule(), ExtImportPrefs::OnDelRule(), ExtImportPrefs::OnRuleTableEdit(), ExtImportPrefs::PopulateOrExchange(), ExtImportPrefs::SwapPluginRows(), and ExtImportPrefs::SwapRows().

Here is the caller graph for this function:

◆ Import()

bool Importer::Import ( AudacityProject project,
const FilePath fName,
ImportProgressListener importProgressListener,
WaveTrackFactory trackFactory,
TrackHolders tracks,
Tags tags,
TranslatableString errorMessage 
)

Definition at line 492 of file Import.cpp.

499{
500 AudacityProject *pProj = &project;
501 auto cleanup = valueRestorer( pProj->mbBusyImporting, true );
502
503 const FileExtension extension{ fName.AfterLast(wxT('.')) };
504
505 // Always refuse to import MIDI, even though the FFmpeg plugin pretends to know how (but makes very bad renderings)
506#ifdef USE_MIDI
507 // MIDI files must be imported, not opened
508 if (FileNames::IsMidi(fName)) {
509 errorMessage = XO(
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.")
511 .Format( fName );
512 return false;
513 }
514#endif
515
516 // Bug #2647: Peter has a Word 2000 .doc file that is recognized and imported by FFmpeg.
517 if (wxFileName(fName).GetExt() == wxT("doc")) {
518 errorMessage =
519 XO("\"%s\" \nis a not an audio file. \nAudacity cannot open this type of file.")
520 .Format( fName );
521 return false;
522 }
523
524 using ImportPluginPtrs = std::vector< ImportPlugin* >;
525
526 // This list is used to call plugins in correct order
527 ImportPluginPtrs importPlugins;
528
529 // This list is used to remember plugins that should have been compatible with the file.
530 ImportPluginPtrs compatiblePlugins;
531
532 // Not implemented (yet?)
533 wxString mime_type = wxT("*");
534
535 // First, add user-selected filter
536 bool usersSelectionOverrides;
537 gPrefs->Read(wxT("/ExtendedImport/OverrideExtendedImportByOpenFileDialogChoice"), &usersSelectionOverrides, false);
538
539 if (usersSelectionOverrides)
540 {
541 // If user explicitly selected a filter,
542 // then we should try importing via corresponding plugin first
543 wxString type = gPrefs->Read(wxT("/LastOpenType"),wxT(""));
544
545 wxLogDebug(wxT("LastOpenType is %s"),type);
546 wxLogDebug(wxT("OverrideExtendedImportByOpenFileDialogChoice is %i"),usersSelectionOverrides);
547
548 for (const auto &plugin : sImportPluginList())
549 {
550 if (plugin->GetPluginFormatDescription().Translation() == type )
551 {
552 // This plugin corresponds to user-selected filter, try it first.
553 wxLogDebug(wxT("Inserting %s"),plugin->GetPluginStringID());
554 importPlugins.insert(importPlugins.begin(), plugin);
555 }
556 }
557 }
558
559 wxLogMessage(wxT("File name is %s"), fName);
560 wxLogMessage(wxT("Mime type is %s"), mime_type.Lower());
561
562 for (const auto &uItem : mExtImportItems)
563 {
564 ExtImportItem *item = uItem.get();
565 bool matches_ext = false, matches_mime = false;
566 wxLogDebug(wxT("Testing extensions"));
567 for (size_t j = 0; j < item->extensions.size(); j++)
568 {
569 wxLogDebug(wxT("%s"), item->extensions[j].Lower());
570 if (wxMatchWild (item->extensions[j].Lower(),fName.Lower(), false))
571 {
572 wxLogDebug(wxT("Match!"));
573 matches_ext = true;
574 break;
575 }
576 }
577 if (item->extensions.size() == 0)
578 {
579 wxLogDebug(wxT("Match! (empty list)"));
580 matches_ext = true;
581 }
582 if (matches_ext)
583 wxLogDebug(wxT("Testing mime types"));
584 else
585 wxLogDebug(wxT("Not testing mime types"));
586 for (size_t j = 0; matches_ext && j < item->mime_types.size(); j++)
587 {
588 if (wxMatchWild (item->mime_types[j].Lower(),mime_type.Lower(), false))
589 {
590 wxLogDebug(wxT("Match!"));
591 matches_mime = true;
592 break;
593 }
594 }
595 if (item->mime_types.size() == 0)
596 {
597 wxLogDebug(wxT("Match! (empty list)"));
598 matches_mime = true;
599 }
600 if (matches_ext && matches_mime)
601 {
602 wxLogDebug(wxT("Complete match!"));
603 for (size_t j = 0; j < item->filter_objects.size() && (item->divider < 0 || (int) j < item->divider); j++)
604 {
605 // the filter_object can be NULL if a suitable importer was not found
606 // this happens when we recompile with --without-ffmpeg and there
607 // is still ffmpeg in prefs from previous --with-ffmpeg builds
608 if (!(item->filter_objects[j]))
609 continue;
610 wxLogDebug(wxT("Inserting %s"),item->filter_objects[j]->GetPluginStringID());
611 importPlugins.push_back(item->filter_objects[j]);
612 }
613 }
614 }
615
616 // Add all plugins that support the extension
617 for (const auto &plugin : sImportPluginList())
618 {
619 // Make sure its not already in the list
620 if (importPlugins.end() ==
621 std::find(importPlugins.begin(), importPlugins.end(), plugin))
622 {
623 if (plugin->SupportsExtension(extension))
624 {
625 wxLogDebug(wxT("Appending %s"),plugin->GetPluginStringID());
626 importPlugins.push_back(plugin);
627 }
628 }
629 }
630
631 // Add remaining plugins
632 for (const auto &plugin : sImportPluginList())
633 {
634 // Make sure its not already in the list
635 if (importPlugins.end() ==
636 std::find(importPlugins.begin(), importPlugins.end(), plugin))
637 {
638 wxLogDebug(wxT("Appending %s"),plugin->GetPluginStringID());
639 importPlugins.push_back(plugin);
640 }
641 }
642
643 ImportProgressResultProxy importResultProxy(importProgressListener);
644
645 // Try the import plugins, in the permuted sequences just determined
646 for (const auto plugin : importPlugins)
647 {
648 // Try to open the file with this plugin (probe it)
649 wxLogMessage(wxT("Opening with %s"),plugin->GetPluginStringID());
650 auto inFile = plugin->Open(fName, pProj);
651 if ( (inFile != NULL) && (inFile->GetStreamCount() > 0) )
652 {
653 wxLogMessage(wxT("Open(%s) succeeded"), fName);
654 if(!importResultProxy.OnImportFileOpened(*inFile))
655 return false;
656
657 inFile->Import(importResultProxy, trackFactory, tracks, tags);
658 const auto importResult = importResultProxy.GetResult();
661 {
662 // LOF ("list-of-files") has different semantics
663 if (extension.IsSameAs(wxT("lof"), false))
664 {
665 return true;
666 }
667
668 // AUP ("legacy projects") have different semantics
669 if (extension.IsSameAs(wxT("aup"), false))
670 {
671 return true;
672 }
673
674 auto end = tracks.end();
675 auto iter = std::remove_if(tracks.begin(), end,
676 [](auto &pList){ return pList->empty(); });
677 if (iter != end) {
678 // importer shouldn't give us empty groups of channels!
679 assert(false);
680 // But correct that and proceed anyway
681 tracks.erase(iter, end);
682 }
683 if (tracks.size() > 0)
684 // success!
685 return true;
686 }
687
688 if (importResultProxy.GetResult() == ImportProgressListener::ImportResult::Cancelled)
689 return false;
690
691 // We could exit here since we had a match on the file extension,
692 // but there may be another plug-in that can import the file and
693 // that may recognize the extension, so we allow the loop to
694 // continue.
695 }
696 }
697 wxLogError(wxT("Importer::Import: Opening failed."));
698
699 // None of our plugins can handle this file. It might be that
700 // Audacity supports this format, but support was not compiled in.
701 // If so, notify the user of this fact
702 for (const auto &unusableImportPlugin : sUnusableImportPluginList())
703 {
704 if( unusableImportPlugin->SupportsExtension(extension) )
705 {
706 errorMessage = XO("This version of Audacity was not compiled with %s support.")
707 .Format( unusableImportPlugin->GetPluginFormatDescription() );
708 return false;
709 }
710 }
711
712 /* warnings for unsupported data types */
713
714 if (compatiblePlugins.empty())
715 {
716 // if someone has sent us a .cda file, send them away
717 if (extension.IsSameAs(wxT("cda"), false)) {
718 errorMessage = XO(
719/* i18n-hint: %s will be the filename */
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.")
721 .Format( fName );
722 return false;
723 }
724
725 // playlist type files
726 if ((extension.IsSameAs(wxT("m3u"), false))||(extension.IsSameAs(wxT("ram"), false))||(extension.IsSameAs(wxT("pls"), false))) {
727 errorMessage = XO(
728/* i18n-hint: %s will be the filename */
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.")
730 .Format( fName );
731 return false;
732 }
733 //WMA files of various forms
734 if ((extension.IsSameAs(wxT("wma"), false))||(extension.IsSameAs(wxT("asf"), false))) {
735 errorMessage = XO(
736/* i18n-hint: %s will be the filename */
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.")
738 .Format( fName );
739 return false;
740 }
741 //AAC files of various forms (probably not encrypted)
742 if ((extension.IsSameAs(wxT("aac"), false))||(extension.IsSameAs(wxT("m4a"), false))||(extension.IsSameAs(wxT("m4r"), false))||(extension.IsSameAs(wxT("mp4"), false))) {
743 errorMessage = XO(
744/* i18n-hint: %s will be the filename */
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.")
746 .Format( fName );
747 return false;
748 }
749 // encrypted itunes files
750 if ((extension.IsSameAs(wxT("m4p"), false))) {
751 errorMessage = XO(
752/* i18n-hint: %s will be the filename */
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.")
754 .Format( fName );
755 return false;
756 }
757 // Real Inc. files of various sorts
758 if ((extension.IsSameAs(wxT("ra"), false))||(extension.IsSameAs(wxT("rm"), false))||(extension.IsSameAs(wxT("rpm"), false))) {
759 errorMessage = XO(
760/* i18n-hint: %s will be the filename */
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.")
762 .Format( fName );
763 return false;
764 }
765
766 // Other notes-based formats
767 if ((extension.IsSameAs(wxT("kar"), false))||(extension.IsSameAs(wxT("mod"), false))||(extension.IsSameAs(wxT("rmi"), false))) {
768 errorMessage = XO(
769/* i18n-hint: %s will be the filename */
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.")
771 .Format( fName );
772 return false;
773 }
774
775 // MusePack files
776 if ((extension.IsSameAs(wxT("mp+"), false))||(extension.IsSameAs(wxT("mpc"), false))||(extension.IsSameAs(wxT("mpp"), false))) {
777 errorMessage = XO(
778/* i18n-hint: %s will be the filename */
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.")
780 .Format( fName );
781 return false;
782 }
783
784 // WavPack files
785 if ((extension.IsSameAs(wxT("wv"), false))||(extension.IsSameAs(wxT("wvc"), false))) {
786 errorMessage = XO(
787/* i18n-hint: %s will be the filename */
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.")
789 .Format( fName );
790 return false;
791 }
792
793 // AC3 files
794 if ((extension.IsSameAs(wxT("ac3"), false))) {
795 errorMessage = XO(
796/* i18n-hint: %s will be the filename */
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.")
798 .Format( fName );
799 return false;
800 }
801
802 // Speex files
803 if ((extension.IsSameAs(wxT("spx"), false))) {
804 errorMessage = XO(
805/* i18n-hint: %s will be the filename */
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.")
807 .Format( fName );
808 return false;
809 }
810
811 // Video files of various forms
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))) {
813 errorMessage = XO(
814/* i18n-hint: %s will be the filename */
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.")
816 .Format( fName );
817 return false;
818 }
819
820 if( !wxFileExists(fName)){
821 errorMessage = XO( "File \"%s\" not found.").Format( fName );
822 return false;
823 }
824
825 // we were not able to recognize the file type
826 TranslatableString extraMessages;
827 for(const auto &importPlugin : sImportPluginList()) {
828 auto message = importPlugin->FailureHint();
829 if (!message.empty()) {
830 extraMessages += message;
831 extraMessages += Verbatim("\n");
832 }
833 }
834
835 errorMessage = XO(
836/* i18n-hint: %s will be the filename */
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 );
839 }
840 else
841 {
842 // We DO have a plugin for this file, but import failed.
843 TranslatableString pluglist;
844
845 for (const auto &plugin : compatiblePlugins)
846 {
847 if (pluglist.empty())
848 pluglist = plugin->GetPluginFormatDescription();
849 else
850 pluglist = XO("%s, %s")
851 .Format( pluglist, plugin->GetPluginFormatDescription() );
852 }
853
854 errorMessage = XO(
855/* i18n-hint: %s will be the filename */
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 );
858 }
859
860 return false;
861}
wxString FileExtension
File extension, not including any leading dot.
Definition: Identifier.h:224
ValueRestorer< T > valueRestorer(T &var)
inline functions provide convenient parameter type deduction
Definition: MemoryX.h:251
audacity::BasicSettings * gPrefs
Definition: Prefs.cpp:68
const auto tracks
const auto project
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...
Definition: Project.h:90
bool mbBusyImporting
Definition: Project.h:130
int divider
Definition: Import.h:59
wxArrayString extensions
Definition: Import.h:70
wxArrayString mime_types
Definition: Import.h:76
std::vector< ImportPlugin * > filter_objects
Definition: Import.h:64
static UnusableImportPluginList & sUnusableImportPluginList()
Definition: Import.cpp:154
Holds a msgid for the translation catalog; may also bind format arguments.
virtual bool Read(const wxString &key, bool *value) const =0
FILES_API bool IsMidi(const FilePath &fName)
auto end(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:159

References ImportProgressListener::Cancelled, ExtImportItem::divider, TranslatableString::empty(), PackedArray::end(), ExtImportItem::extensions, ExtImportItem::filter_objects, gPrefs, FileNames::IsMidi(), AudacityProject::mbBusyImporting, mExtImportItems, ExtImportItem::mime_types, project, audacity::BasicSettings::Read(), sImportPluginList(), ImportProgressListener::Stopped, ImportProgressListener::Success, sUnusableImportPluginList(), tracks, valueRestorer(), Verbatim(), wxT(), and XO().

Referenced by ProjectFileManager::Import().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Initialize()

bool Importer::Initialize ( )

Initialization/Termination

Definition at line 167 of file Import.cpp.

168{
169 // build the list of import plugin and/or unusableImporters.
170 // order is significant. If none match, they will all be tried
171 // in the order defined here.
172
173 using namespace Registry;
175 PathStart,
176 { {wxT(""), wxT("AUP,PCM,OGG,FLAC,MP3,LOF,WavPack,FFmpeg") } }
177 // QT and GStreamer are only conditionally compiled and would get
178 // placed at the end if present
179 };
180
181 static struct MyVisitor final : Visitor {
182 MyVisitor()
183 {
184 // Once only, visit the registry to collect the plug-ins properly
185 // sorted
187 Registry::Visit( *this, &top, &ImporterItem::Registry() );
188 }
189
190 void Visit( SingleItem &item, const Path &path ) override
191 {
192 sImportPluginList().push_back(
193 static_cast<ImporterItem&>( item ).mpPlugin.get() );
194 }
195 } visitor;
196
197 // Ordering of the unusable plugin list is not important.
198
200
202
203 return true;
204}
std::vector< std::unique_ptr< ExtImportItem > > ExtImportItems
Definition: Import.h:37
void ReadImportItems()
Definition: Import.cpp:304
Definition: Menus.h:35
void Visit(Visitor &visitor, BaseItem *pTopItem, const GroupItemBase *pRegistry)
Definition: Registry.cpp:739
static const auto PathStart
Definition: Import.cpp:123
static Registry::GroupItemBase & Registry()
Definition: Import.cpp:128
Common abstract base class for items that are not groups.
Definition: Registry.h:162

References mExtImportItems, anonymous_namespace{Import.cpp}::PathStart, ReadImportItems(), Importer::ImporterItem::Registry(), sImportPluginList(), Registry::Visit(), and wxT().

Referenced by AudacityApp::InitPart2().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

Importer & Importer::operator= ( Importer )
delete

◆ ReadImportItems()

void Importer::ReadImportItems ( )

Reads extended import filters from gPrefs into internal list mExtImportItems

Definition at line 304 of file Import.cpp.

305{
306 int item_counter = 0;
307 wxStringTokenizer toker;
308 wxString item_name;
309 wxString item_value;
310
312 /* Rule string format is:
313 * extension1:extension2:extension3\mime_type1:mime_type2:mime_type3|filter1:filter2:filter3\unusedfilter1:unusedfilter2
314 * backslashes are escaped and unescaped internally
315 */
316 for (item_counter = 0; true; item_counter++)
317 {
318 wxString condition, filters, used_filters, unused_filters, extensions, mime_types;
319 item_name.Printf (wxT("/ExtImportItems/Item%d"), item_counter);
320 /* Break at first non-existent item */
321 if (!gPrefs->Read(item_name, &item_value))
322 break;
323
324 toker.SetString(item_value, wxT("|"), wxTOKEN_RET_EMPTY_ALL);
325 /* Break at first broken item */
326 if (toker.CountTokens() != 2)
327 break;
328
329 auto new_item = std::make_unique<ExtImportItem>();
330
331 /* First token is the filtering condition, second - the filter list */
332 condition = toker.GetNextToken();
333 filters = toker.GetNextToken();
334
335 /* Condition token consists of extension list and mime type list
336 * mime type list can be omitted entirely (complete with '\' separator)*/
337 toker.SetString(condition, wxT("\\"), wxTOKEN_RET_EMPTY_ALL);
338 extensions = toker.GetNextToken();
339 if (toker.HasMoreTokens())
340 mime_types = toker.GetNextToken();
341
342 wxString delims(wxT(":"));
343 StringToList (extensions, delims, new_item->extensions);
344
345 if (!mime_types.empty())
346 StringToList (mime_types, delims, new_item->mime_types);
347
348 /* Filter token consists of used and unused filter lists */
349 toker.SetString(filters, wxT("\\"), wxTOKEN_RET_EMPTY_ALL);
350 used_filters = toker.GetNextToken();
351 if (toker.HasMoreTokens())
352 unused_filters = toker.GetNextToken();
353
354 StringToList (used_filters, delims, new_item->filters);
355
356 if (!unused_filters.empty())
357 {
358 /* Filters are stored in one list, but the position at which
359 * unused filters start is remembered
360 */
361 new_item->divider = new_item->filters.size();
362 StringToList (unused_filters, delims, new_item->filters);
363 }
364 else
365 new_item->divider = -1;
366
367 /* Find corresponding filter object for each filter ID */
368 for (size_t i = 0; i < new_item->filters.size(); i++)
369 {
370 bool found = false;
371 for (const auto &importPlugin : sImportPluginList())
372 {
373 if (importPlugin->GetPluginStringID() == new_item->filters[i])
374 {
375 new_item->filter_objects.push_back(importPlugin);
376 found = true;
377 break;
378 }
379 }
380 /* IDs that do not have corresponding filters, will be shown as-is */
381 if (!found)
382 new_item->filter_objects.push_back(nullptr);
383 }
384 /* Find all filter objects that are not present in the filter list */
385 for (const auto &importPlugin : sImportPluginList())
386 {
387 bool found = false;
388 for (size_t i = 0; i < new_item->filter_objects.size(); i++)
389 {
390 if (importPlugin == new_item->filter_objects[i])
391 {
392 found = true;
393 break;
394 }
395 }
396 /* Add these filters at the bottom of used filter list */
397 if (!found)
398 {
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)
408 new_item->divider++;
409 }
410 }
411 this->mExtImportItems.push_back( std::move(new_item) );
412 }
413}
void StringToList(wxString &str, wxString &delims, wxArrayString &list, wxStringTokenizerMode mod=wxTOKEN_RET_EMPTY_ALL)
Definition: Import.cpp:296

References gPrefs, mExtImportItems, audacity::BasicSettings::Read(), sImportPluginList(), StringToList(), and wxT().

Referenced by Initialize(), and ExtImportPrefs::Populate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SelectDefaultOpenType()

size_t Importer::SelectDefaultOpenType ( const FileNames::FileTypes fileTypes)
static

Choose index of preferred type

Definition at line 279 of file Import.cpp.

280{
281 wxString defaultValue;
282 if ( !fileTypes.empty() )
283 defaultValue = fileTypes[0].description.Translation();
284
285 wxString type = gPrefs->Read(wxT("/DefaultOpenType"), defaultValue);
286 // Convert the type to the filter index
287 auto begin = fileTypes.begin();
288 auto index = std::distance(
289 begin,
290 std::find_if( begin, fileTypes.end(),
291 [&type](const FileNames::FileType &fileType){
292 return fileType.description.Translation() == type; } ) );
293 return (index == fileTypes.size()) ? 0 : index;
294}
auto begin(const Ptr< Type, BaseDeleter > &p)
Enables range-for.
Definition: PackedArray.h:150

References PackedArray::begin(), gPrefs, audacity::BasicSettings::Read(), and wxT().

Referenced by ApplyMacroDialog::OnApplyToFiles(), and ProjectFileManager::ShowOpenDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetDefaultOpenType()

void Importer::SetDefaultOpenType ( const FileNames::FileType type)
static

Remember a file type in preferences

Definition at line 269 of file Import.cpp.

270{
271 // PRL: Preference key /DefaultOpenType, unusually, stores a localized
272 // string!
273 // The bad consequences of a change of locale are not severe -- only that
274 // a default choice of file type for an open dialog is not remembered
275 gPrefs->Write(wxT("/DefaultOpenType"), type.description.Translation());
276 gPrefs->Flush();
277}
wxString Translation() const
virtual bool Flush() noexcept=0
virtual bool Write(const wxString &key, bool value)=0
TranslatableString description
Definition: FileNames.h:60

References FileNames::FileType::description, audacity::BasicSettings::Flush(), gPrefs, TranslatableString::Translation(), audacity::BasicSettings::Write(), and wxT().

Referenced by ProjectFileManager::ShowOpenDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetLastOpenType()

void Importer::SetLastOpenType ( const FileNames::FileType type)
static

Remember a file type in preferences

Definition at line 259 of file Import.cpp.

260{
261 // PRL: Preference key /LastOpenType, unusually, stores a localized
262 // string!
263 // The bad consequences of a change of locale are not severe -- only that
264 // a default choice of file type for an open dialog is not remembered
265 gPrefs->Write(wxT("/LastOpenType"), type.description.Translation());
266 gPrefs->Flush();
267}

References FileNames::FileType::description, audacity::BasicSettings::Flush(), gPrefs, TranslatableString::Translation(), audacity::BasicSettings::Write(), and wxT().

Referenced by anonymous_namespace{FileMenus.cpp}::DoImport(), ProjectManager::OpenFiles(), and ProjectFileManager::ShowOpenDialog().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sImportPluginList()

ImportPluginList & Importer::sImportPluginList ( )
staticprivate

Definition at line 116 of file Import.cpp.

117{
118 static ImportPluginList theList;
119 return theList;
120}
std::vector< ImportPlugin * > ImportPluginList

Referenced by CreateDefaultImportItem(), GetFileTypes(), Import(), Initialize(), and ReadImportItems().

Here is the caller graph for this function:

◆ StringToList()

void Importer::StringToList ( wxString &  str,
wxString &  delims,
wxArrayString &  list,
wxStringTokenizerMode  mod = wxTOKEN_RET_EMPTY_ALL 
)

Helper function - uses wxStringTokenizer to tokenize @str string and appends string-tokens to a list @list. @mod defines tokenizer's behaviour.

Definition at line 296 of file Import.cpp.

297{
298 wxStringTokenizer toker;
299
300 for (toker.SetString(str, delims, mod);
301 toker.HasMoreTokens(); list.push_back(toker.GetNextToken()));
302}
#define str(a)

References str.

Referenced by ExtImportPrefs::OnRuleTableEdit(), and ReadImportItems().

Here is the caller graph for this function:

◆ sUnusableImportPluginList()

UnusableImportPluginList & Importer::sUnusableImportPluginList ( )
staticprivate

Definition at line 154 of file Import.cpp.

155{
156 static UnusableImportPluginList theList;
157 return theList;
158}
std::vector< std::unique_ptr< UnusableImportPlugin > > UnusableImportPluginList

Referenced by Import(), and Importer::RegisteredUnusableImportPlugin::RegisteredUnusableImportPlugin().

Here is the caller graph for this function:

◆ Terminate()

bool Importer::Terminate ( )

Definition at line 206 of file Import.cpp.

207{
209
210 return true;
211}
void WriteImportItems()
Definition: Import.cpp:415

References WriteImportItems().

Referenced by AudacityApp::OnExit().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ WriteImportItems()

void Importer::WriteImportItems ( )

Writes mExtImportItems into gPrefs

Definition at line 415 of file Import.cpp.

416{
417 size_t i;
418 wxString val, name;
419 for (i = 0; i < this->mExtImportItems.size(); i++)
420 {
421 ExtImportItem *item = mExtImportItems[i].get();
422 val.clear();
423
424 for (size_t j = 0; j < item->extensions.size(); j++)
425 {
426 val.Append (item->extensions[j]);
427 if (j < item->extensions.size() - 1)
428 val.Append (wxT(":"));
429 }
430 val.Append (wxT("\\"));
431 for (size_t j = 0; j < item->mime_types.size(); j++)
432 {
433 val.Append (item->mime_types[j]);
434 if (j < item->mime_types.size() - 1)
435 val.Append (wxT(":"));
436 }
437 val.Append (wxT("|"));
438 for (size_t j = 0; j < item->filters.size() && ((int) j < item->divider || item->divider < 0); j++)
439 {
440 val.Append (item->filters[j]);
441 if (j < item->filters.size() - 1 && ((int) j < item->divider - 1 || item->divider < 0))
442 val.Append (wxT(":"));
443 }
444 if (item->divider >= 0)
445 {
446 val.Append (wxT("\\"));
447 for (size_t j = item->divider; j < item->filters.size(); j++)
448 {
449 val.Append (item->filters[j]);
450 if (j < item->filters.size() - 1)
451 val.Append (wxT(":"));
452 }
453 }
454 name.Printf (wxT("/ExtImportItems/Item%d"), (int)i);
455 gPrefs->Write (name, val);
456 gPrefs->Flush();
457 }
458 /* If we used to have more items than we have now, DELETE the excess items.
459 We just keep deleting items and incrementing until we find there aren't any
460 more to DELETE.*/
461 i = this->mExtImportItems.size();
462 do {
463 name.Printf (wxT("/ExtImportItems/Item%d"), (int)i);
464 // No item to DELETE? Then it's time to finish.
465 if (!gPrefs->Read(name, &val))
466 break;
467 // Failure to DELETE probably means a read-only config file.
468 // no point continuing.
469 // TODO: Possibly report (once).
470 if( !gPrefs->DeleteEntry (name))
471 break;
472 i++;
473 } while( true );
474}
const TranslatableString name
Definition: Distortion.cpp:76
wxArrayString filters
Definition: Import.h:50
bool DeleteEntry(const wxString &key)
Deletes specified entry if exists.

References audacity::BasicSettings::DeleteEntry(), ExtImportItem::divider, ExtImportItem::extensions, ExtImportItem::filters, audacity::BasicSettings::Flush(), gPrefs, mExtImportItems, ExtImportItem::mime_types, name, audacity::BasicSettings::Read(), audacity::BasicSettings::Write(), and wxT().

Referenced by ExtImportPrefs::Commit(), and Terminate().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ mExtImportItems

ExtImportItems Importer::mExtImportItems
private

Definition at line 192 of file Import.h.

Referenced by Import(), Initialize(), ReadImportItems(), and WriteImportItems().

◆ mInstance

Importer Importer::mInstance
staticprivate

Definition at line 190 of file Import.h.

Referenced by Get().


The documentation for this class was generated from the following files: