From 842546aec62ab9b0169b60af903e4cc86bf1e562 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 28 Mar 2022 20:12:25 +0200 Subject: [PATCH] Rotator controller and dependent plugins: implemented new message pipes and other fixes. Part of #1154 --- plugins/channelrx/demodadsb/adsbdemod.cpp | 22 +- .../radioastronomy/radioastronomy.cpp | 106 +++++-- .../channelrx/radioastronomy/radioastronomy.h | 23 +- .../radioastronomy/radioastronomygui.cpp | 69 ++--- .../radioastronomy/radioastronomygui.h | 2 +- .../radioastronomy/radioastronomysettings.h | 4 +- plugins/feature/ais/ais.cpp | 37 ++- plugins/feature/aprs/aprs.cpp | 39 ++- .../gs232controller/gs232controller.cpp | 290 ++++++++++++++++-- .../feature/gs232controller/gs232controller.h | 35 ++- .../gs232controller/gs232controllergui.cpp | 65 ++-- .../gs232controller/gs232controllergui.h | 4 +- .../gs232controller/gs232controllersettings.h | 15 + plugins/feature/map/mapmodel.cpp | 24 +- plugins/feature/map/mapmodel.h | 2 +- plugins/feature/radiosonde/radiosonde.cpp | 37 ++- .../satellitetrackerworker.cpp | 24 +- plugins/feature/startracker/startracker.cpp | 37 ++- .../feature/startracker/startrackerworker.cpp | 30 +- plugins/feature/vorlocalizer/vorlocalizer.cpp | 30 +- sdrbase/maincore.h | 8 +- sdrbase/pipes/messagepipeslegacy.cpp | 2 +- sdrbase/pipes/objectpipe.cpp | 6 + sdrbase/pipes/objectpipe.h | 1 + sdrbase/pipes/objectpipesregistrations.cpp | 23 +- 25 files changed, 694 insertions(+), 241 deletions(-) diff --git a/plugins/channelrx/demodadsb/adsbdemod.cpp b/plugins/channelrx/demodadsb/adsbdemod.cpp index fb07a85f6..6bf711ab5 100644 --- a/plugins/channelrx/demodadsb/adsbdemod.cpp +++ b/plugins/channelrx/demodadsb/adsbdemod.cpp @@ -772,21 +772,17 @@ void ADSBDemod::setTarget(const QString& name, float targetAzimuth, float target m_targetAzElValid = true; // Send to Rotator Controllers - MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipesLegacy(); - QList *mapMessageQueues = messagePipes.getMessageQueues(this, "target"); + QList rotatorPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(this, "target", rotatorPipes); - if (mapMessageQueues) + for (const auto& pipe : rotatorPipes) { - QList::iterator it = mapMessageQueues->begin(); - - for (; it != mapMessageQueues->end(); ++it) - { - SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); - swgTarget->setName(new QString(name)); - swgTarget->setAzimuth(targetAzimuth); - swgTarget->setElevation(targetElevation); - (*it)->push(MainCore::MsgTargetAzimuthElevation::create(this, swgTarget)); - } + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); + swgTarget->setName(new QString(name)); + swgTarget->setAzimuth(targetAzimuth); + swgTarget->setElevation(targetElevation); + messageQueue->push(MainCore::MsgTargetAzimuthElevation::create(this, swgTarget)); } } diff --git a/plugins/channelrx/radioastronomy/radioastronomy.cpp b/plugins/channelrx/radioastronomy/radioastronomy.cpp index 53346461b..cf06ca0dd 100644 --- a/plugins/channelrx/radioastronomy/radioastronomy.cpp +++ b/plugins/channelrx/radioastronomy/radioastronomy.cpp @@ -60,6 +60,7 @@ MESSAGE_CLASS_DEFINITION(RadioAstronomy::MsgStopSweep, Message) MESSAGE_CLASS_DEFINITION(RadioAstronomy::MsgSweepComplete, Message) MESSAGE_CLASS_DEFINITION(RadioAstronomy::MsgSweepStatus, Message) MESSAGE_CLASS_DEFINITION(RadioAstronomy::MsgReportAvailableFeatures, Message) +MESSAGE_CLASS_DEFINITION(RadioAstronomy::MsgReportAvailableRotators, Message) const char * const RadioAstronomy::m_channelIdURI = "sdrangel.channel.radioastronomy"; const char * const RadioAstronomy::m_channelId = "RadioAstronomy"; @@ -108,6 +109,12 @@ RadioAstronomy::RadioAstronomy(DeviceAPI *deviceAPI) : this, &RadioAstronomy::handleFeatureAdded ); + QObject::connect( + MainCore::instance(), + &MainCore::featureRemoved, + this, + &RadioAstronomy::handleFeatureRemoved + ); m_sweepTimer.setSingleShot(true); } @@ -115,6 +122,12 @@ RadioAstronomy::RadioAstronomy(DeviceAPI *deviceAPI) : RadioAstronomy::~RadioAstronomy() { qDebug("RadioAstronomy::~RadioAstronomy"); + QObject::disconnect( + MainCore::instance(), + &MainCore::featureRemoved, + this, + &RadioAstronomy::handleFeatureRemoved + ); QObject::disconnect( MainCore::instance(), &MainCore::featureAdded, @@ -733,7 +746,7 @@ void RadioAstronomy::applySettings(const RadioAstronomySettings& settings, bool for (const auto& fval : m_availableFeatures) { - QString starTrackerText = tr("F1:%2 %3").arg(fval.m_deviceSetIndex).arg(fval.m_featureIndex).arg(fval.m_type); + QString starTrackerText = tr("F%1:%2 %3").arg(fval.m_featureSetIndex).arg(fval.m_featureIndex).arg(fval.m_type); if (settings.m_starTracker == starTrackerText) { @@ -1218,6 +1231,7 @@ void RadioAstronomy::scanAvailableFeatures() MessagePipes& messagePipes = mainCore->getMessagePipes(); std::vector& featureSets = mainCore->getFeatureeSets(); m_availableFeatures.clear(); + m_rotators.clear(); for (const auto& featureSet : featureSets) { @@ -1225,28 +1239,38 @@ void RadioAstronomy::scanAvailableFeatures() { Feature *feature = featureSet->getFeatureAt(fei); - if (RadioAstronomySettings::m_pipeURIs.contains(feature->getURI()) && !m_availableFeatures.contains(feature)) + if (RadioAstronomySettings::m_pipeURIs.contains(feature->getURI())) { - qDebug("RadioAstronomy::scanAvailableFeatures: register %d:%d %s (%p)", - featureSet->getIndex(), fei, qPrintable(feature->getURI()), feature); - ObjectPipe *pipe = messagePipes.registerProducerToConsumer(feature, this, "startracker.target"); - MessageQueue *messageQueue = qobject_cast(pipe->m_element); - QObject::connect( - messageQueue, - &MessageQueue::messageEnqueued, - this, - [=](){ this->handleFeatureMessageQueue(messageQueue); }, - Qt::QueuedConnection - ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); - RadioAstronomySettings::AvailableFeature availableFeature = + if (!m_availableFeatures.contains(feature)) + { + qDebug("RadioAstronomy::scanAvailableFeatures: register %d:%d %s (%p)", + featureSet->getIndex(), fei, qPrintable(feature->getURI()), feature); + ObjectPipe *pipe = messagePipes.registerProducerToConsumer(feature, this, "startracker.target"); + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + this, + [=](){ this->handleFeatureMessageQueue(messageQueue); }, + Qt::QueuedConnection + ); + connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + RadioAstronomySettings::AvailableFeature availableFeature = + RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), fei, feature->getIdentifier()}; + m_availableFeatures[feature] = availableFeature; + } + } + else if (feature->getURI() == "sdrangel.feature.gs232controller") + { + RadioAstronomySettings::AvailableFeature rotator = RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), fei, feature->getIdentifier()}; - m_availableFeatures[feature] = availableFeature; + m_rotators[feature] = rotator; } } } notifyUpdateFeatures(); + notifyUpdateRotators(); } void RadioAstronomy::notifyUpdateFeatures() @@ -1259,6 +1283,16 @@ void RadioAstronomy::notifyUpdateFeatures() } } +void RadioAstronomy::notifyUpdateRotators() +{ + if (getMessageQueueToGUI()) + { + MsgReportAvailableRotators *msg = MsgReportAvailableRotators::create(); + msg->getFeatures() = m_rotators.values(); + getMessageQueueToGUI()->push(msg); + } +} + void RadioAstronomy::handleFeatureAdded(int featureSetIndex, Feature *feature) { qDebug("RadioAstronomy::handleFeatureAdded: featureSetIndex: %d:%d feature: %s (%p)", @@ -1281,7 +1315,12 @@ void RadioAstronomy::handleFeatureAdded(int featureSetIndex, Feature *feature) [=](){ this->handleFeatureMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &RadioAstronomy::handleMessagePipeToBeDeleted + ); } RadioAstronomySettings::AvailableFeature availableFeature = @@ -1290,18 +1329,37 @@ void RadioAstronomy::handleFeatureAdded(int featureSetIndex, Feature *feature) notifyUpdateFeatures(); } + else if (feature->getURI() == "sdrangel.feature.gs232controller") + { + if (!m_rotators.contains(feature)) + { + RadioAstronomySettings::AvailableFeature rotator = + RadioAstronomySettings::AvailableFeature{featureSet->getIndex(), feature->getIndexInFeatureSet(), feature->getIdentifier()}; + m_rotators[feature] = rotator; + } + + notifyUpdateRotators(); + } +} + +void RadioAstronomy::handleFeatureRemoved(int featureSetIndex, Feature *feature) +{ + qDebug("RadioAstronomy::handleFeatureRemoved: featureSetIndex: %d (%p)", featureSetIndex, feature); + + if (m_rotators.contains(feature)) + { + m_rotators.remove(feature); + notifyUpdateRotators(); + } } void RadioAstronomy::handleMessagePipeToBeDeleted(int reason, QObject* object) { - if (reason == 0) // producer (channel) + if ((reason == 0) && m_availableFeatures.contains((Feature*) object)) // producer (feature) { - if (m_availableFeatures.contains((Feature*) object)) - { - qDebug("RadioAstronomy::handleMessagePipeToBeDeleted: removing feature at (%p)", object); - m_availableFeatures.remove((Feature*) object); - notifyUpdateFeatures(); - } + qDebug("RadioAstronomy::handleMessagePipeToBeDeleted: removing feature at (%p)", object); + m_availableFeatures.remove((Feature*) object); + notifyUpdateFeatures(); } } diff --git a/plugins/channelrx/radioastronomy/radioastronomy.h b/plugins/channelrx/radioastronomy/radioastronomy.h index 4151b9008..6bd82a1cd 100644 --- a/plugins/channelrx/radioastronomy/radioastronomy.h +++ b/plugins/channelrx/radioastronomy/radioastronomy.h @@ -324,6 +324,24 @@ public: {} }; + class MsgReportAvailableRotators : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QList& getFeatures() { return m_availableFeatures; } + + static MsgReportAvailableRotators* create() { + return new MsgReportAvailableRotators(); + } + + private: + QList m_availableFeatures; + + MsgReportAvailableRotators() : + Message() + {} + }; + RadioAstronomy(DeviceAPI *deviceAPI); virtual ~RadioAstronomy(); virtual void destroy() { delete this; } @@ -405,6 +423,7 @@ private: qint64 m_centerFrequency; QHash m_availableFeatures; + QHash m_rotators; QObject *m_selectedPipe; QNetworkAccessManager *m_networkManager; @@ -440,6 +459,7 @@ private: void calComplete(MsgCalComplete* report); void scanAvailableFeatures(); void notifyUpdateFeatures(); + void notifyUpdateRotators(); private slots: void networkManagerFinished(QNetworkReply *reply); @@ -451,7 +471,8 @@ private slots: void sweepNext(); void sweepComplete(); void handleIndexInDeviceSetChanged(int index); - void handleFeatureAdded(int deviceSetIndex, Feature *feature); + void handleFeatureAdded(int featureSetIndex, Feature *feature); + void handleFeatureRemoved(int featureSetIndex, Feature *feature); void handleMessagePipeToBeDeleted(int reason, QObject* object); void handleFeatureMessageQueue(MessageQueue* messageQueue); }; diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.cpp b/plugins/channelrx/radioastronomy/radioastronomygui.cpp index 352639ada..13de963f1 100644 --- a/plugins/channelrx/radioastronomy/radioastronomygui.cpp +++ b/plugins/channelrx/radioastronomy/radioastronomygui.cpp @@ -942,7 +942,7 @@ void RadioAstronomyGUI::updateAvailableFeatures() ui->starTracker->clear(); for (const auto& feature : m_availableFeatures) { - ui->starTracker->addItem(tr("F%1:%2 %3").arg(feature.m_deviceSetIndex).arg(feature.m_featureIndex).arg(feature.m_type)); + ui->starTracker->addItem(tr("F%1:%2 %3").arg(feature.m_featureSetIndex).arg(feature.m_featureIndex).arg(feature.m_type)); } if (currentText.isEmpty()) @@ -1073,6 +1073,12 @@ bool RadioAstronomyGUI::handleMessage(const Message& message) sensorMeasurementReceived(measurement); return true; } + else if (RadioAstronomy::MsgReportAvailableRotators::match(message)) + { + RadioAstronomy::MsgReportAvailableRotators& report = (RadioAstronomy::MsgReportAvailableRotators&) message; + updateRotatorList(report.getFeatures()); + return true; + } return false; } @@ -2208,8 +2214,6 @@ RadioAstronomyGUI::RadioAstronomyGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUI ui->sweepStartDateTime->setMinimumDateTime(QDateTime::currentDateTime()); ui->spectrumDateTime->setDateTime(QDateTime::currentDateTime()); - updateRotatorList(); - ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); displaySettings(); @@ -2581,52 +2585,33 @@ void RadioAstronomyGUI::tick() ui->channelPower->setText(QString::number(powDbAvg, 'f', 1)); } - if (m_tickCount % 20 == 0) { // 1s - updateRotatorList(); - } - m_tickCount++; } -void RadioAstronomyGUI::updateRotatorList() +void RadioAstronomyGUI::updateRotatorList(const QList& rotators) { // Update list of rotators - std::vector featureSets = MainCore::instance()->getFeatureeSets(); - for (unsigned int i = 0; i < featureSets.size(); i++) + ui->rotator->blockSignals(true); + ui->rotator->clear(); + ui->rotator->addItem("None"); + + for (const auto& rotator : rotators) { - FeatureSet* featureSet = featureSets[i]; - for (int j = 0; j < featureSet->getNumberOfFeatures(); j++) - { - const Feature* feature = featureSet->getFeatureAt(j); - if (feature->getURI() == "sdrangel.feature.gs232controller") - { - // Add if it doesn't already exist - QString name = QString("F%1:%2 GS232Controller").arg(i).arg(j); - if (ui->rotator->findText(name) == -1) - { - ui->rotator->addItem(name); - // Rotator feature can be created after this plugin, so select it - // if the chosen rotator appears - if (name == m_settings.m_rotator) { - ui->rotator->setCurrentIndex(ui->rotator->findText(name)); - } - } - } - else - { - // Try to remove - QString prefix = QString("F%1:%2").arg(i).arg(j); - for (int k = 0; k < ui->rotator->count(); k++) - { - if (ui->rotator->itemText(k).startsWith(prefix)) - { - ui->rotator->removeItem(k); - break; - } - } - } - } + QString name = QString("F%1:%2 %3").arg(rotator.m_featureSetIndex).arg(rotator.m_featureIndex).arg(rotator.m_type); + ui->rotator->addItem(name); } + + // Rotator feature can be created after this plugin, so select it + // if the chosen rotator appears + int rotatorIndex = ui->rotator->findText(m_settings.m_rotator); + + if (rotatorIndex >= 0) { + ui->rotator->setCurrentIndex(rotatorIndex); + } else { + ui->rotator->setCurrentIndex(0); // return to None + } + + ui->rotator->blockSignals(false); } void RadioAstronomyGUI::on_fftSize_currentIndexChanged(int index) diff --git a/plugins/channelrx/radioastronomy/radioastronomygui.h b/plugins/channelrx/radioastronomy/radioastronomygui.h index f246a8efa..8007378b2 100644 --- a/plugins/channelrx/radioastronomy/radioastronomygui.h +++ b/plugins/channelrx/radioastronomy/radioastronomygui.h @@ -322,7 +322,7 @@ private: void displaySpectrumLineFrequency(); void displayRunModeSettings(); void updateAvailableFeatures(); - void updateRotatorList(); + void updateRotatorList(const QList& rotators); bool handleMessage(const Message& message); double degreesToSteradian(double deg) const; double hpbwToSteradians(double hpbw) const; diff --git a/plugins/channelrx/radioastronomy/radioastronomysettings.h b/plugins/channelrx/radioastronomy/radioastronomysettings.h index 46c9cee93..82b3b193e 100644 --- a/plugins/channelrx/radioastronomy/radioastronomysettings.h +++ b/plugins/channelrx/radioastronomy/radioastronomysettings.h @@ -37,7 +37,7 @@ struct RadioAstronomySettings { struct AvailableFeature { - int m_deviceSetIndex; + int m_featureSetIndex; int m_featureIndex; QString m_type; @@ -45,7 +45,7 @@ struct RadioAstronomySettings AvailableFeature(const AvailableFeature&) = default; AvailableFeature& operator=(const AvailableFeature&) = default; bool operator==(const AvailableFeature& a) const { - return (m_deviceSetIndex == a.m_deviceSetIndex) && (m_featureIndex == a.m_featureIndex) && (m_type == a.m_type); + return (m_featureSetIndex == a.m_featureSetIndex) && (m_featureIndex == a.m_featureIndex) && (m_type == a.m_type); } }; diff --git a/plugins/feature/ais/ais.cpp b/plugins/feature/ais/ais.cpp index d2e033f3b..ebcc84fff 100644 --- a/plugins/feature/ais/ais.cpp +++ b/plugins/feature/ais/ais.cpp @@ -55,12 +55,22 @@ AIS::AIS(WebAPIAdapterInterface *webAPIAdapterInterface) : &AIS::networkManagerFinished ); scanAvailableChannels(); - connect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::connect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &AIS::handleChannelAdded + ); } AIS::~AIS() { - disconnect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::disconnect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &AIS::handleChannelAdded + ); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -356,7 +366,12 @@ void AIS::scanAvailableChannels() [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &AIS::handleMessagePipeToBeDeleted + ); m_availableChannels.insert(channel); } } @@ -386,7 +401,12 @@ void AIS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &AIS::handleMessagePipeToBeDeleted + ); m_availableChannels.insert(channel); } } @@ -394,13 +414,10 @@ void AIS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) void AIS::handleMessagePipeToBeDeleted(int reason, QObject* object) { - if (reason == 0) // producer (channel) + if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) { - if (m_availableChannels.contains((ChannelAPI*) object)) - { - qDebug("AIS::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - } + qDebug("AIS::handleMessagePipeToBeDeleted: removing channel at (%p)", object); + m_availableChannels.remove((ChannelAPI*) object); } } diff --git a/plugins/feature/aprs/aprs.cpp b/plugins/feature/aprs/aprs.cpp index 40c375efa..2c0044242 100644 --- a/plugins/feature/aprs/aprs.cpp +++ b/plugins/feature/aprs/aprs.cpp @@ -60,12 +60,22 @@ APRS::APRS(WebAPIAdapterInterface *webAPIAdapterInterface) : &APRS::networkManagerFinished ); scanAvailableChannels(); - connect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::connect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &APRS::handleChannelAdded + ); } APRS::~APRS() { - disconnect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::disconnect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &APRS::handleChannelAdded + ); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -469,7 +479,12 @@ void APRS::scanAvailableChannels() [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &APRS::handleMessagePipeToBeDeleted + ); APRSSettings::AvailableChannel availableChannel = APRSSettings::AvailableChannel{deviceSet->getIndex(), chi, channel->getIdentifier()}; m_availableChannels[channel] = availableChannel; @@ -514,7 +529,12 @@ void APRS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &APRS::handleMessagePipeToBeDeleted + ); } APRSSettings::AvailableChannel availableChannel = @@ -527,14 +547,11 @@ void APRS::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) void APRS::handleMessagePipeToBeDeleted(int reason, QObject* object) { - if (reason == 0) // producer (channel) + if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) { - if (m_availableChannels.contains((ChannelAPI*) object)) - { - qDebug("APRS::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - notifyUpdateChannels(); - } + qDebug("APRS::handleMessagePipeToBeDeleted: removing channel at (%p)", object); + m_availableChannels.remove((ChannelAPI*) object); + notifyUpdateChannels(); } } diff --git a/plugins/feature/gs232controller/gs232controller.cpp b/plugins/feature/gs232controller/gs232controller.cpp index 3247fbe4e..24915b7cb 100644 --- a/plugins/feature/gs232controller/gs232controller.cpp +++ b/plugins/feature/gs232controller/gs232controller.cpp @@ -43,6 +43,7 @@ MESSAGE_CLASS_DEFINITION(GS232Controller::MsgConfigureGS232Controller, Message) MESSAGE_CLASS_DEFINITION(GS232Controller::MsgStartStop, Message) MESSAGE_CLASS_DEFINITION(GS232Controller::MsgReportWorker, Message) +MESSAGE_CLASS_DEFINITION(GS232Controller::MsgReportAvailableChannelOrFeatures, Message) const char* const GS232Controller::m_featureIdURI = "sdrangel.feature.gs232controller"; const char* const GS232Controller::m_featureId = "GS232Controller"; @@ -57,8 +58,6 @@ GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) m_state = StIdle; m_errorMessage = "GS232Controller error"; m_selectedPipe = nullptr; - connect(&m_updatePipesTimer, SIGNAL(timeout()), this, SLOT(updatePipes())); - m_updatePipesTimer.start(1000); m_networkManager = new QNetworkAccessManager(); QObject::connect( m_networkManager, @@ -66,10 +65,58 @@ GS232Controller::GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface) this, &GS232Controller::networkManagerFinished ); + QObject::connect( + MainCore::instance(), + &MainCore::featureAdded, + this, + &GS232Controller::handleFeatureAdded + ); + QObject::connect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &GS232Controller::handleChannelAdded + ); + QObject::connect( + MainCore::instance(), + &MainCore::featureRemoved, + this, + &GS232Controller::handleFeatureRemoved + ); + QObject::connect( + MainCore::instance(), + &MainCore::channelRemoved, + this, + &GS232Controller::handleChannelRemoved + ); } GS232Controller::~GS232Controller() { + QObject::disconnect( + MainCore::instance(), + &MainCore::channelRemoved, + this, + &GS232Controller::handleChannelRemoved + ); + QObject::disconnect( + MainCore::instance(), + &MainCore::featureRemoved, + this, + &GS232Controller::handleFeatureRemoved + ); + QObject::disconnect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &GS232Controller::handleChannelAdded + ); + QObject::disconnect( + MainCore::instance(), + &MainCore::featureAdded, + this, + &GS232Controller::handleFeatureAdded + ); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -96,6 +143,8 @@ void GS232Controller::start() GS232ControllerWorker::MsgConfigureGS232ControllerWorker *msg = GS232ControllerWorker::MsgConfigureGS232ControllerWorker::create(m_settings, true); m_worker->getInputMessageQueue()->push(msg); + + scanAvailableChannelsAndFeatures(); } void GS232Controller::stop() @@ -201,24 +250,6 @@ bool GS232Controller::getOnTarget() const return onTarget; } -void GS232Controller::updatePipes() -{ - QList availablePipes = updateAvailablePipeSources("target", GS232ControllerSettings::m_pipeTypes, GS232ControllerSettings::m_pipeURIs, this); - - if (availablePipes != m_availablePipes) - { - m_availablePipes = availablePipes; - - if (getMessageQueueToGUI()) - { - MsgReportPipes *msgToGUI = MsgReportPipes::create(); - QList& msgAvailablePipes = msgToGUI->getAvailablePipes(); - msgAvailablePipes.append(availablePipes); - getMessageQueueToGUI()->push(msgToGUI); - } - } -} - QByteArray GS232Controller::serialize() const { return m_settings.serialize(); @@ -296,14 +327,49 @@ void GS232Controller::applySettings(const GS232ControllerSettings& settings, boo || (!settings.m_source.isEmpty() && (m_selectedPipe == nullptr)) // Change in available pipes || force) { + MainCore *mainCore = MainCore::instance(); + MessagePipes& messagePipes = mainCore->getMessagePipes(); + + if (m_selectedPipe) + { + qDebug("GS232Controller::applySettings: unregister %s (%p)", qPrintable(m_selectedPipe->objectName()), m_selectedPipe); + messagePipes.unregisterProducerToConsumer(m_selectedPipe, this, "target"); + } + if (!settings.m_source.isEmpty()) { - m_selectedPipe = getPipeEndPoint(settings.m_source, m_availablePipes); + QObject *object = nullptr; - if (m_selectedPipe == nullptr) { + for (const auto& oval : m_availableChannelOrFeatures) + { + QString itemText = tr("%1%2:%3 %4") + .arg(oval.m_kind) + .arg(oval.m_superIndex) + .arg(oval.m_index) + .arg(oval.m_type); + + if (settings.m_source == itemText) + { + object = m_availableChannelOrFeatures.key(oval); + break; + } + } + + if (object) + { + registerPipe(object); + m_selectedPipe = object; + } + else + { + m_selectedPipe = nullptr; qDebug() << "GS232Controller::applySettings: No plugin corresponding to source " << settings.m_source; } } + else + { + m_selectedPipe = nullptr; + } reverseAPIKeys.append("source"); } @@ -663,8 +729,15 @@ void GS232Controller::webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& r { response.getGs232ControllerReport()->setSources(new QList()); - for (int i = 0; i < m_availablePipes.size(); i++) { - response.getGs232ControllerReport()->getSources()->append(new QString(m_availablePipes.at(i).getName())); + for (const auto& item : m_availableChannelOrFeatures) + { + QString itemText = tr("%1%2:%3 %4") + .arg(item.m_kind) + .arg(item.m_superIndex) + .arg(item.m_index) + .arg(item.m_type); + + response.getGs232ControllerReport()->getSources()->append(new QString(itemText)); } QList serialPorts = QSerialPortInfo::availablePorts(); @@ -707,3 +780,172 @@ void GS232Controller::networkManagerFinished(QNetworkReply *reply) reply->deleteLater(); } + +void GS232Controller::scanAvailableChannelsAndFeatures() +{ + qDebug("GS232Controller::scanAvailableChannelsAndFeatures"); + MainCore *mainCore = MainCore::instance(); + std::vector& featureSets = mainCore->getFeatureeSets(); + m_availableChannelOrFeatures.clear(); + + for (const auto& featureSet : featureSets) + { + for (int fei = 0; fei < featureSet->getNumberOfFeatures(); fei++) + { + Feature *feature = featureSet->getFeatureAt(fei); + + if (GS232ControllerSettings::m_pipeURIs.contains(feature->getURI()) && !m_availableChannelOrFeatures.contains(feature)) + { + qDebug("GS232Controller::scanAvailableChannelsAndFeatures: store feature %d:%d %s (%p)", + featureSet->getIndex(), fei, qPrintable(feature->getURI()), feature); + GS232ControllerSettings::AvailableChannelOrFeature availableItem = + GS232ControllerSettings::AvailableChannelOrFeature{"F", featureSet->getIndex(), fei, feature->getIdentifier()}; + m_availableChannelOrFeatures[feature] = availableItem; + } + } + } + + std::vector& deviceSets = mainCore->getDeviceSets(); + + for (const auto& deviceSet : deviceSets) + { + DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; + + if (deviceSourceEngine) + { + for (int chi = 0; chi < deviceSet->getNumberOfChannels(); chi++) + { + ChannelAPI *channel = deviceSet->getChannelAt(chi); + + if (GS232ControllerSettings::m_pipeURIs.contains(channel->getURI()) && !m_availableChannelOrFeatures.contains(channel)) + { + qDebug("GS232Controller::scanAvailableChannelsAndFeatures: store channel %d:%d %s (%p)", + deviceSet->getIndex(), chi, qPrintable(channel->getURI()), channel); + GS232ControllerSettings::AvailableChannelOrFeature availableItem = + GS232ControllerSettings::AvailableChannelOrFeature{"R", deviceSet->getIndex(), chi, channel->getIdentifier()}; + m_availableChannelOrFeatures[channel] = availableItem; + } + } + } + } + + notifyUpdate(); +} + +void GS232Controller::notifyUpdate() +{ + if (getMessageQueueToGUI()) + { + MsgReportAvailableChannelOrFeatures *msg = MsgReportAvailableChannelOrFeatures::create(); + msg->getItems() = m_availableChannelOrFeatures.values(); + getMessageQueueToGUI()->push(msg); + } +} + +void GS232Controller::handleFeatureAdded(int featureSetIndex, Feature *feature) +{ + qDebug("GS232Controller::handleFeatureAdded: featureSetIndex: %d:%d feature: %s (%p)", + featureSetIndex, feature->getIndexInFeatureSet(), qPrintable(feature->getURI()), feature); + FeatureSet *featureSet = MainCore::instance()->getFeatureeSets()[featureSetIndex]; + + if (GS232ControllerSettings::m_pipeURIs.contains(feature->getURI())) + { + GS232ControllerSettings::AvailableChannelOrFeature availableItem = + GS232ControllerSettings::AvailableChannelOrFeature{ + "F", + featureSet->getIndex(), + feature->getIndexInFeatureSet(), + feature->getIdentifier() + }; + m_availableChannelOrFeatures[feature] = availableItem; + + notifyUpdate(); + } +} + +void GS232Controller::handleFeatureRemoved(int featureSetIndex, Feature *feature) +{ + qDebug("GS232Controller::handleFeatureRemoved: featureSetIndex: %d (%p)", featureSetIndex, feature); + + if (m_availableChannelOrFeatures.contains(feature)) + { + m_availableChannelOrFeatures.remove(feature); + notifyUpdate(); + } +} + +void GS232Controller::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) +{ + qDebug("GS232Controller::handleChannelAdded: deviceSetIndex: %d:%d channel: %s (%p)", + deviceSetIndex, channel->getIndexInDeviceSet(), qPrintable(channel->getURI()), channel); + DeviceSet *deviceSet = MainCore::instance()->getDeviceSets()[deviceSetIndex]; + DSPDeviceSourceEngine *deviceSourceEngine = deviceSet->m_deviceSourceEngine; + + if (deviceSourceEngine && GS232ControllerSettings::m_pipeURIs.contains(channel->getURI())) + { + GS232ControllerSettings::AvailableChannelOrFeature availableItem = + GS232ControllerSettings::AvailableChannelOrFeature{ + "R", + deviceSet->getIndex(), + channel->getIndexInDeviceSet(), + channel->getIdentifier() + }; + m_availableChannelOrFeatures[channel] = availableItem; + + notifyUpdate(); + } +} + +void GS232Controller::handleChannelRemoved(int deviceSetIndex, ChannelAPI *channel) +{ + qDebug("GS232Controller::handleChannelRemoved: deviceSetIndex: %d (%p)", deviceSetIndex, channel); + + if (m_availableChannelOrFeatures.contains(channel)) + { + m_availableChannelOrFeatures.remove(channel); + notifyUpdate(); + } +} + +void GS232Controller::registerPipe(QObject *object) +{ + qDebug("GS232Controller::registerPipe: register %s (%p)", qPrintable(object->objectName()), object); + MessagePipes& messagePipes = MainCore::instance()->getMessagePipes(); + ObjectPipe *pipe = messagePipes.registerProducerToConsumer(object, this, "target"); + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + QObject::connect( + messageQueue, + &MessageQueue::messageEnqueued, + this, + [=](){ this->handlePipeMessageQueue(messageQueue); }, + Qt::QueuedConnection + ); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &GS232Controller::handleMessagePipeToBeDeleted + ); +} + +void GS232Controller::handleMessagePipeToBeDeleted(int reason, QObject* object) +{ + if ((reason == 0) && m_availableChannelOrFeatures.contains(object)) // producer + { + qDebug("GS232Controller::handleMessagePipeToBeDeleted: removing channel or feature at (%p)", object); + m_availableChannelOrFeatures.remove(object); + notifyUpdate(); + } +} + +void GS232Controller::handlePipeMessageQueue(MessageQueue* messageQueue) +{ + Message* message; + + while ((message = messageQueue->pop()) != nullptr) + { + if (handleMessage(*message)) { + delete message; + } + } +} diff --git a/plugins/feature/gs232controller/gs232controller.h b/plugins/feature/gs232controller/gs232controller.h index 20dc9084d..26d7b2da5 100644 --- a/plugins/feature/gs232controller/gs232controller.h +++ b/plugins/feature/gs232controller/gs232controller.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include "feature/feature.h" #include "util/message.h" @@ -101,6 +101,24 @@ public: {} }; + class MsgReportAvailableChannelOrFeatures : public Message { + MESSAGE_CLASS_DECLARATION + + public: + QList& getItems() { return m_availableChannelOrFeatures; } + + static MsgReportAvailableChannelOrFeatures* create() { + return new MsgReportAvailableChannelOrFeatures(); + } + + private: + QList m_availableChannelOrFeatures; + + MsgReportAvailableChannelOrFeatures() : + Message() + {} + }; + GS232Controller(WebAPIAdapterInterface *webAPIAdapterInterface); virtual ~GS232Controller(); virtual void destroy() { delete this; } @@ -154,9 +172,8 @@ private: QThread m_thread; GS232ControllerWorker *m_worker; GS232ControllerSettings m_settings; - QList m_availablePipes; - PipeEndPoint *m_selectedPipe; - QTimer m_updatePipesTimer; + QHash m_availableChannelOrFeatures; + QObject *m_selectedPipe; QNetworkAccessManager *m_networkManager; QNetworkRequest m_networkRequest; @@ -169,10 +186,18 @@ private: void applySettings(const GS232ControllerSettings& settings, bool force = false); void webapiReverseSendSettings(QList& featureSettingsKeys, const GS232ControllerSettings& settings, bool force); void webapiFormatFeatureReport(SWGSDRangel::SWGFeatureReport& response); + void scanAvailableChannelsAndFeatures(); + void notifyUpdate(); + void registerPipe(QObject *object); private slots: - void updatePipes(); void networkManagerFinished(QNetworkReply *reply); + void handleFeatureAdded(int featureSetIndex, Feature *feature); + void handleChannelAdded(int deviceSetIndex, ChannelAPI *channel); + void handleFeatureRemoved(int featureSetIndex, Feature *feature); + void handleChannelRemoved(int deviceSetIndex, ChannelAPI *feature); + void handleMessagePipeToBeDeleted(int reason, QObject* object); + void handlePipeMessageQueue(MessageQueue* messageQueue); }; #endif // INCLUDE_FEATURE_GS232CONTROLLER_H_ diff --git a/plugins/feature/gs232controller/gs232controllergui.cpp b/plugins/feature/gs232controller/gs232controllergui.cpp index 0f3dc4293..6d8110bc7 100644 --- a/plugins/feature/gs232controller/gs232controllergui.cpp +++ b/plugins/feature/gs232controller/gs232controllergui.cpp @@ -83,11 +83,11 @@ bool GS232ControllerGUI::handleMessage(const Message& message) return true; } - else if (PipeEndPoint::MsgReportPipes::match(message)) + else if (GS232Controller::MsgReportAvailableChannelOrFeatures::match(message)) { - PipeEndPoint::MsgReportPipes& report = (PipeEndPoint::MsgReportPipes&) message; - m_availablePipes = report.getAvailablePipes(); - updatePipeList(); + GS232Controller::MsgReportAvailableChannelOrFeatures& report = + (GS232Controller::MsgReportAvailableChannelOrFeatures&) message; + updatePipeList(report.getItems()); return true; } else if (GS232ControllerReport::MsgReportAzAl::match(message)) @@ -232,41 +232,56 @@ void GS232ControllerGUI::updateSerialPortList() } } -void GS232ControllerGUI::updatePipeList() +void GS232ControllerGUI::updatePipeList(const QList& sources) { QString currentText = ui->sources->currentText(); + QString newText; ui->sources->blockSignals(true); ui->sources->clear(); - QList::const_iterator it = m_availablePipes.begin(); - for (int i = 0; it != m_availablePipes.end(); ++it, i++) + for (const auto& source : sources) { - ui->sources->addItem(it->getName()); + QString name = tr("%1%2:%3 %4") + .arg(source.m_kind) + .arg(source.m_superIndex) + .arg(source.m_index) + .arg(source.m_type); + ui->sources->addItem(name); } - if (currentText.isEmpty()) + int index = ui->sources->findText(m_settings.m_source); + ui->sources->setCurrentIndex(index); + + if (index < 0) // current source is not found { - // Source feature may be loaded after this, so may not have existed when - // displaySettings was called - if (m_availablePipes.size() > 0) { - ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source)); - } - } - else - { - ui->sources->setCurrentIndex(ui->sources->findText(currentText)); + m_settings.m_source = ""; + ui->targetName->setText(""); + applySettings(); } + // if (currentText.isEmpty()) + // { + // // Source feature may be loaded after this, so may not have existed when + // // displaySettings was called + // if (sources.size() > 0) { + // ui->sources->setCurrentIndex(ui->sources->findText(m_settings.m_source)); + // } + // } + // else + // { + // ui->sources->setCurrentIndex(ui->sources->findText(currentText)); + // } + ui->sources->blockSignals(false); - QString newText = ui->sources->currentText(); + // QString newText = ui->sources->currentText(); - if (currentText != newText) - { - m_settings.m_source = newText; - ui->targetName->setText(""); - applySettings(); - } + // if (currentText != newText) + // { + // m_settings.m_source = newText; + // ui->targetName->setText(""); + // applySettings(); + // } } void GS232ControllerGUI::leaveEvent(QEvent*) diff --git a/plugins/feature/gs232controller/gs232controllergui.h b/plugins/feature/gs232controller/gs232controllergui.h index 04c24f467..5ecdd8932 100644 --- a/plugins/feature/gs232controller/gs232controllergui.h +++ b/plugins/feature/gs232controller/gs232controllergui.h @@ -23,7 +23,6 @@ #include "feature/featuregui.h" #include "util/messagequeue.h" -#include "pipes/pipeendpoint.h" #include "settings/rollupstate.h" #include "gs232controllersettings.h" @@ -54,7 +53,6 @@ private: GS232ControllerSettings m_settings; RollupState m_rollupState; bool m_doApplySettings; - QList m_availablePipes; GS232Controller* m_gs232Controller; MessageQueue m_inputMessageQueue; @@ -70,7 +68,7 @@ private: void displaySettings(); void updateConnectionWidgets(); void updateDecimals(GS232ControllerSettings::Protocol protocol); - void updatePipeList(); + void updatePipeList(const QList& sources); void updateSerialPortList(); bool handleMessage(const Message& message); diff --git a/plugins/feature/gs232controller/gs232controllersettings.h b/plugins/feature/gs232controller/gs232controllersettings.h index d91bd6c10..f922022f8 100644 --- a/plugins/feature/gs232controller/gs232controllersettings.h +++ b/plugins/feature/gs232controller/gs232controllersettings.h @@ -28,6 +28,21 @@ class Serializable; struct GS232ControllerSettings { + struct AvailableChannelOrFeature + { + QString m_kind; //!< "R" for channel, "F" for feature + int m_superIndex; + int m_index; + QString m_type; + + AvailableChannelOrFeature() = default; + AvailableChannelOrFeature(const AvailableChannelOrFeature&) = default; + AvailableChannelOrFeature& operator=(const AvailableChannelOrFeature&) = default; + bool operator==(const AvailableChannelOrFeature& a) const { + return (m_kind == a.m_kind) && (m_superIndex == a.m_superIndex) && (m_index == a.m_index) && (m_type == a.m_type); + } + }; + float m_azimuth; float m_elevation; QString m_serialPort; diff --git a/plugins/feature/map/mapmodel.cpp b/plugins/feature/map/mapmodel.cpp index 6b25e63e1..cd87fc1bf 100644 --- a/plugins/feature/map/mapmodel.cpp +++ b/plugins/feature/map/mapmodel.cpp @@ -18,7 +18,6 @@ #include #include "channel/channelwebapiutils.h" -#include "pipes/messagepipeslegacy.h" #include "maincore.h" #include "mapmodel.h" @@ -358,20 +357,17 @@ void MapModel::updateTarget() azEl->calculate(); // Send to Rotator Controllers - MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipesLegacy(); - QList *mapMessageQueues = messagePipes.getMessageQueues(m_gui->getMap(), "target"); - if (mapMessageQueues) - { - QList::iterator it = mapMessageQueues->begin(); + QList rotatorPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(this, "target", rotatorPipes); - for (; it != mapMessageQueues->end(); ++it) - { - SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); - swgTarget->setName(new QString(m_items[m_target]->m_name)); - swgTarget->setAzimuth(azEl->getAzimuth()); - swgTarget->setElevation(azEl->getElevation()); - (*it)->push(MainCore::MsgTargetAzimuthElevation::create(m_gui->getMap(), swgTarget)); - } + for (const auto& pipe : rotatorPipes) + { + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); + swgTarget->setName(new QString(m_items[m_target]->m_name)); + swgTarget->setAzimuth(azEl->getAzimuth()); + swgTarget->setElevation(azEl->getElevation()); + messageQueue->push(MainCore::MsgTargetAzimuthElevation::create(m_gui->getMap(), swgTarget)); } } diff --git a/plugins/feature/map/mapmodel.h b/plugins/feature/map/mapmodel.h index 2b63dc740..b649e410e 100644 --- a/plugins/feature/map/mapmodel.h +++ b/plugins/feature/map/mapmodel.h @@ -23,7 +23,6 @@ #include #include "util/azel.h" -#include "pipes/pipeendpoint.h" #include "mapsettings.h" #include "cesiuminterface.h" @@ -32,6 +31,7 @@ class MapModel; class MapGUI; class CZML; +class PipeEndPoint; // Information required about each item displayed on the map class MapItem { diff --git a/plugins/feature/radiosonde/radiosonde.cpp b/plugins/feature/radiosonde/radiosonde.cpp index e7aa7aea1..f2c214fd3 100644 --- a/plugins/feature/radiosonde/radiosonde.cpp +++ b/plugins/feature/radiosonde/radiosonde.cpp @@ -55,12 +55,22 @@ Radiosonde::Radiosonde(WebAPIAdapterInterface *webAPIAdapterInterface) : &Radiosonde::networkManagerFinished ); scanAvailableChannels(); - connect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::connect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &Radiosonde::handleChannelAdded + ); } Radiosonde::~Radiosonde() { - disconnect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::disconnect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &Radiosonde::handleChannelAdded + ); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -356,7 +366,12 @@ void Radiosonde::scanAvailableChannels() [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &Radiosonde::handleMessagePipeToBeDeleted + ); m_availableChannels.insert(channel); } } @@ -386,7 +401,12 @@ void Radiosonde::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &Radiosonde::handleMessagePipeToBeDeleted + ); m_availableChannels.insert(channel); } } @@ -394,13 +414,10 @@ void Radiosonde::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) void Radiosonde::handleMessagePipeToBeDeleted(int reason, QObject* object) { - if (reason == 0) // producer (channel) + if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) { - if (m_availableChannels.contains((ChannelAPI*) object)) - { - qDebug("Radiosonde::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - } + qDebug("Radiosonde::handleMessagePipeToBeDeleted: removing channel at (%p)", object); + m_availableChannels.remove((ChannelAPI*) object); } } diff --git a/plugins/feature/satellitetracker/satellitetrackerworker.cpp b/plugins/feature/satellitetracker/satellitetrackerworker.cpp index e0b107f0e..2170f8ac1 100644 --- a/plugins/feature/satellitetracker/satellitetrackerworker.cpp +++ b/plugins/feature/satellitetracker/satellitetrackerworker.cpp @@ -405,20 +405,18 @@ void SatelliteTrackerWorker::update() azimuth = std::fmod(azimuth + 180.0, 360.0); elevation = 180.0 - elevation; } - MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipesLegacy(); - QList *rotatorMessageQueues = messagePipes.getMessageQueues(m_satelliteTracker, "target"); - if (rotatorMessageQueues) - { - QList::iterator it = rotatorMessageQueues->begin(); - for (; it != rotatorMessageQueues->end(); ++it) - { - SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); - swgTarget->setName(new QString(m_settings.m_target)); - swgTarget->setAzimuth(azimuth); - swgTarget->setElevation(elevation); - (*it)->push(MainCore::MsgTargetAzimuthElevation::create(m_satelliteTracker, swgTarget)); - } + QList rotatorPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(m_satelliteTracker, "target", rotatorPipes); + + for (const auto& pipe : rotatorPipes) + { + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); + swgTarget->setName(new QString(m_settings.m_target)); + swgTarget->setAzimuth(azimuth); + swgTarget->setElevation(elevation); + messageQueue->push(MainCore::MsgTargetAzimuthElevation::create(m_satelliteTracker, swgTarget)); } } diff --git a/plugins/feature/startracker/startracker.cpp b/plugins/feature/startracker/startracker.cpp index ac56c837a..721a4ed77 100644 --- a/plugins/feature/startracker/startracker.cpp +++ b/plugins/feature/startracker/startracker.cpp @@ -69,12 +69,22 @@ StarTracker::StarTracker(WebAPIAdapterInterface *webAPIAdapterInterface) : m_temps.append(new FITS(":/startracker/startracker/1420mhz_ra_dec.fits")); m_spectralIndex = new FITS(":/startracker/startracker/408mhz_ra_dec_spectral_index.fits"); scanAvailableChannels(); - connect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::connect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &StarTracker::handleChannelAdded + ); } StarTracker::~StarTracker() { - disconnect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::disconnect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &StarTracker::handleChannelAdded + ); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -918,7 +928,12 @@ void StarTracker::scanAvailableChannels() [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &StarTracker::handleMessagePipeToBeDeleted + ); m_availableChannels.insert(channel); } } @@ -947,7 +962,12 @@ void StarTracker::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &StarTracker::handleMessagePipeToBeDeleted + ); m_availableChannels.insert(channel); } } @@ -955,13 +975,10 @@ void StarTracker::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) void StarTracker::handleMessagePipeToBeDeleted(int reason, QObject* object) { - if (reason == 0) // producer (channel) + if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) { - if (m_availableChannels.contains((ChannelAPI*) object)) - { - qDebug("StarTracker::handleMessagePipeToBeDeleted: removing channel at (%p)", object); - m_availableChannels.remove((ChannelAPI*) object); - } + qDebug("StarTracker::handleMessagePipeToBeDeleted: removing channel at (%p)", object); + m_availableChannels.remove((ChannelAPI*) object); } } diff --git a/plugins/feature/startracker/startrackerworker.cpp b/plugins/feature/startracker/startrackerworker.cpp index a4238b1bb..b1cb9b890 100644 --- a/plugins/feature/startracker/startrackerworker.cpp +++ b/plugins/feature/startracker/startrackerworker.cpp @@ -580,26 +580,21 @@ void StarTrackerWorker::update() } } - MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipesLegacy(); - QList* messageQueues; - // Send Az/El to Rotator Controllers // Unless we're receiving settings to display from a Radio Astronomy plugins if (!m_settings.m_link) { - messageQueues = messagePipes.getMessageQueues(m_starTracker, "target"); - if (messageQueues) - { - QList::iterator it = messageQueues->begin(); + QList rotatorPipes; + MainCore::instance()->getMessagePipes().getMessagePipes(m_starTracker, "target", rotatorPipes); - for (; it != messageQueues->end(); ++it) - { - SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); - swgTarget->setName(new QString(m_settings.m_target)); - swgTarget->setAzimuth(aa.az); - swgTarget->setElevation(aa.alt); - (*it)->push(MainCore::MsgTargetAzimuthElevation::create(m_starTracker, swgTarget)); - } + for (const auto& pipe : rotatorPipes) + { + MessageQueue *messageQueue = qobject_cast(pipe->m_element); + SWGSDRangel::SWGTargetAzimuthElevation *swgTarget = new SWGSDRangel::SWGTargetAzimuthElevation(); + swgTarget->setName(new QString(m_settings.m_target)); + swgTarget->setAzimuth(aa.az); + swgTarget->setElevation(aa.alt); + messageQueue->push(MainCore::MsgTargetAzimuthElevation::create(m_starTracker, swgTarget)); } } @@ -608,7 +603,7 @@ void StarTrackerWorker::update() if (!m_settings.m_link) { QList starTrackerPipes; - MainCore::instance()->getMessagePipes().getMessagePipes(this, "startracker.target", starTrackerPipes); + MainCore::instance()->getMessagePipes().getMessagePipes(m_starTracker, "startracker.target", starTrackerPipes); for (const auto& pipe : starTrackerPipes) { @@ -641,7 +636,10 @@ void StarTrackerWorker::update() // Send to Map if (m_settings.m_drawSunOnMap || m_settings.m_drawMoonOnMap || m_settings.m_drawStarOnMap) { + MessagePipesLegacy& messagePipes = MainCore::instance()->getMessagePipesLegacy(); + QList* messageQueues; messageQueues = messagePipes.getMessageQueues(m_starTracker, "mapitems"); + if (messageQueues) { // Different between GMST(Lst at Greenwich) and RA diff --git a/plugins/feature/vorlocalizer/vorlocalizer.cpp b/plugins/feature/vorlocalizer/vorlocalizer.cpp index ce155ffe9..f618cc580 100644 --- a/plugins/feature/vorlocalizer/vorlocalizer.cpp +++ b/plugins/feature/vorlocalizer/vorlocalizer.cpp @@ -62,12 +62,22 @@ VORLocalizer::VORLocalizer(WebAPIAdapterInterface *webAPIAdapterInterface) : this, &VORLocalizer::networkManagerFinished ); - connect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::connect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &VORLocalizer::handleChannelAdded + ); } VORLocalizer::~VORLocalizer() { - disconnect(MainCore::instance(), SIGNAL(channelAdded(int, ChannelAPI*)), this, SLOT(handleChannelAdded(int, ChannelAPI*))); + QObject::disconnect( + MainCore::instance(), + &MainCore::channelAdded, + this, + &VORLocalizer::handleChannelAdded + ); QObject::disconnect( m_networkManager, &QNetworkAccessManager::finished, @@ -264,13 +274,10 @@ bool VORLocalizer::handleMessage(const Message& cmd) void VORLocalizer::handleMessagePipeToBeDeleted(int reason, QObject* object) { - if (reason == 0) // producer (channel) + if ((reason == 0) && m_availableChannels.contains((ChannelAPI*) object)) // producer (channel) { - if (m_availableChannels.contains((ChannelAPI*) object)) - { - m_availableChannels.remove((ChannelAPI*) object); - updateChannels(); - } + m_availableChannels.remove((ChannelAPI*) object); + updateChannels(); } } @@ -679,7 +686,12 @@ void VORLocalizer::handleChannelAdded(int deviceSetIndex, ChannelAPI *channel) [=](){ this->handleChannelMessageQueue(messageQueue); }, Qt::QueuedConnection ); - connect(pipe, SIGNAL(toBeDeleted(int, QObject*)), this, SLOT(handleMessagePipeToBeDeleted(int, QObject*))); + QObject::connect( + pipe, + &ObjectPipe::toBeDeleted, + this, + &VORLocalizer::handleMessagePipeToBeDeleted + ); } VORLocalizerSettings::AvailableChannel availableChannel = diff --git a/sdrbase/maincore.h b/sdrbase/maincore.h index 26fd38678..15a117459 100644 --- a/sdrbase/maincore.h +++ b/sdrbase/maincore.h @@ -610,19 +610,19 @@ public: MESSAGE_CLASS_DECLARATION public: - const PipeEndPoint *getPipeSource() const { return m_pipeSource; } + const QObject *getPipeSource() const { return m_pipeSource; } SWGSDRangel::SWGTargetAzimuthElevation *getSWGTargetAzimuthElevation() const { return m_swgTargetAzimuthElevation; } - static MsgTargetAzimuthElevation* create(const PipeEndPoint *pipeSource, SWGSDRangel::SWGTargetAzimuthElevation *swgTargetAzimuthElevation) + static MsgTargetAzimuthElevation* create(const QObject *pipeSource, SWGSDRangel::SWGTargetAzimuthElevation *swgTargetAzimuthElevation) { return new MsgTargetAzimuthElevation(pipeSource, swgTargetAzimuthElevation); } private: - const PipeEndPoint *m_pipeSource; + const QObject *m_pipeSource; SWGSDRangel::SWGTargetAzimuthElevation *m_swgTargetAzimuthElevation; - MsgTargetAzimuthElevation(const PipeEndPoint *pipeSource, SWGSDRangel::SWGTargetAzimuthElevation *swgTargetAzimuthElevation) : + MsgTargetAzimuthElevation(const QObject *pipeSource, SWGSDRangel::SWGTargetAzimuthElevation *swgTargetAzimuthElevation) : Message(), m_pipeSource(pipeSource), m_swgTargetAzimuthElevation(swgTargetAzimuthElevation) diff --git a/sdrbase/pipes/messagepipeslegacy.cpp b/sdrbase/pipes/messagepipeslegacy.cpp index 2c918f436..6d9355bba 100644 --- a/sdrbase/pipes/messagepipeslegacy.cpp +++ b/sdrbase/pipes/messagepipeslegacy.cpp @@ -58,7 +58,7 @@ MessageQueue *MessagePipesLegacy::unregisterChannelToFeature(const PipeEndPoint QList* MessagePipesLegacy::getMessageQueues(const PipeEndPoint *source, const QString& type) { - qDebug("MessagePipesLegacy::getMessageQueues: %p %s", source, qPrintable(type)); + //qDebug("MessagePipesLegacy::getMessageQueues: %p %s", source, qPrintable(type)); return m_registrations.getElements(source, type); } diff --git a/sdrbase/pipes/objectpipe.cpp b/sdrbase/pipes/objectpipe.cpp index 10962f775..24e17713d 100644 --- a/sdrbase/pipes/objectpipe.cpp +++ b/sdrbase/pipes/objectpipe.cpp @@ -28,10 +28,16 @@ ObjectPipe::ObjectPipe() : void ObjectPipe::setToBeDeleted(int reason, QObject *object) { + qDebug("ObjectPipe::setToBeDeleted: %d (%p)", reason, object); m_gcCount = 2; // will defer actual deletion by one GC pass emit toBeDeleted(reason, object); } +void ObjectPipe::unsetToBeDeleted() +{ + m_gcCount = 0; +} + int ObjectPipe::getGCCount() const { return m_gcCount; } diff --git a/sdrbase/pipes/objectpipe.h b/sdrbase/pipes/objectpipe.h index 5882730c7..3d26935a5 100644 --- a/sdrbase/pipes/objectpipe.h +++ b/sdrbase/pipes/objectpipe.h @@ -31,6 +31,7 @@ public: ObjectPipe& operator=(const ObjectPipe&) = default; void setToBeDeleted(int reason, QObject *object); + void unsetToBeDeleted(); int getGCCount() const; int decreaseGCCount(); diff --git a/sdrbase/pipes/objectpipesregistrations.cpp b/sdrbase/pipes/objectpipesregistrations.cpp index c92c2b0eb..928a2b9fb 100644 --- a/sdrbase/pipes/objectpipesregistrations.cpp +++ b/sdrbase/pipes/objectpipesregistrations.cpp @@ -45,13 +45,32 @@ ObjectPipe *ObjectPipesRegistrations::registerProducerToConsumer(const QObject * for (auto& pipe : m_pipes) // check if pipe exists already - there is a unique pipe per producer, consumer and type { - if ((producer == pipe->m_producer) && (consumer == pipe->m_consumer) && (typeId == pipe->m_typeId)) { + if ((producer == pipe->m_producer) && (consumer == pipe->m_consumer) && (typeId == pipe->m_typeId)) + { + qDebug("ObjectPipesRegistrations::registerProducerToConsumer: return existing pipe %p %p %s %s", + producer, consumer, qPrintable(pipe->m_element->objectName()), qPrintable(type)); + pipe->unsetToBeDeleted(); + if (!m_producerPipes[producer].contains(pipe)) { + m_producerPipes[producer].push_back(pipe); + } + if (!m_consumerPipes[consumer].contains(pipe)) { + m_consumerPipes[consumer].push_back(pipe); + } + if (!m_typeIdPipes[typeId].contains(pipe)) { + m_typeIdPipes[typeId].push_back(pipe); + } + if (!m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].contains(pipe)) { + m_producerAndTypeIdPipes[std::make_tuple(producer, typeId)].push_back(pipe); + } + if (!m_pipeMap.contains(std::make_tuple(producer, consumer, typeId))) { + m_pipeMap[std::make_tuple(producer, consumer, typeId)] = pipe; + } return pipe; } } QObject *element = m_objectPipeElementsStore->createElement(); - qDebug("ObjectPipesRegistrations::registerProducerToConsumer: %p %p %s %s", + qDebug("ObjectPipesRegistrations::registerProducerToConsumer: new pipe %p %p %s %s", producer, consumer, qPrintable(element->objectName()), qPrintable(type)); m_pipes.push_back(new ObjectPipe()); m_pipes.back()->m_pipeId = ++m_pipeId;