/** This function processes all the change requests to remove all the the redundant ones, and to tell what kind of initialization must be done. Depending on the results, the convolution engines might be reset, or simply updated, or they might not need any change at all. */ void processFifo() { if (getNumRemainingEntries() == 0 || isThreadRunning() || mustInterpolate) return; // retrieve the information from the FIFO for processing Array<ChangeRequest> requests; Array<juce::var> requestParameters; while (getNumRemainingEntries() > 0) { ChangeRequest type = ChangeRequest::changeEngine; juce::var parameter; readFromFifo (type, parameter); requests.add (type); requestParameters.add (parameter); } // remove any useless messages for (int i = 0; i < (int) ChangeRequest::numChangeRequestTypes; ++i) { bool exists = false; for (int n = requests.size(); --n >= 0;) { if (requests[n] == (ChangeRequest) i) { if (! exists) { exists = true; } else { requests.remove (n); requestParameters.remove (n); } } } } changeLevel = 0; for (int n = 0; n < requests.size(); ++n) { switch (requests[n]) { case ChangeRequest::changeEngine: changeLevel = 3; break; case ChangeRequest::changeSampleRate: { double newSampleRate = requestParameters[n]; if (currentInfo.sampleRate != newSampleRate) changeLevel = 3; currentInfo.sampleRate = newSampleRate; } break; case ChangeRequest::changeMaximumBufferSize: { int newMaximumBufferSize = requestParameters[n]; if (currentInfo.maximumBufferSize != (size_t) newMaximumBufferSize) changeLevel = 3; currentInfo.maximumBufferSize = (size_t) newMaximumBufferSize; } break; case ChangeRequest::changeSource: { auto* arrayParameters = requestParameters[n].getArray(); auto newSourceType = static_cast<SourceType> (static_cast<int> (arrayParameters->getUnchecked (0))); if (currentInfo.sourceType != newSourceType) changeLevel = jmax (2, changeLevel); if (newSourceType == SourceType::sourceBinaryData) { auto& prm = arrayParameters->getRawDataPointer()[1]; auto* newMemoryBlock = prm.getBinaryData(); auto* newPtr = newMemoryBlock->getData(); auto newSize = newMemoryBlock->getSize(); if (currentInfo.sourceData != newPtr || currentInfo.sourceDataSize != newSize) changeLevel = jmax (2, changeLevel); currentInfo.sourceType = SourceType::sourceBinaryData; currentInfo.sourceData = newPtr; currentInfo.sourceDataSize = newSize; currentInfo.fileImpulseResponse = File(); } else if (newSourceType == SourceType::sourceAudioFile) { File newFile (arrayParameters->getUnchecked (1).toString()); if (currentInfo.fileImpulseResponse != newFile) changeLevel = jmax (2, changeLevel); currentInfo.sourceType = SourceType::sourceAudioFile; currentInfo.fileImpulseResponse = newFile; currentInfo.sourceData = nullptr; currentInfo.sourceDataSize = 0; } else if (newSourceType == SourceType::sourceAudioBuffer) { double bufferSampleRate (arrayParameters->getUnchecked (1)); changeLevel = jmax (2, changeLevel); currentInfo.sourceType = SourceType::sourceAudioBuffer; currentInfo.bufferSampleRate = bufferSampleRate; currentInfo.fileImpulseResponse = File(); currentInfo.sourceData = nullptr; currentInfo.sourceDataSize = 0; } } break; case ChangeRequest::changeImpulseResponseSize: { int64 newSize = requestParameters[n]; if (currentInfo.impulseResponseSize != (size_t) newSize) changeLevel = jmax (1, changeLevel); currentInfo.impulseResponseSize = (size_t) newSize; } break; case ChangeRequest::changeStereo: { bool newWantsStereo = requestParameters[n]; if (currentInfo.wantsStereo != newWantsStereo) changeLevel = jmax (1, changeLevel); currentInfo.wantsStereo = newWantsStereo; } break; case ChangeRequest::changeTrimming: { bool newWantsTrimming = requestParameters[n]; if (currentInfo.wantsTrimming != newWantsTrimming) changeLevel = jmax(1, changeLevel); currentInfo.wantsTrimming = newWantsTrimming; } break; default: jassertfalse; break; } } if (currentInfo.sourceType == SourceType::sourceNone) { currentInfo.sourceType = SourceType::sourceAudioBuffer; if (currentInfo.sampleRate == 0) currentInfo.sampleRate = 44100; if (currentInfo.maximumBufferSize == 0) currentInfo.maximumBufferSize = 128; currentInfo.bufferSampleRate = currentInfo.sampleRate; currentInfo.impulseResponseSize = 1; currentInfo.fileImpulseResponse = File(); currentInfo.sourceData = nullptr; currentInfo.sourceDataSize = 0; AudioBuffer<float> newBuffer; newBuffer.setSize (1, 1); newBuffer.setSample (0, 0, 1.f); copyBufferToTemporaryLocation (newBuffer); } // action depending on the change level if (changeLevel == 3) { interpolationBuffer.setSize (2, static_cast<int> (currentInfo.maximumBufferSize)); processImpulseResponse(); initializeConvolutionEngines(); } else if (changeLevel == 2) { startThread(); } else if (changeLevel == 1) { startThread(); } }
void SignalChainManager::updateVisibleEditors(GenericEditor* activeEditor, int index, int insertionPoint, int action) { enum actions {ADD, MOVE, REMOVE, ACTIVATE, UPDATE}; // Step 1: update the editor array if (action == ADD) { //std::cout << " Adding editor." << std::endl; editorArray.insert(insertionPoint, activeEditor); } else if (action == MOVE) { // std::cout << " Moving editors." << std::endl; if (insertionPoint < index) editorArray.move(index, insertionPoint); else if (insertionPoint > index) editorArray.move(index, insertionPoint-1); } else if (action == REMOVE) { // std::cout << " Removing editor." << std::endl; GenericProcessor* p = (GenericProcessor*) editorArray[index]->getProcessor(); // GenericProcessor* source = p->getSourceNode(); if (p->getSourceNode() != nullptr) if (p->getSourceNode()->isSplitter()) p->getSourceNode()->setSplitterDestNode(nullptr); // if the processor to be removed is a merger, // we need to inform the other source that its merger has disappeared if (p->isMerger()) { p->switchIO(); if (p->getSourceNode() != nullptr) p->getSourceNode()->setDestNode(nullptr); } // if the processor to be removed is a splitter, we need to make sure // there aren't any orphaned processors if (p->isSplitter()) { p->switchIO(0); if (p->getDestNode() != nullptr) { // std::cout << "Found an orphaned signal chain" << std::endl; p->getDestNode()->setSourceNode(nullptr); createNewTab(p->getDestNode()->getEditor()); } p->switchIO(1); if (p->getDestNode() != nullptr) { // std::cout << "Found an orphaned signal chain" << std::endl; p->getDestNode()->setSourceNode(nullptr); createNewTab(p->getDestNode()->getEditor()); } } editorArray.remove(index); int t = activeEditor->tabNumber(); // std::cout << editorArray.size() << " " << t << std::endl; bool merger; if (editorArray.size() > 0) { // take the next processor in the array GenericProcessor* p2 = (GenericProcessor*) editorArray[0]->getProcessor(); merger = (p2->isMerger() && p2->stillHasSource()); if (merger) { // std::cout << "We've got a merger!" << std::endl; //p2->switchIO(0); p2->setMergerSourceNode(p->getSourceNode()); MergerEditor* me = (MergerEditor*) editorArray[0]; me->switchSource(); // p2->setMergerSourceNode(nullptr); } } if (editorArray.size() > 0 && !merger) // if there are still editors in this chain { if (t > -1) // pass on tab { // std::cout << "passing on the tab." << std::endl; int nextEditor = jmax(0,0);//index-1); editorArray[nextEditor]->tabNumber(t); signalChainArray[t]->setEditor(editorArray[nextEditor]); } int nextEditor = jmin(index,editorArray.size()-1); activeEditor = editorArray[nextEditor]; activeEditor->select(); //activeEditor->grabKeyboardFocus(); } else { // std::cout << "Tab number " << t << std::endl; removeTab(t); if (signalChainArray.size() > 0) // if there are other chains { int nextTab = jmin(t,signalChainArray.size()-1); activeEditor = signalChainArray[nextTab]->getEditor(); activeEditor->select(); signalChainArray[nextTab]->setToggleState(true, dontSendNotification); // send it back to update connections } else { activeEditor = 0; // nothing is active // signalChainNeedsSource = true; } } } else //no change { // std::cout << "Activating editor" << std::endl; } // Step 2: update connections if (action != ACTIVATE && action != UPDATE && editorArray.size() > 0) { // std::cout << "Updating connections." << std::endl; GenericProcessor* source = 0; GenericProcessor* dest = (GenericProcessor*) editorArray[0]->getProcessor(); dest->setSourceNode(source); for (int n = 1; n < editorArray.size(); n++) { dest = (GenericProcessor*) editorArray[n]->getProcessor(); source = (GenericProcessor*) editorArray[n-1]->getProcessor(); dest->setSourceNode(source); } dest->setDestNode(0); } // Step 3: check for new tabs if (action != ACTIVATE && action != UPDATE) { // std::cout << "Checking for new tabs." << std::endl; for (int n = 0; n < editorArray.size(); n++) { GenericProcessor* p = (GenericProcessor*) editorArray[n]->getProcessor(); if (p->getSourceNode() == 0)// && editorArray[n]->tabNumber() == -1) { if (editorArray[n]->tabNumber() == -1) { if (!p->isMerger()) { // std::cout << p->getName() << " has no source node. Creating a new tab." << std::endl; createNewTab(editorArray[n]); } } } else { if (editorArray[n]->tabNumber() > -1) { removeTab(editorArray[n]->tabNumber()); } editorArray[n]->tabNumber(-1); // reset tab status } if (p->isMerger()) { // std::cout << "It's a merger!" << std::endl; //createNewTab(editorArray[n]); } } } // Step 4: Refresh editors in editor array, based on active editor for (int n = 0; n < editorArray.size(); n++) { editorArray[n]->setVisible(false); } editorArray.clear(); // std::cout << "Cleared editor array." << std::endl; GenericEditor* editorToAdd = activeEditor; while (editorToAdd != 0) { // std::cout << "Inserting " << editorToAdd->getName() << " at point 0." << std::endl; editorArray.insert(0,editorToAdd); GenericProcessor* currentProcessor = (GenericProcessor*) editorToAdd->getProcessor(); GenericProcessor* source = currentProcessor->getSourceNode(); if (source != nullptr) { // std::cout << "Source: " << source->getName() << std::endl; // need to switch the splitter somehow if (action == ACTIVATE || action == UPDATE) { if (source->isSplitter()) { source->setPathToProcessor(currentProcessor); } } editorToAdd = (GenericEditor*) source->getEditor(); } else { if (editorToAdd->tabNumber() >= 0 && editorToAdd->tabNumber() < signalChainArray.size()) signalChainArray[editorToAdd->tabNumber()]->setToggleState(true, dontSendNotification); // std::cout << "No source found." << std::endl; editorToAdd = 0; } } editorToAdd = activeEditor; while (editorToAdd != 0) { GenericProcessor* currentProcessor = (GenericProcessor*) editorToAdd->getProcessor(); GenericProcessor* dest = currentProcessor->getDestNode(); if (dest != 0) { // std::cout << "Destination: " << dest->getName() << std::endl; editorToAdd = (GenericEditor*) dest->getEditor(); editorArray.add(editorToAdd); // std::cout << "Inserting " << editorToAdd->getName() << " at the end." << std::endl; if (dest->isMerger()) { // std::cout << "It's a merger!" << std::endl; editorToAdd->switchIO(0); if (dest->getSourceNode() != currentProcessor) editorToAdd->switchIO(1); } } else { // std::cout << "No dest found." << std::endl; editorToAdd = 0; } } // Step 5: check the validity of the signal chain if (true) { //action != ACTIVATE) { bool enable = true; if (editorArray.size() == 1) { GenericProcessor* source = (GenericProcessor*) editorArray[0]->getProcessor(); if (source->isSource()) editorArray[0]->setEnabledState(true); else editorArray[0]->setEnabledState(false); } else { for (int n = 0; n < editorArray.size()-1; n++) { GenericProcessor* source = (GenericProcessor*) editorArray[n]->getProcessor(); GenericProcessor* dest = (GenericProcessor*) editorArray[n+1]->getProcessor(); if (n == 0 && !source->isSource()) enable = false; editorArray[n]->setEnabledState(enable); if (source->canSendSignalTo(dest) && source->enabledState()) enable = true; else enable = false; if (source->isSplitter()) { if (source->getDestNode() != dest) { //source->switchIO(); editorArray[n]->switchDest(); } } // if (enable) // std::cout << "Enabling node." << std::endl; // else // std::cout << "Not enabling node." << std::endl; editorArray[n+1]->setEnabledState(enable); } } } // Step 6: inform the tabs that something has changed for (int n = 0; n < signalChainArray.size(); n++) { if (signalChainArray[n]->getToggleState()) { signalChainArray[n]->hasNewConnections(true); } } // Step 7: update all settings if (action != ACTIVATE) { // std::cout << "Updating settings." << std::endl; Array<GenericProcessor*> splitters; for (int n = 0; n < signalChainArray.size(); n++) { // iterate through signal chains GenericEditor* source = signalChainArray[n]->getEditor(); GenericProcessor* p = source->getProcessor(); // p->update(); // GenericProcessor* dest = p->getDestNode(); while (p != 0) { // iterate through processors p->update(); if (p->isSplitter()) { splitters.add(p); } p = p->getDestNode(); if (p == 0 && splitters.size() > 0) { splitters.getFirst()->switchIO(); // switch the signal chain p = splitters[0]->getDestNode(); splitters.getFirst()->switchIO(); // switch it back splitters.remove(0); } } } } // std::cout << "Finished adding new editor." << std::endl << std::endl << std::endl; }
void ProcessorGraph::updateConnections(Array<SignalChainTabButton*, CriticalSection> tabs) { clearConnections(); // clear processor graph std::cout << "Updating connections:" << std::endl; std::cout << std::endl; std::cout << std::endl; Array<GenericProcessor*> splitters; // GenericProcessor* activeSplitter = nullptr; for (int n = 0; n < tabs.size(); n++) // cycle through the tabs { std::cout << "Signal chain: " << n << std::endl; std::cout << std::endl; GenericEditor* sourceEditor = (GenericEditor*) tabs[n]->getEditor(); GenericProcessor* source = (GenericProcessor*) sourceEditor->getProcessor(); while (source != nullptr)// && destEditor->isEnabled()) { std::cout << "Source node: " << source->getName() << "." << std::endl; GenericProcessor* dest = (GenericProcessor*) source->getDestNode(); if (source->isEnabledState()) { // add the connections to audio and record nodes if necessary if (!(source->isSink() || source->isSplitter() || source->isMerger() || source->isUtility()) && !(source->wasConnected)) { std::cout << " Connecting to audio and record nodes." << std::endl; connectProcessorToAudioAndRecordNodes(source); } else { std::cout << " NOT connecting to audio and record nodes." << std::endl; } if (dest != nullptr) { while (dest->isMerger()) // find the next dest that's not a merger { dest = dest->getDestNode(); if (dest == nullptr) break; } if (dest != nullptr) { while (dest->isSplitter()) { if (!dest->wasConnected) { if (!splitters.contains(dest)) { splitters.add(dest); dest->switchIO(0); // go down first path } else { int splitterIndex = splitters.indexOf(dest); splitters.remove(splitterIndex); dest->switchIO(1); // go down second path dest->wasConnected = true; // make sure we don't re-use this splitter } } dest = dest->getDestNode(); if (dest == nullptr) break; } if (dest != nullptr) { if (dest->isEnabledState()) { connectProcessors(source, dest); } } } else { std::cout << " No dest node." << std::endl; } } else { std::cout << " No dest node." << std::endl; } } std::cout << std::endl; source->wasConnected = true; source = dest; // switch source and dest if (source == nullptr && splitters.size() > 0) { source = splitters.getLast(); GenericProcessor* newSource;// = source->getSourceNode(); while (source->isSplitter() || source->isMerger()) { newSource = source->getSourceNode(); newSource->setPathToProcessor(source); source = newSource; } } } // end while source != 0 } // end "tabs" for loop //Update RecordNode internal channel mappings Array<EventChannel*> extraChannels; getMessageCenter()->addSpecialProcessorChannels(extraChannels); getRecordNode()->addSpecialProcessorChannels(extraChannels); } // end method
void ScriptDebuggerRemote::debug(ScriptLanguage *p_script,bool p_can_continue) { if (!tcp_client->is_connected()) { ERR_EXPLAIN("Script Debugger failed to connect, but being used anyway."); ERR_FAIL(); } packet_peer_stream->put_var("debug_enter"); packet_peer_stream->put_var(2); packet_peer_stream->put_var(p_can_continue); packet_peer_stream->put_var(p_script->debug_get_error()); while(true) { _get_output(); if (packet_peer_stream->get_available_packet_count()>0) { Variant var; Error err = packet_peer_stream->get_var(var); ERR_CONTINUE( err != OK); ERR_CONTINUE( var.get_type()!=Variant::ARRAY ); Array cmd = var; ERR_CONTINUE( cmd.size()==0); ERR_CONTINUE( cmd[0].get_type()!=Variant::STRING ); String command = cmd[0]; if (command=="get_stack_dump") { packet_peer_stream->put_var("stack_dump"); int slc = p_script->debug_get_stack_level_count(); packet_peer_stream->put_var( slc ); for(int i=0;i<slc;i++) { Dictionary d; d["file"]=p_script->debug_get_stack_level_source(i); d["line"]=p_script->debug_get_stack_level_line(i); d["function"]=p_script->debug_get_stack_level_function(i); //d["id"]=p_script->debug_get_stack_level_ d["id"]=0; packet_peer_stream->put_var( d ); } } else if (command=="get_stack_frame_vars") { cmd.remove(0); ERR_CONTINUE( cmd.size()!=1 ); int lv = cmd[0]; List<String> members; List<Variant> member_vals; p_script->debug_get_stack_level_members(lv,&members,&member_vals); ERR_CONTINUE( members.size() !=member_vals.size() ); List<String> locals; List<Variant> local_vals; p_script->debug_get_stack_level_locals(lv,&locals,&local_vals); ERR_CONTINUE( locals.size() !=local_vals.size() ); packet_peer_stream->put_var("stack_frame_vars"); packet_peer_stream->put_var(2+locals.size()*2+members.size()*2); { //members packet_peer_stream->put_var(members.size()); List<String>::Element *E=members.front(); List<Variant>::Element *F=member_vals.front(); while(E) { if (F->get().get_type()==Variant::OBJECT) { packet_peer_stream->put_var("*"+E->get()); packet_peer_stream->put_var(safe_get_instance_id(F->get())); } else { packet_peer_stream->put_var(E->get()); packet_peer_stream->put_var(F->get()); } E=E->next(); F=F->next(); } } { //locals packet_peer_stream->put_var(locals.size()); List<String>::Element *E=locals.front(); List<Variant>::Element *F=local_vals.front(); while(E) { if (F->get().get_type()==Variant::OBJECT) { packet_peer_stream->put_var("*"+E->get()); packet_peer_stream->put_var(safe_get_instance_id(F->get())); } else { packet_peer_stream->put_var(E->get()); packet_peer_stream->put_var(F->get()); } E=E->next(); F=F->next(); } } } else if (command=="step") { set_depth(-1); set_lines_left(1); break; } else if (command=="next") { set_depth(0); set_lines_left(1); break; } else if (command=="continue") { set_depth(-1); set_lines_left(-1); break; } else if (command=="break") { ERR_PRINT("Got break when already broke!"); break; } else if (command=="request_scene_tree") { if (request_scene_tree) request_scene_tree(request_scene_tree_ud); } else if (command=="request_video_mem") { _send_video_memory(); } else if (command=="breakpoint") { bool set = cmd[3]; if (set) insert_breakpoint(cmd[2],cmd[1]); else remove_breakpoint(cmd[2],cmd[1]); } else { _parse_live_edit(cmd); } } else { OS::get_singleton()->delay_usec(10000); } } packet_peer_stream->put_var("debug_exit"); packet_peer_stream->put_var(0); }