void AudioPluginOSCGUIManager::updateProgram(InstrumentId instrument, int position) { RG_DEBUG << "AudioPluginOSCGUIManager::updateProgram(" << instrument << "," << position << ")" << endl; if (m_guis.find(instrument) == m_guis.end() || m_guis[instrument].find(position) == m_guis[instrument].end()) return ; PluginContainer *container = 0; container = m_studio->getContainerById(instrument); if (!container) return; AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) return; unsigned long rv = StudioControl::getPluginProgram (pluginInstance->getMappedId(), strtoqstr(pluginInstance->getProgram())); int bank = rv >> 16; int program = rv - (bank << 16); RG_DEBUG << "AudioPluginOSCGUIManager::updateProgram(" << instrument << "," << position << "): rv " << rv << ", bank " << bank << ", program " << program << endl; m_guis[instrument][position]->sendProgram(bank, program); }
void AudioPluginOSCGUIManager::updatePort(InstrumentId instrument, int position, int port) { RG_DEBUG << "AudioPluginOSCGUIManager::updatePort(" << instrument << "," << position << "," << port << ")" << endl; if (m_guis.find(instrument) == m_guis.end() || m_guis[instrument].find(position) == m_guis[instrument].end()) return ; PluginContainer *container = 0; container = m_studio->getContainerById(instrument); if (!container) return; AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) return ; PluginPortInstance *porti = pluginInstance->getPort(port); if (!porti) return ; RG_DEBUG << "AudioPluginOSCGUIManager::updatePort(" << instrument << "," << position << "," << port << "): value " << porti->value << endl; m_guis[instrument][position]->sendPortValue(port, porti->value); }
static void RT_process(SoundPlugin *plugin, int64_t time, int num_frames, float **inputs, float **outputs){ Data *data = (Data*)plugin->data; #if 0 for(int ch=0; ch<data->num_output_channels ; ch++) memset(outputs[ch], 0, sizeof(float)*num_frames); return; #endif // 1. Process audio AudioPluginInstance *instance = data->audio_instance; AudioSampleBuffer &buffer = data->buffer; for(int ch=0; ch<data->num_input_channels ; ch++) memcpy(buffer.getWritePointer(ch), inputs[ch], sizeof(float)*num_frames); int pos = CRASHREPORTER_set_plugin_name(plugin->type->name);{ instance->processBlock(buffer, data->midi_buffer); }CRASHREPORTER_unset_plugin_name(pos); for(int ch=0; ch<data->num_output_channels ; ch++) memcpy(outputs[ch], buffer.getReadPointer(ch), sizeof(float)*num_frames); // 2. Send out midi (untested, need plugin to test with) volatile struct Patch *patch = plugin->patch; if (patch!=NULL) { MidiBuffer::Iterator iterator(data->midi_buffer); MidiMessage message; int samplePosition; while(iterator.getNextEvent(message, samplePosition)){ #ifndef RELEASE if (samplePosition >= num_frames || samplePosition < 0) RT_message("The instrument named \"%s\" of type %s/%s\n" "returned illegal sample position: %d", patch==NULL?"<no name>":patch->name, plugin->type->type_name, plugin->type->name, samplePosition ); #endif // Make sure samplePosition has a legal value if (samplePosition >= num_frames) samplePosition = num_frames-1; if (samplePosition < 0) samplePosition = 0; int64_t delta_time = PLAYER_get_block_delta_time(pc->start_time+samplePosition); int64_t radium_time = pc->start_time + delta_time; RT_MIDI_send_msg_to_patch_receivers((struct Patch*)patch, message, radium_time); } } }
static int get_current_preset(struct SoundPlugin *plugin){ #if JUCE_LINUX const MessageManagerLock mmLock; #endif Data *data = (Data*)plugin->data; AudioPluginInstance *instance = data->audio_instance; return instance->getCurrentProgram(); }
static void set_current_preset(struct SoundPlugin *plugin, int num){ #if JUCE_LINUX const MessageManagerLock mmLock; #endif Data *data = (Data*)plugin->data; AudioPluginInstance *instance = data->audio_instance; instance->setCurrentProgram(num); }
static const char *get_preset_name(struct SoundPlugin *plugin, int num){ #if JUCE_LINUX const MessageManagerLock mmLock; #endif Data *data = (Data*)plugin->data; AudioPluginInstance *instance = data->audio_instance; return talloc_strdup(instance->getProgramName(num).toRawUTF8()); }
static void set_preset_name(struct SoundPlugin *plugin, int num, const char* new_name){ #if JUCE_LINUX const MessageManagerLock mmLock; #endif Data *data = (Data*)plugin->data; AudioPluginInstance *instance = data->audio_instance; instance->changeProgramName(num, new_name); }
void AudioPluginOSCGUIManager::startGUI(InstrumentId instrument, int position) { RG_DEBUG << "AudioPluginOSCGUIManager::startGUI: " << instrument << "," << position << endl; checkOSCThread(); if (m_guis.find(instrument) != m_guis.end() && m_guis[instrument].find(position) != m_guis[instrument].end()) { RG_DEBUG << "stopping GUI first"; stopGUI(instrument, position); } // check the label PluginContainer *container = 0; container = m_studio->getContainerById(instrument); if (!container) { RG_DEBUG << "AudioPluginOSCGUIManager::startGUI: no such instrument or buss as " << instrument << endl; return; } AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) { RG_DEBUG << "AudioPluginOSCGUIManager::startGUI: no plugin at position " << position << " for instrument " << instrument << endl; return ; } try { AudioPluginOSCGUI *gui = new AudioPluginOSCGUI(pluginInstance, getOSCUrl(instrument, position, strtoqstr(pluginInstance->getIdentifier())), getFriendlyName(instrument, position, strtoqstr(pluginInstance->getIdentifier()))); m_guis[instrument][position] = gui; } catch (Exception e) { RG_DEBUG << "AudioPluginOSCGUIManager::startGUI: failed to start GUI: " << e.getMessage() << endl; } }
FilterModel FilterGraph::formatFilterModel (AudioProcessorGraph::Node* const node) { //FOR SAVING AND UPDATING FilterModel filter; AudioPluginInstance* plugin = dynamic_cast<AudioPluginInstance*>(node->getProcessor()); if (plugin == nullptr) { jassertfalse; return filter; } PluginDescription pd; plugin->fillInPluginDescription(pd); fill_in_filter_pd_info(node, filter, pd); return filter; }
bool AudioPluginOSCGUIManager::hasGUI(InstrumentId instrument, int position) { PluginContainer *container = 0; container = m_studio->getContainerById(instrument); if (!container) return false; AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) return false; try { QString filePath = AudioPluginOSCGUI::getGUIFilePath (strtoqstr(pluginInstance->getIdentifier())); return ( !filePath.isEmpty() ); } catch (Exception e) { // that's OK return false; } }
// The caller is responsible for deleting the object that is returned AudioPluginInstance *createSynthInstance() { AudioPluginFormatManager pluginManager; pluginManager.addDefaultFormats(); PluginDescription desc; desc.fileOrIdentifier = resolveRelativePath(PLUGIN_REL_PATH); // DBG << desc.fileOrIdentifier << endl; desc.uid = 0; String errorMessage; AudioPluginInstance *instance = pluginManager.createPluginInstance(desc, errorMessage); if (!instance) { DBG << "Error creating plugin instance: " << errorMessage << endl; exit(1); } // Force initialization on the main thread. This preparation will redone with proper values later. instance->prepareToPlay(44100, 512); return instance; }
static AudioPluginInstance *get_audio_instance(const TypeData *type_data, float sample_rate, int block_size){ static bool inited=false; static AudioPluginFormatManager formatManager; if (inited==false){ formatManager.addDefaultFormats(); inited=true; } //int uid = VST_get_uid(type_data->library_file_full_path); //printf("uid: %d\n",uid); //getchar(); //((PluginDescription*)description)->uid = uid; //if (uid==-1) // return NULL; String errorMessage; PluginDescription description; description.fileOrIdentifier = String(type_data->file_or_identifier); description.uid = type_data->uid; AudioPluginInstance *instance = formatManager.createPluginInstance(description,sample_rate,block_size,errorMessage); if (instance==NULL){ GFX_Message(NULL, "Unable to open VST plugin %s: %s\n",description.fileOrIdentifier.toRawUTF8(), errorMessage.toRawUTF8()); return NULL; } instance->setPlayHead(&myAudioPlayHead); instance->prepareToPlay(sample_rate, block_size); return instance; }
void AudioPluginOSCGUIManager::updateConfiguration(InstrumentId instrument, int position, QString key) { RG_DEBUG << "AudioPluginOSCGUIManager::updateConfiguration(" << instrument << "," << position << "," << key << ")" << endl; if (m_guis.find(instrument) == m_guis.end() || m_guis[instrument].find(position) == m_guis[instrument].end()) return ; PluginContainer *container = m_studio->getContainerById(instrument); if (!container) return; AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) return; QString value = strtoqstr(pluginInstance->getConfigurationValue(qstrtostr(key))); RG_DEBUG << "AudioPluginOSCGUIManager::updatePort(" << instrument << "," << position << "," << key << "): value " << value << endl; m_guis[instrument][position]->sendConfiguration(key, value); }
bool AudioPluginOSCGUIManager::parseOSCPath(QString path, InstrumentId &instrument, int &position, QString &method) { RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath(" << path << ")"; if (!m_studio) return false; QString pluginStr("/plugin/"); if (path.startsWith("//")) { path = path.right(path.length() - 1); } if (!path.startsWith(pluginStr)) { RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath: malformed path " << path << endl; return false; } path = path.right(path.length() - pluginStr.length()); QString type = path.section('/', 0, 0); QString instrumentStr = path.section('/', 1, 1); QString positionStr = path.section('/', 2, 2); QString label = path.section('/', 3, -2); method = path.section('/', -1, -1); if (instrumentStr.isEmpty() || positionStr.isEmpty() ) { RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath: no instrument or position in " << path; return false; } instrument = instrumentStr.toUInt(); if (positionStr == "synth") { position = Instrument::SYNTH_PLUGIN_POSITION; } else { position = positionStr.toInt(); } // check the label PluginContainer *container = m_studio->getContainerById(instrument); if (!container) { RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath: no such instrument or buss as " << instrument << " in path " << path << endl; return false; } AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) { RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath: no plugin at position " << position << " for instrument " << instrument << " in path " << path << endl; return false; } QString identifier = strtoqstr(pluginInstance->getIdentifier()); QString iType, iSoName, iLabel; PluginIdentifier::parseIdentifier(identifier, iType, iSoName, iLabel); if (iLabel != label) { RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath: wrong label for plugin" << " at position " << position << " for instrument " << instrument << " in path " << path << " (actual label is " << iLabel << ")" << endl; return false; } RG_DEBUG << "AudioPluginOSCGUIManager::parseOSCPath: good path " << path << ", got mapped id " << pluginInstance->getMappedId() << endl; return true; }
XmlElement* PMixDocument::createNodeXml (AudioProcessorGraph::Node* const node) noexcept { AudioPluginInstance* plugin = dynamic_cast <AudioPluginInstance*> (node->getProcessor()); if (plugin == nullptr) { jassertfalse; return nullptr; } XmlElement* e = new XmlElement ("NODE"); e->setAttribute ("uid", (int) node->nodeID); e->setAttribute ("x", node->properties ["x"].toString()); e->setAttribute ("y", node->properties ["y"].toString()); e->setAttribute ("uiLastX", node->properties ["uiLastX"].toString()); e->setAttribute ("uiLastY", node->properties ["uiLastY"].toString()); e->setAttribute ("uiStatus", node->properties ["uiStatus"].toString()); PluginDescription pd; plugin->fillInPluginDescription (pd); if(!InternalPluginFormat::isInternalFormat(pd.name)) { e->setAttribute("colour", node->properties ["colour"].toString()); e->setAttribute ("iposx", node->properties ["iposx"].toString()); e->setAttribute ("iposy", node->properties ["iposy"].toString()); } e->addChildElement (pd.createXml()); XmlElement* state = new XmlElement ("STATE"); MemoryBlock m; node->getProcessor()->getStateInformation (m); state->addTextElement (m.toBase64Encoding()); e->addChildElement (state); if(!InternalPluginFormat::isInternalFormat(pd.name)) { XmlElement* params = new XmlElement ("PARAMS"); Array<var>* paramsArray = node->properties.getVarPointer("params")->getArray(); params->addTextElement("["); for(int i=0;i<paramsArray->size();i++) { var parameterIdx = paramsArray->getReference(i); params->addTextElement(parameterIdx.toString()); if(i != paramsArray->size()-1) params->addTextElement(", "); } params->addTextElement("]"); e->addChildElement(params); Array<var>* presetsArr = node->properties.getVarPointer("presets")->getArray(); for(int i=0;i<presetsArr->size();i++) { XmlElement* presetXML = new XmlElement ("PRESET"); DynamicObject* thePreset = presetsArr->getReference(i).getDynamicObject(); presetXML->setAttribute("name", thePreset->getProperty("name").toString()); presetXML->setAttribute("x", thePreset->getProperty("x").toString()); presetXML->setAttribute("y", thePreset->getProperty("y").toString()); presetXML->setAttribute("radius", thePreset->getProperty("radius").toString()); presetXML->setAttribute("hidden", thePreset->getProperty("hidden").toString()); //presetXML->setAttribute("distance", thePreset->getProperty("distance").toString()); presetXML->setAttribute("coeff", thePreset->getProperty("coeff").toString()); presetXML->setAttribute("uid", thePreset->getProperty("uid").toString()); Array<var>* paramsArray = thePreset->getProperty("state").getArray(); presetXML->addTextElement("["); for(int i=0;i<paramsArray->size();i++) { var parameterIdx = paramsArray->getReference(i); presetXML->addTextElement(parameterIdx.toString()); if(i != paramsArray->size()-1) presetXML->addTextElement(", "); } presetXML->addTextElement("]"); e->addChildElement(presetXML); } } return e; }
bool handlePluginRequest(const PluginRequestParameters ¶ms, OutputStream &ostream, ThreadSafePlugin *plugin = nullptr) { if (!plugin) { // It's very possible that all of this was a premature optimization. // For VSTs at least, code loading and caching is handled by ModuleHandle::findOrCreateModule, // and each instantiation only requires a couple of disc hits for working directory setting. // On the other hand, we want to make sure that each audio request has a "fresh" instance. // The easiest way to do this is by bypassing the instance pool and instantiating on demand. #if PLUGIN_POOL_SIZE // Recurse with a plugin from the pool, locking on it. // Keep trying with a delay until a timeout occurs. const int TIMEOUT = 5000, WAIT = 200; int64 startTime = Time::currentTimeMillis(); while (Time::currentTimeMillis() < startTime + TIMEOUT) { int i = 0; while ((plugin = pluginPool[i++])) { const ScopedTryLock pluginTryLock(plugin->crit); if (pluginTryLock.isLocked()) { DBG << "Handling with plugin " << i << endl; return handlePluginRequest(params, ostream, plugin); } } DBG << "Trying again in " << WAIT << endl; Thread::sleep(WAIT); } // If we were unable to obtain a lock, return failure. DBG << "Timeout" << endl; return false; #else ThreadSafePlugin temporaryPlugin(createSynthInstance()); return handlePluginRequest(params, ostream, &temporaryPlugin); #endif } else { // Re-acquire or acquire the lock. const ScopedLock pluginLock(plugin->crit); AudioPluginInstance *instance = plugin->instance; // unmanaged, for simplicity // Attempt to reset the plugin in all ways possible. instance->reset(); // Setting default parameters here causes miniTERA to become unresponsive to parameter settings. // It's possible that it's effectively pressing some interface buttons that change the editor mode entirely. // It's not necessary anyways if the plugin instance has been freshly created (see above). // pluginParametersOldNewFallback(instance, nullptr, &pluginDefaults); // note that the defaults may be empty instance->setCurrentProgram(0); // Load preset if specified, before listing or modifying parameters! if (params.presetNumber >= 0 && params.presetNumber < instance->getNumPrograms()) { DBG << "Setting program/preset: " << params.presetNumber << endl; instance->setCurrentProgram(params.presetNumber); } int currentProgram = instance->getCurrentProgram(); DBG << "Current program/preset: " << currentProgram << " - " << instance->getProgramName(currentProgram) << endl; // Set parameters, starting with named, then indexed pluginParametersSet(instance, params.parameters); pluginParametersSetIndexed(instance, params.indexedParameters); // If parameters requested, output them and return if (params.listParameters) { DBG << "Rendering parameter list: # parameters " << instance->getNumPrograms() << endl; // Output each parameter setting in two places: // an indexed array and a dictionary by name // All DynamicObjects created will be freed when their var's leave scope. DynamicObject *outer = new DynamicObject(); DynamicObject *innerParams = new DynamicObject(); var indexedParamVar; { for (int i = 0, n = instance->getNumParameters(); i < n; ++i) { String name = instance->getParameterName(i); float val = instance->getParameter(i); innerParams->setProperty(name, val); DynamicObject *indexedInnerObj = new DynamicObject(); indexedInnerObj->setProperty("index", i); indexedInnerObj->setProperty("name", name); indexedInnerObj->setProperty("value", val); indexedParamVar.append(var(indexedInnerObj)); // frees indexedInnerObj when this scope ends } } outer->setProperty(Identifier("parameters"), var(innerParams)); outer->setProperty(Identifier("indexedParameters"), indexedParamVar); // List presets/programs. var progVar; { for (int i = 0, n = instance->getNumPrograms(); i < n; ++i) { progVar.append(var(instance->getProgramName(i))); } } outer->setProperty(Identifier("presets"), progVar); var outerVar(outer); JSON::writeToStream(ostream, outerVar); // DBG << JSON::toString(outerVar, true /* allOnOneLine */) << endl; return true; } // Now attempt to render audio. AudioFormatManager formatManager; formatManager.registerBasicFormats(); OptionalScopedPointer<AudioFormat> outputFormat(formatManager.findFormatForFileExtension(params.getFormatName()), false); if (!outputFormat) return false; instance->setNonRealtime(true); instance->prepareToPlay(params.sampleRate, params.blockSize); instance->setNonRealtime(true); // The writer takes ownership of the output stream; the writer will delete it when the writer leaves scope. // Therefore, we pass a special pointer class that does not allow the writer to delete it. OutputStream *ostreamNonDeleting = new NonDeletingOutputStream(&ostream); ScopedPointer<AudioFormatWriter> writer(outputFormat->createWriterFor(ostreamNonDeleting, params.sampleRate, params.nChannels, params.bitDepth, StringPairArray(), 0)); // Create a MIDI buffer MidiBuffer midiBuffer; midiBuffer.addEvent(MidiMessage::noteOn(params.midiChannel, (uint8)params.midiPitch, (uint8)params.midiVelocity), 0 /* time */); midiBuffer.addEvent(MidiMessage::allNotesOff(params.midiChannel), params.noteSeconds * params.sampleRate); AudioSampleBuffer buffer(params.nChannels, params.blockSize); int numBuffers = (int)(params.renderSeconds * params.sampleRate / params.blockSize); for (int i = 0; i < numBuffers; ++i) { // DBG << "Processing block " << i << "..." << flush; instance->processBlock(buffer, midiBuffer); // DBG << " left RMS level " << buffer.getRMSLevel(0, 0, params.blockSize) << endl; writer->writeFromAudioSampleBuffer(buffer, 0 /* offset into buffer */, params.blockSize); } instance->reset(); return true; } }
void ManageMetronomeDialog::populate(int deviceIndex) { m_metronomeInstrument->clear(); DeviceList *devices = m_doc->getStudio().getDevices(); DeviceListConstIterator it; int count = 0; Device *dev = 0; for (it = devices->begin(); it != devices->end(); it++) { dev = *it; if (!isSuitable(dev)) continue; if (count == deviceIndex) break; count++; } // sanity if (count < 0 || dev == 0 || !isSuitable(dev)) { return ; } // populate instrument list InstrumentList list = dev->getPresentationInstruments(); InstrumentList::iterator iit; const MidiMetronome *metronome = getMetronome(dev); // if we've got no metronome against this device then create one if (metronome == 0) { InstrumentId id = SystemInstrumentBase; for (iit = list.begin(); iit != list.end(); ++iit) { if ((*iit)->isPercussion()) { id = (*iit)->getId(); break; } } setMetronome(dev, MidiMetronome(id)); metronome = getMetronome(dev); } // metronome should now be set but we still check it if (metronome) { int position = 0; int count = 0; for (iit = list.begin(); iit != list.end(); ++iit) { QString iname(QObject::tr((*iit)->getName().c_str())); QString ipname((*iit)->getLocalizedPresentationName()); QString programName(QObject::tr((*iit)->getProgramName().c_str())); QString text; if ((*iit)->getType() == Instrument::SoftSynth) { iname.replace(QObject::tr("Synth plugin "), ""); programName = ""; AudioPluginInstance *plugin = (*iit)->getPlugin (Instrument::SYNTH_PLUGIN_POSITION); if (plugin) programName = strtoqstr(plugin->getDisplayName()); } else { iname = ipname; } if (programName != "") { text = tr("%1 (%2)").arg(iname).arg(programName); } else { text = iname; } m_metronomeInstrument->addItem(text); if ((*iit)->getId() == metronome->getInstrument()) { position = count; } count++; } m_metronomeInstrument->setCurrentIndex(position); m_barPitch = metronome->getBarPitch(); m_beatPitch = metronome->getBeatPitch(); m_subBeatPitch = metronome->getSubBeatPitch(); slotPitchSelectorChanged(0); m_metronomeResolution->setCurrentIndex(metronome->getDepth()); m_metronomeBarVely->setValue(metronome->getBarVelocity()); m_metronomeBeatVely->setValue(metronome->getBeatVelocity()); m_metronomeSubBeatVely->setValue(metronome->getSubBeatVelocity()); m_playEnabled->setChecked(m_doc->getComposition().usePlayMetronome()); m_recordEnabled->setChecked(m_doc->getComposition().useRecordMetronome()); slotResolutionChanged(metronome->getDepth()); } }
void AudioPluginOSCGUIManager::dispatch() { if (!m_studio) return ; while (m_oscBuffer.getReadSpace() > 0) { OSCMessage *message = 0; m_oscBuffer.read(&message, 1); int instrument = message->getTarget(); int position = message->getTargetData(); PluginContainer *container = m_studio->getContainerById(instrument); if (!container) continue; AudioPluginInstance *pluginInstance = container->getPlugin(position); if (!pluginInstance) continue; AudioPluginOSCGUI *gui = 0; if (m_guis.find(instrument) == m_guis.end()) { RG_DEBUG << "AudioPluginOSCGUIManager: no GUI for instrument " << instrument << endl; } else if (m_guis[instrument].find(position) == m_guis[instrument].end()) { RG_DEBUG << "AudioPluginOSCGUIManager: no GUI for instrument " << instrument << ", position " << position << endl; } else { gui = m_guis[instrument][position]; } std::string method = message->getMethod(); char type; const lo_arg *arg; // These generally call back on the RosegardenMainWindow. We'd // like to emit signals, but making AudioPluginOSCGUIManager a // QObject is problematic if it's only conditionally compiled. if (method == "control") { if (message->getArgCount() != 2) { RG_DEBUG << "AudioPluginOSCGUIManager: wrong number of args (" << message->getArgCount() << ") for control method" << endl; goto done; } if (!(arg = message->getArg(0, type)) || type != 'i') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get port number" << endl; goto done; } int port = arg->i; if (!(arg = message->getArg(1, type)) || type != 'f') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get port value" << endl; goto done; } float value = arg->f; RG_DEBUG << "AudioPluginOSCGUIManager: setting port " << port << " to value " << value << endl; m_mainWindow->slotChangePluginPort(instrument, position, port, value); } else if (method == "program") { if (message->getArgCount() != 2) { RG_DEBUG << "AudioPluginOSCGUIManager: wrong number of args (" << message->getArgCount() << ") for program method" << endl; goto done; } if (!(arg = message->getArg(0, type)) || type != 'i') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get bank number" << endl; goto done; } int bank = arg->i; if (!(arg = message->getArg(1, type)) || type != 'i') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get program number" << endl; goto done; } int program = arg->i; QString programName = StudioControl::getPluginProgram (pluginInstance->getMappedId(), bank, program); m_mainWindow->slotChangePluginProgram(instrument, position, programName); } else if (method == "update") { if (message->getArgCount() != 1) { RG_DEBUG << "AudioPluginOSCGUIManager: wrong number of args (" << message->getArgCount() << ") for update method" << endl; goto done; } if (!(arg = message->getArg(0, type)) || type != 's') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get GUI URL" << endl; goto done; } QString url = &arg->s; if (!gui) { RG_DEBUG << "AudioPluginOSCGUIManager: no GUI for update method" << endl; goto done; } gui->setGUIUrl(url); for (AudioPluginInstance::ConfigMap::const_iterator i = pluginInstance->getConfiguration().begin(); i != pluginInstance->getConfiguration().end(); ++i) { QString key = strtoqstr(i->first); QString value = strtoqstr(i->second); #ifdef DSSI_PROJECT_DIRECTORY_KEY if (key == PluginIdentifier::RESERVED_PROJECT_DIRECTORY_KEY) { key = DSSI_PROJECT_DIRECTORY_KEY; } #endif RG_DEBUG << "update: configuration: " << key << " -> " << value << endl; gui->sendConfiguration(key, value); } unsigned long rv = StudioControl::getPluginProgram (pluginInstance->getMappedId(), strtoqstr(pluginInstance->getProgram())); int bank = rv >> 16; int program = rv - (bank << 16); gui->sendProgram(bank, program); int controlCount = 0; for (PortInstanceIterator i = pluginInstance->begin(); i != pluginInstance->end(); ++i) { gui->sendPortValue((*i)->number, (*i)->value); /* Avoid overloading the GUI if there are lots and lots of ports */ if (++controlCount % 50 == 0) usleep(300000); } gui->show(); } else if (method == "configure") { if (message->getArgCount() != 2) { RG_DEBUG << "AudioPluginOSCGUIManager: wrong number of args (" << message->getArgCount() << ") for configure method" << endl; goto done; } if (!(arg = message->getArg(0, type)) || type != 's') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get configure key" << endl; goto done; } QString key = &arg->s; if (!(arg = message->getArg(1, type)) || type != 's') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get configure value" << endl; goto done; } QString value = &arg->s; #ifdef DSSI_RESERVED_CONFIGURE_PREFIX if (key.startsWith(DSSI_RESERVED_CONFIGURE_PREFIX) || key == PluginIdentifier::RESERVED_PROJECT_DIRECTORY_KEY) { RG_DEBUG << "AudioPluginOSCGUIManager: illegal reserved configure call from gui: " << key << " -> " << value; goto done; } #endif RG_DEBUG << "AudioPluginOSCGUIManager: configure(" << key << "," << value << ")" << endl; m_mainWindow->slotChangePluginConfiguration(instrument, position, #ifdef DSSI_GLOBAL_CONFIGURE_PREFIX key.startsWith(DSSI_GLOBAL_CONFIGURE_PREFIX), #else false, #endif key, value); } else if (method == "midi") { if (message->getArgCount() != 1) { RG_DEBUG << "AudioPluginOSCGUIManager: wrong number of args (" << message->getArgCount() << ") for midi method" << endl; goto done; } if (!(arg = message->getArg(0, type)) || type != 'm') { RG_DEBUG << "AudioPluginOSCGUIManager: failed to get MIDI event" << endl; goto done; } RG_DEBUG << "AudioPluginOSCGUIManager: handling MIDI message"; // let's only handle note on and note off int eventCode = arg->m[1]; int eventType = eventCode & MIDI_MESSAGE_TYPE_MASK; if (eventType == MIDI_NOTE_ON || eventType == MIDI_NOTE_OFF) { MappedEvent ev(instrument, MappedEvent::MidiNote, MidiByte(arg->m[2]), MidiByte(arg->m[3]), RealTime::zeroTime, RealTime::zeroTime, RealTime::zeroTime); if (eventType == MIDI_NOTE_OFF) ev.setVelocity(0); StudioControl::sendMappedEvent(ev); } } else if (method == "exiting") { RG_DEBUG << "AudioPluginOSCGUIManager: GUI exiting"; stopGUI(instrument, position); m_mainWindow->slotPluginGUIExited(instrument, position); } else { RG_DEBUG << "AudioPluginOSCGUIManager: unknown method " << method; } done: delete message; }
void TrackParameterBox::updateInstrument(const Instrument *instrument) { // As with the Device field above, this will rarely change and it is // expensive to clear and reload. So, we should cache enough info to // detect a real change. This would be Instrument names and IDs. const DeviceId deviceId = instrument->getDevice()->getId(); const Device &device = *(m_doc->getStudio().getDevice(deviceId)); const InstrumentList instrumentList = device.getPresentationInstruments(); // Generate local instrument name and ID lists to compare against the // members. std::vector<InstrumentId> instrumentIds; std::vector<QString> instrumentNames; // For each instrument for (size_t instrumentIndex = 0; instrumentIndex < instrumentList.size(); ++instrumentIndex) { const Instrument &loopInstrument = *(instrumentList[instrumentIndex]); instrumentIds.push_back(loopInstrument.getId()); QString instrumentName(QObject::tr(loopInstrument.getName().c_str())); QString programName( QObject::tr(loopInstrument.getProgramName().c_str())); if (loopInstrument.getType() == Instrument::SoftSynth) { instrumentName.replace(QObject::tr("Synth plugin"), ""); programName = ""; AudioPluginInstance *plugin = instrument->getPlugin(Instrument::SYNTH_PLUGIN_POSITION); if (plugin) programName = strtoqstr(plugin->getDisplayName()); } if (programName != "") instrumentName += " (" + programName + ")"; // cut off the redundant eg. "General MIDI Device" that appears in the // combo right above here anyway instrumentName = instrumentName.mid( instrumentName.indexOf("#"), instrumentName.length()); instrumentNames.push_back(instrumentName); } // If there has been an actual change if (instrumentIds != m_instrumentIds2 || instrumentNames != m_instrumentNames2) { // Update the cache. m_instrumentIds2 = instrumentIds; m_instrumentNames2 = instrumentNames; // Reload the combobox m_instrument->clear(); // For each instrument, add the name to the combobox. // ??? If we used a QStringList, we could just call addItems(). for (size_t instrumentIndex = 0; instrumentIndex < m_instrumentNames2.size(); ++instrumentIndex) { m_instrument->addItem(m_instrumentNames2[instrumentIndex]); } } // Find the current instrument in the instrument ID list. const InstrumentId instrumentId = instrument->getId(); // Assume not found. int currentIndex = -1; // For each Instrument for (size_t instrumentIndex = 0; instrumentIndex < m_instrumentIds2.size(); ++instrumentIndex) { // If this is the selected Instrument if (m_instrumentIds2[instrumentIndex] == instrumentId) { currentIndex = instrumentIndex; break; } } // Set the index. m_instrument->setCurrentIndex(currentIndex); }
virtual void menuItemSelected(int menuItemID, int) { if (menuItemID == 200) { WildcardFileFilter wildcardFilter("*.mid", String::empty, "Midi files"); FileBrowserComponent browser(FileBrowserComponent::canSelectFiles | FileBrowserComponent::openMode, lastOpenedFile.exists() ? lastOpenedFile : File(String("C:\\Users\\GeorgeKrueger\\Documents")), &wildcardFilter, nullptr); FileChooserDialogBox dialogBox("Open a midi file", "Please choose a midi file to open...", browser, false, Colours::lightgrey); if (dialogBox.show()) { File selectedFile = browser.getSelectedFile(0); lastOpenedFile = selectedFile; FileInputStream fileStream(selectedFile); juce::MidiFile midiFile; midiFile.readFrom(fileStream); int numTracks = midiFile.getNumTracks(); midiFile.convertTimestampTicksToSeconds(); String msg; msg << "Opened midi file: " << selectedFile.getFileName() << " Tracks: " << numTracks << "\n"; log(msg); for (int i = 0; i < numTracks; ++i) { const MidiMessageSequence* msgSeq = midiFile.getTrack(i); OwnedArray<PluginDescription> results; String plugFile = "C:\\VST\\FMMF.dll"; VSTPluginFormat vstFormat; vstFormat.findAllTypesForFile(results, plugFile); if (results.size() > 0) { msg.clear(); msg << "Found " << results.size() << " plugin(s) matching file " << plugFile << "\n"; log(msg); int secsToRender = 10; double sampleRate = 44100; int totalSizeInSamples = static_cast<int>(44100 * secsToRender); AudioPluginInstance* plugInst = vstFormat.createInstanceFromDescription(*results[0], sampleRate, totalSizeInSamples); if (!plugInst) { msg.clear(); msg << "Failed to load plugin " << plugFile << "\n"; log(msg); continue; } int numInputChannels = plugInst->getTotalNumInputChannels(); int numOutputChannels = plugInst->getTotalNumOutputChannels(); msg.clear(); msg << "Plugin input channels: " << numInputChannels << " output channels: " << numOutputChannels << " Current program: " << plugInst->getCurrentProgram() << "\n"; log(msg); int maxChannels = std::max(numInputChannels, numOutputChannels); AudioBuffer<float> buffer(maxChannels, totalSizeInSamples); MidiBuffer midiMessages; for (int j = 0; j < msgSeq->getNumEvents(); ++j) { MidiMessageSequence::MidiEventHolder* midiEventHolder = msgSeq->getEventPointer(j); MidiMessage midiMsg = midiEventHolder->message; int samplePos = static_cast<int>(midiMsg.getTimeStamp() * sampleRate); midiMessages.addEvent(midiMsg, samplePos); } plugInst->prepareToPlay(sampleRate, totalSizeInSamples); plugInst->processBlock(buffer, midiMessages); /*File txtOutFile("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\soundserver2\\out.txt"); FileOutputStream* txtOutStream = txtOutFile.createOutputStream(); for (int j = 0; j < 44100; ++j) { float sample = buffer.getSample(0, j); txtOutStream->writeFloat(sample); txtOutStream->writeText(" ", true, false); }*/ File outputFile("C:\\Users\\GeorgeKrueger\\Documents\\GitHub\\soundserver2\\out.wav"); if (outputFile.exists()) { outputFile.deleteFile(); } FileOutputStream* fileOutputStream = outputFile.createOutputStream(); WavAudioFormat wavFormat; StringPairArray metadataValues; juce::AudioFormatWriter* wavFormatWriter = wavFormat.createWriterFor( fileOutputStream, sampleRate, 2, 16, metadataValues, 0); bool writeAudioDataRet = wavFormatWriter->writeFromAudioSampleBuffer(buffer, 0, buffer.getNumSamples()); wavFormatWriter->flush(); msg.clear(); msg << "Done writing to output file " << outputFile.getFileName() << " . Write return value: " << (int)writeAudioDataRet << "\n"; log(msg); delete wavFormatWriter; delete plugInst; } else { msg.clear(); msg << "Could not find plugin from file " << plugFile << "\n"; log(msg); } } } } }
// ??? Break this stuff off into an InstrumentPopup class. This class is too // big. void TrackButtons::populateInstrumentPopup(Instrument *thisTrackInstr, QMenu* instrumentPopup) { // pixmaps for icons to show connection states as variously colored boxes // ??? Factor out the icon-related stuff to make this routine clearer. // getIcon(Instrument *) would be ideal, but might not be easy. // getIcon(Device *) would also be needed. static QPixmap connectedPixmap, unconnectedPixmap, connectedUsedPixmap, unconnectedUsedPixmap, connectedSelectedPixmap, unconnectedSelectedPixmap; static bool havePixmaps = false; if (!havePixmaps) { IconLoader il; connectedPixmap = il.loadPixmap("connected"); connectedUsedPixmap = il.loadPixmap("connected-used"); connectedSelectedPixmap = il.loadPixmap("connected-selected"); unconnectedPixmap = il.loadPixmap("unconnected"); unconnectedUsedPixmap = il.loadPixmap("unconnected-used"); unconnectedSelectedPixmap = il.loadPixmap("unconnected-selected"); havePixmaps = true; } Composition &comp = m_doc->getComposition(); // clear the popup instrumentPopup->clear(); QMenu *currentSubMenu = 0; // position index int count = 0; int currentDevId = -1; // Get the list Studio &studio = m_doc->getStudio(); InstrumentList list = studio.getPresentationInstruments(); // For each instrument for (InstrumentList::iterator it = list.begin(); it != list.end(); ++it) { if (!(*it)) continue; // sanity check // get the Localized instrument name, with the string hackery performed // in Instrument QString iname((*it)->getLocalizedPresentationName()); // translate the program name // // Note we are converting the string from std to Q back to std then to // C. This is obviously ridiculous, but the fact that we have programName // here at all makes me think it exists as some kind of necessary hack // to coax tr() into behaving nicely. I decided to change it as little // as possible to get it to compile, and not refactor this down to the // simplest way to call tr() on a C string. QString programName(strtoqstr((*it)->getProgramName())); programName = QObject::tr(programName.toStdString().c_str()); Device *device = (*it)->getDevice(); DeviceId devId = device->getId(); bool connectedIcon = false; // Determine the proper program name and whether it is connected if ((*it)->getType() == Instrument::SoftSynth) { programName = ""; AudioPluginInstance *plugin = (*it)->getPlugin(Instrument::SYNTH_PLUGIN_POSITION); if (plugin) { // we don't translate any plugin program names or other texts programName = strtoqstr(plugin->getDisplayName()); connectedIcon = (plugin->getIdentifier() != ""); } } else if ((*it)->getType() == Instrument::Audio) { connectedIcon = true; } else { QString conn = RosegardenSequencer::getInstance()-> getConnection(devId); connectedIcon = (conn != ""); } // These two are for selecting the correct icon to display. bool instrUsedByMe = false; bool instrUsedByAnyone = false; if (thisTrackInstr && thisTrackInstr->getId() == (*it)->getId()) { instrUsedByMe = true; instrUsedByAnyone = true; } // If we have switched to a new device, we'll create a new submenu if (devId != (DeviceId)(currentDevId)) { currentDevId = int(devId); // For selecting the correct icon to display. bool deviceUsedByAnyone = false; if (instrUsedByMe) deviceUsedByAnyone = true; else { for (Composition::trackcontainer::iterator tit = comp.getTracks().begin(); tit != comp.getTracks().end(); ++tit) { if (tit->second->getInstrument() == (*it)->getId()) { instrUsedByAnyone = true; deviceUsedByAnyone = true; break; } Instrument *instr = studio.getInstrumentById(tit->second->getInstrument()); if (instr && (instr->getDevice()->getId() == devId)) { deviceUsedByAnyone = true; } } } QIcon icon (connectedIcon ? (deviceUsedByAnyone ? connectedUsedPixmap : connectedPixmap) : (deviceUsedByAnyone ? unconnectedUsedPixmap : unconnectedPixmap)); // Create a submenu for this device QMenu *subMenu = new QMenu(instrumentPopup); subMenu->setMouseTracking(true); subMenu->setIcon(icon); // Not needed so long as AA_DontShowIconsInMenus is false. //subMenu->menuAction()->setIconVisibleInMenu(true); // Menu title QString deviceName = QObject::tr(device->getName().c_str()); subMenu->setTitle(deviceName); // QObject name subMenu->setObjectName(deviceName); // Add the submenu to the popup menu instrumentPopup->addMenu(subMenu); // Connect the submenu to slotInstrumentSelected() connect(subMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotInstrumentSelected(QAction*))); currentSubMenu = subMenu; } else if (!instrUsedByMe) {