/** 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
Example #4
0
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);

}