static void get_dup_producer_names(map<BString, int32>& dups) { int32 id = 0; BMidiProducer* prod; while ((prod=BMidiRoster::NextProducer(&id)) != NULL) { if (!prod->IsLocal()) { BString name(prod->Name()); dup_name_map::iterator it = dups.find(name); if (it != dups.end()) (*it).second = (*it).second + 1; else { dups.insert(dup_name_map::value_type(name, 1)); } } } dup_name_map::iterator i; for (i = dups.begin(); i != dups.end(); i++) { if (i->second < 2) { dups.erase(i); /* THIS IS ABSOLUTELY NECESSARY -- if you try to iterate * over begin() when the map is empty(), it just hangs. */ if (dups.empty()) break; i = dups.begin(); } } for (i = dups.begin(); i != dups.end(); i++) { i->second = 1; } }
AmFilterRoster* AmFilterRoster::Default() { if (atomic_or(&gFilterRosterCreated, 1) == 0) { gFilterRoster = new AmFilterRoster("Default Filter Roster"); gFilterRoster->AddSearchPath("%A/add-ons/Filters"); gFilterRoster->AddDirectory(B_SYSTEM_ADDONS_DIRECTORY,"AngryRedPlanet/Sequitur/Filters"); gFilterRoster->AddDirectory(B_USER_ADDONS_DIRECTORY,"AngryRedPlanet/Sequitur/Filters"); // Here are our standard filter addons... AmFilterAddOn *addon; // Forcibly add in all existing consumers, so that when we // return we have everything as it currently exists. This is // to take care of situations where, say, the file loader is the // first thing to open the roster and immediately starts trying // to instantiate consumer filters. BMidiConsumer* cons; /* Hack -- keep track of the producer / consumer names that are * installed, and if a name gets installed more than one, increment * a counter for it. This is so users can run multiple instances of * a softsynth and access each independently. */ dup_name_map dups; get_dup_consumer_names(dups); int32 id = 0; while ((cons=BMidiRoster::NextConsumer(&id)) != NULL) { if (!cons->IsLocal()) { BString msg("Installing MIDI consumer "); msg += cons->Name(); msg += "..."; am_report_startup_status(msg.String()); int32 index = 0; dup_name_map::iterator i = dups.find(BString(cons->Name())); if (i != dups.end()) { index = i->second; i->second = i->second + 1; } addon = new AmConsumerFilterAddOn(NULL, cons, index); if (addon) { printf("Installing consumer %s (#%ld)\n", cons->Name(), cons->ID()); gFilterRoster->InstallAddOn(new AmFilterAddOnHandle(addon)); #if 0 BMessage props; if( cons->GetProperties( &props ) == B_OK ) { printf("****** CONSUMER HAS PROPERTIES:\n"); props.PrintToStream(); printf("****** END PROPERTIES\n"); } #endif } } } dups.erase(dups.begin(), dups.end()); get_dup_producer_names(dups); id = 0; BMidiProducer* prod; while ((prod=BMidiRoster::NextProducer(&id)) != NULL) { if (!prod->IsLocal()) { BString msg("Installing MIDI producer "); msg += prod->Name(); msg += "..."; am_report_startup_status(msg.String()); int32 index = 0; dup_name_map::iterator i = dups.find(BString(prod->Name())); if (i != dups.end()) { index = i->second; i->second = i->second + 1; } addon = new AmProducerFilterAddOn(NULL, prod, index); if (addon) { printf("Installing producer%s (#%ld)\n", prod->Name(), prod->ID()); gFilterRoster->InstallAddOn(new AmFilterAddOnHandle(addon)); } } } /* Add in a filter for the BeOS MIDI synth if there's any * audio output. */ status_t err; am_report_startup_status("Installing MIDI Synth consumer..."); BMediaRoster* roster = BMediaRoster::Roster( &err ); if( err == B_OK && roster ) { media_node node; err = roster->GetAudioOutput( &node ); if( err == B_OK ) { // Add in a filter for the BeOS MIDI synth. if ((addon = new AmConsumerFilterAddOn(NULL)) != NULL) gFilterRoster->InstallAddOn(new AmFilterAddOnHandle(addon)); // node.ReleaseNode(); } } /* Add the generic input/output filters, for tool and multi filter pipelines. */ if ((addon = new AmNullInputAddOn(NULL)) != NULL) gFilterRoster->InstallAddOn(new AmFilterAddOnHandle(addon)); if ((addon = new AmNullOutputAddOn(NULL)) != NULL) gFilterRoster->InstallAddOn(new AmFilterAddOnHandle(addon)); // Go! gFilterRoster->Run(); } else { while (!gFilterRoster) sleep(20000); } return gFilterRoster; }
virtual void MessageReceived(BMessage *message) { if (message->what == B_MIDI_EVENT) { int32 op, id; const char* type; if (message->FindInt32("be:op", &op) == B_OK && message->FindInt32("be:id", &id) == B_OK && message->FindString("be:type", &type) == B_OK) { BAutolock _l(mRoster.Locker()); // First look for a filter with this ID. AmFilterAddOnHandle* handle = NULL; AmConsumerFilterAddOn* caddon = NULL; AmProducerFilterAddOn* paddon = NULL; for (int32 i=0; i<mRoster.CountAddOns(); i++) { handle = dynamic_cast<AmFilterAddOnHandle*>(mRoster.AddOnAt(i)); if (!handle) continue; caddon = dynamic_cast<AmConsumerFilterAddOn*>(handle->AddOn()); paddon = dynamic_cast<AmProducerFilterAddOn*>(handle->AddOn()); if (caddon && caddon->ConsumerID() == id) { break; } if (paddon && paddon->ProducerID() == id) { break; } } if (op == B_MIDI_REGISTERED) { // Only add if the newly registered consumer // doesn't already exist in the roster. if (strcmp(type, "consumer") == 0 && (!caddon || caddon->ConsumerID() != id) ) { BMidiConsumer* cons = BMidiRoster::FindConsumer(id); if (!cons) return; if (cons->IsLocal()) return; caddon = new AmConsumerFilterAddOn(NULL, cons); if (caddon) { printf("Installing consumer %s (#%ld)\n", cons->Name(), cons->ID()); mRoster.InstallAddOn(new AmFilterAddOnHandle(caddon)); } } else if (strcmp(type, "producer") == 0 && (!paddon || paddon->ProducerID() != id) ) { BMidiProducer* prod = BMidiRoster::FindProducer(id); if (!prod) return; if (prod->IsLocal()) return; paddon = new AmProducerFilterAddOn( NULL, prod ); if (paddon) { printf("Installing producer %s (#%ld)\n", prod->Name(), prod->ID()); mRoster.InstallAddOn(new AmFilterAddOnHandle(paddon)); } } } else if (op == B_MIDI_UNREGISTERED) { if (handle && caddon || paddon) { printf("Removing %s (#%ld)\n", caddon ? caddon->Name().String() : paddon->Name().String(), caddon ? caddon->ConsumerID() : paddon->ProducerID()); mRoster.RemoveAddOn(handle); } } } return; } BHandler::MessageReceived(message); }