From ddb0bfbf9d576062b90a7349b9687269ee12a990 Mon Sep 17 00:00:00 2001
From: jsiegle <jsiegle@mit.edu>
Date: Sun, 19 Jan 2014 14:54:42 -0500
Subject: [PATCH] Update ChannelMappingNode from spikesorting version

---
 Source/Processors/ChannelMappingNode.cpp      |  54 ++--
 Source/Processors/ChannelMappingNode.h        |   1 +
 .../Editors/ChannelMappingEditor.cpp          | 271 ++++++++++++++----
 .../Processors/Editors/ChannelMappingEditor.h |  17 +-
 Source/Processors/Editors/ChannelSelector.cpp |  23 +-
 Source/Processors/Editors/ChannelSelector.h   |   3 +
 6 files changed, 279 insertions(+), 90 deletions(-)

diff --git a/Source/Processors/ChannelMappingNode.cpp b/Source/Processors/ChannelMappingNode.cpp
index ad738cad3..bff623d80 100644
--- a/Source/Processors/ChannelMappingNode.cpp
+++ b/Source/Processors/ChannelMappingNode.cpp
@@ -64,17 +64,34 @@ AudioProcessorEditor* ChannelMappingNode::createEditor()
 
 void ChannelMappingNode::updateSettings()
 {
+	int j;
 	if (getNumInputs() > 0)
 		channelBuffer.setSize(getNumInputs(), 10000);
 
 	if (getNumInputs() != previousChannelCount)
 	{
 		previousChannelCount = getNumInputs();
+		if (editorIsConfigured)
+		{
+			j = 0;
+			for (int i = 0; i < getNumInputs(); i++)
+			{
+				if (enabledChannelArray[i])
+				{
+					j++;
+				}
+				else
+				{
+					channels.remove(j);
+				}
+			}
+			settings.numOutputs = j;
+		}
 	}
 	else
 	{
-		int j=0;
-		for (int i=0; i < getNumInputs(); i++)
+		j = 0;
+		for (int i = 0; i < getNumInputs(); i++)
 		{
 			if (enabledChannelArray[i])
 			{
@@ -106,6 +123,10 @@ void ChannelMappingNode::setParameter(int parameterIndex, float newValue)
 	{
 		enabledChannelArray.set(currentChannel, (newValue != 0) ? true : false);
 	}
+	else if (parameterIndex == 4)
+	{
+		editorIsConfigured = (newValue != 0) ? true : false;
+	}
 	else
 	{
 		channelArray.set(currentChannel, (int) newValue);
@@ -118,40 +139,33 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer,
 								 int& nSamples)
 {
 	int j=0;
+	int i=0;
+	int realChan;
 
 	// use copy constructor to set the data to refer to
 	channelBuffer = buffer;
 
-	// copy it back into the buffer according to the channel mapping
 	buffer.clear();
 
-	for (int i = 0; i < buffer.getNumChannels(); i++)
+	while (j < settings.numOutputs)
 	{
-		if (enabledChannelArray[channelArray[i]])
+		realChan = channelArray[i];
+		if ((realChan < channelBuffer.getNumChannels()) && (enabledChannelArray[realChan]))
 		{
+			// copy it back into the buffer according to the channel mapping
 			buffer.addFrom(j, // destChannel
 				0, // destStartSample
 				channelBuffer, // source
-				channelArray[i], // sourceChannel
+				realChan, // sourceChannel
 				0, // sourceStartSample
 				nSamples, // numSamples
 				1.0f // gain to apply to source (positive for original signal)
 				);
-			j++;
-		}
-
-	}
 
-	j=0;
-	// now do the referencing
-	for (int i = 0; i < buffer.getNumChannels(); i++)
-	{
-		int realChan = channelArray[i];
-		if (enabledChannelArray[realChan])
-		{
-			if ((referenceArray[realChan] > -1) && referenceChannels[referenceArray[realChan]] > -1)
+			// now do the referencing
+			if ((referenceArray[realChan] > -1) && (referenceChannels[referenceArray[realChan]] > -1)
+				&& (referenceChannels[referenceArray[realChan]] < channelBuffer.getNumChannels()))
 			{
-
 				buffer.addFrom(j, // destChannel
 					0, // destStartSample
 					channelBuffer, // source
@@ -163,6 +177,8 @@ void ChannelMappingNode::process(AudioSampleBuffer& buffer,
 			}
 			j++;
 		}
+		i++;
+
 	}
 
 }
diff --git a/Source/Processors/ChannelMappingNode.h b/Source/Processors/ChannelMappingNode.h
index 2a9fc159b..3de6d7775 100644
--- a/Source/Processors/ChannelMappingNode.h
+++ b/Source/Processors/ChannelMappingNode.h
@@ -70,6 +70,7 @@ private:
 	Array<bool> enabledChannelArray;
 
 	int previousChannelCount;
+	bool editorIsConfigured;
 
     AudioSampleBuffer channelBuffer;
 
diff --git a/Source/Processors/Editors/ChannelMappingEditor.cpp b/Source/Processors/Editors/ChannelMappingEditor.cpp
index bc5602d8d..349150893 100644
--- a/Source/Processors/Editors/ChannelMappingEditor.cpp
+++ b/Source/Processors/Editors/ChannelMappingEditor.cpp
@@ -30,24 +30,34 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 ChannelMappingEditor::ChannelMappingEditor(GenericProcessor* parentNode, bool useDefaultParameterEditors=true)
-	: GenericEditor(parentNode, useDefaultParameterEditors), previousChannelCount(0)
+	: GenericEditor(parentNode, useDefaultParameterEditors), previousChannelCount(0), isConfigured(false)
 
 {
 	desiredWidth = 340;
 
+    scrollDistance = 0;
+
 	selectAllButton = new ElectrodeEditorButton("Select All",Font("Small Text",14,Font::plain));
 	selectAllButton->addListener(this);
 	addAndMakeVisible(selectAllButton);
-	selectAllButton->setBounds(140,110,110,10);
+	selectAllButton->setBounds(125,110,110,10);
 	selectAllButton->setToggleState(false, false);
 
 	modifyButton = new ElectrodeEditorButton("Remap",Font("Small Text",14,Font::plain));
 	modifyButton->addListener(this);
 	addAndMakeVisible(modifyButton);
-	modifyButton->setBounds(250,110,60,10);
+	modifyButton->setBounds(220,110,60,10);
 	modifyButton->setToggleState(false, false);
 	modifyButton->setClickingTogglesState(true);
 
+	resetButton = new ElectrodeEditorButton("Reset", Font("Small Text",14,Font::plain));
+	resetButton->addListener(this);
+	addAndMakeVisible(resetButton);
+	resetButton->setBounds(285,110,60,10);
+	resetButton->setToggleState(true,false);
+	resetButton->setClickingTogglesState(false);
+	resetButton->setEnabled(false);
+
 	//    channelSelector->setRadioStatus(true);
 
 	for (int i = 0 ; i < NUM_REFERENCES; i++)
@@ -77,46 +87,80 @@ ChannelMappingEditor::~ChannelMappingEditor()
 
 void ChannelMappingEditor::updateSettings()
 {
+	if (isConfigured)
+	{	
+		if (getProcessor()->getNumInputs() > previousChannelCount)
+		{
+			createElectrodeButtons(getProcessor()->getNumInputs(),false);
+			previousChannelCount = getProcessor()->getNumInputs();
+		}
+		else if (!reorderActive)
+		{
+			checkUnusedChannels();
+		}
 
-	if (getProcessor()->getNumInputs() != previousChannelCount)
+	} else if (getProcessor()->getNumInputs() != previousChannelCount)
 	{
-
 		createElectrodeButtons(getProcessor()->getNumInputs());
-
 		previousChannelCount = getProcessor()->getNumInputs();
-
 	}
-
 }
 
-void ChannelMappingEditor::createElectrodeButtons(int numNeeded)
+void ChannelMappingEditor::createElectrodeButtons(int numNeeded, bool clearPrevious)
 {
+	int startButton;
 
-	electrodeButtons.clear();
-
-	referenceArray.clear();
-	channelArray.clear();
-	referenceChannels.clear();
-	enabledChannelArray.clear();
+	if (clearPrevious)
+	{
+		electrodeButtons.clear();
 
-	int width = 20;
-	int height = 15;
+		referenceArray.clear();
+		channelArray.clear();
+		referenceChannels.clear();
+		enabledChannelArray.clear();
+		startButton=0;
+		previousClickedChan = -1;
+		previousShiftClickedChan = -1;
+		referenceButtons[0]->setToggleState(true,false);
+		selectedReference = 0;
+		modifyButton->setToggleState(false,false);
+		reorderActive = false;
+		channelSelector->activateButtons();
 
-	int row = 0;
-	int column = 0;
+	}
+	else
+	{
+		startButton = previousChannelCount;
+		if (startButton > numNeeded) return;
+		//row = startButton/16;
+		//column = startButton % 16;
+	}
 
-	for (int i = 0; i < numNeeded; i++)
+	for (int i = startButton; i < numNeeded; i++)
 	{
 		ElectrodeButton* button = new ElectrodeButton(i+1);
 		electrodeButtons.add(button);
 
-		button->setBounds(10+(column++)*(width), 30+row*(height), width, 15);
-		button->setToggleState(false,false);
 		button->setRadioGroupId(0);
+		
+        // if (!getCollapsedState())
+        //     addAndMakeVisible(button);
+        // else
+        addChildComponent(button); // determine visibility in refreshButtonLocations()
 
-		addAndMakeVisible(button);
 		button->addListener(this);
-
+		if (reorderActive)
+		{
+			button->setToggleState(true,false);
+			electrodeButtons[i]->setClickingTogglesState(false);
+			electrodeButtons[i]->addMouseListener(this,false);
+		}
+		else
+		{
+			button->setToggleState(false,false);
+			electrodeButtons[i]->setClickingTogglesState(true);
+		}
+		
 		referenceArray.add(-1);
 
 		getProcessor()->setCurrentChannel(i);
@@ -127,33 +171,55 @@ void ChannelMappingEditor::createElectrodeButtons(int numNeeded)
 		channelArray.add(i+1);
 		enabledChannelArray.add(true);
 
-		if (column % 16 == 0)
-		{
-			column = 0;
-			row++;
-		}
-
 	}
-	getProcessor()->setCurrentChannel(-1);
-	for (int i = 0; i < NUM_REFERENCES; i++)
+
+	if (clearPrevious)
 	{
+		getProcessor()->setCurrentChannel(-1);
+		for (int i = 0; i < NUM_REFERENCES; i++)
+		{
 
-		getProcessor()->setParameter(2,i); //Clear reference
-		referenceChannels.add(-1);
+			getProcessor()->setParameter(2,i); //Clear reference
+			referenceChannels.add(-1);
+			referenceButtons[i]->setEnabled(true);
+		}
 	}
+	channelSelector->setRadioStatus(true);
 
-	referenceButtons[0]->setToggleState(true,false);
-	selectedReference = 0;
+    refreshButtonLocations();
+}
 
-	modifyButton->setToggleState(false,false);
-	reorderActive = false;
-	previousClickedChan = -1;
-	previousShiftClickedChan = -1;
+void ChannelMappingEditor::refreshButtonLocations()
+{
+    int width = 19;
+    int height = 15;
+    int row = (int) -scrollDistance;
+    int column = 0;
 
+    for (int i = 0; i < electrodeButtons.size(); i++)
+    {
 
-	channelSelector->setRadioStatus(true);
+        ElectrodeButton* button = electrodeButtons[i];
+
+        button->setBounds(10+(column++)*(width), 30+row*(height), width, 15);
+
+        if (row <= 4 && row >= 0 && !getCollapsedState())
+            button->setVisible(true);
+        else
+            button->setVisible(false);
+
+        if (column % 16 == 0)
+        {
+            column = 0;
+            row++;
+        }
+    }
 }
 
+void ChannelMappingEditor::collapsedStateChanged()
+{
+    refreshButtonLocations();
+}
 
 void ChannelMappingEditor::buttonEvent(Button* button)
 {
@@ -166,6 +232,14 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 			setChannelReference(electrodeButtons[i]);
 		}
 		previousClickedChan = -1;
+		setConfigured(true);		
+	}
+	else if (button == resetButton)
+	{
+		createElectrodeButtons(getProcessor()->getNumInputs());
+		previousChannelCount = getProcessor()->getNumInputs();
+		setConfigured(false);
+		getEditorViewport()->makeEditorVisible(this, false, true);
 	}
 	else if (button == modifyButton)
 	{
@@ -174,7 +248,7 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 			channelSelector->activateButtons();
 			reorderActive = false;
 			selectedReference = 0;
-			for (int i=0; i < referenceButtons.size(); i++)
+			for (int i = 0; i < referenceButtons.size(); i++)
 			{
 				referenceButtons[i]->setEnabled(true);
 			}
@@ -199,7 +273,7 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 				{
 					electrodeButtons[i]->setToggleState(false,false);
 				}
-				if (enabledChannelArray[electrodeButtons[i]->getChannelNum()-1])
+				if ((enabledChannelArray[electrodeButtons[i]->getChannelNum()-1]) && (electrodeButtons[i]->getChannelNum() <= getProcessor()->getNumInputs()))
 				{
 					electrodeButtons[i]->setEnabled(true);
 				}
@@ -234,7 +308,7 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 					electrodeButtons[i]->setToggleState(false,false);
 				}
 				electrodeButtons[i]->addMouseListener(this,false);
-				
+
 			}
 			selectAllButton->setEnabled(false);
 		}
@@ -245,7 +319,8 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 
 		Array<int> a;
 
-		if (referenceChannels[selectedReference] >= 0 )
+		if ((referenceChannels[selectedReference] >= 0 ) 
+			&& (referenceChannels[selectedReference] < channelSelector->getNumChannels() ))
 		{
 			a.add(referenceChannels[selectedReference]);
 		}
@@ -269,6 +344,7 @@ void ChannelMappingEditor::buttonEvent(Button* button)
 	{
 		if (!reorderActive)
 		{
+			setConfigured(true);
 			int clickedChan = electrodeButtons.indexOf((ElectrodeButton*)button);
 
 			if (ModifierKeys::getCurrentModifiers().isShiftDown() && (previousClickedChan >= 0))
@@ -419,16 +495,21 @@ void ChannelMappingEditor::channelChanged(int chan)
 {
 	if (!reorderActive)
 	{
+		setConfigured(true);
 		getProcessor()->setCurrentChannel(chan-1);
 		getProcessor()->setParameter(2,selectedReference);
 		referenceChannels.set(selectedReference,chan-1);
 	}
 }
 
-void ChannelMappingEditor::saveEditorParameters(XmlElement* xml)
+void ChannelMappingEditor::saveCustomParameters(XmlElement* xml)
 {
 	xml->setAttribute("Type", "ChannelMappingEditor");
 
+	//Made a bit generic in case future expansions need more settings
+	XmlElement* settingsXml = xml->createNewChildElement("SETTING");
+	settingsXml->setAttribute("Type","visibleChannels");
+	settingsXml->setAttribute("Value",previousChannelCount);
 	for (int i = 0; i < channelArray.size(); i++)
 	{
 		XmlElement* channelXml = xml->createNewChildElement("CHANNEL");
@@ -446,9 +527,20 @@ void ChannelMappingEditor::saveEditorParameters(XmlElement* xml)
 
 }
 
-void ChannelMappingEditor::loadEditorParameters(XmlElement* xml)
+void ChannelMappingEditor::loadCustomParameters(XmlElement* xml)
 {
-
+	setConfigured(true);
+	forEachXmlChildElementWithTagName(*xml,	settingXml, "SETTING")
+	{
+		if (settingXml->getStringAttribute("Type").equalsIgnoreCase("visibleChannels"))
+		{
+			int nChans = settingXml->getIntAttribute("Value");
+			if (nChans > getProcessor()->getNumInputs())
+			{
+				createElectrodeButtons(nChans,false);
+			}
+		}
+	}
 	forEachXmlChildElementWithTagName(*xml, channelXml, "CHANNEL")
 	{
 		int i = channelXml->getIntAttribute("Number");
@@ -467,7 +559,7 @@ void ChannelMappingEditor::loadEditorParameters(XmlElement* xml)
 			electrodeButtons[i]->setChannelNum(mapping);
 			electrodeButtons[i]->setEnabled(enabled);
 			electrodeButtons[i]->repaint();
-			
+
 
 			getProcessor()->setCurrentChannel(i);
 
@@ -499,16 +591,18 @@ void ChannelMappingEditor::loadEditorParameters(XmlElement* xml)
 	}
 
 	for (int i = 0; i < electrodeButtons.size(); i++)
+	{
+		if (referenceArray[electrodeButtons[i]->getChannelNum()-1] == selectedReference)
 		{
-			if (referenceArray[electrodeButtons[i]->getChannelNum()-1] == selectedReference)
-			{
-				electrodeButtons[i]->setToggleState(true,false);
-			}
-			else
-			{
-				electrodeButtons[i]->setToggleState(false,false);
-			}
+			electrodeButtons[i]->setToggleState(true,false);
 		}
+		else
+		{
+			electrodeButtons[i]->setToggleState(false,false);
+		}
+	}
+
+    refreshButtonLocations();
 
 }
 
@@ -569,7 +663,7 @@ void ChannelMappingEditor::mouseDrag(const MouseEvent &e)
 
 			if (hoverButton != lastHoverButton)
 			{
-				
+
 				electrodeButtons[lastHoverButton]->setVisible(true);
 				electrodeButtons[hoverButton]->setVisible(false);
 
@@ -605,7 +699,7 @@ void ChannelMappingEditor::mouseDrag(const MouseEvent &e)
 				}
 				electrodeButtons[hoverButton]->setChannelNum(draggingChannel);
 				electrodeButtons[hoverButton]->setToggleState(enabledChannelArray[draggingChannel-1],false);
-				
+
 				lastHoverButton = hoverButton;
 				repaint();
 			}
@@ -622,7 +716,11 @@ void ChannelMappingEditor::mouseUp(const MouseEvent &e)
 		isDragging = false;
 		electrodeButtons[lastHoverButton]->setVisible(true);
 		int from, to;
-		if (lastHoverButton < initialDraggedButton)
+		if (lastHoverButton == initialDraggedButton) 
+		{
+			return;
+		}
+		else if (lastHoverButton < initialDraggedButton)
 		{
 			from = lastHoverButton;
 			to = initialDraggedButton;
@@ -637,6 +735,7 @@ void ChannelMappingEditor::mouseUp(const MouseEvent &e)
 		{
 			setChannelPosition(i,electrodeButtons[i]->getChannelNum());
 		}
+		setConfigured(true);
 	}
 }
 
@@ -651,6 +750,7 @@ void ChannelMappingEditor::mouseDoubleClick(const MouseEvent &e)
 {
 	if ((reorderActive) && electrodeButtons.contains((ElectrodeButton*)e.originalComponent))
 	{
+		setConfigured(true);
 		ElectrodeButton *button = (ElectrodeButton*)e.originalComponent;
 
 		if (button->getToggleState())
@@ -669,4 +769,53 @@ void ChannelMappingEditor::mouseDoubleClick(const MouseEvent &e)
 		}
 		getEditorViewport()->makeEditorVisible(this, false, true);
 	}
-}
\ No newline at end of file
+}
+
+void ChannelMappingEditor::mouseWheelMove(const MouseEvent& event,
+                                           const MouseWheelDetails& wheel)
+{
+
+    float maxScrollDistance = ceil(float(electrodeButtons.size() - 80) / 16.0f);
+
+   // std::cout << "Got wheel move: " << wheel.deltaY << std::endl;
+   // channelSelector->shiftChannelsVertical(-wheel.deltaY);
+    scrollDistance -= wheel.deltaY*2;
+
+    if (scrollDistance > maxScrollDistance)
+        scrollDistance = maxScrollDistance;
+
+    if (scrollDistance < 0)
+        scrollDistance = 0;
+
+    refreshButtonLocations();
+}
+
+void ChannelMappingEditor::checkUnusedChannels()
+{
+	for (int i = 0; i < electrodeButtons.size(); i++)
+	{
+		if (electrodeButtons[i]->getChannelNum() > getProcessor()->getNumInputs())
+		{
+			electrodeButtons[i]->setEnabled(false);
+		}
+		else
+		{
+			if (enabledChannelArray[electrodeButtons[i]->getChannelNum()-1])
+			{
+				electrodeButtons[i]->setEnabled(true);
+			}
+			else
+			{
+				electrodeButtons[i]->setEnabled(false);
+			}
+		}
+	}
+}
+void ChannelMappingEditor::setConfigured(bool state)
+{
+	isConfigured = state;
+	resetButton->setEnabled(state);
+	resetButton->setToggleState(!state,false);
+	getProcessor()->setParameter(4,state?1:0);
+}
+
diff --git a/Source/Processors/Editors/ChannelMappingEditor.h b/Source/Processors/Editors/ChannelMappingEditor.h
index b8e137194..74897536b 100644
--- a/Source/Processors/Editors/ChannelMappingEditor.h
+++ b/Source/Processors/Editors/ChannelMappingEditor.h
@@ -52,10 +52,10 @@ public:
 
     void updateSettings();
 
-    void createElectrodeButtons(int numNeeded);
+    void createElectrodeButtons(int numNeeded, bool clearPrevious = true);
 
-    void saveEditorParameters(XmlElement* xml);
-    void loadEditorParameters(XmlElement* xml);
+    void saveCustomParameters(XmlElement* xml);
+    void loadCustomParameters(XmlElement* xml);
 
     void channelChanged(int chan);
 
@@ -65,16 +65,24 @@ public:
 
 	void mouseDoubleClick(const MouseEvent &e);
 
+    void mouseWheelMove(const MouseEvent& event, const MouseWheelDetails& wheel);
+
+    void collapsedStateChanged();
 
 private:
 
 	void setChannelReference(ElectrodeButton *button);
 	void setChannelPosition(int position, int channel);
+	void checkUnusedChannels();
+	void setConfigured(bool state);
+
+    void refreshButtonLocations();
 
 	OwnedArray<ElectrodeButton> electrodeButtons;
 	OwnedArray<ElectrodeButton> referenceButtons;
     ScopedPointer<ElectrodeEditorButton> selectAllButton;
     ScopedPointer<ElectrodeEditorButton> modifyButton;
+	ScopedPointer<ElectrodeEditorButton> resetButton;
 
     Array<int> channelArray;
     Array<int> referenceArray;
@@ -92,6 +100,9 @@ private:
 	int initialDraggedButton;
 	int draggingChannel;
 	int lastHoverButton;
+	bool isConfigured;
+
+    float scrollDistance;
 	
 
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ChannelMappingEditor);
diff --git a/Source/Processors/Editors/ChannelSelector.cpp b/Source/Processors/Editors/ChannelSelector.cpp
index 9866414f3..1433cd15e 100755
--- a/Source/Processors/Editors/ChannelSelector.cpp
+++ b/Source/Processors/Editors/ChannelSelector.cpp
@@ -143,7 +143,7 @@ void ChannelSelector::shiftChannelsVertical(float amount)
         offsetUD = jmax(offsetUD, float(parameterButtons.size())/8*-10.68f);
     }
 
-    std::cout << "offsetUD = " << offsetUD << std::endl;
+    //std::cout << "offsetUD = " << offsetUD << std::endl;
 
     refreshButtonBoundaries();
 
@@ -432,7 +432,11 @@ void ChannelSelector::setAudioStatus(int chan, bool b)
 
 }
 
-
+void ChannelSelector::clearAudio()
+{
+    for (int chan = 0; chan < audioButtons.size(); chan++)
+        audioButtons[chan]->setToggleState(false, true);
+}
 
 int ChannelSelector::getDesiredWidth()
 {
@@ -555,11 +559,12 @@ void ChannelSelector::buttonClicked(Button* button)
             //int channelNum = editor->getStartChannel() + b->getChannel() - 1;
             bool status = b->getToggleState();
 
+            std::cout << "Requesting audio monitor for channel " << ch->num << std::endl;
+
             if (acquisitionIsActive) // use setParameter to change parameter safely
             {
                 editor->getProcessorGraph()->
-                getAudioNode()->
-                setChannelStatus(ch, status);
+                    getAudioNode()->setChannelStatus(ch, status);
             }
             else     // change parameter directly
             {
@@ -590,8 +595,12 @@ void ChannelSelector::buttonClicked(Button* button)
             }
 
         }
-        else
+        else // parameter type
         {
+
+            GenericEditor* editor = (GenericEditor*) getParentComponent();
+            editor->channelChanged(b->getChannel()-1);
+
             // do nothing
             if (radioStatus) // if radio buttons are active
             {
@@ -832,8 +841,8 @@ void ChannelSelectorRegion::mouseWheelMove(const MouseEvent& event,
                                            const MouseWheelDetails& wheel)
 {
 
-    std::cout << "Got wheel move: " << wheel.deltaY << std::endl;
-    channelSelector->shiftChannelsVertical(wheel.deltaY);
+   // std::cout << "Got wheel move: " << wheel.deltaY << std::endl;
+    channelSelector->shiftChannelsVertical(-wheel.deltaY);
 }
 
 void ChannelSelectorRegion::paint(Graphics& g)
diff --git a/Source/Processors/Editors/ChannelSelector.h b/Source/Processors/Editors/ChannelSelector.h
index 466fc6196..e71ee2983 100755
--- a/Source/Processors/Editors/ChannelSelector.h
+++ b/Source/Processors/Editors/ChannelSelector.h
@@ -94,6 +94,9 @@ public:
     /** Set whether a particular channel should be monitored. */
     void setAudioStatus(int, bool);
 
+    /** Sets all audio monitors to 'false' */
+    void clearAudio();
+
     /** Set whether a particular channel is selected for editing parameters. */
     void setParamStatus(int, bool);
 
-- 
GitLab