@@ -552,11 +552,90 @@ Result Addsynth::readFromResource(const String& name)
552552 return read (stream);
553553}
554554
555+ Result Addsynth::readFromFile (const File& file)
556+ {
557+ if (!file.exists ())
558+ return Result::fail (" File does not exist" );
559+
560+ const auto ext{ file.getFileExtension ().toLowerCase () };
561+
562+ if (ext == " .ae0" ) {
563+ FileInputStream stream (file);
564+ return read (stream);
565+ }
566+
567+ if (ext == " .json" ) {
568+ FileInputStream stream (file);
569+ auto stop = JSON::parse (stream);
570+ // @todo We don't handle JSON parsing errors currently
571+ fromVar (stop);
572+ return Result::ok ();
573+ }
574+
575+ return Result::fail (" Unknown file format" );
576+ }
577+
555578// ==============================================================================
556579
557580Model::Model ()
558581 : _synths()
559582 , _nameToSynthMap()
583+ {
584+ loadExternalPipes ();
585+ loadEmbeddedPipes ();
586+ }
587+
588+ StringArray Model::getStopNames () const
589+ {
590+ StringArray stops;
591+
592+ for (const auto * synth : _synths) {
593+ stops.add (synth->getStopName ());
594+ }
595+
596+ return stops;
597+ }
598+
599+ Addsynth* Model::getStopByName (const juce::String& name)
600+ {
601+ auto it = _nameToSynthMap.find (name);
602+
603+ if (it == _nameToSynthMap.end ())
604+ return nullptr ;
605+
606+ return it->second ;
607+ }
608+
609+ void Model::loadExternalPipes ()
610+ {
611+ File configFile{ aeolus::getCustomOrganConfigFile () };
612+ const String configFileName{ configFile.getFileName () };
613+ File configFolder{ configFile.getParentDirectory () };
614+
615+ if (!configFolder.exists ())
616+ return ;
617+
618+ for (DirectoryEntry entry : RangedDirectoryIterator (configFolder, true )) {
619+ auto file{ entry.getFile () };
620+ const auto ext{ file.getFileExtension ().toLowerCase () };
621+
622+ if ((ext == " .json" && file.getFileName () != configFileName) || (ext == " .ae0" )) {
623+ auto synth = std::make_unique<Addsynth>();
624+ const auto res{ synth->readFromFile (file) };
625+
626+ if (res.wasOk ()) {
627+ String stopName{ file.getFileNameWithoutExtension () };
628+ synth->setStopName (stopName);
629+
630+ addSynth (std::move (synth));
631+ } else {
632+ DBG (" Failed to read: " << res.getErrorMessage ());
633+ }
634+ }
635+ }
636+ }
637+
638+ void Model::loadEmbeddedPipes ()
560639{
561640 for (int i = 0 ; i < BinaryData::namedResourceListSize; ++i) {
562641 String filename (BinaryData::originalFilenames[i]);
@@ -590,34 +669,27 @@ Model::Model()
590669 }
591670
592671 if (ok) {
593- auto * ptr = synth.get ();
594- ptr->setStopName (stopName);
595-
596- _synths.add (synth.release ());
597- _nameToSynthMap[stopName] = ptr;
672+ synth->setStopName (stopName);
673+ addSynth (std::move (synth));
598674 }
599675 }
600676}
601677
602- StringArray Model::getStopNames () const
603- {
604- StringArray stops;
605-
606- for (const auto * synth : _synths) {
607- stops.add (synth->getStopName ());
608- }
609-
610- return stops;
611- }
612-
613- Addsynth* Model::getStopByName (const juce::String& name)
678+ void Model::addSynth (std::unique_ptr<Addsynth>&& synthToAdd)
614679{
615- auto it = _nameToSynthMap.find (name);
680+ std::unique_ptr<Addsynth> synth{ std::move (synthToAdd) };
681+ const String stopName{ synth->getStopName () };
616682
617- if (it == _nameToSynthMap.end ())
618- return nullptr ;
683+ if (_nameToSynthMap.find (stopName) == _nameToSynthMap.end ()) {
684+ auto * ptr = synth.get ();
685+ ptr->setStopName (stopName);
619686
620- return it->second ;
687+ _synths.add (synth.release ());
688+ _nameToSynthMap[stopName] = ptr;
689+ } else {
690+ // Pipe with this name already exists - it won't be added again
691+ DBG (" Pipe " << stopName << " duplicate found" );
692+ }
621693}
622694
623695JUCE_IMPLEMENT_SINGLETON (Model)
0 commit comments