Skip to content

Commit ed4270b

Browse files
committed
Handle invalid headstage selections gracefully
- Immediately shut down the port voltage to prevent damage to devices - Display the selected vs. connected headstages so the user is aware of what is incorrect - Only present a single button (Okay) to the user so they acknowledge the information - Leave the devices in a disconnected state so the user can update the drop-down menu if needed, or give them time to connect devices manually
1 parent 9996ee2 commit ed4270b

File tree

3 files changed

+38
-176
lines changed

3 files changed

+38
-176
lines changed

Source/OnixSourceCanvas.cpp

Lines changed: 34 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -262,184 +262,61 @@ OnixDeviceMap OnixSourceCanvas::getSelectedDevices(std::vector<std::shared_ptr<S
262262
return tabMap;
263263
}
264264

265-
void OnixSourceCanvas::askKeepRemove(int offset)
265+
bool OnixSourceCanvas::verifyHeadstageSelection()
266266
{
267-
std::string selectedHeadstage = editor->getHeadstageSelected(offset);
268-
269-
std::string msg = "Headstage " + selectedHeadstage + " is selected on " + OnixDevice::getPortName(offset) + ", but was not discovered there.\n\n";
270-
msg += "Select one of the options below to continue:\n";
271-
msg += " [Keep Current] to keep " + selectedHeadstage + " selected.\n";
272-
msg += " [Remove] to remove " + selectedHeadstage + ".\n - Note: this will delete any settings that were modified.";
273-
274-
int result = AlertWindow::show(
275-
MessageBoxOptions()
276-
.withIconType(MessageBoxIconType::WarningIcon)
277-
.withTitle("Headstage Not Found")
278-
.withMessage(msg)
279-
.withButton("Keep Current")
280-
.withButton("Remove")
281-
);
282-
283-
switch (result)
284-
{
285-
case 0: // Remove
286-
removeTabs(PortController::getPortFromIndex(offset));
287-
break;
288-
case 1: // Keep Current
289-
break;
290-
default:
291-
break;
292-
}
293-
}
267+
auto selectedDevices = getSelectedDevices(settingsInterfaces);
268+
auto connectedDevices = source->getConnectedDevices(true);
294269

295-
void OnixSourceCanvas::askKeepUpdate(int offset, std::string foundHeadstage, OnixDeviceVector devices)
296-
{
297-
std::string selectedHeadstage = editor->getHeadstageSelected(offset);
298-
299-
if (selectedHeadstage == foundHeadstage) return;
300-
301-
std::string msg = "Headstage " + selectedHeadstage + " is selected on " + OnixDevice::getPortName(offset) + ". ";
302-
msg += "However, headstage " + foundHeadstage + " was found on " + OnixDevice::getPortName(offset) + ". \n\n";
303-
msg += "Select one of the options below to continue:\n";
304-
msg += " [Keep Current] to keep " + selectedHeadstage + " selected.\n";
305-
msg += " [Update] to change the selected headstage to " + foundHeadstage + ".\n - Note: this will delete any settings that were modified.";
306-
307-
int result = AlertWindow::show(
308-
MessageBoxOptions()
309-
.withIconType(MessageBoxIconType::WarningIcon)
310-
.withTitle("Mismatched Headstages")
311-
.withMessage(msg)
312-
.withButton("Keep Current")
313-
.withButton("Update")
314-
);
315-
316-
switch (result)
270+
if (selectedDevices != connectedDevices)
317271
{
318-
case 0: // Update
319-
{
320-
PortName port = PortController::getPortFromIndex(offset);
321-
removeTabs(port);
272+
auto connectedOffsets = OnixDevice::getUniqueOffsets(connectedDevices);
273+
auto selectedOffsets = OnixDevice::getUniqueOffsets(selectedDevices);
322274

323-
CustomTabComponent* tab = addTopLevelTab(getTopLevelTabName(port, foundHeadstage), (int)port);
324-
populateSourceTabs(tab, devices);
325-
}
326-
break;
327-
case 1: // Keep Current
328-
break;
329-
default:
330-
break;
331-
}
332-
}
333-
334-
void OnixSourceCanvas::refreshTabs()
335-
{
336-
auto selectedMap = createSelectedMap(settingsInterfaces);
337-
auto foundMap = source->createDeviceMap(true);
275+
auto hubNames = source->getHubNames();
338276

339-
if (selectedMap != foundMap)
340-
{
341-
std::vector<int> selectedIndices, foundIndices;
277+
std::string title = "Invalid Headstage Selection", msg;
342278

343-
for (const auto& [key, _] : selectedMap) { selectedIndices.emplace_back(key); }
344-
for (const auto& [key, _] : foundMap) { foundIndices.emplace_back(key); }
279+
msg = "There is a mismatch between the headstages that are selected, and the headstages that are connected.\n\n";
280+
msg += "Selected headstage";
281+
msg += (selectedOffsets.size() > 1) ? "s" : "";
282+
msg += ":\n\n";
345283

346-
auto selectedOffsets = OnixDevice::getUniqueOffsetsFromIndices(selectedIndices);
347-
auto foundOffsets = OnixDevice::getUniqueOffsetsFromIndices(foundIndices);
348-
349-
if (foundIndices.size() == 0 || foundOffsets.size() == 0) // NB: No devices found
284+
if (selectedOffsets.size() == 0)
350285
{
351-
if (selectedMap.size() != 0)
352-
{
353-
for (const auto& offset : selectedOffsets)
354-
{
355-
askKeepRemove(offset);
356-
}
357-
}
286+
msg += "None\n";
358287
}
359-
else if (selectedIndices.size() == 0) // NB: No headstages selected, add all found headstages
288+
else
360289
{
361-
for (auto& [offset, hubName] : source->getHubNames())
290+
for (const auto offset : selectedOffsets)
362291
{
363-
addHub(hubName, offset);
292+
msg += OnixDevice::getPortName(offset) + ": " + editor->getHeadstageSelected(offset) + "\n";
364293
}
365294
}
366-
else if (selectedOffsets.size() == foundOffsets.size()) // NB: Same number of ports selected and found
367-
{
368-
auto hubNames = source->getHubNames();
369295

370-
if (selectedOffsets.size() == 1)
371-
{
372-
if (hubNames.size() != 2)
373-
{
374-
LOGE("Wrong number of headstages found in the source node.");
375-
return;
376-
}
377-
378-
if (selectedOffsets[0] == foundOffsets[0]) // NB: Selected headstage is different from the found headstage on the same port
379-
{
380-
askKeepUpdate(selectedOffsets[0], hubNames[foundOffsets[0]], source->getDataSources());
381-
}
382-
else // NB: Selected headstage on one port is not found, and the found headstage is not selected on the other port
383-
{
384-
askKeepRemove(selectedOffsets[0]);
385-
386-
addHub(hubNames[foundOffsets[0]], foundOffsets[0]);
387-
}
388-
}
389-
else // NB: Two headstages are selected on different ports, and at least one of those headstages does not match the found headstages
390-
{
391-
for (const auto& offset : foundOffsets)
392-
{
393-
if (hubNames[offset] != editor->getHeadstageSelected(offset))
394-
{
395-
askKeepUpdate(offset, hubNames[offset], source->getDataSourcesFromOffset(offset));
396-
}
397-
}
398-
}
296+
msg += "\nConnected headstage";
297+
msg += (connectedOffsets.size() > 1) ? "s" : "";
298+
msg += ":\n\n";
299+
300+
if (connectedOffsets.size() == 0)
301+
{
302+
msg += "None\n";
399303
}
400-
else // NB: Different number of ports selected versus found
304+
else
401305
{
402-
auto hubNames = source->getHubNames();
403-
404-
if (selectedOffsets.size() > foundOffsets.size()) // NB: More headstages selected than found
405-
{
406-
for (const auto& offset : selectedOffsets)
407-
{
408-
if (offset == foundOffsets[0])
409-
{
410-
if (hubNames[offset] != editor->getHeadstageSelected(offset))
411-
{
412-
askKeepUpdate(offset, hubNames[offset], source->getDataSourcesFromOffset(offset));
413-
}
414-
}
415-
else
416-
{
417-
askKeepRemove(offset);
418-
}
419-
}
420-
}
421-
else // NB: More headstages found than selected
306+
for (const auto offset : connectedOffsets)
422307
{
423-
for (const auto& offset : foundOffsets)
424-
{
425-
if (offset == selectedOffsets[0])
426-
{
427-
if (hubNames[offset] != editor->getHeadstageSelected(offset))
428-
{
429-
askKeepUpdate(offset, hubNames[offset], source->getDataSourcesFromOffset(offset));
430-
}
431-
}
432-
else
433-
{
434-
addHub(hubNames[offset], offset);
435-
}
436-
}
308+
msg += OnixDevice::getPortName(offset) + ": " + hubNames[offset] + "\n";
437309
}
438310
}
311+
312+
msg += "\nVerify that the correct headstage(s) are selected, and that all hardware connections are correct before trying to connect again.";
313+
314+
Onix1::showWarningMessageBoxAsync(title, msg);
315+
316+
return false;
439317
}
440318

441-
CoreServices::updateSignalChain(editor);
442-
editor->refreshComboBoxSelection();
319+
return true;
443320
}
444321

445322
void OnixSourceCanvas::update() const

Source/OnixSourceCanvas.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ namespace OnixSourcePlugin
5959
/** Removes all tabs from the canvas */
6060
void removeAllTabs();
6161

62-
/** Called when the hardware is connected, to ensure the right tabs are present */
63-
void refreshTabs();
62+
/** Called when the hardware is connected, to ensure the correct headstage is found */
63+
bool verifyHeadstageSelection();
6464

6565
/** Called when the Visualizer is first created, and optionally when
6666
the parameters of the underlying processor are changed */
@@ -113,18 +113,6 @@ namespace OnixSourcePlugin
113113

114114
std::string getTopLevelTabName(PortName port, std::string headstage);
115115

116-
/**
117-
Create an alert window that asks whether to keep the selected headstage on the given port,
118-
or to remove it since the hardware was not found
119-
*/
120-
void askKeepRemove(int offset);
121-
122-
/**
123-
Create an alert window that asks whether to keep the selected headstage on the given port,
124-
or to update to the headstage that was found
125-
*/
126-
void askKeepUpdate(int offset, std::string foundHeadstage, OnixDeviceVector devices);
127-
128116
JUCE_LEAK_DETECTOR(OnixSourceCanvas);
129117
};
130118
}

Source/OnixSourceEditor.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,12 +357,9 @@ bool OnixSourceEditor::configureAllDevices()
357357
if (!OnixSource::checkHubFirmwareCompatibility(source->getContext(), deviceTable))
358358
return false;
359359

360-
if (source->initializeDevices(deviceTable, false))
361-
canvas->refreshTabs();
362-
else
360+
if (!source->initializeDevices(deviceTable, false) || !canvas->verifyHeadstageSelection())
363361
{
364-
CoreServices::sendStatusMessage("Error configuring hardware. Check logs for more details.");
365-
connectButton->setToggleState(false, sendNotification);
362+
setConnectedStatus(false);
366363
return false;
367364
}
368365

0 commit comments

Comments
 (0)