From 8203b7ded92ca7d0c48c9fc8ac4cd4bb6ffb66ab Mon Sep 17 00:00:00 2001 From: f4exb Date: Wed, 12 Apr 2017 18:59:26 +0200 Subject: [PATCH] Source handling refactoring (1) --- sdrbase/mainwindow.cpp | 2117 +++++++++++++++--------------- sdrbase/plugin/pluginmanager.cpp | 1634 +++++++++++------------ 2 files changed, 1885 insertions(+), 1866 deletions(-) diff --git a/sdrbase/mainwindow.cpp b/sdrbase/mainwindow.cpp index 482c99740..a89d506c9 100644 --- a/sdrbase/mainwindow.cpp +++ b/sdrbase/mainwindow.cpp @@ -1,1051 +1,1066 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mainwindow.h" -#include "ui_mainwindow.h" -#include "device/devicesourceapi.h" -#include "device/devicesinkapi.h" -#include "audio/audiodeviceinfo.h" -#include "gui/indicator.h" -#include "gui/presetitem.h" -#include "gui/addpresetdialog.h" -#include "gui/pluginsdialog.h" -#include "gui/aboutdialog.h" -#include "gui/rollupwidget.h" -#include "gui/channelwindow.h" -#include "gui/audiodialog.h" -#include "gui/samplingdevicecontrol.h" -#include "gui/mypositiondialog.h" -#include "dsp/dspengine.h" -#include "dsp/spectrumvis.h" -#include "dsp/dspcommands.h" -#include "plugin/plugingui.h" -#include "plugin/pluginapi.h" -#include "plugin/plugingui.h" - -#include "gui/glspectrum.h" -#include "gui/glspectrumgui.h" - -#include -#include - -MainWindow::MainWindow(QWidget* parent) : - QMainWindow(parent), - ui(new Ui::MainWindow), - m_masterTabIndex(0), - m_settings(), - m_dspEngine(DSPEngine::instance()), - m_lastEngineState((DSPDeviceSourceEngine::State)-1), - m_inputGUI(0), - m_sampleRate(0), - m_centerFrequency(0), - m_sampleFileName(std::string("./test.sdriq")) -{ - qDebug() << "MainWindow::MainWindow: start"; - - m_settings.setAudioDeviceInfo(&m_audioDeviceInfo); - - ui->setupUi(this); - createStatusBar(); - - setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); - setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - // work around broken Qt dock widget ordering - removeDockWidget(ui->inputViewDock); - removeDockWidget(ui->inputSelectDock); - removeDockWidget(ui->spectraDisplayDock); - removeDockWidget(ui->presetDock); - removeDockWidget(ui->channelDock); - addDockWidget(Qt::LeftDockWidgetArea, ui->inputSelectDock); - addDockWidget(Qt::LeftDockWidgetArea, ui->inputViewDock); - addDockWidget(Qt::LeftDockWidgetArea, ui->spectraDisplayDock); - addDockWidget(Qt::LeftDockWidgetArea, ui->presetDock); - addDockWidget(Qt::RightDockWidgetArea, ui->channelDock); - - ui->inputViewDock->show(); - ui->inputSelectDock->show(); - ui->spectraDisplayDock->show(); - ui->presetDock->show(); - ui->channelDock->show(); - - ui->menu_Window->addAction(ui->inputViewDock->toggleViewAction()); - ui->menu_Window->addAction(ui->inputSelectDock->toggleViewAction()); - ui->menu_Window->addAction(ui->spectraDisplayDock->toggleViewAction()); - ui->menu_Window->addAction(ui->presetDock->toggleViewAction()); - ui->menu_Window->addAction(ui->channelDock->toggleViewAction()); - - ui->tabInputsView->setStyleSheet("QWidget { background: rgb(50,50,50); } " - "QToolButton::checked { background: rgb(128,70,0); } " - "QComboBox::item:selected { color: rgb(255,140,0); } " - "QTabWidget::pane { border: 1px solid #C06900; } " - "QTabBar::tab:selected { background: rgb(128,70,0); }"); - ui->tabInputsSelect->setStyleSheet("QWidget { background: rgb(50,50,50); } " - "QToolButton::checked { background: rgb(128,70,0); } " - "QComboBox::item:selected { color: rgb(255,140,0); } " - "QTabWidget::pane { border: 1px solid #808080; } " - "QTabBar::tab:selected { background: rgb(100,100,100); }"); - - m_pluginManager = new PluginManager(this); - m_pluginManager->loadPlugins(); - - connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()), Qt::QueuedConnection); - - connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); - m_statusTimer.start(1000); - - m_masterTimer.start(50); - - qDebug() << "MainWindow::MainWindow: add the first device..."; - - addSourceDevice(); // add the first device - - qDebug() << "MainWindow::MainWindow: load settings..."; - - loadSettings(); - - qDebug() << "MainWindow::MainWindow: select SampleSource from settings..."; - - int sampleSourceIndex = m_settings.getSourceIndex(); - sampleSourceIndex = m_pluginManager->selectSampleSourceByIndex(sampleSourceIndex, m_deviceUIs.back()->m_deviceSourceAPI); - - if (sampleSourceIndex < 0) - { - qCritical("MainWindow::MainWindow: no sample source. Exit"); - exit(0); - } - - bool sampleSourceSignalsBlocked = m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(true); - m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->setCurrentIndex(sampleSourceIndex); - m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(sampleSourceSignalsBlocked); - - qDebug() << "MainWindow::MainWindow: load current preset settings..."; - - loadPresetSettings(m_settings.getWorkingPreset(), 0); - - qDebug() << "MainWindow::MainWindow: apply settings..."; - - applySettings(); - - qDebug() << "MainWindow::MainWindow: update preset controls..."; - - updatePresetControls(); - - connect(ui->tabInputsView, SIGNAL(currentChanged(int)), this, SLOT(tabInputViewIndexChanged())); - - qDebug() << "MainWindow::MainWindow: end"; -} - -MainWindow::~MainWindow() -{ - delete m_pluginManager; - delete m_dateTimeWidget; - delete m_showSystemWidget; - - delete ui; -} - -void MainWindow::addSourceDevice() -{ - DSPDeviceSourceEngine *dspDeviceSourceEngine = m_dspEngine->addDeviceSourceEngine(); - dspDeviceSourceEngine->start(); - - uint dspDeviceSourceEngineUID = dspDeviceSourceEngine->getUID(); - char uidCStr[16]; - sprintf(uidCStr, "UID:%d", dspDeviceSourceEngineUID); - - m_deviceUIs.push_back(new DeviceUISet(m_masterTimer)); - m_deviceUIs.back()->m_deviceSourceEngine = dspDeviceSourceEngine; - - int deviceTabIndex = m_deviceUIs.size()-1; - char tabNameCStr[16]; - sprintf(tabNameCStr, "R%d", deviceTabIndex); - - DeviceSourceAPI *deviceSourceAPI = new DeviceSourceAPI(this, deviceTabIndex, dspDeviceSourceEngine, m_deviceUIs.back()->m_spectrum, m_deviceUIs.back()->m_channelWindow); - - m_deviceUIs.back()->m_deviceSourceAPI = deviceSourceAPI; - m_deviceUIs.back()->m_samplingDeviceControl->setDeviceAPI(deviceSourceAPI); - m_deviceUIs.back()->m_samplingDeviceControl->setPluginManager(m_pluginManager); - m_pluginManager->populateRxChannelComboBox(m_deviceUIs.back()->m_samplingDeviceControl->getChannelSelector()); - - connect(m_deviceUIs.back()->m_samplingDeviceControl->getAddChannelButton(), SIGNAL(clicked(bool)), this, SLOT(on_channel_addClicked(bool))); - - dspDeviceSourceEngine->addSink(m_deviceUIs.back()->m_spectrumVis); - ui->tabSpectra->addTab(m_deviceUIs.back()->m_spectrum, tabNameCStr); - ui->tabSpectraGUI->addTab(m_deviceUIs.back()->m_spectrumGUI, tabNameCStr); - ui->tabChannels->addTab(m_deviceUIs.back()->m_channelWindow, tabNameCStr); - - bool sampleSourceSignalsBlocked = m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(true); - m_pluginManager->duplicateLocalSampleSourceDevices(dspDeviceSourceEngineUID); - m_pluginManager->fillSampleSourceSelector(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector(), dspDeviceSourceEngineUID); - - connect(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelectionConfirm(), SIGNAL(clicked(bool)), this, SLOT(on_sampleSource_confirmClicked(bool))); - - m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(sampleSourceSignalsBlocked); - ui->tabInputsSelect->addTab(m_deviceUIs.back()->m_samplingDeviceControl, tabNameCStr); - ui->tabInputsSelect->setTabToolTip(deviceTabIndex, QString(uidCStr)); - - int sampleSourceIndex = m_pluginManager->selectSampleSourceBySerialOrSequence("sdrangel.samplesource.filesource", "0", 0, m_deviceUIs.back()->m_deviceSourceAPI); -} - -void MainWindow::addSinkDevice() -{ - DSPDeviceSinkEngine *dspDeviceSinkEngine = m_dspEngine->addDeviceSinkEngine(); - dspDeviceSinkEngine->start(); - - uint dspDeviceSinkEngineUID = dspDeviceSinkEngine->getUID(); - char uidCStr[16]; - sprintf(uidCStr, "UID:%d", dspDeviceSinkEngineUID); - - m_deviceUIs.push_back(new DeviceUISet(m_masterTimer)); - m_deviceUIs.back()->m_deviceSourceEngine = 0; - m_deviceUIs.back()->m_deviceSinkEngine = dspDeviceSinkEngine; - - int deviceTabIndex = m_deviceUIs.size()-1; - char tabNameCStr[16]; - sprintf(tabNameCStr, "T%d", deviceTabIndex); - - DeviceSinkAPI *deviceSinkAPI = new DeviceSinkAPI(this, deviceTabIndex, dspDeviceSinkEngine, m_deviceUIs.back()->m_spectrum, m_deviceUIs.back()->m_channelWindow); - - m_deviceUIs.back()->m_deviceSourceAPI = 0; - m_deviceUIs.back()->m_deviceSinkAPI = deviceSinkAPI; - m_deviceUIs.back()->m_samplingDeviceControl->setDeviceAPI(deviceSinkAPI); - m_deviceUIs.back()->m_samplingDeviceControl->setPluginManager(m_pluginManager); - m_pluginManager->populateTxChannelComboBox(m_deviceUIs.back()->m_samplingDeviceControl->getChannelSelector()); - - connect(m_deviceUIs.back()->m_samplingDeviceControl->getAddChannelButton(), SIGNAL(clicked(bool)), this, SLOT(on_channel_addClicked(bool))); - - dspDeviceSinkEngine->addSpectrumSink(m_deviceUIs.back()->m_spectrumVis); - ui->tabSpectra->addTab(m_deviceUIs.back()->m_spectrum, tabNameCStr); - ui->tabSpectraGUI->addTab(m_deviceUIs.back()->m_spectrumGUI, tabNameCStr); - ui->tabChannels->addTab(m_deviceUIs.back()->m_channelWindow, tabNameCStr); - - bool sampleSourceSignalsBlocked = m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(true); - m_pluginManager->duplicateLocalSampleSinkDevices(dspDeviceSinkEngineUID); - m_pluginManager->fillSampleSinkSelector(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector(), dspDeviceSinkEngineUID); - - connect(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelectionConfirm(), SIGNAL(clicked(bool)), this, SLOT(on_sampleSink_confirmClicked(bool))); - - m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(sampleSourceSignalsBlocked); - ui->tabInputsSelect->addTab(m_deviceUIs.back()->m_samplingDeviceControl, tabNameCStr); - ui->tabInputsSelect->setTabToolTip(deviceTabIndex, QString(uidCStr)); - - int sampleSinkIndex = m_pluginManager->selectSampleSinkBySerialOrSequence("sdrangel.samplesink.filesink", "0", 0, m_deviceUIs.back()->m_deviceSinkAPI); -} - -void MainWindow::removeLastDevice() -{ - if (m_deviceUIs.back()->m_deviceSourceEngine) // source tab - { - DSPDeviceSourceEngine *lastDeviceEngine = m_deviceUIs.back()->m_deviceSourceEngine; - lastDeviceEngine->stopAcquistion(); - lastDeviceEngine->removeSink(m_deviceUIs.back()->m_spectrumVis); - - ui->tabSpectraGUI->removeTab(ui->tabSpectraGUI->count() - 1); - ui->tabSpectra->removeTab(ui->tabSpectra->count() - 1); - - m_deviceUIs.back()->m_deviceSourceAPI->freeAll(); - m_deviceUIs.back()->m_deviceSourceAPI->clearBuddiesLists(); // remove old API from buddies lists - - ui->tabChannels->removeTab(ui->tabChannels->count() - 1); - - ui->tabInputsSelect->removeTab(ui->tabInputsSelect->count() - 1); - - m_deviceWidgetTabs.removeLast();m_pluginManager->loadPlugins(); - ui->tabInputsView->clear(); - - for (int i = 0; i < m_deviceWidgetTabs.size(); i++) - { - qDebug("MainWindow::removeLastDevice: adding back tab for %s", m_deviceWidgetTabs[i].displayName.toStdString().c_str()); - ui->tabInputsView->addTab(m_deviceWidgetTabs[i].gui, m_deviceWidgetTabs[i].tabName); - ui->tabInputsView->setTabToolTip(i, m_deviceWidgetTabs[i].displayName); - } - - delete m_deviceUIs.back(); - - lastDeviceEngine->stop(); - m_dspEngine->removeLastDeviceSourceEngine(); - } - else if (m_deviceUIs.back()->m_deviceSinkEngine) // sink tab - { - DSPDeviceSinkEngine *lastDeviceEngine = m_deviceUIs.back()->m_deviceSinkEngine; - lastDeviceEngine->stopGeneration(); - lastDeviceEngine->removeSpectrumSink(m_deviceUIs.back()->m_spectrumVis); - - ui->tabSpectraGUI->removeTab(ui->tabSpectraGUI->count() - 1); - ui->tabSpectra->removeTab(ui->tabSpectra->count() - 1); - - m_deviceUIs.back()->m_deviceSinkAPI->freeAll(); - m_deviceUIs.back()->m_deviceSinkAPI->clearBuddiesLists(); // remove old API from buddies lists - - ui->tabChannels->removeTab(ui->tabChannels->count() - 1); - - ui->tabInputsSelect->removeTab(ui->tabInputsSelect->count() - 1); - - m_deviceWidgetTabs.removeLast(); - ui->tabInputsView->clear(); - - for (int i = 0; i < m_deviceWidgetTabs.size(); i++) - { - qDebug("MainWindow::removeLastDevice: adding back tab for %s", m_deviceWidgetTabs[i].displayName.toStdString().c_str()); - ui->tabInputsView->addTab(m_deviceWidgetTabs[i].gui, m_deviceWidgetTabs[i].tabName); - ui->tabInputsView->setTabToolTip(i, m_deviceWidgetTabs[i].displayName); - } - - delete m_deviceUIs.back(); - - lastDeviceEngine->stop(); - m_dspEngine->removeLastDeviceSinkEngine(); - } - - m_deviceUIs.pop_back(); -} - -void MainWindow::addChannelRollup(int deviceTabIndex, QWidget* widget) -{ - if (deviceTabIndex < ui->tabInputsView->count()) - { - DeviceUISet *deviceUI = m_deviceUIs[deviceTabIndex]; - deviceUI->m_channelWindow->addRollupWidget(widget); - ui->channelDock->show(); - ui->channelDock->raise(); - } -} - -void MainWindow::addViewAction(QAction* action) -{ - ui->menu_Window->addAction(action); -} - -void MainWindow::setDeviceGUI(int deviceTabIndex, QWidget* gui, const QString& deviceDisplayName, bool sourceDevice) -{ - char tabNameCStr[16]; - - if (sourceDevice) - { - sprintf(tabNameCStr, "R%d", deviceTabIndex); - } - else - { - sprintf(tabNameCStr, "T%d", deviceTabIndex); - } - - qDebug("MainWindow::setDeviceGUI: insert %s tab at %d", sourceDevice ? "Rx" : "Tx", deviceTabIndex); - - if (deviceTabIndex < m_deviceWidgetTabs.size()) - { - m_deviceWidgetTabs[deviceTabIndex] = {gui, deviceDisplayName, QString(tabNameCStr)}; - } - else - { - m_deviceWidgetTabs.append({gui, deviceDisplayName, QString(tabNameCStr)}); - } - - ui->tabInputsView->clear(); - - for (int i = 0; i < m_deviceWidgetTabs.size(); i++) - { - qDebug("MainWindow::setDeviceGUI: adding tab for %s", m_deviceWidgetTabs[i].displayName.toStdString().c_str()); - ui->tabInputsView->addTab(m_deviceWidgetTabs[i].gui, m_deviceWidgetTabs[i].tabName); - ui->tabInputsView->setTabToolTip(i, m_deviceWidgetTabs[i].displayName); - } - - ui->tabInputsView->setCurrentIndex(deviceTabIndex); -} - -void MainWindow::loadSettings() -{ - qDebug() << "MainWindow::loadSettings"; - - m_settings.load(); - m_settings.sortPresets(); - - for(int i = 0; i < m_settings.getPresetCount(); ++i) - { - addPresetToTree(m_settings.getPreset(i)); - } -} - -void MainWindow::loadPresetSettings(const Preset* preset, int tabIndex) -{ - qDebug("MainWindow::loadPresetSettings: preset [%s | %s]", - qPrintable(preset->getGroup()), - qPrintable(preset->getDescription())); - - if (tabIndex >= 0) - { - DeviceUISet *deviceUI = m_deviceUIs[tabIndex]; - - if (deviceUI->m_deviceSourceEngine) // source device - { - deviceUI->m_spectrumGUI->deserialize(preset->getSpectrumConfig()); - deviceUI->m_deviceSourceAPI->loadSourceSettings(preset); - deviceUI->m_deviceSourceAPI->loadChannelSettings(preset, &(m_pluginManager->m_pluginAPI)); - } - else if (deviceUI->m_deviceSinkEngine) // sink device - { - deviceUI->m_spectrumGUI->deserialize(preset->getSpectrumConfig()); - deviceUI->m_deviceSinkAPI->loadSinkSettings(preset); - deviceUI->m_deviceSinkAPI->loadChannelSettings(preset, &(m_pluginManager->m_pluginAPI)); - } - } - - // has to be last step - restoreState(preset->getLayout()); -} - -void MainWindow::savePresetSettings(Preset* preset, int tabIndex) -{ - qDebug("MainWindow::savePresetSettings: preset [%s | %s]", - qPrintable(preset->getGroup()), - qPrintable(preset->getDescription())); - - // Save from currently selected source tab - //int currentSourceTabIndex = ui->tabInputsView->currentIndex(); - DeviceUISet *deviceUI = m_deviceUIs[tabIndex]; - - if (deviceUI->m_deviceSourceEngine) // source device - { - preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); - preset->clearChannels(); - deviceUI->m_deviceSourceAPI->saveChannelSettings(preset); - deviceUI->m_deviceSourceAPI->saveSourceSettings(preset); - } - else if (deviceUI->m_deviceSinkEngine) // sink device - { - preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); - preset->clearChannels(); - preset->setSourcePreset(false); - deviceUI->m_deviceSinkAPI->saveChannelSettings(preset); - deviceUI->m_deviceSinkAPI->saveSinkSettings(preset); - } - - preset->setLayout(saveState()); -} - -void MainWindow::createStatusBar() -{ - QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR); -#if QT_VERSION >= 0x050400 - m_showSystemWidget = new QLabel("SDRangel v3.3.4 " + qtVersionStr + QSysInfo::prettyProductName(), this); -#else - m_showSystemWidget = new QLabel("SDRangel v3.3.4 " + qtVersionStr, this); -#endif - statusBar()->addPermanentWidget(m_showSystemWidget); - - m_dateTimeWidget = new QLabel(tr("Date"), this); - m_dateTimeWidget->setToolTip(tr("Current date/time")); - statusBar()->addPermanentWidget(m_dateTimeWidget); -} - -void MainWindow::closeEvent(QCloseEvent*) -{ -} - -void MainWindow::updatePresetControls() -{ - ui->presetTree->resizeColumnToContents(0); - - if(ui->presetTree->currentItem() != 0) - { - ui->presetDelete->setEnabled(true); - ui->presetLoad->setEnabled(true); - } - else - { - ui->presetDelete->setEnabled(false); - ui->presetLoad->setEnabled(false); - } -} - -QTreeWidgetItem* MainWindow::addPresetToTree(const Preset* preset) -{ - QTreeWidgetItem* group = 0; - - for(int i = 0; i < ui->presetTree->topLevelItemCount(); i++) - { - if(ui->presetTree->topLevelItem(i)->text(0) == preset->getGroup()) - { - group = ui->presetTree->topLevelItem(i); - break; - } - } - - if(group == 0) - { - QStringList sl; - sl.append(preset->getGroup()); - group = new QTreeWidgetItem(ui->presetTree, sl, PGroup); - group->setFirstColumnSpanned(true); - group->setExpanded(true); - ui->presetTree->sortByColumn(0, Qt::AscendingOrder); - } - - QStringList sl; - sl.append(QString("%1").arg(preset->getCenterFrequency() / 1e6f, 0, 'f', 3)); // frequency column - sl.append(QString("%1").arg(preset->isSourcePreset() ? 'R' : 'T')); // mode column - sl.append(preset->getDescription()); // description column - PresetItem* item = new PresetItem(group, sl, preset->getCenterFrequency(), PItem); - item->setTextAlignment(0, Qt::AlignRight); - item->setData(0, Qt::UserRole, qVariantFromValue(preset)); - ui->presetTree->resizeColumnToContents(0); // Resize frequency column to minimum - ui->presetTree->resizeColumnToContents(1); // Resize mode column to minimum - - updatePresetControls(); - return item; -} - -void MainWindow::applySettings() -{ -} - -void MainWindow::handleMessages() -{ - Message* message; - - while ((message = m_inputMessageQueue.pop()) != 0) - { - qDebug("MainWindow::handleMessages: message: %s", message->getIdentifier()); - delete message; - } -} - -void MainWindow::on_action_View_Fullscreen_toggled(bool checked) -{ - if(checked) - showFullScreen(); - else showNormal(); -} - -void MainWindow::on_presetSave_clicked() -{ - QStringList groups; - QString group; - QString description = ""; - for(int i = 0; i < ui->presetTree->topLevelItemCount(); i++) - groups.append(ui->presetTree->topLevelItem(i)->text(0)); - - QTreeWidgetItem* item = ui->presetTree->currentItem(); - if(item != 0) { - if(item->type() == PGroup) - group = item->text(0); - else if(item->type() == PItem) { - group = item->parent()->text(0); - description = item->text(0); - } - } - - AddPresetDialog dlg(groups, group, this); - - if (description.length() > 0) { - dlg.setDescription(description); - } - - if(dlg.exec() == QDialog::Accepted) { - Preset* preset = m_settings.newPreset(dlg.group(), dlg.description()); - savePresetSettings(preset, ui->tabInputsView->currentIndex()); - - ui->presetTree->setCurrentItem(addPresetToTree(preset)); - } -} - -void MainWindow::on_presetUpdate_clicked() -{ - QTreeWidgetItem* item = ui->presetTree->currentItem(); - - if(item != 0) { - if(item->type() == PItem) { - const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); - if (preset != 0) { - Preset* preset_mod = const_cast(preset); - savePresetSettings(preset_mod, ui->tabInputsView->currentIndex()); - } - } - } -} - -void MainWindow::on_presetExport_clicked() -{ - QTreeWidgetItem* item = ui->presetTree->currentItem(); - - if(item != 0) { - if(item->type() == PItem) - { - const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); - QString base64Str = preset->serialize().toBase64(); - QString fileName = QFileDialog::getSaveFileName(this, - tr("Open preset export file"), ".", tr("Preset export files (*.prex)")); - - if (fileName != "") - { - QFileInfo fileInfo(fileName); - - if (fileInfo.suffix() != "prex") { - fileName += ".prex"; - } - - QFile exportFile(fileName); - - if (exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) - { - QTextStream outstream(&exportFile); - outstream << base64Str; - exportFile.close(); - } - else - { - QMessageBox::information(this, tr("Message"), tr("Cannot open file for writing")); - } - } - } - } -} - -void MainWindow::on_presetImport_clicked() -{ - QTreeWidgetItem* item = ui->presetTree->currentItem(); - - if(item != 0) - { - QString group; - - if (item->type() == PGroup) { - group = item->text(0); - } else if (item->type() == PItem) { - group = item->parent()->text(0); - } else { - return; - } - - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open preset export file"), ".", tr("Preset export files (*.prex)")); - - if (fileName != "") - { - QFile exportFile(fileName); - - if (exportFile.open(QIODevice::ReadOnly | QIODevice::Text)) - { - QByteArray base64Str; - QTextStream instream(&exportFile); - instream >> base64Str; - exportFile.close(); - - Preset* preset = m_settings.newPreset("", ""); - preset->deserialize(QByteArray::fromBase64(base64Str)); - preset->setGroup(group); // override with current group - - ui->presetTree->setCurrentItem(addPresetToTree(preset)); - } - else - { - QMessageBox::information(this, tr("Message"), tr("Cannot open file for reading")); - } - } - } -} - -void MainWindow::on_settingsSave_clicked() -{ - savePresetSettings(m_settings.getWorkingPreset(), ui->tabInputsView->currentIndex()); - m_settings.save(); -} - -void MainWindow::on_presetLoad_clicked() -{ - qDebug() << "MainWindow::on_presetLoad_clicked"; - - QTreeWidgetItem* item = ui->presetTree->currentItem(); - - if(item == 0) - { - qDebug("MainWindow::on_presetLoad_clicked: item null"); - updatePresetControls(); - return; - } - - const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); - - if(preset == 0) - { - qDebug("MainWindow::on_presetLoad_clicked: preset null"); - return; - } - - loadPresetSettings(preset, ui->tabInputsView->currentIndex()); - applySettings(); -} - -void MainWindow::on_presetDelete_clicked() -{ - QTreeWidgetItem* item = ui->presetTree->currentItem(); - if(item == 0) { - updatePresetControls(); - return; - } - const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); - if(preset == 0) - return; - - if(QMessageBox::question(this, tr("Delete Preset"), tr("Do you want to delete preset '%1'?").arg(preset->getDescription()), QMessageBox::No | QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { - delete item; - m_settings.deletePreset(preset); - } -} - -void MainWindow::on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) -{ - updatePresetControls(); -} - -void MainWindow::on_presetTree_itemActivated(QTreeWidgetItem *item, int column) -{ - on_presetLoad_clicked(); -} - -void MainWindow::on_action_Loaded_Plugins_triggered() -{ - PluginsDialog pluginsDialog(m_pluginManager, this); - pluginsDialog.exec(); -} - -void MainWindow::on_action_Audio_triggered() -{ - AudioDialog audioDialog(&m_audioDeviceInfo, this); - audioDialog.exec(); - m_dspEngine->setAudioInputVolume(m_audioDeviceInfo.getInputVolume()); - m_dspEngine->setAudioInputDeviceIndex(m_audioDeviceInfo.getInputDeviceIndex()); - m_dspEngine->setAudioOutputDeviceIndex(m_audioDeviceInfo.getOutputDeviceIndex()); -} - -void MainWindow::on_action_My_Position_triggered() -{ - MyPositionDialog myPositionDialog(m_settings, this); - myPositionDialog.exec(); -} - -void MainWindow::on_action_DV_Serial_triggered(bool checked) -{ - m_dspEngine->setDVSerialSupport(checked); - - if (checked) - { - std::vector deviceNames; - m_dspEngine->getDVSerialNames(deviceNames); - - if (deviceNames.size() == 0) - { - QMessageBox::information(this, tr("Message"), tr("No DV serial devices found")); - } - else - { - std::vector::iterator it = deviceNames.begin(); - std::string deviceNamesStr = "DV Serial devices found: "; - - while (it != deviceNames.end()) - { - if (it != deviceNames.begin()) { - deviceNamesStr += ","; - } - - deviceNamesStr += *it; - ++it; - } - - QMessageBox::information(this, tr("Message"), tr(deviceNamesStr.c_str())); - } - } -} - -void MainWindow::on_sampleSource_confirmClicked(bool checked) -{ - // Do it in the currently selected source tab - int currentSourceTabIndex = ui->tabInputsSelect->currentIndex(); - - if (currentSourceTabIndex >= 0) - { - qDebug("MainWindow::on_sampleSource_confirmClicked: tab at %d", currentSourceTabIndex); - DeviceUISet *deviceUI = m_deviceUIs[currentSourceTabIndex]; - deviceUI->m_deviceSourceAPI->saveSourceSettings(m_settings.getWorkingPreset()); // save old API settings - int selectedComboIndex = deviceUI->m_samplingDeviceControl->getDeviceSelector()->currentIndex(); - void *devicePtr = deviceUI->m_samplingDeviceControl->getDeviceSelector()->itemData(selectedComboIndex).value(); - deviceUI->m_deviceSourceAPI->stopAcquisition(); - deviceUI->m_deviceSourceAPI->clearBuddiesLists(); // clear old API buddies lists - m_pluginManager->selectSampleSourceByDevice(devicePtr, deviceUI->m_deviceSourceAPI); // sets the new API - deviceUI->m_deviceSourceAPI->loadSourceSettings(m_settings.getWorkingPreset()); // load new API settings - - // add to buddies list - std::vector::iterator it = m_deviceUIs.begin(); - for (; it != m_deviceUIs.end(); ++it) - { - if (*it != deviceUI) // do not add to itself - { - if ((*it)->m_deviceSourceEngine) // it is a source device - { - if ((deviceUI->m_deviceSourceAPI->getHardwareId() == (*it)->m_deviceSourceAPI->getHardwareId()) && - (deviceUI->m_deviceSourceAPI->getSampleSourceSerial() == (*it)->m_deviceSourceAPI->getSampleSourceSerial())) - { - (*it)->m_deviceSourceAPI->addSourceBuddy(deviceUI->m_deviceSourceAPI); - } - } - - if ((*it)->m_deviceSinkEngine) // it is a sink device - { - if ((deviceUI->m_deviceSourceAPI->getHardwareId() == (*it)->m_deviceSinkAPI->getHardwareId()) && - (deviceUI->m_deviceSourceAPI->getSampleSourceSerial() == (*it)->m_deviceSinkAPI->getSampleSinkSerial())) - { - (*it)->m_deviceSinkAPI->addSourceBuddy(deviceUI->m_deviceSourceAPI); - } - } - } - } - - if (currentSourceTabIndex == 0) - { - m_settings.setSourceIndex(deviceUI->m_samplingDeviceControl->getDeviceSelector()->currentIndex()); - } - } -} - -void MainWindow::on_sampleSink_confirmClicked(bool checked) -{ - // Do it in the currently selected source tab - int currentSinkTabIndex = ui->tabInputsSelect->currentIndex(); - - if (currentSinkTabIndex >= 0) - { - qDebug("MainWindow::on_sampleSink_confirmClicked: tab at %d", currentSinkTabIndex); - DeviceUISet *deviceUI = m_deviceUIs[currentSinkTabIndex]; - deviceUI->m_deviceSinkAPI->saveSinkSettings(m_settings.getWorkingPreset()); // save old API settings - int selectedComboIndex = deviceUI->m_samplingDeviceControl->getDeviceSelector()->currentIndex(); - void *devicePtr = deviceUI->m_samplingDeviceControl->getDeviceSelector()->itemData(selectedComboIndex).value(); - deviceUI->m_deviceSinkAPI->stopGeneration(); - deviceUI->m_deviceSinkAPI->clearBuddiesLists(); // remove old API from buddies lists - m_pluginManager->selectSampleSinkByDevice(devicePtr, deviceUI->m_deviceSinkAPI); // sets the new API - deviceUI->m_deviceSinkAPI->loadSinkSettings(m_settings.getWorkingPreset()); // load new API settings - - // add to buddies list - std::vector::iterator it = m_deviceUIs.begin(); - for (; it != m_deviceUIs.end(); ++it) - { - if (*it != deviceUI) // do not add to itself - { - if ((*it)->m_deviceSourceEngine) // it is a source device - { - if ((deviceUI->m_deviceSinkAPI->getHardwareId() == (*it)->m_deviceSourceAPI->getHardwareId()) && - (deviceUI->m_deviceSinkAPI->getSampleSinkSerial() == (*it)->m_deviceSourceAPI->getSampleSourceSerial())) - { - (*it)->m_deviceSourceAPI->addSinkBuddy(deviceUI->m_deviceSinkAPI); - } - } - - if ((*it)->m_deviceSinkEngine) // it is a sink device - { - if ((deviceUI->m_deviceSinkAPI->getHardwareId() == (*it)->m_deviceSinkAPI->getHardwareId()) && - (deviceUI->m_deviceSinkAPI->getSampleSinkSerial() == (*it)->m_deviceSinkAPI->getSampleSinkSerial())) - { - (*it)->m_deviceSinkAPI->addSinkBuddy(deviceUI->m_deviceSinkAPI); - } - } - } - } - } -} - -void MainWindow::on_channel_addClicked(bool checked) -{ - // Do it in the currently selected source tab - int currentSourceTabIndex = ui->tabInputsSelect->currentIndex(); - - if (currentSourceTabIndex >= 0) - { - DeviceUISet *deviceUI = m_deviceUIs[currentSourceTabIndex]; - - if (deviceUI->m_deviceSourceEngine) // source device => Rx channels - { - m_pluginManager->createRxChannelInstance(deviceUI->m_samplingDeviceControl->getChannelSelector()->currentIndex(), deviceUI->m_deviceSourceAPI); - } - else if (deviceUI->m_deviceSinkEngine) // sink device => Tx channels - { - uint32_t nbSources = deviceUI->m_deviceSinkAPI->getNumberOfSources(); - - if (nbSources > 0) { - QMessageBox::information(this, tr("Message"), tr("%1 channel(s) already in use. Multiple transmission channels is experimental. You may experience performance problems").arg(nbSources)); - } - - m_pluginManager->createTxChannelInstance(deviceUI->m_samplingDeviceControl->getChannelSelector()->currentIndex(), deviceUI->m_deviceSinkAPI); - } - } - -} - -void MainWindow::on_action_About_triggered() -{ - AboutDialog dlg(this); - dlg.exec(); -} - -void MainWindow::on_action_addSourceDevice_triggered() -{ - addSourceDevice(); -} - -void MainWindow::on_action_addSinkDevice_triggered() -{ - addSinkDevice(); -} - -void MainWindow::on_action_removeLastDevice_triggered() -{ - if (m_deviceUIs.size() > 1) - { - removeLastDevice(); - } -} - -void MainWindow::on_action_reloadDevices_triggered() -{ - // all devices must be stopped - std::vector::iterator it = m_deviceUIs.begin(); - for (; it != m_deviceUIs.end(); ++it) - { - if ((*it)->m_deviceSourceEngine) // it is a source device - { - if ((*it)->m_deviceSourceEngine->state() == DSPDeviceSourceEngine::StRunning) - { - QMessageBox::information(this, tr("Message"), tr("Stop all devices for reload to take effect")); - return; - } - } - - if ((*it)->m_deviceSinkEngine) // it is a sink device - { - if ((*it)->m_deviceSinkEngine->state() == DSPDeviceSinkEngine::StRunning) - { - QMessageBox::information(this, tr("Message"), tr("Stop all devices for reload to take effect")); - return; - } - } - } - - // re-scan devices - m_pluginManager->updateSampleSourceDevices(); - m_pluginManager->updateSampleSinkDevices(); - - // re-populate device selectors keeping the same selection - it = m_deviceUIs.begin(); - for (; it != m_deviceUIs.end(); ++it) - { - if ((*it)->m_deviceSourceEngine) // it is a source device - { - QComboBox *deviceSelectorComboBox = (*it)->m_samplingDeviceControl->getDeviceSelector(); - bool sampleSourceSignalsBlocked = deviceSelectorComboBox->blockSignals(true); - m_pluginManager->fillSampleSourceSelector(deviceSelectorComboBox, (*it)->m_deviceSourceEngine->getUID()); - int newIndex = m_pluginManager->getSampleSourceSelectorIndex(deviceSelectorComboBox, (*it)->m_deviceSourceAPI); - deviceSelectorComboBox->setCurrentIndex(newIndex); - deviceSelectorComboBox->blockSignals(sampleSourceSignalsBlocked); - } - - if ((*it)->m_deviceSinkEngine) // it is a sink device - { - QComboBox *deviceSelectorComboBox = (*it)->m_samplingDeviceControl->getDeviceSelector(); - bool sampleSinkSignalsBlocked = deviceSelectorComboBox->blockSignals(true); - m_pluginManager->fillSampleSinkSelector(deviceSelectorComboBox, (*it)->m_deviceSinkEngine->getUID()); - int newIndex = m_pluginManager->getSampleSinkSelectorIndex(deviceSelectorComboBox, (*it)->m_deviceSinkAPI); - deviceSelectorComboBox->setCurrentIndex(newIndex); - deviceSelectorComboBox->blockSignals(sampleSinkSignalsBlocked); - } - } -} - -void MainWindow::on_action_Exit_triggered() -{ - savePresetSettings(m_settings.getWorkingPreset(), 0); - m_settings.save(); - - while (m_deviceUIs.size() > 0) - { - removeLastDevice(); - } -} - -void MainWindow::tabInputViewIndexChanged() -{ - int inputViewIndex = ui->tabInputsView->currentIndex(); - - if ((inputViewIndex >= 0) && (m_masterTabIndex >= 0) && (inputViewIndex != m_masterTabIndex)) - { - DeviceUISet *deviceUI = m_deviceUIs[inputViewIndex]; - DeviceUISet *lastdeviceUI = m_deviceUIs[m_masterTabIndex]; - lastdeviceUI->m_mainWindowState = saveState(); - restoreState(deviceUI->m_mainWindowState); - m_masterTabIndex = inputViewIndex; - } - - ui->tabSpectra->setCurrentIndex(inputViewIndex); - ui->tabChannels->setCurrentIndex(inputViewIndex); - ui->tabInputsSelect->setCurrentIndex(inputViewIndex); - ui->tabSpectraGUI->setCurrentIndex(inputViewIndex); -} - -void MainWindow::updateStatus() -{ - m_dateTimeWidget->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss t")); -} - -MainWindow::DeviceUISet::DeviceUISet(QTimer& timer) -{ - m_spectrum = new GLSpectrum; - m_spectrumVis = new SpectrumVis(m_spectrum); - m_spectrum->connectTimer(timer); - m_spectrumGUI = new GLSpectrumGUI; - m_spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, m_spectrum); - m_channelWindow = new ChannelWindow; - m_samplingDeviceControl = new SamplingDeviceControl; - m_deviceSourceEngine = 0; - m_deviceSourceAPI = 0; - m_deviceSinkEngine = 0; - m_deviceSinkAPI = 0; - - // m_spectrum needs to have its font to be set since it cannot be inherited from the main window - QFont font; - font.setFamily(QStringLiteral("Sans Serif")); - font.setPointSize(9); - m_spectrum->setFont(font); - -} - -MainWindow::DeviceUISet::~DeviceUISet() -{ - delete m_samplingDeviceControl; - delete m_channelWindow; - delete m_spectrumGUI; - delete m_spectrumVis; - delete m_spectrum; -} +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // +// written by Christian Daniel // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "device/devicesourceapi.h" +#include "device/devicesinkapi.h" +#include "audio/audiodeviceinfo.h" +#include "gui/indicator.h" +#include "gui/presetitem.h" +#include "gui/addpresetdialog.h" +#include "gui/pluginsdialog.h" +#include "gui/aboutdialog.h" +#include "gui/rollupwidget.h" +#include "gui/channelwindow.h" +#include "gui/audiodialog.h" +#include "gui/samplingdevicecontrol.h" +#include "gui/mypositiondialog.h" +#include "dsp/dspengine.h" +#include "dsp/spectrumvis.h" +#include "dsp/dspcommands.h" +#include "plugin/plugingui.h" +#include "plugin/pluginapi.h" +#include "plugin/plugingui.h" + +#include "gui/glspectrum.h" +#include "gui/glspectrumgui.h" + +#include +#include + +MainWindow::MainWindow(QWidget* parent) : + QMainWindow(parent), + ui(new Ui::MainWindow), + m_masterTabIndex(0), + m_settings(), + m_dspEngine(DSPEngine::instance()), + m_lastEngineState((DSPDeviceSourceEngine::State)-1), + m_inputGUI(0), + m_sampleRate(0), + m_centerFrequency(0), + m_sampleFileName(std::string("./test.sdriq")) +{ + qDebug() << "MainWindow::MainWindow: start"; + + m_settings.setAudioDeviceInfo(&m_audioDeviceInfo); + + ui->setupUi(this); + createStatusBar(); + + setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); + setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); + setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); + setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + + // work around broken Qt dock widget ordering + removeDockWidget(ui->inputViewDock); + removeDockWidget(ui->inputSelectDock); + removeDockWidget(ui->spectraDisplayDock); + removeDockWidget(ui->presetDock); + removeDockWidget(ui->channelDock); + addDockWidget(Qt::LeftDockWidgetArea, ui->inputSelectDock); + addDockWidget(Qt::LeftDockWidgetArea, ui->inputViewDock); + addDockWidget(Qt::LeftDockWidgetArea, ui->spectraDisplayDock); + addDockWidget(Qt::LeftDockWidgetArea, ui->presetDock); + addDockWidget(Qt::RightDockWidgetArea, ui->channelDock); + + ui->inputViewDock->show(); + ui->inputSelectDock->show(); + ui->spectraDisplayDock->show(); + ui->presetDock->show(); + ui->channelDock->show(); + + ui->menu_Window->addAction(ui->inputViewDock->toggleViewAction()); + ui->menu_Window->addAction(ui->inputSelectDock->toggleViewAction()); + ui->menu_Window->addAction(ui->spectraDisplayDock->toggleViewAction()); + ui->menu_Window->addAction(ui->presetDock->toggleViewAction()); + ui->menu_Window->addAction(ui->channelDock->toggleViewAction()); + + ui->tabInputsView->setStyleSheet("QWidget { background: rgb(50,50,50); } " + "QToolButton::checked { background: rgb(128,70,0); } " + "QComboBox::item:selected { color: rgb(255,140,0); } " + "QTabWidget::pane { border: 1px solid #C06900; } " + "QTabBar::tab:selected { background: rgb(128,70,0); }"); + ui->tabInputsSelect->setStyleSheet("QWidget { background: rgb(50,50,50); } " + "QToolButton::checked { background: rgb(128,70,0); } " + "QComboBox::item:selected { color: rgb(255,140,0); } " + "QTabWidget::pane { border: 1px solid #808080; } " + "QTabBar::tab:selected { background: rgb(100,100,100); }"); + + m_pluginManager = new PluginManager(this); + m_pluginManager->loadPlugins(); + + connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()), Qt::QueuedConnection); + + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); + m_statusTimer.start(1000); + + m_masterTimer.start(50); + + qDebug() << "MainWindow::MainWindow: add the first device..."; + + addSourceDevice(); // add the first device + + qDebug() << "MainWindow::MainWindow: load settings..."; + + loadSettings(); + + qDebug() << "MainWindow::MainWindow: select SampleSource from settings..."; + + int sampleSourceIndex = m_settings.getSourceIndex(); + sampleSourceIndex = m_pluginManager->selectSampleSourceByIndex(sampleSourceIndex, m_deviceUIs.back()->m_deviceSourceAPI); + + if (sampleSourceIndex < 0) + { + qCritical("MainWindow::MainWindow: no sample source. Exit"); + exit(0); + } + + bool sampleSourceSignalsBlocked = m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(true); + m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->setCurrentIndex(sampleSourceIndex); + m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(sampleSourceSignalsBlocked); + + qDebug() << "MainWindow::MainWindow: load current preset settings..."; + + loadPresetSettings(m_settings.getWorkingPreset(), 0); + + qDebug() << "MainWindow::MainWindow: apply settings..."; + + applySettings(); + + qDebug() << "MainWindow::MainWindow: update preset controls..."; + + updatePresetControls(); + + connect(ui->tabInputsView, SIGNAL(currentChanged(int)), this, SLOT(tabInputViewIndexChanged())); + + qDebug() << "MainWindow::MainWindow: end"; +} + +MainWindow::~MainWindow() +{ + delete m_pluginManager; + delete m_dateTimeWidget; + delete m_showSystemWidget; + + delete ui; +} + +void MainWindow::addSourceDevice() +{ + DSPDeviceSourceEngine *dspDeviceSourceEngine = m_dspEngine->addDeviceSourceEngine(); + dspDeviceSourceEngine->start(); + + uint dspDeviceSourceEngineUID = dspDeviceSourceEngine->getUID(); + char uidCStr[16]; + sprintf(uidCStr, "UID:%d", dspDeviceSourceEngineUID); + + m_deviceUIs.push_back(new DeviceUISet(m_masterTimer)); + m_deviceUIs.back()->m_deviceSourceEngine = dspDeviceSourceEngine; + + int deviceTabIndex = m_deviceUIs.size()-1; + char tabNameCStr[16]; + sprintf(tabNameCStr, "R%d", deviceTabIndex); + + DeviceSourceAPI *deviceSourceAPI = new DeviceSourceAPI(this, deviceTabIndex, dspDeviceSourceEngine, m_deviceUIs.back()->m_spectrum, m_deviceUIs.back()->m_channelWindow); + + m_deviceUIs.back()->m_deviceSourceAPI = deviceSourceAPI; + m_deviceUIs.back()->m_samplingDeviceControl->setDeviceAPI(deviceSourceAPI); + m_deviceUIs.back()->m_samplingDeviceControl->setPluginManager(m_pluginManager); + m_pluginManager->populateRxChannelComboBox(m_deviceUIs.back()->m_samplingDeviceControl->getChannelSelector()); + + connect(m_deviceUIs.back()->m_samplingDeviceControl->getAddChannelButton(), SIGNAL(clicked(bool)), this, SLOT(on_channel_addClicked(bool))); + + dspDeviceSourceEngine->addSink(m_deviceUIs.back()->m_spectrumVis); + ui->tabSpectra->addTab(m_deviceUIs.back()->m_spectrum, tabNameCStr); + ui->tabSpectraGUI->addTab(m_deviceUIs.back()->m_spectrumGUI, tabNameCStr); + ui->tabChannels->addTab(m_deviceUIs.back()->m_channelWindow, tabNameCStr); + + bool sampleSourceSignalsBlocked = m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(true); + m_pluginManager->duplicateLocalSampleSourceDevices(dspDeviceSourceEngineUID); + m_pluginManager->fillSampleSourceSelector(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector(), dspDeviceSourceEngineUID); + + connect(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelectionConfirm(), SIGNAL(clicked(bool)), this, SLOT(on_sampleSource_confirmClicked(bool))); + + m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(sampleSourceSignalsBlocked); + ui->tabInputsSelect->addTab(m_deviceUIs.back()->m_samplingDeviceControl, tabNameCStr); + ui->tabInputsSelect->setTabToolTip(deviceTabIndex, QString(uidCStr)); + + int sampleSourceIndex = m_pluginManager->selectSampleSourceBySerialOrSequence("sdrangel.samplesource.filesource", "0", 0, m_deviceUIs.back()->m_deviceSourceAPI); +} + +void MainWindow::addSinkDevice() +{ + DSPDeviceSinkEngine *dspDeviceSinkEngine = m_dspEngine->addDeviceSinkEngine(); + dspDeviceSinkEngine->start(); + + uint dspDeviceSinkEngineUID = dspDeviceSinkEngine->getUID(); + char uidCStr[16]; + sprintf(uidCStr, "UID:%d", dspDeviceSinkEngineUID); + + m_deviceUIs.push_back(new DeviceUISet(m_masterTimer)); + m_deviceUIs.back()->m_deviceSourceEngine = 0; + m_deviceUIs.back()->m_deviceSinkEngine = dspDeviceSinkEngine; + + int deviceTabIndex = m_deviceUIs.size()-1; + char tabNameCStr[16]; + sprintf(tabNameCStr, "T%d", deviceTabIndex); + + DeviceSinkAPI *deviceSinkAPI = new DeviceSinkAPI(this, deviceTabIndex, dspDeviceSinkEngine, m_deviceUIs.back()->m_spectrum, m_deviceUIs.back()->m_channelWindow); + + m_deviceUIs.back()->m_deviceSourceAPI = 0; + m_deviceUIs.back()->m_deviceSinkAPI = deviceSinkAPI; + m_deviceUIs.back()->m_samplingDeviceControl->setDeviceAPI(deviceSinkAPI); + m_deviceUIs.back()->m_samplingDeviceControl->setPluginManager(m_pluginManager); + m_pluginManager->populateTxChannelComboBox(m_deviceUIs.back()->m_samplingDeviceControl->getChannelSelector()); + + connect(m_deviceUIs.back()->m_samplingDeviceControl->getAddChannelButton(), SIGNAL(clicked(bool)), this, SLOT(on_channel_addClicked(bool))); + + dspDeviceSinkEngine->addSpectrumSink(m_deviceUIs.back()->m_spectrumVis); + ui->tabSpectra->addTab(m_deviceUIs.back()->m_spectrum, tabNameCStr); + ui->tabSpectraGUI->addTab(m_deviceUIs.back()->m_spectrumGUI, tabNameCStr); + ui->tabChannels->addTab(m_deviceUIs.back()->m_channelWindow, tabNameCStr); + + bool sampleSourceSignalsBlocked = m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(true); + m_pluginManager->duplicateLocalSampleSinkDevices(dspDeviceSinkEngineUID); + m_pluginManager->fillSampleSinkSelector(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector(), dspDeviceSinkEngineUID); + + connect(m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelectionConfirm(), SIGNAL(clicked(bool)), this, SLOT(on_sampleSink_confirmClicked(bool))); + + m_deviceUIs.back()->m_samplingDeviceControl->getDeviceSelector()->blockSignals(sampleSourceSignalsBlocked); + ui->tabInputsSelect->addTab(m_deviceUIs.back()->m_samplingDeviceControl, tabNameCStr); + ui->tabInputsSelect->setTabToolTip(deviceTabIndex, QString(uidCStr)); + + int sampleSinkIndex = m_pluginManager->selectSampleSinkBySerialOrSequence("sdrangel.samplesink.filesink", "0", 0, m_deviceUIs.back()->m_deviceSinkAPI); +} + +void MainWindow::removeLastDevice() +{ + if (m_deviceUIs.back()->m_deviceSourceEngine) // source tab + { + DSPDeviceSourceEngine *lastDeviceEngine = m_deviceUIs.back()->m_deviceSourceEngine; + lastDeviceEngine->stopAcquistion(); + lastDeviceEngine->removeSink(m_deviceUIs.back()->m_spectrumVis); + + ui->tabSpectraGUI->removeTab(ui->tabSpectraGUI->count() - 1); + ui->tabSpectra->removeTab(ui->tabSpectra->count() - 1); + + m_deviceUIs.back()->m_deviceSourceAPI->freeAll(); + m_deviceUIs.back()->m_deviceSourceAPI->clearBuddiesLists(); // remove old API from buddies lists + + ui->tabChannels->removeTab(ui->tabChannels->count() - 1); + + ui->tabInputsSelect->removeTab(ui->tabInputsSelect->count() - 1); + + m_deviceWidgetTabs.removeLast();m_pluginManager->loadPlugins(); + ui->tabInputsView->clear(); + + for (int i = 0; i < m_deviceWidgetTabs.size(); i++) + { + qDebug("MainWindow::removeLastDevice: adding back tab for %s", m_deviceWidgetTabs[i].displayName.toStdString().c_str()); + ui->tabInputsView->addTab(m_deviceWidgetTabs[i].gui, m_deviceWidgetTabs[i].tabName); + ui->tabInputsView->setTabToolTip(i, m_deviceWidgetTabs[i].displayName); + } + + delete m_deviceUIs.back(); + + lastDeviceEngine->stop(); + m_dspEngine->removeLastDeviceSourceEngine(); + } + else if (m_deviceUIs.back()->m_deviceSinkEngine) // sink tab + { + DSPDeviceSinkEngine *lastDeviceEngine = m_deviceUIs.back()->m_deviceSinkEngine; + lastDeviceEngine->stopGeneration(); + lastDeviceEngine->removeSpectrumSink(m_deviceUIs.back()->m_spectrumVis); + + ui->tabSpectraGUI->removeTab(ui->tabSpectraGUI->count() - 1); + ui->tabSpectra->removeTab(ui->tabSpectra->count() - 1); + + m_deviceUIs.back()->m_deviceSinkAPI->freeAll(); + m_deviceUIs.back()->m_deviceSinkAPI->clearBuddiesLists(); // remove old API from buddies lists + + ui->tabChannels->removeTab(ui->tabChannels->count() - 1); + + ui->tabInputsSelect->removeTab(ui->tabInputsSelect->count() - 1); + + m_deviceWidgetTabs.removeLast(); + ui->tabInputsView->clear(); + + for (int i = 0; i < m_deviceWidgetTabs.size(); i++) + { + qDebug("MainWindow::removeLastDevice: adding back tab for %s", m_deviceWidgetTabs[i].displayName.toStdString().c_str()); + ui->tabInputsView->addTab(m_deviceWidgetTabs[i].gui, m_deviceWidgetTabs[i].tabName); + ui->tabInputsView->setTabToolTip(i, m_deviceWidgetTabs[i].displayName); + } + + delete m_deviceUIs.back(); + + lastDeviceEngine->stop(); + m_dspEngine->removeLastDeviceSinkEngine(); + } + + m_deviceUIs.pop_back(); +} + +void MainWindow::addChannelRollup(int deviceTabIndex, QWidget* widget) +{ + if (deviceTabIndex < ui->tabInputsView->count()) + { + DeviceUISet *deviceUI = m_deviceUIs[deviceTabIndex]; + deviceUI->m_channelWindow->addRollupWidget(widget); + ui->channelDock->show(); + ui->channelDock->raise(); + } +} + +void MainWindow::addViewAction(QAction* action) +{ + ui->menu_Window->addAction(action); +} + +void MainWindow::setDeviceGUI(int deviceTabIndex, QWidget* gui, const QString& deviceDisplayName, bool sourceDevice) +{ + char tabNameCStr[16]; + + if (sourceDevice) + { + sprintf(tabNameCStr, "R%d", deviceTabIndex); + } + else + { + sprintf(tabNameCStr, "T%d", deviceTabIndex); + } + + qDebug("MainWindow::setDeviceGUI: insert %s tab at %d", sourceDevice ? "Rx" : "Tx", deviceTabIndex); + + if (deviceTabIndex < m_deviceWidgetTabs.size()) + { + m_deviceWidgetTabs[deviceTabIndex] = {gui, deviceDisplayName, QString(tabNameCStr)}; + } + else + { + m_deviceWidgetTabs.append({gui, deviceDisplayName, QString(tabNameCStr)}); + } + + ui->tabInputsView->clear(); + + for (int i = 0; i < m_deviceWidgetTabs.size(); i++) + { + qDebug("MainWindow::setDeviceGUI: adding tab for %s", m_deviceWidgetTabs[i].displayName.toStdString().c_str()); + ui->tabInputsView->addTab(m_deviceWidgetTabs[i].gui, m_deviceWidgetTabs[i].tabName); + ui->tabInputsView->setTabToolTip(i, m_deviceWidgetTabs[i].displayName); + } + + ui->tabInputsView->setCurrentIndex(deviceTabIndex); +} + +void MainWindow::loadSettings() +{ + qDebug() << "MainWindow::loadSettings"; + + m_settings.load(); + m_settings.sortPresets(); + + for(int i = 0; i < m_settings.getPresetCount(); ++i) + { + addPresetToTree(m_settings.getPreset(i)); + } +} + +void MainWindow::loadPresetSettings(const Preset* preset, int tabIndex) +{ + qDebug("MainWindow::loadPresetSettings: preset [%s | %s]", + qPrintable(preset->getGroup()), + qPrintable(preset->getDescription())); + + if (tabIndex >= 0) + { + DeviceUISet *deviceUI = m_deviceUIs[tabIndex]; + + if (deviceUI->m_deviceSourceEngine) // source device + { + deviceUI->m_spectrumGUI->deserialize(preset->getSpectrumConfig()); + deviceUI->m_deviceSourceAPI->loadSourceSettings(preset); + deviceUI->m_deviceSourceAPI->loadChannelSettings(preset, &(m_pluginManager->m_pluginAPI)); + } + else if (deviceUI->m_deviceSinkEngine) // sink device + { + deviceUI->m_spectrumGUI->deserialize(preset->getSpectrumConfig()); + deviceUI->m_deviceSinkAPI->loadSinkSettings(preset); + deviceUI->m_deviceSinkAPI->loadChannelSettings(preset, &(m_pluginManager->m_pluginAPI)); + } + } + + // has to be last step + restoreState(preset->getLayout()); +} + +void MainWindow::savePresetSettings(Preset* preset, int tabIndex) +{ + qDebug("MainWindow::savePresetSettings: preset [%s | %s]", + qPrintable(preset->getGroup()), + qPrintable(preset->getDescription())); + + // Save from currently selected source tab + //int currentSourceTabIndex = ui->tabInputsView->currentIndex(); + DeviceUISet *deviceUI = m_deviceUIs[tabIndex]; + + if (deviceUI->m_deviceSourceEngine) // source device + { + preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); + preset->clearChannels(); + deviceUI->m_deviceSourceAPI->saveChannelSettings(preset); + deviceUI->m_deviceSourceAPI->saveSourceSettings(preset); + } + else if (deviceUI->m_deviceSinkEngine) // sink device + { + preset->setSpectrumConfig(deviceUI->m_spectrumGUI->serialize()); + preset->clearChannels(); + preset->setSourcePreset(false); + deviceUI->m_deviceSinkAPI->saveChannelSettings(preset); + deviceUI->m_deviceSinkAPI->saveSinkSettings(preset); + } + + preset->setLayout(saveState()); +} + +void MainWindow::createStatusBar() +{ + QString qtVersionStr = QString("Qt %1 ").arg(QT_VERSION_STR); +#if QT_VERSION >= 0x050400 + m_showSystemWidget = new QLabel("SDRangel v3.3.4 " + qtVersionStr + QSysInfo::prettyProductName(), this); +#else + m_showSystemWidget = new QLabel("SDRangel v3.3.4 " + qtVersionStr, this); +#endif + statusBar()->addPermanentWidget(m_showSystemWidget); + + m_dateTimeWidget = new QLabel(tr("Date"), this); + m_dateTimeWidget->setToolTip(tr("Current date/time")); + statusBar()->addPermanentWidget(m_dateTimeWidget); +} + +void MainWindow::closeEvent(QCloseEvent*) +{ +} + +void MainWindow::updatePresetControls() +{ + ui->presetTree->resizeColumnToContents(0); + + if(ui->presetTree->currentItem() != 0) + { + ui->presetDelete->setEnabled(true); + ui->presetLoad->setEnabled(true); + } + else + { + ui->presetDelete->setEnabled(false); + ui->presetLoad->setEnabled(false); + } +} + +QTreeWidgetItem* MainWindow::addPresetToTree(const Preset* preset) +{ + QTreeWidgetItem* group = 0; + + for(int i = 0; i < ui->presetTree->topLevelItemCount(); i++) + { + if(ui->presetTree->topLevelItem(i)->text(0) == preset->getGroup()) + { + group = ui->presetTree->topLevelItem(i); + break; + } + } + + if(group == 0) + { + QStringList sl; + sl.append(preset->getGroup()); + group = new QTreeWidgetItem(ui->presetTree, sl, PGroup); + group->setFirstColumnSpanned(true); + group->setExpanded(true); + ui->presetTree->sortByColumn(0, Qt::AscendingOrder); + } + + QStringList sl; + sl.append(QString("%1").arg(preset->getCenterFrequency() / 1e6f, 0, 'f', 3)); // frequency column + sl.append(QString("%1").arg(preset->isSourcePreset() ? 'R' : 'T')); // mode column + sl.append(preset->getDescription()); // description column + PresetItem* item = new PresetItem(group, sl, preset->getCenterFrequency(), PItem); + item->setTextAlignment(0, Qt::AlignRight); + item->setData(0, Qt::UserRole, qVariantFromValue(preset)); + ui->presetTree->resizeColumnToContents(0); // Resize frequency column to minimum + ui->presetTree->resizeColumnToContents(1); // Resize mode column to minimum + + updatePresetControls(); + return item; +} + +void MainWindow::applySettings() +{ +} + +void MainWindow::handleMessages() +{ + Message* message; + + while ((message = m_inputMessageQueue.pop()) != 0) + { + qDebug("MainWindow::handleMessages: message: %s", message->getIdentifier()); + delete message; + } +} + +void MainWindow::on_action_View_Fullscreen_toggled(bool checked) +{ + if(checked) + showFullScreen(); + else showNormal(); +} + +void MainWindow::on_presetSave_clicked() +{ + QStringList groups; + QString group; + QString description = ""; + for(int i = 0; i < ui->presetTree->topLevelItemCount(); i++) + groups.append(ui->presetTree->topLevelItem(i)->text(0)); + + QTreeWidgetItem* item = ui->presetTree->currentItem(); + if(item != 0) { + if(item->type() == PGroup) + group = item->text(0); + else if(item->type() == PItem) { + group = item->parent()->text(0); + description = item->text(0); + } + } + + AddPresetDialog dlg(groups, group, this); + + if (description.length() > 0) { + dlg.setDescription(description); + } + + if(dlg.exec() == QDialog::Accepted) { + Preset* preset = m_settings.newPreset(dlg.group(), dlg.description()); + savePresetSettings(preset, ui->tabInputsView->currentIndex()); + + ui->presetTree->setCurrentItem(addPresetToTree(preset)); + } +} + +void MainWindow::on_presetUpdate_clicked() +{ + QTreeWidgetItem* item = ui->presetTree->currentItem(); + + if(item != 0) { + if(item->type() == PItem) { + const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); + if (preset != 0) { + Preset* preset_mod = const_cast(preset); + savePresetSettings(preset_mod, ui->tabInputsView->currentIndex()); + } + } + } +} + +void MainWindow::on_presetExport_clicked() +{ + QTreeWidgetItem* item = ui->presetTree->currentItem(); + + if(item != 0) { + if(item->type() == PItem) + { + const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); + QString base64Str = preset->serialize().toBase64(); + QString fileName = QFileDialog::getSaveFileName(this, + tr("Open preset export file"), ".", tr("Preset export files (*.prex)")); + + if (fileName != "") + { + QFileInfo fileInfo(fileName); + + if (fileInfo.suffix() != "prex") { + fileName += ".prex"; + } + + QFile exportFile(fileName); + + if (exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QTextStream outstream(&exportFile); + outstream << base64Str; + exportFile.close(); + } + else + { + QMessageBox::information(this, tr("Message"), tr("Cannot open file for writing")); + } + } + } + } +} + +void MainWindow::on_presetImport_clicked() +{ + QTreeWidgetItem* item = ui->presetTree->currentItem(); + + if(item != 0) + { + QString group; + + if (item->type() == PGroup) { + group = item->text(0); + } else if (item->type() == PItem) { + group = item->parent()->text(0); + } else { + return; + } + + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open preset export file"), ".", tr("Preset export files (*.prex)")); + + if (fileName != "") + { + QFile exportFile(fileName); + + if (exportFile.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QByteArray base64Str; + QTextStream instream(&exportFile); + instream >> base64Str; + exportFile.close(); + + Preset* preset = m_settings.newPreset("", ""); + preset->deserialize(QByteArray::fromBase64(base64Str)); + preset->setGroup(group); // override with current group + + ui->presetTree->setCurrentItem(addPresetToTree(preset)); + } + else + { + QMessageBox::information(this, tr("Message"), tr("Cannot open file for reading")); + } + } + } +} + +void MainWindow::on_settingsSave_clicked() +{ + savePresetSettings(m_settings.getWorkingPreset(), ui->tabInputsView->currentIndex()); + m_settings.save(); +} + +void MainWindow::on_presetLoad_clicked() +{ + qDebug() << "MainWindow::on_presetLoad_clicked"; + + QTreeWidgetItem* item = ui->presetTree->currentItem(); + + if(item == 0) + { + qDebug("MainWindow::on_presetLoad_clicked: item null"); + updatePresetControls(); + return; + } + + const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); + + if(preset == 0) + { + qDebug("MainWindow::on_presetLoad_clicked: preset null"); + return; + } + + loadPresetSettings(preset, ui->tabInputsView->currentIndex()); + applySettings(); +} + +void MainWindow::on_presetDelete_clicked() +{ + QTreeWidgetItem* item = ui->presetTree->currentItem(); + if(item == 0) { + updatePresetControls(); + return; + } + const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); + if(preset == 0) + return; + + if(QMessageBox::question(this, tr("Delete Preset"), tr("Do you want to delete preset '%1'?").arg(preset->getDescription()), QMessageBox::No | QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { + delete item; + m_settings.deletePreset(preset); + } +} + +void MainWindow::on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) +{ + updatePresetControls(); +} + +void MainWindow::on_presetTree_itemActivated(QTreeWidgetItem *item, int column) +{ + on_presetLoad_clicked(); +} + +void MainWindow::on_action_Loaded_Plugins_triggered() +{ + PluginsDialog pluginsDialog(m_pluginManager, this); + pluginsDialog.exec(); +} + +void MainWindow::on_action_Audio_triggered() +{ + AudioDialog audioDialog(&m_audioDeviceInfo, this); + audioDialog.exec(); + m_dspEngine->setAudioInputVolume(m_audioDeviceInfo.getInputVolume()); + m_dspEngine->setAudioInputDeviceIndex(m_audioDeviceInfo.getInputDeviceIndex()); + m_dspEngine->setAudioOutputDeviceIndex(m_audioDeviceInfo.getOutputDeviceIndex()); +} + +void MainWindow::on_action_My_Position_triggered() +{ + MyPositionDialog myPositionDialog(m_settings, this); + myPositionDialog.exec(); +} + +void MainWindow::on_action_DV_Serial_triggered(bool checked) +{ + m_dspEngine->setDVSerialSupport(checked); + + if (checked) + { + std::vector deviceNames; + m_dspEngine->getDVSerialNames(deviceNames); + + if (deviceNames.size() == 0) + { + QMessageBox::information(this, tr("Message"), tr("No DV serial devices found")); + } + else + { + std::vector::iterator it = deviceNames.begin(); + std::string deviceNamesStr = "DV Serial devices found: "; + + while (it != deviceNames.end()) + { + if (it != deviceNames.begin()) { + deviceNamesStr += ","; + } + + deviceNamesStr += *it; + ++it; + } + + QMessageBox::information(this, tr("Message"), tr(deviceNamesStr.c_str())); + } + } +} + +void MainWindow::on_sampleSource_confirmClicked(bool checked) +{ + // Do it in the currently selected source tab + int currentSourceTabIndex = ui->tabInputsSelect->currentIndex(); + + if (currentSourceTabIndex >= 0) + { + qDebug("MainWindow::on_sampleSource_confirmClicked: tab at %d", currentSourceTabIndex); + DeviceUISet *deviceUI = m_deviceUIs[currentSourceTabIndex]; + deviceUI->m_deviceSourceAPI->saveSourceSettings(m_settings.getWorkingPreset()); // save old API settings + int selectedComboIndex = deviceUI->m_samplingDeviceControl->getDeviceSelector()->currentIndex(); + void *devicePtr = deviceUI->m_samplingDeviceControl->getDeviceSelector()->itemData(selectedComboIndex).value(); + deviceUI->m_deviceSourceAPI->stopAcquisition(); + + // TODO: deviceUI->m_deviceSourceAPI->setSampleSourcePluginGUI(0); // deletes old GUI and input object + deviceUI->m_deviceSourceAPI->clearBuddiesLists(); // clear old API buddies lists + + m_pluginManager->selectSampleSourceByDevice(devicePtr, deviceUI->m_deviceSourceAPI); // sets the new API + + // TODO: move up add to buddies list + + // TODO: +// // constructs new GUI and input object +// QWidget *gui; +// PluginManager::SamplingDevice *sampleSourceDevice = (PluginManager::SamplingDevice *) devicePtr; +// PluginGUI *pluginGUI = sampleSourceDevice->m_plugin->createSampleSourcePluginGUI(sampleSourceDevice->m_deviceId, &gui, deviceUI->m_deviceSourceAPI); +// +// deviceUI->m_deviceSourceAPI->setSampleSourcePluginGUI(pluginGUI); +// deviceUI->m_deviceSourceAPI->setInputGUI(gui, sampleSourceDevice->m_displayName); + + deviceUI->m_deviceSourceAPI->loadSourceSettings(m_settings.getWorkingPreset()); // load new API settings + + // add to buddies list + std::vector::iterator it = m_deviceUIs.begin(); + for (; it != m_deviceUIs.end(); ++it) + { + if (*it != deviceUI) // do not add to itself + { + if ((*it)->m_deviceSourceEngine) // it is a source device + { + if ((deviceUI->m_deviceSourceAPI->getHardwareId() == (*it)->m_deviceSourceAPI->getHardwareId()) && + (deviceUI->m_deviceSourceAPI->getSampleSourceSerial() == (*it)->m_deviceSourceAPI->getSampleSourceSerial())) + { + (*it)->m_deviceSourceAPI->addSourceBuddy(deviceUI->m_deviceSourceAPI); + } + } + + if ((*it)->m_deviceSinkEngine) // it is a sink device + { + if ((deviceUI->m_deviceSourceAPI->getHardwareId() == (*it)->m_deviceSinkAPI->getHardwareId()) && + (deviceUI->m_deviceSourceAPI->getSampleSourceSerial() == (*it)->m_deviceSinkAPI->getSampleSinkSerial())) + { + (*it)->m_deviceSinkAPI->addSourceBuddy(deviceUI->m_deviceSourceAPI); + } + } + } + } + + if (currentSourceTabIndex == 0) + { + m_settings.setSourceIndex(deviceUI->m_samplingDeviceControl->getDeviceSelector()->currentIndex()); + } + } +} + +void MainWindow::on_sampleSink_confirmClicked(bool checked) +{ + // Do it in the currently selected source tab + int currentSinkTabIndex = ui->tabInputsSelect->currentIndex(); + + if (currentSinkTabIndex >= 0) + { + qDebug("MainWindow::on_sampleSink_confirmClicked: tab at %d", currentSinkTabIndex); + DeviceUISet *deviceUI = m_deviceUIs[currentSinkTabIndex]; + deviceUI->m_deviceSinkAPI->saveSinkSettings(m_settings.getWorkingPreset()); // save old API settings + int selectedComboIndex = deviceUI->m_samplingDeviceControl->getDeviceSelector()->currentIndex(); + void *devicePtr = deviceUI->m_samplingDeviceControl->getDeviceSelector()->itemData(selectedComboIndex).value(); + deviceUI->m_deviceSinkAPI->stopGeneration(); + deviceUI->m_deviceSinkAPI->clearBuddiesLists(); // remove old API from buddies lists + m_pluginManager->selectSampleSinkByDevice(devicePtr, deviceUI->m_deviceSinkAPI); // sets the new API + deviceUI->m_deviceSinkAPI->loadSinkSettings(m_settings.getWorkingPreset()); // load new API settings + + // add to buddies list + std::vector::iterator it = m_deviceUIs.begin(); + for (; it != m_deviceUIs.end(); ++it) + { + if (*it != deviceUI) // do not add to itself + { + if ((*it)->m_deviceSourceEngine) // it is a source device + { + if ((deviceUI->m_deviceSinkAPI->getHardwareId() == (*it)->m_deviceSourceAPI->getHardwareId()) && + (deviceUI->m_deviceSinkAPI->getSampleSinkSerial() == (*it)->m_deviceSourceAPI->getSampleSourceSerial())) + { + (*it)->m_deviceSourceAPI->addSinkBuddy(deviceUI->m_deviceSinkAPI); + } + } + + if ((*it)->m_deviceSinkEngine) // it is a sink device + { + if ((deviceUI->m_deviceSinkAPI->getHardwareId() == (*it)->m_deviceSinkAPI->getHardwareId()) && + (deviceUI->m_deviceSinkAPI->getSampleSinkSerial() == (*it)->m_deviceSinkAPI->getSampleSinkSerial())) + { + (*it)->m_deviceSinkAPI->addSinkBuddy(deviceUI->m_deviceSinkAPI); + } + } + } + } + } +} + +void MainWindow::on_channel_addClicked(bool checked) +{ + // Do it in the currently selected source tab + int currentSourceTabIndex = ui->tabInputsSelect->currentIndex(); + + if (currentSourceTabIndex >= 0) + { + DeviceUISet *deviceUI = m_deviceUIs[currentSourceTabIndex]; + + if (deviceUI->m_deviceSourceEngine) // source device => Rx channels + { + m_pluginManager->createRxChannelInstance(deviceUI->m_samplingDeviceControl->getChannelSelector()->currentIndex(), deviceUI->m_deviceSourceAPI); + } + else if (deviceUI->m_deviceSinkEngine) // sink device => Tx channels + { + uint32_t nbSources = deviceUI->m_deviceSinkAPI->getNumberOfSources(); + + if (nbSources > 0) { + QMessageBox::information(this, tr("Message"), tr("%1 channel(s) already in use. Multiple transmission channels is experimental. You may experience performance problems").arg(nbSources)); + } + + m_pluginManager->createTxChannelInstance(deviceUI->m_samplingDeviceControl->getChannelSelector()->currentIndex(), deviceUI->m_deviceSinkAPI); + } + } + +} + +void MainWindow::on_action_About_triggered() +{ + AboutDialog dlg(this); + dlg.exec(); +} + +void MainWindow::on_action_addSourceDevice_triggered() +{ + addSourceDevice(); +} + +void MainWindow::on_action_addSinkDevice_triggered() +{ + addSinkDevice(); +} + +void MainWindow::on_action_removeLastDevice_triggered() +{ + if (m_deviceUIs.size() > 1) + { + removeLastDevice(); + } +} + +void MainWindow::on_action_reloadDevices_triggered() +{ + // all devices must be stopped + std::vector::iterator it = m_deviceUIs.begin(); + for (; it != m_deviceUIs.end(); ++it) + { + if ((*it)->m_deviceSourceEngine) // it is a source device + { + if ((*it)->m_deviceSourceEngine->state() == DSPDeviceSourceEngine::StRunning) + { + QMessageBox::information(this, tr("Message"), tr("Stop all devices for reload to take effect")); + return; + } + } + + if ((*it)->m_deviceSinkEngine) // it is a sink device + { + if ((*it)->m_deviceSinkEngine->state() == DSPDeviceSinkEngine::StRunning) + { + QMessageBox::information(this, tr("Message"), tr("Stop all devices for reload to take effect")); + return; + } + } + } + + // re-scan devices + m_pluginManager->updateSampleSourceDevices(); + m_pluginManager->updateSampleSinkDevices(); + + // re-populate device selectors keeping the same selection + it = m_deviceUIs.begin(); + for (; it != m_deviceUIs.end(); ++it) + { + if ((*it)->m_deviceSourceEngine) // it is a source device + { + QComboBox *deviceSelectorComboBox = (*it)->m_samplingDeviceControl->getDeviceSelector(); + bool sampleSourceSignalsBlocked = deviceSelectorComboBox->blockSignals(true); + m_pluginManager->fillSampleSourceSelector(deviceSelectorComboBox, (*it)->m_deviceSourceEngine->getUID()); + int newIndex = m_pluginManager->getSampleSourceSelectorIndex(deviceSelectorComboBox, (*it)->m_deviceSourceAPI); + deviceSelectorComboBox->setCurrentIndex(newIndex); + deviceSelectorComboBox->blockSignals(sampleSourceSignalsBlocked); + } + + if ((*it)->m_deviceSinkEngine) // it is a sink device + { + QComboBox *deviceSelectorComboBox = (*it)->m_samplingDeviceControl->getDeviceSelector(); + bool sampleSinkSignalsBlocked = deviceSelectorComboBox->blockSignals(true); + m_pluginManager->fillSampleSinkSelector(deviceSelectorComboBox, (*it)->m_deviceSinkEngine->getUID()); + int newIndex = m_pluginManager->getSampleSinkSelectorIndex(deviceSelectorComboBox, (*it)->m_deviceSinkAPI); + deviceSelectorComboBox->setCurrentIndex(newIndex); + deviceSelectorComboBox->blockSignals(sampleSinkSignalsBlocked); + } + } +} + +void MainWindow::on_action_Exit_triggered() +{ + savePresetSettings(m_settings.getWorkingPreset(), 0); + m_settings.save(); + + while (m_deviceUIs.size() > 0) + { + removeLastDevice(); + } +} + +void MainWindow::tabInputViewIndexChanged() +{ + int inputViewIndex = ui->tabInputsView->currentIndex(); + + if ((inputViewIndex >= 0) && (m_masterTabIndex >= 0) && (inputViewIndex != m_masterTabIndex)) + { + DeviceUISet *deviceUI = m_deviceUIs[inputViewIndex]; + DeviceUISet *lastdeviceUI = m_deviceUIs[m_masterTabIndex]; + lastdeviceUI->m_mainWindowState = saveState(); + restoreState(deviceUI->m_mainWindowState); + m_masterTabIndex = inputViewIndex; + } + + ui->tabSpectra->setCurrentIndex(inputViewIndex); + ui->tabChannels->setCurrentIndex(inputViewIndex); + ui->tabInputsSelect->setCurrentIndex(inputViewIndex); + ui->tabSpectraGUI->setCurrentIndex(inputViewIndex); +} + +void MainWindow::updateStatus() +{ + m_dateTimeWidget->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss t")); +} + +MainWindow::DeviceUISet::DeviceUISet(QTimer& timer) +{ + m_spectrum = new GLSpectrum; + m_spectrumVis = new SpectrumVis(m_spectrum); + m_spectrum->connectTimer(timer); + m_spectrumGUI = new GLSpectrumGUI; + m_spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, m_spectrum); + m_channelWindow = new ChannelWindow; + m_samplingDeviceControl = new SamplingDeviceControl; + m_deviceSourceEngine = 0; + m_deviceSourceAPI = 0; + m_deviceSinkEngine = 0; + m_deviceSinkAPI = 0; + + // m_spectrum needs to have its font to be set since it cannot be inherited from the main window + QFont font; + font.setFamily(QStringLiteral("Sans Serif")); + font.setPointSize(9); + m_spectrum->setFont(font); + +} + +MainWindow::DeviceUISet::~DeviceUISet() +{ + delete m_samplingDeviceControl; + delete m_channelWindow; + delete m_spectrumGUI; + delete m_spectrumVis; + delete m_spectrum; +} diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp index 2b407c577..82753217d 100644 --- a/sdrbase/plugin/pluginmanager.cpp +++ b/sdrbase/plugin/pluginmanager.cpp @@ -1,815 +1,819 @@ -/////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // -// // -// This program is free software; you can redistribute it and/or modify // -// it under the terms of the GNU General Public License as published by // -// the Free Software Foundation as version 3 of the License, or // -// // -// This program is distributed in the hope that it will be useful, // -// but WITHOUT ANY WARRANTY; without even the implied warranty of // -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // -// GNU General Public License V3 for more details. // -// // -// You should have received a copy of the GNU General Public License // -// along with this program. If not, see . // -/////////////////////////////////////////////////////////////////////////////////// - -#include "device/devicesourceapi.h" -#include "device/devicesinkapi.h" -#include -#include -#include -#include - -#include "plugin/pluginmanager.h" -#include "plugin/plugingui.h" -#include "settings/preset.h" -#include "mainwindow.h" -#include "gui/glspectrum.h" -#include "util/message.h" - -#include -#include "dsp/dspdevicesourceengine.h" -#include "dsp/dspdevicesinkengine.h" - -const QString PluginManager::m_sdrDaemonHardwareID = "SDRdaemon"; -const QString PluginManager::m_sdrDaemonDeviceTypeID = "sdrangel.samplesource.sdrdaemon"; -const QString PluginManager::m_sdrDaemonFECHardwareID = "SDRdaemonFEC"; -const QString PluginManager::m_sdrDaemonFECDeviceTypeID = "sdrangel.samplesource.sdrdaemonfec"; -const QString PluginManager::m_fileSourceHardwareID = "FileSource"; -const QString PluginManager::m_fileSourceDeviceTypeID = "sdrangel.samplesource.filesource"; -const QString PluginManager::m_fileSinkDeviceTypeID = "sdrangel.samplesink.filesink"; - -PluginManager::PluginManager(MainWindow* mainWindow, QObject* parent) : - QObject(parent), - m_pluginAPI(this, mainWindow), - m_mainWindow(mainWindow) -{ -} - -PluginManager::~PluginManager() -{ -// freeAll(); -} - -void PluginManager::loadPlugins() -{ - QString applicationDirPath = QApplication::instance()->applicationDirPath(); - QString applicationLibPath = applicationDirPath + "/../lib"; - qDebug() << "PluginManager::loadPlugins: " << qPrintable(applicationDirPath) << ", " << qPrintable(applicationLibPath); - - QDir pluginsBinDir = QDir(applicationDirPath); - QDir pluginsLibDir = QDir(applicationLibPath); - - loadPlugins(pluginsBinDir); - loadPlugins(pluginsLibDir); - - qSort(m_plugins); - - for (Plugins::const_iterator it = m_plugins.begin(); it != m_plugins.end(); ++it) - { - it->pluginInterface->initPlugin(&m_pluginAPI); - } - - updateSampleSourceDevices(); - updateSampleSinkDevices(); -} - -void PluginManager::registerRxChannel(const QString& channelName, PluginInterface* plugin) -{ - qDebug() << "PluginManager::registerRxChannel " - << plugin->getPluginDescriptor().displayedName.toStdString().c_str() - << " with channel name " << channelName; - - m_rxChannelRegistrations.append(PluginAPI::ChannelRegistration(channelName, plugin)); -} - -void PluginManager::registerTxChannel(const QString& channelName, PluginInterface* plugin) -{ - qDebug() << "PluginManager::registerTxChannel " - << plugin->getPluginDescriptor().displayedName.toStdString().c_str() - << " with channel name " << channelName; - - m_txChannelRegistrations.append(PluginAPI::ChannelRegistration(channelName, plugin)); -} - -void PluginManager::registerSampleSource(const QString& sourceName, PluginInterface* plugin) -{ - qDebug() << "PluginManager::registerSampleSource " - << plugin->getPluginDescriptor().displayedName.toStdString().c_str() - << " with source name " << sourceName.toStdString().c_str(); - - m_sampleSourceRegistrations.append(SamplingDeviceRegistration(sourceName, plugin)); -} - -void PluginManager::registerSampleSink(const QString& sinkName, PluginInterface* plugin) -{ - qDebug() << "PluginManager::registerSampleSink " - << plugin->getPluginDescriptor().displayedName.toStdString().c_str() - << " with sink name " << sinkName.toStdString().c_str(); - - m_sampleSinkRegistrations.append(SamplingDeviceRegistration(sinkName, plugin)); -} - -void PluginManager::updateSampleSourceDevices() -{ - m_sampleSourceDevices.clear(); - - for(int i = 0; i < m_sampleSourceRegistrations.count(); ++i) - { - PluginInterface::SamplingDevices ssd = m_sampleSourceRegistrations[i].m_plugin->enumSampleSources(); - - for(int j = 0; j < ssd.count(); ++j) - { - m_sampleSourceDevices.append(SamplingDevice(m_sampleSourceRegistrations[i].m_plugin, - ssd[j].displayedName, - ssd[j].hardwareId, - ssd[j].id, - ssd[j].serial, - ssd[j].sequence)); - } - } -} - -void PluginManager::updateSampleSinkDevices() -{ - m_sampleSinkDevices.clear(); - - for(int i = 0; i < m_sampleSinkRegistrations.count(); ++i) - { - PluginInterface::SamplingDevices ssd = m_sampleSinkRegistrations[i].m_plugin->enumSampleSinks(); - - for(int j = 0; j < ssd.count(); ++j) - { - m_sampleSinkDevices.append(SamplingDevice(m_sampleSinkRegistrations[i].m_plugin, - ssd[j].displayedName, - ssd[j].hardwareId, - ssd[j].id, - ssd[j].serial, - ssd[j].sequence)); - } - } -} - -void PluginManager::duplicateLocalSampleSourceDevices(uint deviceUID) -{ - if (deviceUID == 0) { - return; - } - - SamplingDevice *sdrDaemonSSD0 = 0; - SamplingDevice *sdrDaemonFECSSD0 = 0; - SamplingDevice *fileSourceSSD0 = 0; - bool duplicateSDRDaemon = true; - bool duplicateSDRDaemonFEC = true; - bool duplicateFileSource = true; - - for(int i = 0; i < m_sampleSourceDevices.count(); ++i) - { - if (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonDeviceTypeID) // SDRdaemon - { - if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 - sdrDaemonSSD0 = &m_sampleSourceDevices[i]; - } - else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there - duplicateSDRDaemon = false; - } - } - else if (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonFECDeviceTypeID) // SDRdaemon with FEC - { - if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 - sdrDaemonFECSSD0 = &m_sampleSourceDevices[i]; - } - else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there - duplicateSDRDaemonFEC = false; - } - } - else if (m_sampleSourceDevices[i].m_deviceId == m_fileSourceDeviceTypeID) // File Source - { - if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 - fileSourceSSD0 = &m_sampleSourceDevices[i]; - } - else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there - duplicateFileSource = false; - } - } - } - - if (sdrDaemonSSD0 && duplicateSDRDaemon) // append item for a new instance - { - m_sampleSourceDevices.append( - SamplingDevice( - sdrDaemonSSD0->m_plugin, - QString("SDRdaemon[%1]").arg(deviceUID), - sdrDaemonSSD0->m_hadrwareId, - sdrDaemonSSD0->m_deviceId, - sdrDaemonSSD0->m_deviceSerial, - deviceUID - ) - ); - } - - if (sdrDaemonFECSSD0 && duplicateSDRDaemonFEC) // append item for a new instance - { - m_sampleSourceDevices.append( - SamplingDevice( - sdrDaemonFECSSD0->m_plugin, - QString("SDRdaemonFEC[%1]").arg(deviceUID), - sdrDaemonFECSSD0->m_hadrwareId, - sdrDaemonFECSSD0->m_deviceId, - sdrDaemonFECSSD0->m_deviceSerial, - deviceUID - ) - ); - } - - if (fileSourceSSD0 && duplicateFileSource) // append item for a new instance - { - m_sampleSourceDevices.append( - SamplingDevice( - fileSourceSSD0->m_plugin, - QString("FileSource[%1]").arg(deviceUID), - fileSourceSSD0->m_hadrwareId, - fileSourceSSD0->m_deviceId, - fileSourceSSD0->m_deviceSerial, - deviceUID - ) - ); - } -} - -void PluginManager::duplicateLocalSampleSinkDevices(uint deviceUID) -{ - if (deviceUID == 0) { - return; - } - - SamplingDevice *fileSinkSSD0 = 0; - bool duplicateFileSink = true; - - for(int i = 0; i < m_sampleSinkDevices.count(); ++i) - { - if (m_sampleSinkDevices[i].m_deviceId == m_fileSinkDeviceTypeID) // File Sink - { - if (m_sampleSinkDevices[i].m_deviceSequence == 0) { // reference to device 0 - fileSinkSSD0 = &m_sampleSinkDevices[i]; - } - else if (m_sampleSinkDevices[i].m_deviceSequence == deviceUID) { // already there - duplicateFileSink = false; - } - } - } - - if (fileSinkSSD0 && duplicateFileSink) // append item for a new instance - { - m_sampleSinkDevices.append( - SamplingDevice( - fileSinkSSD0->m_plugin, - QString("FileSink[%1]").arg(deviceUID), - fileSinkSSD0->m_hadrwareId, - fileSinkSSD0->m_deviceId, - fileSinkSSD0->m_deviceSerial, - deviceUID - ) - ); - } -} - -void PluginManager::fillSampleSourceSelector(QComboBox* comboBox, uint deviceUID) -{ - comboBox->clear(); - - for(int i = 0; i < m_sampleSourceDevices.count(); i++) - { - // For "local" devices show only ones that concern this device set - if ((m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonDeviceTypeID) - || (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonFECDeviceTypeID) - || (m_sampleSourceDevices[i].m_deviceId == m_fileSourceDeviceTypeID)) - { - if (deviceUID != m_sampleSourceDevices[i].m_deviceSequence) { - continue; - } - } - - comboBox->addItem(m_sampleSourceDevices[i].m_displayName, qVariantFromValue((void *) &m_sampleSourceDevices[i])); - } -} - -int PluginManager::getSampleSourceSelectorIndex(QComboBox* comboBox, DeviceSourceAPI *deviceSourceAPI) -{ - for (int i = 0; i < comboBox->count(); i++) - { - SamplingDevice *samplingDevice = (SamplingDevice*) (comboBox->itemData(i)).value(); - - if ((samplingDevice->m_deviceId == deviceSourceAPI->getSampleSourceId()) && - (samplingDevice->m_deviceSerial == deviceSourceAPI->getSampleSourceSerial()) && - (samplingDevice->m_deviceSequence == deviceSourceAPI->getSampleSourceSequence())) - { - return i; - } - } - - return 0; // default to first item -} - -void PluginManager::fillSampleSinkSelector(QComboBox* comboBox, uint deviceUID) -{ - comboBox->clear(); - - for(int i = 0; i < m_sampleSinkDevices.count(); i++) - { - // For "local" devices show only ones that concern this device set - if (m_sampleSinkDevices[i].m_deviceId == m_fileSinkDeviceTypeID) - { - if (deviceUID != m_sampleSinkDevices[i].m_deviceSequence) { - continue; - } - } - - comboBox->addItem(m_sampleSinkDevices[i].m_displayName, qVariantFromValue((void *) &m_sampleSinkDevices[i])); - } -} - -int PluginManager::getSampleSinkSelectorIndex(QComboBox* comboBox, DeviceSinkAPI *deviceSinkAPI) -{ - for (int i = 0; i < comboBox->count(); i++) - { - SamplingDevice *samplingDevice = (SamplingDevice*) (comboBox->itemData(i)).value(); - - if ((samplingDevice->m_deviceId == deviceSinkAPI->getSampleSinkId()) && - (samplingDevice->m_deviceSerial == deviceSinkAPI->getSampleSinkSerial()) && - (samplingDevice->m_deviceSequence == deviceSinkAPI->getSampleSinkSequence())) - { - return i; - } - } - - return 0; // default to first item -} - -int PluginManager::selectSampleSourceByIndex(int index, DeviceSourceAPI *deviceAPI) -{ - qDebug("PluginManager::selectSampleSourceByIndex: index: %d", index); - - if (m_sampleSourceDevices.count() == 0) - { - return -1; - } - - if (index < 0) - { - return -1; - } - - if (index >= m_sampleSourceDevices.count()) - { - index = 0; - } - - qDebug() << "PluginManager::selectSampleSourceByIndex: m_sampleSource at index " << index - << " hid: " << m_sampleSourceDevices[index].m_hadrwareId.toStdString().c_str() - << " id: " << m_sampleSourceDevices[index].m_deviceId.toStdString().c_str() - << " ser: " << m_sampleSourceDevices[index].m_deviceSerial.toStdString().c_str() - << " seq: " << m_sampleSourceDevices[index].m_deviceSequence; - - deviceAPI->stopAcquisition(); - deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = m_sampleSourceDevices[index].m_plugin->createSampleSourcePluginGUI(m_sampleSourceDevices[index].m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSourceSequence(m_sampleSourceDevices[index].m_deviceSequence); - deviceAPI->setHardwareId(m_sampleSourceDevices[index].m_hadrwareId); - deviceAPI->setSampleSourceId(m_sampleSourceDevices[index].m_deviceId); - deviceAPI->setSampleSourceSerial(m_sampleSourceDevices[index].m_deviceSerial); - deviceAPI->setSampleSourcePluginGUI(pluginGUI); - deviceAPI->setInputGUI(gui, m_sampleSourceDevices[index].m_displayName); - - return index; -} - -int PluginManager::selectSampleSinkByIndex(int index, DeviceSinkAPI *deviceAPI) -{ - qDebug("PluginManager::selectSampleSinkByIndex: index: %d", index); - - if (m_sampleSinkDevices.count() == 0) - { - return -1; - } - - if (index < 0) - { - return -1; - } - - if (index >= m_sampleSinkDevices.count()) - { - index = 0; - } - - qDebug() << "PluginManager::selectSampleSinkByIndex: m_sampleSink at index " << index - << " hid: " << m_sampleSinkDevices[index].m_hadrwareId.toStdString().c_str() - << " id: " << m_sampleSinkDevices[index].m_deviceId.toStdString().c_str() - << " ser: " << m_sampleSinkDevices[index].m_deviceSerial.toStdString().c_str() - << " seq: " << m_sampleSinkDevices[index].m_deviceSequence; - - deviceAPI->stopGeneration(); - deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = m_sampleSinkDevices[index].m_plugin->createSampleSinkPluginGUI(m_sampleSinkDevices[index].m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSinkSequence(m_sampleSinkDevices[index].m_deviceSequence); - deviceAPI->setHardwareId(m_sampleSinkDevices[index].m_hadrwareId); - deviceAPI->setSampleSinkId(m_sampleSinkDevices[index].m_deviceId); - deviceAPI->setSampleSinkSerial(m_sampleSinkDevices[index].m_deviceSerial); - deviceAPI->setSampleSinkPluginGUI(pluginGUI); - deviceAPI->setOutputGUI(gui, m_sampleSinkDevices[index].m_displayName); - - return index; -} - -int PluginManager::selectFirstSampleSource(const QString& sourceId, DeviceSourceAPI *deviceAPI) -{ - qDebug("PluginManager::selectFirstSampleSource by id: [%s]", qPrintable(sourceId)); - - int index = -1; - - for (int i = 0; i < m_sampleSourceDevices.count(); i++) - { - qDebug("*** %s vs %s", qPrintable(m_sampleSourceDevices[i].m_deviceId), qPrintable(sourceId)); - - if(m_sampleSourceDevices[i].m_deviceId == sourceId) - { - index = i; - break; - } - } - - if(index == -1) - { - if(m_sampleSourceDevices.count() > 0) - { - index = 0; - } - else - { - return -1; - } - } - - qDebug() << "PluginManager::selectFirstSampleSource: m_sampleSource at index " << index - << " hid: " << m_sampleSourceDevices[index].m_hadrwareId.toStdString().c_str() - << " id: " << m_sampleSourceDevices[index].m_deviceId.toStdString().c_str() - << " ser: " << m_sampleSourceDevices[index].m_deviceSerial.toStdString().c_str() - << " seq: " << m_sampleSourceDevices[index].m_deviceSequence; - - deviceAPI->stopAcquisition(); - deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = m_sampleSourceDevices[index].m_plugin->createSampleSourcePluginGUI(m_sampleSourceDevices[index].m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSourceSequence(m_sampleSourceDevices[index].m_deviceSequence); - deviceAPI->setHardwareId(m_sampleSourceDevices[index].m_hadrwareId); - deviceAPI->setSampleSourceId(m_sampleSourceDevices[index].m_deviceId); - deviceAPI->setSampleSourceSerial(m_sampleSourceDevices[index].m_deviceSerial); - deviceAPI->setSampleSourcePluginGUI(pluginGUI); - deviceAPI->setInputGUI(gui, m_sampleSourceDevices[index].m_displayName); - - return index; -} - -int PluginManager::selectFirstSampleSink(const QString& sinkId, DeviceSinkAPI *deviceAPI) -{ - qDebug("PluginManager::selectFirstSampleSink by id: [%s]", qPrintable(sinkId)); - - int index = -1; - - for (int i = 0; i < m_sampleSinkDevices.count(); i++) - { - qDebug("*** %s vs %s", qPrintable(m_sampleSinkDevices[i].m_deviceId), qPrintable(sinkId)); - - if(m_sampleSinkDevices[i].m_deviceId == sinkId) - { - index = i; - break; - } - } - - if(index == -1) - { - if(m_sampleSinkDevices.count() > 0) - { - index = 0; - } - else - { - return -1; - } - } - - qDebug() << "PluginManager::selectFirstSampleSink: m_sampleSink at index " << index - << " hid: " << m_sampleSinkDevices[index].m_hadrwareId.toStdString().c_str() - << " id: " << m_sampleSinkDevices[index].m_deviceId.toStdString().c_str() - << " ser: " << m_sampleSinkDevices[index].m_deviceSerial.toStdString().c_str() - << " seq: " << m_sampleSinkDevices[index].m_deviceSequence; - - deviceAPI->stopGeneration(); - deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = m_sampleSinkDevices[index].m_plugin->createSampleSinkPluginGUI(m_sampleSinkDevices[index].m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSinkSequence(m_sampleSinkDevices[index].m_deviceSequence); - deviceAPI->setHardwareId(m_sampleSinkDevices[index].m_hadrwareId); - deviceAPI->setSampleSinkId(m_sampleSinkDevices[index].m_deviceId); - deviceAPI->setSampleSinkSerial(m_sampleSinkDevices[index].m_deviceSerial); - deviceAPI->setSampleSinkPluginGUI(pluginGUI); - deviceAPI->setOutputGUI(gui, m_sampleSinkDevices[index].m_displayName); - - return index; -} - -int PluginManager::selectSampleSourceBySerialOrSequence(const QString& sourceId, const QString& sourceSerial, int sourceSequence, DeviceSourceAPI *deviceAPI) -{ - qDebug("PluginManager::selectSampleSourceBySequence by sequence: id: %s ser: %s seq: %d", qPrintable(sourceId), qPrintable(sourceSerial), sourceSequence); - - int index = -1; - int index_matchingSequence = -1; - int index_firstOfKind = -1; - - for (int i = 0; i < m_sampleSourceDevices.count(); i++) - { - if (m_sampleSourceDevices[i].m_deviceId == sourceId) - { - index_firstOfKind = i; - - if (m_sampleSourceDevices[i].m_deviceSerial == sourceSerial) - { - index = i; // exact match - break; - } - - if (m_sampleSourceDevices[i].m_deviceSequence == sourceSequence) - { - index_matchingSequence = i; - } - } - } - - if(index == -1) // no exact match - { - if (index_matchingSequence == -1) // no matching sequence - { - if (index_firstOfKind == -1) // no matching device type - { - if(m_sampleSourceDevices.count() > 0) // take first if any - { - index = 0; - } - else - { - return -1; // return if no device attached - } - } - else - { - index = index_firstOfKind; // take first that matches device type - } - } - else - { - index = index_matchingSequence; // take the one that matches the sequence in the device type - } - } - - qDebug() << "PluginManager::selectSampleSourceBySequence: m_sampleSource at index " << index - << " hid: " << m_sampleSourceDevices[index].m_hadrwareId.toStdString().c_str() - << " id: " << m_sampleSourceDevices[index].m_deviceId.toStdString().c_str() - << " ser: " << m_sampleSourceDevices[index].m_deviceSerial.toStdString().c_str() - << " seq: " << m_sampleSourceDevices[index].m_deviceSequence; - - deviceAPI->stopAcquisition(); - deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = m_sampleSourceDevices[index].m_plugin->createSampleSourcePluginGUI(m_sampleSourceDevices[index].m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSourceSequence(m_sampleSourceDevices[index].m_deviceSequence); - deviceAPI->setHardwareId(m_sampleSourceDevices[index].m_hadrwareId); - deviceAPI->setSampleSourceId(m_sampleSourceDevices[index].m_deviceId); - deviceAPI->setSampleSourceSerial(m_sampleSourceDevices[index].m_deviceSerial); - deviceAPI->setSampleSourcePluginGUI(pluginGUI); - deviceAPI->setInputGUI(gui, m_sampleSourceDevices[index].m_displayName); - - return index; -} - -int PluginManager::selectSampleSinkBySerialOrSequence(const QString& sinkId, const QString& sinkSerial, int sinkSequence, DeviceSinkAPI *deviceAPI) -{ - qDebug("PluginManager::selectSampleSinkBySerialOrSequence by sequence: id: %s ser: %s seq: %d", qPrintable(sinkId), qPrintable(sinkSerial), sinkSequence); - - int index = -1; - int index_matchingSequence = -1; - int index_firstOfKind = -1; - - for (int i = 0; i < m_sampleSinkDevices.count(); i++) - { - if (m_sampleSinkDevices[i].m_deviceId == sinkId) - { - index_firstOfKind = i; - - if (m_sampleSinkDevices[i].m_deviceSerial == sinkSerial) - { - index = i; // exact match - break; - } - - if (m_sampleSinkDevices[i].m_deviceSequence == sinkSequence) - { - index_matchingSequence = i; - } - } - } - - if(index == -1) // no exact match - { - if (index_matchingSequence == -1) // no matching sequence - { - if (index_firstOfKind == -1) // no matching device type - { - if(m_sampleSinkDevices.count() > 0) // take first if any - { - index = 0; - } - else - { - return -1; // return if no device attached - } - } - else - { - index = index_firstOfKind; // take first that matches device type - } - } - else - { - index = index_matchingSequence; // take the one that matches the sequence in the device type - } - } - - qDebug() << "PluginManager::selectSampleSinkBySerialOrSequence: m_sampleSink at index " << index - << " hid: " << m_sampleSinkDevices[index].m_hadrwareId.toStdString().c_str() - << " id: " << m_sampleSinkDevices[index].m_deviceId.toStdString().c_str() - << " ser: " << m_sampleSinkDevices[index].m_deviceSerial.toStdString().c_str() - << " seq: " << m_sampleSinkDevices[index].m_deviceSequence; - - deviceAPI->stopGeneration(); - deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = m_sampleSinkDevices[index].m_plugin->createSampleSinkPluginGUI(m_sampleSinkDevices[index].m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSinkSequence(m_sampleSinkDevices[index].m_deviceSequence); - deviceAPI->setHardwareId(m_sampleSinkDevices[index].m_hadrwareId); - deviceAPI->setSampleSinkId(m_sampleSinkDevices[index].m_deviceId); - deviceAPI->setSampleSinkSerial(m_sampleSinkDevices[index].m_deviceSerial); - deviceAPI->setSampleSinkPluginGUI(pluginGUI); - deviceAPI->setOutputGUI(gui, m_sampleSinkDevices[index].m_displayName); - - return index; -} - -void PluginManager::selectSampleSourceByDevice(void *devicePtr, DeviceSourceAPI *deviceAPI) -{ - SamplingDevice *sampleSourceDevice = (SamplingDevice *) devicePtr; - - qDebug() << "PluginManager::selectSampleSourceByDevice: " - << " hid: " << sampleSourceDevice->m_hadrwareId.toStdString().c_str() - << " id: " << sampleSourceDevice->m_deviceId.toStdString().c_str() - << " ser: " << sampleSourceDevice->m_deviceSerial.toStdString().c_str() - << " seq: " << sampleSourceDevice->m_deviceSequence; - - deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = sampleSourceDevice->m_plugin->createSampleSourcePluginGUI(sampleSourceDevice->m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSourceSequence(sampleSourceDevice->m_deviceSequence); - deviceAPI->setHardwareId(sampleSourceDevice->m_hadrwareId); - deviceAPI->setSampleSourceId(sampleSourceDevice->m_deviceId); - deviceAPI->setSampleSourceSerial(sampleSourceDevice->m_deviceSerial); - deviceAPI->setSampleSourcePluginGUI(pluginGUI); - deviceAPI->setInputGUI(gui, sampleSourceDevice->m_displayName); -} - -void PluginManager::selectSampleSinkByDevice(void *devicePtr, DeviceSinkAPI *deviceAPI) -{ - SamplingDevice *sampleSinkDevice = (SamplingDevice *) devicePtr; - - qDebug() << "PluginManager::selectSampleSinkByDevice: " - << " hid: " << sampleSinkDevice->m_hadrwareId.toStdString().c_str() - << " id: " << sampleSinkDevice->m_deviceId.toStdString().c_str() - << " ser: " << sampleSinkDevice->m_deviceSerial.toStdString().c_str() - << " seq: " << sampleSinkDevice->m_deviceSequence; - - deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists - - QWidget *gui; - PluginGUI *pluginGUI = sampleSinkDevice->m_plugin->createSampleSinkPluginGUI(sampleSinkDevice->m_deviceId, &gui, deviceAPI); - - // m_sampleSourcePluginGUI = pluginGUI; - deviceAPI->setSampleSinkSequence(sampleSinkDevice->m_deviceSequence); - deviceAPI->setHardwareId(sampleSinkDevice->m_hadrwareId); - deviceAPI->setSampleSinkId(sampleSinkDevice->m_deviceId); - deviceAPI->setSampleSinkSerial(sampleSinkDevice->m_deviceSerial); - deviceAPI->setSampleSinkPluginGUI(pluginGUI); - deviceAPI->setOutputGUI(gui, sampleSinkDevice->m_displayName); -} - -void PluginManager::loadPlugins(const QDir& dir) -{ - QDir pluginsDir(dir); - - foreach (QString fileName, pluginsDir.entryList(QDir::Files)) - { - if (fileName.endsWith(".so") || fileName.endsWith(".dll") || fileName.endsWith(".dylib")) - { - qDebug() << "PluginManager::loadPlugins: fileName: " << qPrintable(fileName); - - QPluginLoader* loader = new QPluginLoader(pluginsDir.absoluteFilePath(fileName)); - PluginInterface* plugin = qobject_cast(loader->instance()); - - if (loader->isLoaded()) - { - qWarning("PluginManager::loadPlugins: loaded plugin %s", qPrintable(fileName)); - } - else - { - qWarning() << "PluginManager::loadPlugins: " << qPrintable(loader->errorString()); - } - - if (plugin != 0) - { - m_plugins.append(Plugin(fileName, loader, plugin)); - } - else - { - loader->unload(); - } - - delete loader; // Valgrind memcheck - } - } - - // recursive calls on subdirectories - - foreach (QString dirName, pluginsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) - { - loadPlugins(pluginsDir.absoluteFilePath(dirName)); - } -} - -void PluginManager::populateRxChannelComboBox(QComboBox *channels) -{ - for(PluginAPI::ChannelRegistrations::iterator it = m_rxChannelRegistrations.begin(); it != m_rxChannelRegistrations.end(); ++it) - { - const PluginDescriptor& pluginDescipror = it->m_plugin->getPluginDescriptor(); - channels->addItem(pluginDescipror.displayedName); - } -} - -void PluginManager::populateTxChannelComboBox(QComboBox *channels) -{ - for(PluginAPI::ChannelRegistrations::iterator it = m_txChannelRegistrations.begin(); it != m_txChannelRegistrations.end(); ++it) - { - const PluginDescriptor& pluginDescipror = it->m_plugin->getPluginDescriptor(); - channels->addItem(pluginDescipror.displayedName); - } -} - -void PluginManager::createRxChannelInstance(int channelPluginIndex, DeviceSourceAPI *deviceAPI) -{ - if (channelPluginIndex < m_rxChannelRegistrations.size()) - { - PluginInterface *pluginInterface = m_rxChannelRegistrations[channelPluginIndex].m_plugin; - pluginInterface->createRxChannel(m_rxChannelRegistrations[channelPluginIndex].m_channelName, deviceAPI); - } -} - -void PluginManager::createTxChannelInstance(int channelPluginIndex, DeviceSinkAPI *deviceAPI) -{ - if (channelPluginIndex < m_txChannelRegistrations.size()) - { - PluginInterface *pluginInterface = m_txChannelRegistrations[channelPluginIndex].m_plugin; - pluginInterface->createTxChannel(m_txChannelRegistrations[channelPluginIndex].m_channelName, deviceAPI); - } -} +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// // +// This program is free software; you can redistribute it and/or modify // +// it under the terms of the GNU General Public License as published by // +// the Free Software Foundation as version 3 of the License, or // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License V3 for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program. If not, see . // +/////////////////////////////////////////////////////////////////////////////////// + +#include "device/devicesourceapi.h" +#include "device/devicesinkapi.h" +#include +#include +#include +#include + +#include "plugin/pluginmanager.h" +#include "plugin/plugingui.h" +#include "settings/preset.h" +#include "mainwindow.h" +#include "gui/glspectrum.h" +#include "util/message.h" + +#include +#include "dsp/dspdevicesourceengine.h" +#include "dsp/dspdevicesinkengine.h" + +const QString PluginManager::m_sdrDaemonHardwareID = "SDRdaemon"; +const QString PluginManager::m_sdrDaemonDeviceTypeID = "sdrangel.samplesource.sdrdaemon"; +const QString PluginManager::m_sdrDaemonFECHardwareID = "SDRdaemonFEC"; +const QString PluginManager::m_sdrDaemonFECDeviceTypeID = "sdrangel.samplesource.sdrdaemonfec"; +const QString PluginManager::m_fileSourceHardwareID = "FileSource"; +const QString PluginManager::m_fileSourceDeviceTypeID = "sdrangel.samplesource.filesource"; +const QString PluginManager::m_fileSinkDeviceTypeID = "sdrangel.samplesink.filesink"; + +PluginManager::PluginManager(MainWindow* mainWindow, QObject* parent) : + QObject(parent), + m_pluginAPI(this, mainWindow), + m_mainWindow(mainWindow) +{ +} + +PluginManager::~PluginManager() +{ +// freeAll(); +} + +void PluginManager::loadPlugins() +{ + QString applicationDirPath = QApplication::instance()->applicationDirPath(); + QString applicationLibPath = applicationDirPath + "/../lib"; + qDebug() << "PluginManager::loadPlugins: " << qPrintable(applicationDirPath) << ", " << qPrintable(applicationLibPath); + + QDir pluginsBinDir = QDir(applicationDirPath); + QDir pluginsLibDir = QDir(applicationLibPath); + + loadPlugins(pluginsBinDir); + loadPlugins(pluginsLibDir); + + qSort(m_plugins); + + for (Plugins::const_iterator it = m_plugins.begin(); it != m_plugins.end(); ++it) + { + it->pluginInterface->initPlugin(&m_pluginAPI); + } + + updateSampleSourceDevices(); + updateSampleSinkDevices(); +} + +void PluginManager::registerRxChannel(const QString& channelName, PluginInterface* plugin) +{ + qDebug() << "PluginManager::registerRxChannel " + << plugin->getPluginDescriptor().displayedName.toStdString().c_str() + << " with channel name " << channelName; + + m_rxChannelRegistrations.append(PluginAPI::ChannelRegistration(channelName, plugin)); +} + +void PluginManager::registerTxChannel(const QString& channelName, PluginInterface* plugin) +{ + qDebug() << "PluginManager::registerTxChannel " + << plugin->getPluginDescriptor().displayedName.toStdString().c_str() + << " with channel name " << channelName; + + m_txChannelRegistrations.append(PluginAPI::ChannelRegistration(channelName, plugin)); +} + +void PluginManager::registerSampleSource(const QString& sourceName, PluginInterface* plugin) +{ + qDebug() << "PluginManager::registerSampleSource " + << plugin->getPluginDescriptor().displayedName.toStdString().c_str() + << " with source name " << sourceName.toStdString().c_str(); + + m_sampleSourceRegistrations.append(SamplingDeviceRegistration(sourceName, plugin)); +} + +void PluginManager::registerSampleSink(const QString& sinkName, PluginInterface* plugin) +{ + qDebug() << "PluginManager::registerSampleSink " + << plugin->getPluginDescriptor().displayedName.toStdString().c_str() + << " with sink name " << sinkName.toStdString().c_str(); + + m_sampleSinkRegistrations.append(SamplingDeviceRegistration(sinkName, plugin)); +} + +void PluginManager::updateSampleSourceDevices() +{ + m_sampleSourceDevices.clear(); + + for(int i = 0; i < m_sampleSourceRegistrations.count(); ++i) + { + PluginInterface::SamplingDevices ssd = m_sampleSourceRegistrations[i].m_plugin->enumSampleSources(); + + for(int j = 0; j < ssd.count(); ++j) + { + m_sampleSourceDevices.append(SamplingDevice(m_sampleSourceRegistrations[i].m_plugin, + ssd[j].displayedName, + ssd[j].hardwareId, + ssd[j].id, + ssd[j].serial, + ssd[j].sequence)); + } + } +} + +void PluginManager::updateSampleSinkDevices() +{ + m_sampleSinkDevices.clear(); + + for(int i = 0; i < m_sampleSinkRegistrations.count(); ++i) + { + PluginInterface::SamplingDevices ssd = m_sampleSinkRegistrations[i].m_plugin->enumSampleSinks(); + + for(int j = 0; j < ssd.count(); ++j) + { + m_sampleSinkDevices.append(SamplingDevice(m_sampleSinkRegistrations[i].m_plugin, + ssd[j].displayedName, + ssd[j].hardwareId, + ssd[j].id, + ssd[j].serial, + ssd[j].sequence)); + } + } +} + +void PluginManager::duplicateLocalSampleSourceDevices(uint deviceUID) +{ + if (deviceUID == 0) { + return; + } + + SamplingDevice *sdrDaemonSSD0 = 0; + SamplingDevice *sdrDaemonFECSSD0 = 0; + SamplingDevice *fileSourceSSD0 = 0; + bool duplicateSDRDaemon = true; + bool duplicateSDRDaemonFEC = true; + bool duplicateFileSource = true; + + for(int i = 0; i < m_sampleSourceDevices.count(); ++i) + { + if (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonDeviceTypeID) // SDRdaemon + { + if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 + sdrDaemonSSD0 = &m_sampleSourceDevices[i]; + } + else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there + duplicateSDRDaemon = false; + } + } + else if (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonFECDeviceTypeID) // SDRdaemon with FEC + { + if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 + sdrDaemonFECSSD0 = &m_sampleSourceDevices[i]; + } + else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there + duplicateSDRDaemonFEC = false; + } + } + else if (m_sampleSourceDevices[i].m_deviceId == m_fileSourceDeviceTypeID) // File Source + { + if (m_sampleSourceDevices[i].m_deviceSequence == 0) { // reference to device 0 + fileSourceSSD0 = &m_sampleSourceDevices[i]; + } + else if (m_sampleSourceDevices[i].m_deviceSequence == deviceUID) { // already there + duplicateFileSource = false; + } + } + } + + if (sdrDaemonSSD0 && duplicateSDRDaemon) // append item for a new instance + { + m_sampleSourceDevices.append( + SamplingDevice( + sdrDaemonSSD0->m_plugin, + QString("SDRdaemon[%1]").arg(deviceUID), + sdrDaemonSSD0->m_hadrwareId, + sdrDaemonSSD0->m_deviceId, + sdrDaemonSSD0->m_deviceSerial, + deviceUID + ) + ); + } + + if (sdrDaemonFECSSD0 && duplicateSDRDaemonFEC) // append item for a new instance + { + m_sampleSourceDevices.append( + SamplingDevice( + sdrDaemonFECSSD0->m_plugin, + QString("SDRdaemonFEC[%1]").arg(deviceUID), + sdrDaemonFECSSD0->m_hadrwareId, + sdrDaemonFECSSD0->m_deviceId, + sdrDaemonFECSSD0->m_deviceSerial, + deviceUID + ) + ); + } + + if (fileSourceSSD0 && duplicateFileSource) // append item for a new instance + { + m_sampleSourceDevices.append( + SamplingDevice( + fileSourceSSD0->m_plugin, + QString("FileSource[%1]").arg(deviceUID), + fileSourceSSD0->m_hadrwareId, + fileSourceSSD0->m_deviceId, + fileSourceSSD0->m_deviceSerial, + deviceUID + ) + ); + } +} + +void PluginManager::duplicateLocalSampleSinkDevices(uint deviceUID) +{ + if (deviceUID == 0) { + return; + } + + SamplingDevice *fileSinkSSD0 = 0; + bool duplicateFileSink = true; + + for(int i = 0; i < m_sampleSinkDevices.count(); ++i) + { + if (m_sampleSinkDevices[i].m_deviceId == m_fileSinkDeviceTypeID) // File Sink + { + if (m_sampleSinkDevices[i].m_deviceSequence == 0) { // reference to device 0 + fileSinkSSD0 = &m_sampleSinkDevices[i]; + } + else if (m_sampleSinkDevices[i].m_deviceSequence == deviceUID) { // already there + duplicateFileSink = false; + } + } + } + + if (fileSinkSSD0 && duplicateFileSink) // append item for a new instance + { + m_sampleSinkDevices.append( + SamplingDevice( + fileSinkSSD0->m_plugin, + QString("FileSink[%1]").arg(deviceUID), + fileSinkSSD0->m_hadrwareId, + fileSinkSSD0->m_deviceId, + fileSinkSSD0->m_deviceSerial, + deviceUID + ) + ); + } +} + +void PluginManager::fillSampleSourceSelector(QComboBox* comboBox, uint deviceUID) +{ + comboBox->clear(); + + for(int i = 0; i < m_sampleSourceDevices.count(); i++) + { + // For "local" devices show only ones that concern this device set + if ((m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonDeviceTypeID) + || (m_sampleSourceDevices[i].m_deviceId == m_sdrDaemonFECDeviceTypeID) + || (m_sampleSourceDevices[i].m_deviceId == m_fileSourceDeviceTypeID)) + { + if (deviceUID != m_sampleSourceDevices[i].m_deviceSequence) { + continue; + } + } + + comboBox->addItem(m_sampleSourceDevices[i].m_displayName, qVariantFromValue((void *) &m_sampleSourceDevices[i])); + } +} + +int PluginManager::getSampleSourceSelectorIndex(QComboBox* comboBox, DeviceSourceAPI *deviceSourceAPI) +{ + for (int i = 0; i < comboBox->count(); i++) + { + SamplingDevice *samplingDevice = (SamplingDevice*) (comboBox->itemData(i)).value(); + + if ((samplingDevice->m_deviceId == deviceSourceAPI->getSampleSourceId()) && + (samplingDevice->m_deviceSerial == deviceSourceAPI->getSampleSourceSerial()) && + (samplingDevice->m_deviceSequence == deviceSourceAPI->getSampleSourceSequence())) + { + return i; + } + } + + return 0; // default to first item +} + +void PluginManager::fillSampleSinkSelector(QComboBox* comboBox, uint deviceUID) +{ + comboBox->clear(); + + for(int i = 0; i < m_sampleSinkDevices.count(); i++) + { + // For "local" devices show only ones that concern this device set + if (m_sampleSinkDevices[i].m_deviceId == m_fileSinkDeviceTypeID) + { + if (deviceUID != m_sampleSinkDevices[i].m_deviceSequence) { + continue; + } + } + + comboBox->addItem(m_sampleSinkDevices[i].m_displayName, qVariantFromValue((void *) &m_sampleSinkDevices[i])); + } +} + +int PluginManager::getSampleSinkSelectorIndex(QComboBox* comboBox, DeviceSinkAPI *deviceSinkAPI) +{ + for (int i = 0; i < comboBox->count(); i++) + { + SamplingDevice *samplingDevice = (SamplingDevice*) (comboBox->itemData(i)).value(); + + if ((samplingDevice->m_deviceId == deviceSinkAPI->getSampleSinkId()) && + (samplingDevice->m_deviceSerial == deviceSinkAPI->getSampleSinkSerial()) && + (samplingDevice->m_deviceSequence == deviceSinkAPI->getSampleSinkSequence())) + { + return i; + } + } + + return 0; // default to first item +} + +int PluginManager::selectSampleSourceByIndex(int index, DeviceSourceAPI *deviceAPI) +{ + qDebug("PluginManager::selectSampleSourceByIndex: index: %d", index); + + if (m_sampleSourceDevices.count() == 0) + { + return -1; + } + + if (index < 0) + { + return -1; + } + + if (index >= m_sampleSourceDevices.count()) + { + index = 0; + } + + qDebug() << "PluginManager::selectSampleSourceByIndex: m_sampleSource at index " << index + << " hid: " << m_sampleSourceDevices[index].m_hadrwareId.toStdString().c_str() + << " id: " << m_sampleSourceDevices[index].m_deviceId.toStdString().c_str() + << " ser: " << m_sampleSourceDevices[index].m_deviceSerial.toStdString().c_str() + << " seq: " << m_sampleSourceDevices[index].m_deviceSequence; + + deviceAPI->stopAcquisition(); + deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists + + QWidget *gui; + PluginGUI *pluginGUI = m_sampleSourceDevices[index].m_plugin->createSampleSourcePluginGUI(m_sampleSourceDevices[index].m_deviceId, &gui, deviceAPI); + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSourceSequence(m_sampleSourceDevices[index].m_deviceSequence); + deviceAPI->setHardwareId(m_sampleSourceDevices[index].m_hadrwareId); + deviceAPI->setSampleSourceId(m_sampleSourceDevices[index].m_deviceId); + deviceAPI->setSampleSourceSerial(m_sampleSourceDevices[index].m_deviceSerial); + deviceAPI->setSampleSourcePluginGUI(pluginGUI); + deviceAPI->setInputGUI(gui, m_sampleSourceDevices[index].m_displayName); + + return index; +} + +int PluginManager::selectSampleSinkByIndex(int index, DeviceSinkAPI *deviceAPI) +{ + qDebug("PluginManager::selectSampleSinkByIndex: index: %d", index); + + if (m_sampleSinkDevices.count() == 0) + { + return -1; + } + + if (index < 0) + { + return -1; + } + + if (index >= m_sampleSinkDevices.count()) + { + index = 0; + } + + qDebug() << "PluginManager::selectSampleSinkByIndex: m_sampleSink at index " << index + << " hid: " << m_sampleSinkDevices[index].m_hadrwareId.toStdString().c_str() + << " id: " << m_sampleSinkDevices[index].m_deviceId.toStdString().c_str() + << " ser: " << m_sampleSinkDevices[index].m_deviceSerial.toStdString().c_str() + << " seq: " << m_sampleSinkDevices[index].m_deviceSequence; + + deviceAPI->stopGeneration(); + deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists + + QWidget *gui; + PluginGUI *pluginGUI = m_sampleSinkDevices[index].m_plugin->createSampleSinkPluginGUI(m_sampleSinkDevices[index].m_deviceId, &gui, deviceAPI); + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSinkSequence(m_sampleSinkDevices[index].m_deviceSequence); + deviceAPI->setHardwareId(m_sampleSinkDevices[index].m_hadrwareId); + deviceAPI->setSampleSinkId(m_sampleSinkDevices[index].m_deviceId); + deviceAPI->setSampleSinkSerial(m_sampleSinkDevices[index].m_deviceSerial); + deviceAPI->setSampleSinkPluginGUI(pluginGUI); + deviceAPI->setOutputGUI(gui, m_sampleSinkDevices[index].m_displayName); + + return index; +} + +int PluginManager::selectFirstSampleSource(const QString& sourceId, DeviceSourceAPI *deviceAPI) +{ + qDebug("PluginManager::selectFirstSampleSource by id: [%s]", qPrintable(sourceId)); + + int index = -1; + + for (int i = 0; i < m_sampleSourceDevices.count(); i++) + { + qDebug("*** %s vs %s", qPrintable(m_sampleSourceDevices[i].m_deviceId), qPrintable(sourceId)); + + if(m_sampleSourceDevices[i].m_deviceId == sourceId) + { + index = i; + break; + } + } + + if(index == -1) + { + if(m_sampleSourceDevices.count() > 0) + { + index = 0; + } + else + { + return -1; + } + } + + qDebug() << "PluginManager::selectFirstSampleSource: m_sampleSource at index " << index + << " hid: " << m_sampleSourceDevices[index].m_hadrwareId.toStdString().c_str() + << " id: " << m_sampleSourceDevices[index].m_deviceId.toStdString().c_str() + << " ser: " << m_sampleSourceDevices[index].m_deviceSerial.toStdString().c_str() + << " seq: " << m_sampleSourceDevices[index].m_deviceSequence; + + deviceAPI->stopAcquisition(); + deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists + + QWidget *gui; + PluginGUI *pluginGUI = m_sampleSourceDevices[index].m_plugin->createSampleSourcePluginGUI(m_sampleSourceDevices[index].m_deviceId, &gui, deviceAPI); + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSourceSequence(m_sampleSourceDevices[index].m_deviceSequence); + deviceAPI->setHardwareId(m_sampleSourceDevices[index].m_hadrwareId); + deviceAPI->setSampleSourceId(m_sampleSourceDevices[index].m_deviceId); + deviceAPI->setSampleSourceSerial(m_sampleSourceDevices[index].m_deviceSerial); + deviceAPI->setSampleSourcePluginGUI(pluginGUI); + deviceAPI->setInputGUI(gui, m_sampleSourceDevices[index].m_displayName); + + return index; +} + +int PluginManager::selectFirstSampleSink(const QString& sinkId, DeviceSinkAPI *deviceAPI) +{ + qDebug("PluginManager::selectFirstSampleSink by id: [%s]", qPrintable(sinkId)); + + int index = -1; + + for (int i = 0; i < m_sampleSinkDevices.count(); i++) + { + qDebug("*** %s vs %s", qPrintable(m_sampleSinkDevices[i].m_deviceId), qPrintable(sinkId)); + + if(m_sampleSinkDevices[i].m_deviceId == sinkId) + { + index = i; + break; + } + } + + if(index == -1) + { + if(m_sampleSinkDevices.count() > 0) + { + index = 0; + } + else + { + return -1; + } + } + + qDebug() << "PluginManager::selectFirstSampleSink: m_sampleSink at index " << index + << " hid: " << m_sampleSinkDevices[index].m_hadrwareId.toStdString().c_str() + << " id: " << m_sampleSinkDevices[index].m_deviceId.toStdString().c_str() + << " ser: " << m_sampleSinkDevices[index].m_deviceSerial.toStdString().c_str() + << " seq: " << m_sampleSinkDevices[index].m_deviceSequence; + + deviceAPI->stopGeneration(); + deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists + + QWidget *gui; + PluginGUI *pluginGUI = m_sampleSinkDevices[index].m_plugin->createSampleSinkPluginGUI(m_sampleSinkDevices[index].m_deviceId, &gui, deviceAPI); + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSinkSequence(m_sampleSinkDevices[index].m_deviceSequence); + deviceAPI->setHardwareId(m_sampleSinkDevices[index].m_hadrwareId); + deviceAPI->setSampleSinkId(m_sampleSinkDevices[index].m_deviceId); + deviceAPI->setSampleSinkSerial(m_sampleSinkDevices[index].m_deviceSerial); + deviceAPI->setSampleSinkPluginGUI(pluginGUI); + deviceAPI->setOutputGUI(gui, m_sampleSinkDevices[index].m_displayName); + + return index; +} + +int PluginManager::selectSampleSourceBySerialOrSequence(const QString& sourceId, const QString& sourceSerial, int sourceSequence, DeviceSourceAPI *deviceAPI) +{ + qDebug("PluginManager::selectSampleSourceBySequence by sequence: id: %s ser: %s seq: %d", qPrintable(sourceId), qPrintable(sourceSerial), sourceSequence); + + int index = -1; + int index_matchingSequence = -1; + int index_firstOfKind = -1; + + for (int i = 0; i < m_sampleSourceDevices.count(); i++) + { + if (m_sampleSourceDevices[i].m_deviceId == sourceId) + { + index_firstOfKind = i; + + if (m_sampleSourceDevices[i].m_deviceSerial == sourceSerial) + { + index = i; // exact match + break; + } + + if (m_sampleSourceDevices[i].m_deviceSequence == sourceSequence) + { + index_matchingSequence = i; + } + } + } + + if(index == -1) // no exact match + { + if (index_matchingSequence == -1) // no matching sequence + { + if (index_firstOfKind == -1) // no matching device type + { + if(m_sampleSourceDevices.count() > 0) // take first if any + { + index = 0; + } + else + { + return -1; // return if no device attached + } + } + else + { + index = index_firstOfKind; // take first that matches device type + } + } + else + { + index = index_matchingSequence; // take the one that matches the sequence in the device type + } + } + + qDebug() << "PluginManager::selectSampleSourceBySequence: m_sampleSource at index " << index + << " hid: " << m_sampleSourceDevices[index].m_hadrwareId.toStdString().c_str() + << " id: " << m_sampleSourceDevices[index].m_deviceId.toStdString().c_str() + << " ser: " << m_sampleSourceDevices[index].m_deviceSerial.toStdString().c_str() + << " seq: " << m_sampleSourceDevices[index].m_deviceSequence; + + deviceAPI->stopAcquisition(); + deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists + + QWidget *gui; + PluginGUI *pluginGUI = m_sampleSourceDevices[index].m_plugin->createSampleSourcePluginGUI(m_sampleSourceDevices[index].m_deviceId, &gui, deviceAPI); + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSourceSequence(m_sampleSourceDevices[index].m_deviceSequence); + deviceAPI->setHardwareId(m_sampleSourceDevices[index].m_hadrwareId); + deviceAPI->setSampleSourceId(m_sampleSourceDevices[index].m_deviceId); + deviceAPI->setSampleSourceSerial(m_sampleSourceDevices[index].m_deviceSerial); + deviceAPI->setSampleSourcePluginGUI(pluginGUI); + deviceAPI->setInputGUI(gui, m_sampleSourceDevices[index].m_displayName); + + return index; +} + +int PluginManager::selectSampleSinkBySerialOrSequence(const QString& sinkId, const QString& sinkSerial, int sinkSequence, DeviceSinkAPI *deviceAPI) +{ + qDebug("PluginManager::selectSampleSinkBySerialOrSequence by sequence: id: %s ser: %s seq: %d", qPrintable(sinkId), qPrintable(sinkSerial), sinkSequence); + + int index = -1; + int index_matchingSequence = -1; + int index_firstOfKind = -1; + + for (int i = 0; i < m_sampleSinkDevices.count(); i++) + { + if (m_sampleSinkDevices[i].m_deviceId == sinkId) + { + index_firstOfKind = i; + + if (m_sampleSinkDevices[i].m_deviceSerial == sinkSerial) + { + index = i; // exact match + break; + } + + if (m_sampleSinkDevices[i].m_deviceSequence == sinkSequence) + { + index_matchingSequence = i; + } + } + } + + if(index == -1) // no exact match + { + if (index_matchingSequence == -1) // no matching sequence + { + if (index_firstOfKind == -1) // no matching device type + { + if(m_sampleSinkDevices.count() > 0) // take first if any + { + index = 0; + } + else + { + return -1; // return if no device attached + } + } + else + { + index = index_firstOfKind; // take first that matches device type + } + } + else + { + index = index_matchingSequence; // take the one that matches the sequence in the device type + } + } + + qDebug() << "PluginManager::selectSampleSinkBySerialOrSequence: m_sampleSink at index " << index + << " hid: " << m_sampleSinkDevices[index].m_hadrwareId.toStdString().c_str() + << " id: " << m_sampleSinkDevices[index].m_deviceId.toStdString().c_str() + << " ser: " << m_sampleSinkDevices[index].m_deviceSerial.toStdString().c_str() + << " seq: " << m_sampleSinkDevices[index].m_deviceSequence; + + deviceAPI->stopGeneration(); + deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists + + QWidget *gui; + PluginGUI *pluginGUI = m_sampleSinkDevices[index].m_plugin->createSampleSinkPluginGUI(m_sampleSinkDevices[index].m_deviceId, &gui, deviceAPI); + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSinkSequence(m_sampleSinkDevices[index].m_deviceSequence); + deviceAPI->setHardwareId(m_sampleSinkDevices[index].m_hadrwareId); + deviceAPI->setSampleSinkId(m_sampleSinkDevices[index].m_deviceId); + deviceAPI->setSampleSinkSerial(m_sampleSinkDevices[index].m_deviceSerial); + deviceAPI->setSampleSinkPluginGUI(pluginGUI); + deviceAPI->setOutputGUI(gui, m_sampleSinkDevices[index].m_displayName); + + return index; +} + +void PluginManager::selectSampleSourceByDevice(void *devicePtr, DeviceSourceAPI *deviceAPI) +{ + SamplingDevice *sampleSourceDevice = (SamplingDevice *) devicePtr; + + qDebug() << "PluginManager::selectSampleSourceByDevice: " + << " hid: " << sampleSourceDevice->m_hadrwareId.toStdString().c_str() + << " id: " << sampleSourceDevice->m_deviceId.toStdString().c_str() + << " ser: " << sampleSourceDevice->m_deviceSerial.toStdString().c_str() + << " seq: " << sampleSourceDevice->m_deviceSequence; + + deviceAPI->setSampleSourcePluginGUI(0); // this effectively destroys the previous GUI if it exists // TODO: move out + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSourceSequence(sampleSourceDevice->m_deviceSequence); + deviceAPI->setHardwareId(sampleSourceDevice->m_hadrwareId); + deviceAPI->setSampleSourceId(sampleSourceDevice->m_deviceId); + deviceAPI->setSampleSourceSerial(sampleSourceDevice->m_deviceSerial); + + // TOOD: move out the rest + + QWidget *gui; + PluginGUI *pluginGUI = sampleSourceDevice->m_plugin->createSampleSourcePluginGUI(sampleSourceDevice->m_deviceId, &gui, deviceAPI); + + deviceAPI->setSampleSourcePluginGUI(pluginGUI); + deviceAPI->setInputGUI(gui, sampleSourceDevice->m_displayName); +} + +void PluginManager::selectSampleSinkByDevice(void *devicePtr, DeviceSinkAPI *deviceAPI) +{ + SamplingDevice *sampleSinkDevice = (SamplingDevice *) devicePtr; + + qDebug() << "PluginManager::selectSampleSinkByDevice: " + << " hid: " << sampleSinkDevice->m_hadrwareId.toStdString().c_str() + << " id: " << sampleSinkDevice->m_deviceId.toStdString().c_str() + << " ser: " << sampleSinkDevice->m_deviceSerial.toStdString().c_str() + << " seq: " << sampleSinkDevice->m_deviceSequence; + + deviceAPI->setSampleSinkPluginGUI(0); // this effectively destroys the previous GUI if it exists + + // m_sampleSourcePluginGUI = pluginGUI; + deviceAPI->setSampleSinkSequence(sampleSinkDevice->m_deviceSequence); + deviceAPI->setHardwareId(sampleSinkDevice->m_hadrwareId); + deviceAPI->setSampleSinkId(sampleSinkDevice->m_deviceId); + deviceAPI->setSampleSinkSerial(sampleSinkDevice->m_deviceSerial); + + QWidget *gui; + PluginGUI *pluginGUI = sampleSinkDevice->m_plugin->createSampleSinkPluginGUI(sampleSinkDevice->m_deviceId, &gui, deviceAPI); + + deviceAPI->setSampleSinkPluginGUI(pluginGUI); + deviceAPI->setOutputGUI(gui, sampleSinkDevice->m_displayName); +} + +void PluginManager::loadPlugins(const QDir& dir) +{ + QDir pluginsDir(dir); + + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + if (fileName.endsWith(".so") || fileName.endsWith(".dll") || fileName.endsWith(".dylib")) + { + qDebug() << "PluginManager::loadPlugins: fileName: " << qPrintable(fileName); + + QPluginLoader* loader = new QPluginLoader(pluginsDir.absoluteFilePath(fileName)); + PluginInterface* plugin = qobject_cast(loader->instance()); + + if (loader->isLoaded()) + { + qWarning("PluginManager::loadPlugins: loaded plugin %s", qPrintable(fileName)); + } + else + { + qWarning() << "PluginManager::loadPlugins: " << qPrintable(loader->errorString()); + } + + if (plugin != 0) + { + m_plugins.append(Plugin(fileName, loader, plugin)); + } + else + { + loader->unload(); + } + + delete loader; // Valgrind memcheck + } + } + + // recursive calls on subdirectories + + foreach (QString dirName, pluginsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) + { + loadPlugins(pluginsDir.absoluteFilePath(dirName)); + } +} + +void PluginManager::populateRxChannelComboBox(QComboBox *channels) +{ + for(PluginAPI::ChannelRegistrations::iterator it = m_rxChannelRegistrations.begin(); it != m_rxChannelRegistrations.end(); ++it) + { + const PluginDescriptor& pluginDescipror = it->m_plugin->getPluginDescriptor(); + channels->addItem(pluginDescipror.displayedName); + } +} + +void PluginManager::populateTxChannelComboBox(QComboBox *channels) +{ + for(PluginAPI::ChannelRegistrations::iterator it = m_txChannelRegistrations.begin(); it != m_txChannelRegistrations.end(); ++it) + { + const PluginDescriptor& pluginDescipror = it->m_plugin->getPluginDescriptor(); + channels->addItem(pluginDescipror.displayedName); + } +} + +void PluginManager::createRxChannelInstance(int channelPluginIndex, DeviceSourceAPI *deviceAPI) +{ + if (channelPluginIndex < m_rxChannelRegistrations.size()) + { + PluginInterface *pluginInterface = m_rxChannelRegistrations[channelPluginIndex].m_plugin; + pluginInterface->createRxChannel(m_rxChannelRegistrations[channelPluginIndex].m_channelName, deviceAPI); + } +} + +void PluginManager::createTxChannelInstance(int channelPluginIndex, DeviceSinkAPI *deviceAPI) +{ + if (channelPluginIndex < m_txChannelRegistrations.size()) + { + PluginInterface *pluginInterface = m_txChannelRegistrations[channelPluginIndex].m_plugin; + pluginInterface->createTxChannel(m_txChannelRegistrations[channelPluginIndex].m_channelName, deviceAPI); + } +}