diff --git a/app/main.cpp b/app/main.cpp index f3f6ce875..25c12f281 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -26,6 +26,9 @@ #include #include #endif +#ifdef ANDROID +#include "util/android.h" +#endif #include "loggerwithfile.h" #include "mainwindow.h" @@ -49,6 +52,9 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) && (QT_VERSION <= QT_VERSION_CHECK(6, 0, 0)) QApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton); #endif +#ifndef ANDROID + QApplication::setAttribute(Qt::AA_DontUseNativeDialogs); // Don't use on Android, otherwise we can't access files on internal storage +#endif QApplication a(argc, argv); @@ -111,6 +117,20 @@ static int runQtApplication(int argc, char* argv[], qtwebapp::LoggerWithFile *lo #endif #endif + +#ifdef ANDROID + // Default sized sliders can be hard to move using touch GUIs, so increase szie + // FIXME: How can we do a double border around the handle, as Fusion style seems to use? + // Dialog borders are hard to see as is (perhaps as Android doesn't have a title bar), so use same color as for MDI + qApp->setStyleSheet("QSlider {min-height: 20px; } " + "QSlider::groove:horizontal { border: 1px solid #2e2e2e; height: 1px; background: #444444; margin: 1px 0;}" + "QSlider::handle:horizontal { background: #585858; border: 1px double #676767; width: 16px; margin: -8px 0px; border-radius: 3px;}" + "QSlider::sub-page {background: #ff8c00; border: 1px solid #2e2e2e;border-top-right-radius: 0px;border-bottom-right-radius: 0px;border-top-left-radius: 5px;border-bottom-left-radius: 5px;}" + "QSlider::add-page {background: #444444; border: 1px solid #2e2e2e;border-top-right-radius: 5px;border-bottom-right-radius: 5px;border-top-left-radius: 0px;border-bottom-left-radius: 0px;}" + "QDialog { border: 1px solid #ff8c00;}" + ); +#endif + MainParser parser; parser.parse(*qApp); @@ -160,10 +180,18 @@ int main(int argc, char* argv[]) QSurfaceFormat::setDefaultFormat(sfc); #endif - qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp); +#ifdef ANDROID + qtwebapp::LoggerWithFile *logger = nullptr; + qInstallMessageHandler(Android::messageHandler); +#else + qtwebapp::LoggerWithFile *logger = new qtwebapp::LoggerWithFile(qApp); logger->installMsgHandler(); +#endif + int res = runQtApplication(argc, argv, logger); + delete logger; + qWarning("SDRangel quit."); return res; } diff --git a/sdrbase/CMakeLists.txt b/sdrbase/CMakeLists.txt index d1bcb297e..13faff1c9 100644 --- a/sdrbase/CMakeLists.txt +++ b/sdrbase/CMakeLists.txt @@ -1,6 +1,7 @@ project (sdrbase) if(WIN32) + # This should probably be in ../CMakeLists.txt with the other variables like it set(OPUS_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/external/windows/libopus/include") set(OPUS_LIBRARIES "${CMAKE_SOURCE_DIR}/external/windows/libopus/lib/x64/libopus.lib") endif() @@ -45,10 +46,11 @@ if (LIBSIGMF_FOUND AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(sdrbase_LIBSIGMF_LIB ${LIBSIGMF_LIBRARIES}) endif() -# serialdv now required -add_definitions(-DDSD_USE_SERIALDV) -include_directories(${LIBSERIALDV_INCLUDE_DIR}) -set(sdrbase_SERIALDV_LIB ${LIBSERIALDV_LIBRARY}) +if (LIBSERIALDV_FOUND) + add_definitions(-DDSD_USE_SERIALDV) + include_directories(${LIBSERIALDV_INCLUDE_DIR}) + set(sdrbase_SERIALDV_LIB ${LIBSERIALDV_LIBRARY}) +endif() set(sdrbase_SOURCES ${sdrbase_SOURCES} @@ -168,6 +170,7 @@ set(sdrbase_SOURCES settings/rollupstate.cpp util/ais.cpp + util/android.cpp util/aviationweather.cpp util/ax25.cpp util/aprs.cpp @@ -388,6 +391,7 @@ set(sdrbase_HEADERS settings/rollupstate.h util/ais.h + util/android.h util/aviationweather.h util/ax25.h util/aprs.h @@ -491,6 +495,7 @@ target_link_libraries(sdrbase Qt::Core Qt::Multimedia Qt::WebSockets + Qt::Positioning httpserver logging qrtplib @@ -499,8 +504,15 @@ target_link_libraries(sdrbase if (Qt6_FOUND) target_link_libraries(sdrbase Qt::Core5Compat + Qt::CorePrivate ) endif() +if(ANDROID AND NOT ENABLE_QT6) + target_link_libraries(sdrbase Qt::AndroidExtras) +endif() +if(ANDROID) + target_link_libraries(sdrbase log) +endif() install(TARGETS sdrbase DESTINATION ${INSTALL_LIB_DIR}) diff --git a/sdrbase/device/deviceenumerator.cpp b/sdrbase/device/deviceenumerator.cpp index f4ecd56c9..8ca2e8038 100644 --- a/sdrbase/device/deviceenumerator.cpp +++ b/sdrbase/device/deviceenumerator.cpp @@ -17,8 +17,6 @@ #include -#include "plugin/pluginmanager.h" - #include "deviceenumerator.h" Q_GLOBAL_STATIC(DeviceEnumerator, deviceEnumerator) @@ -246,89 +244,101 @@ bool DeviceEnumerator::isMIMOEnumerated(const QString& deviceHwId, int deviceSeq return false; } -void DeviceEnumerator::enumerateRxDevices(PluginManager *pluginManager) +void DeviceEnumerator::enumerateDevices(PluginAPI::SamplingDeviceRegistrations& deviceRegistrations, DevicesEnumeration& enumeration, PluginInterface::SamplingDevice::StreamType type) { - m_rxEnumeration.clear(); - PluginAPI::SamplingDeviceRegistrations& rxDeviceRegistrations = pluginManager->getSourceDeviceRegistrations(); - int index = 0; + DevicesEnumeration tempEnumeration; + PluginInterface::OriginDevices originDevices; + QStringList originDevicesHwIds; - for (int i = 0; i < rxDeviceRegistrations.count(); i++) + for (int i = 0; i < deviceRegistrations.count(); i++) { - qDebug("DeviceEnumerator::enumerateRxDevices: %s", qPrintable(rxDeviceRegistrations[i].m_deviceId)); - rxDeviceRegistrations[i].m_plugin->enumOriginDevices(m_originDevicesHwIds, m_originDevices); - PluginInterface::SamplingDevices samplingDevices = rxDeviceRegistrations[i].m_plugin->enumSampleSources(m_originDevices); + qDebug("DeviceEnumerator::enumerateDevices: %s", qPrintable(deviceRegistrations[i].m_deviceId)); + deviceRegistrations[i].m_plugin->enumOriginDevices(originDevicesHwIds, originDevices); + PluginInterface::SamplingDevices samplingDevices; + if (type == PluginInterface::SamplingDevice::StreamSingleRx) { + samplingDevices = deviceRegistrations[i].m_plugin->enumSampleSources(originDevices); + } else if (type == PluginInterface::SamplingDevice::StreamSingleTx) { + samplingDevices = deviceRegistrations[i].m_plugin->enumSampleSinks(originDevices); + } else { + samplingDevices = deviceRegistrations[i].m_plugin->enumSampleMIMO(originDevices); + } for (int j = 0; j < samplingDevices.count(); j++) { - m_rxEnumeration.push_back( + tempEnumeration.push_back( DeviceEnumeration( samplingDevices[j], - rxDeviceRegistrations[i].m_plugin, - index + deviceRegistrations[i].m_plugin, + 0 // Index will be set when adding to enumeration below ) ); - index++; } } + + // We don't remove devices that are no-longer found from the enumeration list, in case their + // index is referenced in some other object (E.g. DeviceGUI) + // Instead we mark as removed. If later re-added, then we re-use the same index + for (DevicesEnumeration::iterator it = enumeration.begin(); it != enumeration.end(); ++it) + { + bool found = false; + for (DevicesEnumeration::iterator it2 = tempEnumeration.begin(); it2 != tempEnumeration.end(); ++it2) + { + if (it->m_samplingDevice == it2->m_samplingDevice) + { + found = true; + break; + } + } + if (!found) { + it->m_samplingDevice.removed = true; + } + } + + // Add new entries and update existing (in case re-added or sequence number has changed) + int index = enumeration.size(); + for (DevicesEnumeration::iterator it = tempEnumeration.begin(); it != tempEnumeration.end(); ++it) + { + + bool found = false; + for (DevicesEnumeration::iterator it2 = enumeration.begin(); it2 != enumeration.end(); ++it2) + { + if (it->m_samplingDevice == it2->m_samplingDevice) + { + it2->m_samplingDevice.removed = false; + it2->m_samplingDevice.displayedName = it->m_samplingDevice.displayedName; + found = true; + break; + } + + } + if (!found) + { + it->m_index = index++; + enumeration.push_back(*it); + } + } +} + +void DeviceEnumerator::enumerateRxDevices(PluginManager *pluginManager) +{ + enumerateDevices(pluginManager->getSourceDeviceRegistrations(), m_rxEnumeration, PluginInterface::SamplingDevice::StreamSingleRx); } void DeviceEnumerator::enumerateTxDevices(PluginManager *pluginManager) { - m_txEnumeration.clear(); - PluginAPI::SamplingDeviceRegistrations& txDeviceRegistrations = pluginManager->getSinkDeviceRegistrations(); - int index = 0; - - for (int i = 0; i < txDeviceRegistrations.count(); i++) - { - qDebug("DeviceEnumerator::enumerateTxDevices: %s", qPrintable(txDeviceRegistrations[i].m_deviceId)); - txDeviceRegistrations[i].m_plugin->enumOriginDevices(m_originDevicesHwIds, m_originDevices); - PluginInterface::SamplingDevices samplingDevices = txDeviceRegistrations[i].m_plugin->enumSampleSinks(m_originDevices); - - for (int j = 0; j < samplingDevices.count(); j++) - { - m_txEnumeration.push_back( - DeviceEnumeration( - samplingDevices[j], - txDeviceRegistrations[i].m_plugin, - index - ) - ); - index++; - } - } + enumerateDevices(pluginManager->getSinkDeviceRegistrations(), m_txEnumeration, PluginInterface::SamplingDevice::StreamSingleTx); } void DeviceEnumerator::enumerateMIMODevices(PluginManager *pluginManager) { - m_mimoEnumeration.clear(); - PluginAPI::SamplingDeviceRegistrations& mimoDeviceRegistrations = pluginManager->getMIMODeviceRegistrations(); - int index = 0; - - for (int i = 0; i < mimoDeviceRegistrations.count(); i++) - { - qDebug("DeviceEnumerator::enumerateMIMODevices: %s", qPrintable(mimoDeviceRegistrations[i].m_deviceId)); - mimoDeviceRegistrations[i].m_plugin->enumOriginDevices(m_originDevicesHwIds, m_originDevices); - PluginInterface::SamplingDevices samplingDevices = mimoDeviceRegistrations[i].m_plugin->enumSampleMIMO(m_originDevices); - - for (int j = 0; j < samplingDevices.count(); j++) - { - m_mimoEnumeration.push_back( - DeviceEnumeration( - samplingDevices[j], - mimoDeviceRegistrations[i].m_plugin, - index - ) - ); - index++; - } - } + enumerateDevices(pluginManager->getMIMODeviceRegistrations(), m_mimoEnumeration, PluginInterface::SamplingDevice::StreamMIMO); } void DeviceEnumerator::listRxDeviceNames(QList& list, std::vector& indexes) const { for (DevicesEnumeration::const_iterator it = m_rxEnumeration.begin(); it != m_rxEnumeration.end(); ++it) { - if ((it->m_samplingDevice.claimed < 0) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice)) + if (((it->m_samplingDevice.claimed < 0) && (!it->m_samplingDevice.removed)) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice)) { list.append(it->m_samplingDevice.displayedName); indexes.push_back(it->m_index); @@ -340,7 +350,7 @@ void DeviceEnumerator::listTxDeviceNames(QList& list, std::vector& { for (DevicesEnumeration::const_iterator it = m_txEnumeration.begin(); it != m_txEnumeration.end(); ++it) { - if ((it->m_samplingDevice.claimed < 0) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice)) + if (((it->m_samplingDevice.claimed < 0) && (!it->m_samplingDevice.removed)) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice)) { list.append(it->m_samplingDevice.displayedName); indexes.push_back(it->m_index); @@ -352,7 +362,7 @@ void DeviceEnumerator::listMIMODeviceNames(QList& list, std::vectorm_samplingDevice.claimed < 0) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice)) + if (((it->m_samplingDevice.claimed < 0) && (!it->m_samplingDevice.removed)) || (it->m_samplingDevice.type == PluginInterface::SamplingDevice::BuiltInDevice)) { list.append(it->m_samplingDevice.displayedName); indexes.push_back(it->m_index); diff --git a/sdrbase/device/deviceenumerator.h b/sdrbase/device/deviceenumerator.h index 3cd7e68d4..0c35f3f43 100644 --- a/sdrbase/device/deviceenumerator.h +++ b/sdrbase/device/deviceenumerator.h @@ -21,6 +21,7 @@ #include #include "plugin/plugininterface.h" +#include "plugin/pluginmanager.h" #include "device/deviceuserargs.h" #include "export.h" @@ -85,9 +86,8 @@ private: DevicesEnumeration m_rxEnumeration; DevicesEnumeration m_txEnumeration; DevicesEnumeration m_mimoEnumeration; - PluginInterface::OriginDevices m_originDevices; - QStringList m_originDevicesHwIds; + void enumerateDevices(PluginAPI::SamplingDeviceRegistrations& deviceRegistrations, DevicesEnumeration& enumeration, PluginInterface::SamplingDevice::StreamType type); PluginInterface *getRxRegisteredPlugin(PluginManager *pluginManager, const QString& deviceHwId); PluginInterface *getTxRegisteredPlugin(PluginManager *pluginManager, const QString& deviceHwId); PluginInterface *getMIMORegisteredPlugin(PluginManager *pluginManager, const QString& deviceHwId); diff --git a/sdrbase/maincore.cpp b/sdrbase/maincore.cpp index ee84eda5f..44dc1866f 100644 --- a/sdrbase/maincore.cpp +++ b/sdrbase/maincore.cpp @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include "loggerwithfile.h" #include "dsp/dsptypes.h" @@ -71,6 +73,8 @@ MainCore::MainCore() m_masterTimer.start(50); m_startMsecsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); m_masterElapsedTimer.start(); + // Position can take a while to determine, so we start updates at program startup + initPosition(); } MainCore::~MainCore() @@ -335,3 +339,36 @@ void MainCore::debugMaps() feIt.value()->getIndex(), feIt.key()->getIndexInFeatureSet(), qPrintable(feIt.key()->getURI()), qPrintable(feIt.key()->getName())); } } + +void MainCore::initPosition() +{ + m_positionSource = QGeoPositionInfoSource::createDefaultSource(this); + if (m_positionSource) + { + connect(m_positionSource, &QGeoPositionInfoSource::positionUpdated, this, &MainCore::positionUpdated); + m_positionSource->startUpdates(); + } + else + { + qDebug() << "MainCore::initPosition: No position source."; + } +} + +const QGeoPositionInfo& MainCore::getPosition() const +{ + return m_position; +} + +void MainCore::positionUpdated(const QGeoPositionInfo &info) +{ + if (info.isValid()) + { + m_position = info; + if (m_settings.getAutoUpdatePosition()) + { + m_settings.setLatitude(m_position.coordinate().latitude()); + m_settings.setLongitude(m_position.coordinate().longitude()); + m_settings.setAltitude(m_position.coordinate().altitude()); + } + } +} diff --git a/sdrbase/maincore.h b/sdrbase/maincore.h index dcf44ddef..e2c86ebd9 100644 --- a/sdrbase/maincore.h +++ b/sdrbase/maincore.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "export.h" #include "settings/mainsettings.h" @@ -38,6 +39,7 @@ class FeatureSet; class Feature; class PluginManager; class MessageQueue; +class QGeoPositionInfoSource; namespace qtwebapp { class LoggerWithFile; @@ -846,7 +848,7 @@ public: qint64 getStartMsecsSinceEpoch() const { return m_startMsecsSinceEpoch; } //!< Epoch timestamp in millisecodns close to elapsed timer start const MainSettings& getSettings() const { return m_settings; } MessageQueue *getMainMessageQueue() { return m_mainMessageQueue; } - const PluginManager *getPluginManager() const { return m_pluginManager; } + PluginManager *getPluginManager() const { return m_pluginManager; } std::vector& getDeviceSets() { return m_deviceSets; } std::vector& getFeatureeSets() { return m_featureSets; } void setLoggingOptions(); @@ -875,6 +877,8 @@ public: // pipes MessagePipes& getMessagePipes() { return m_messagePipes; } DataPipes& getDataPipes() { return m_dataPipes; } + // Position + const QGeoPositionInfo& getPosition() const; friend class MainServer; friend class MainWindow; @@ -883,6 +887,9 @@ public: friend class DeviceSetPresetsDialog; friend class ConfigurationsDialog; +public slots: + void positionUpdated(const QGeoPositionInfo &info); + signals: void deviceSetAdded(int index, DeviceAPI *device); void deviceChanged(int index); @@ -912,7 +919,10 @@ private: PluginManager* m_pluginManager; MessagePipes m_messagePipes; DataPipes m_dataPipes; + QGeoPositionInfoSource *m_positionSource; + QGeoPositionInfo m_position; + void initPosition(); void debugMaps(); }; diff --git a/sdrbase/plugin/plugininterface.h b/sdrbase/plugin/plugininterface.h index 8dff4d372..b60ad4676 100644 --- a/sdrbase/plugin/plugininterface.h +++ b/sdrbase/plugin/plugininterface.h @@ -66,6 +66,7 @@ public: int deviceNbItems; //!< Number of items (or streams) in the device. >1 for composite devices. int deviceItemIndex; //!< For composite devices this is the Rx or Tx stream index. -1 if not initialized int claimed; //!< This is the device set index if claimed else -1 + bool removed; //!< Set if device has been removed SamplingDevice(const QString& _displayedName, const QString& _hardwareId, @@ -85,8 +86,17 @@ public: streamType(_streamType), deviceNbItems(_deviceNbItems), deviceItemIndex(_deviceItemIndex), - claimed(-1) + claimed(-1), + removed(false) { } + + bool operator==(const SamplingDevice& rhs) const + { + return displayedName == rhs.displayedName + && hardwareId == rhs.hardwareId + && id == rhs.id + && serial == rhs.serial; + } }; typedef QList SamplingDevices; diff --git a/sdrbase/settings/mainsettings.h b/sdrbase/settings/mainsettings.h index 26af1c809..27573666f 100644 --- a/sdrbase/settings/mainsettings.h +++ b/sdrbase/settings/mainsettings.h @@ -151,6 +151,12 @@ public: emit preferenceChanged(Preferences::Altitude); } + bool getAutoUpdatePosition() const { return m_preferences.getAutoUpdatePosition(); } + void setAutoUpdatePosition(bool autoUpdatePosition) + { + m_preferences.setAutoUpdatePosition(autoUpdatePosition); + } + QtMsgType getConsoleMinLogLevel() const { return m_preferences.getConsoleMinLogLevel(); } void setConsoleMinLogLevel(const QtMsgType& minLogLevel) { diff --git a/sdrbase/settings/preferences.cpp b/sdrbase/settings/preferences.cpp index 156074c93..dbef62e1e 100644 --- a/sdrbase/settings/preferences.cpp +++ b/sdrbase/settings/preferences.cpp @@ -17,6 +17,7 @@ void Preferences::resetToDefaults() m_latitude = 49.012423; // Set an interesting location so map doesn't open up in the middle of the ocean m_longitude = 8.418125; m_altitude = 0.0f; + m_autoUpdatePosition = true; m_useLogFile = false; m_logFileName = "sdrangel.log"; m_consoleMinLogLevel = QtDebugMsg; @@ -41,6 +42,7 @@ QByteArray Preferences::serialize() const s.writeFloat((int) Altitude, m_altitude); s.writeS32((int) SourceItemIndex, m_sourceItemIndex); s.writeS32((int) Multisampling, m_multisampling); + s.writeBool((int) AutoUpdatePosition, m_autoUpdatePosition); return s.final(); } @@ -95,9 +97,11 @@ bool Preferences::deserialize(const QByteArray& data) } d.readS32((int) Multisampling, &m_multisampling, 0); + d.readBool((int) AutoUpdatePosition, &m_autoUpdatePosition, true); return true; - } else + } + else { resetToDefaults(); return false; diff --git a/sdrbase/settings/preferences.h b/sdrbase/settings/preferences.h index 07356f78f..87c1d15a0 100644 --- a/sdrbase/settings/preferences.h +++ b/sdrbase/settings/preferences.h @@ -22,7 +22,8 @@ public: StationName, Altitude, SourceItemIndex, - Multisampling + Multisampling, + AutoUpdatePosition }; Preferences(); @@ -60,6 +61,9 @@ public: float getAltitude() const { return m_altitude; } void setAltitude(float altitude) { m_altitude = altitude; } + bool getAutoUpdatePosition() const { return m_autoUpdatePosition; } + void setAutoUpdatePosition(bool autoUpdatePosition) { m_autoUpdatePosition = autoUpdatePosition; } + QtMsgType getConsoleMinLogLevel() const { return m_consoleMinLogLevel; } void setConsoleMinLogLevel(const QtMsgType& minLogLevel) { m_consoleMinLogLevel = minLogLevel; } @@ -87,6 +91,7 @@ protected: float m_latitude; //!< Position of the station float m_longitude; float m_altitude; //!< Altitude in metres + bool m_autoUpdatePosition; //!< Automatically update position from GPS QtMsgType m_consoleMinLogLevel; QtMsgType m_fileMinLogLevel; diff --git a/sdrbase/util/android.cpp b/sdrbase/util/android.cpp new file mode 100644 index 000000000..2d755ae72 --- /dev/null +++ b/sdrbase/util/android.cpp @@ -0,0 +1,213 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Jon Beniston, M7RCE // +// // +// 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 // +// (at your option) any later version. // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifdef ANDROID + +#include + +#include + +#include "android.h" + +#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) + +#include +#include +#include + +void Android::sendIntent() +{ + QJniObject url = QJniObject::fromString("iqsrc://-f 1090000000 -p 1234 -s 2000000 -a 127.0.0.1 -g 100"); + QJniObject intent = QJniObject::callStaticObjectMethod("android/content/Intent", "parseUri", "(Ljava/lang/String;I)Landroid/content/Intent;", url.object(), 0x00000001); // Creates Intent(ACTION_VIEW, url) + QtAndroidPrivate::startActivity(intent, 0, [](int requestCode, int resultCode, const QJniObject &data) { + (void) data; + + qDebug() << "MainCore::sendIntent " << requestCode << resultCode; + }); +} + +QStringList Android::listUSBDeviceSerials(int vid, int pid) +{ + QStringList serials; + QJniEnvironment jniEnv; + + QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) + { + QJniObject serialsObj = activity.callObjectMethod("listUSBDeviceSerials", "(II)[Ljava/lang/String;", vid, pid); + int serialsLen = jniEnv->GetArrayLength(serialsObj.object()); + for (int i = 0; i < serialsLen; i++) + { + QJniObject arrayElement = jniEnv->GetObjectArrayElement(serialsObj.object(), i); + QString serial = arrayElement.toString(); + serials.append(serial); + } + } + + return serials; +} + +int Android::openUSBDevice(const QString &serial) +{ + int fd = -1; + QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) + { + QJniObject serialsObj = QJniObject::fromString(serial); + fd = activity.callMethod("openUSBDevice", "(Ljava/lang/String;)I", serialsObj.object()); + } + + return fd; +} + +void Android::closeUSBDevice(int fd) +{ + if (fd >= 0) + { + QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) { + activity.callMethod("closeUSBDevice", "(I)V", fd); + } else { + qCritical() << "MainCore::closeUSBDevice: activity is not valid."; + } + } +} + +void Android::moveTaskToBack() +{ + QJniObject activity = QJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) { + activity.callMethod("moveTaskToBack", "(Z)Z", true); + } +} + +#else // QT_VERSION + +#include +#include +#include +#include +#include + +void Android::sendIntent() +{ + QAndroidJniObject url = QAndroidJniObject::fromString("iqsrc://-f 1090000000 -p 1234 -s 2000000 -a 127.0.0.1 -g 100"); + QAndroidJniObject intent = QAndroidJniObject::callStaticObjectMethod("android/content/Intent", "parseUri", "(Ljava/lang/String;I)Landroid/content/Intent;", url.object(), 0x00000001); // Creates Intent(ACTION_VIEW, url) + QtAndroid::startActivity(intent, 0, [](int requestCode, int resultCode, const QAndroidJniObject &data) { + (void) data; + + qDebug() << "MainCore::sendIntent " << requestCode << resultCode; + }); +} + +QStringList Android::listUSBDeviceSerials(int vid, int pid) +{ + QStringList serials; + QAndroidJniEnvironment jniEnv; + + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) + { + QAndroidJniObject serialsObj = activity.callObjectMethod("listUSBDeviceSerials", "(II)[Ljava/lang/String;", vid, pid); + int serialsLen = jniEnv->GetArrayLength(serialsObj.object()); + for (int i = 0; i < serialsLen; i++) + { + QAndroidJniObject arrayElement = jniEnv->GetObjectArrayElement(serialsObj.object(), i); + QString serial = arrayElement.toString(); + serials.append(serial); + } + } + + return serials; +} + +int Android::openUSBDevice(const QString &serial) +{ + int fd = -1; + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) + { + QAndroidJniObject serialsObj = QAndroidJniObject::fromString(serial); + fd = activity.callMethod("openUSBDevice", "(Ljava/lang/String;)I", serialsObj.object()); + } + + return fd; +} + +void Android::closeUSBDevice(int fd) +{ + if (fd >= 0) + { + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) { + activity.callMethod("closeUSBDevice", "(I)V", fd); + } else { + qCritical() << "MainCore::closeUSBDevice: activity is not valid."; + } + } +} + +void Android::moveTaskToBack() +{ + QAndroidJniObject activity = QAndroidJniObject::callStaticObjectMethod("org/qtproject/qt5/android/QtNative", "activity", "()Landroid/app/Activity;"); + if (activity.isValid()) { + activity.callMethod("moveTaskToBack", "(Z)Z", true); + } +} + +#endif // QT6 + +// Redirect qDebug/qWarning to Android log, so we can view remotely with adb +void Android::messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + QString report = msg; + if (context.file && !QString(context.file).isEmpty()) + { + report += " in file "; + report += QString(context.file); + report += " line "; + report += QString::number(context.line); + } + if (context.function && !QString(context.function).isEmpty()) + { + report += +" function "; + report += QString(context.function); + } + const char * const local = report.toLocal8Bit().constData(); + const char * const applicationName = "sdrangel"; + switch (type) + { + case QtDebugMsg: + __android_log_write(ANDROID_LOG_DEBUG, applicationName, local); + break; + case QtInfoMsg: + __android_log_write(ANDROID_LOG_INFO, applicationName, local); + break; + case QtWarningMsg: + __android_log_write(ANDROID_LOG_WARN, applicationName, local); + break; + case QtCriticalMsg: + __android_log_write(ANDROID_LOG_ERROR, applicationName, local); + break; + case QtFatalMsg: + default: + __android_log_write(ANDROID_LOG_FATAL, applicationName, local); + abort(); + } +} + +#endif // ANDROID diff --git a/sdrbase/util/android.h b/sdrbase/util/android.h new file mode 100644 index 000000000..ef97d5eed --- /dev/null +++ b/sdrbase/util/android.h @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2022 Jon Beniston, M7RCE // +// // +// 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 // +// (at your option) any later version. // +// // +// 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRBASE_ANDROID_H_ +#define SDRBASE_ANDROID_H_ + +#ifdef ANDROID + +#include +#include + +#include "export.h" + +// Android specific functions +class SDRBASE_API Android +{ +public: + + static void sendIntent(); + static QStringList listUSBDeviceSerials(int vid, int pid); + static int openUSBDevice(const QString &serial); + static void closeUSBDevice(int fd); + static void moveTaskToBack(); + static void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg); + +}; + +#endif // ANDROID + +#endif // SDRBASE_ANDROID_H_ diff --git a/sdrgui/gui/configurationsdialog.cpp b/sdrgui/gui/configurationsdialog.cpp index c324f18b2..f05756277 100644 --- a/sdrgui/gui/configurationsdialog.cpp +++ b/sdrgui/gui/configurationsdialog.cpp @@ -27,11 +27,26 @@ #include "settings/configuration.h" -ConfigurationsDialog::ConfigurationsDialog(QWidget* parent) : +ConfigurationsDialog::ConfigurationsDialog(bool openOnly, QWidget* parent) : QDialog(parent), ui(new Ui::ConfigurationsDialog) { ui->setupUi(this); + if (openOnly) + { + ui->buttonBox->setStandardButtons(QDialogButtonBox::Close | QDialogButtonBox::Open); + ui->configurationDelete->setVisible(false); + ui->configurationEdit->setVisible(false); + ui->configurationExport->setVisible(false); + ui->configurationImport->setVisible(false); + ui->configurationLoad->setVisible(false); + ui->configurationSave->setVisible(false); + ui->configurationUpdate->setVisible(false); + } + else + { + ui->description->setVisible(false); + } } ConfigurationsDialog::~ConfigurationsDialog() @@ -354,9 +369,7 @@ void ConfigurationsDialog::on_configurationExport_clicked() tr("Open preset export file"), ".", tr("Configuration export files (*.cfgx)"), - 0, - QFileDialog::DontUseNativeDialog - ); + 0); if (fileName != "") { @@ -404,8 +417,7 @@ void ConfigurationsDialog::on_configurationImport_clicked() tr("Open preset export file"), ".", tr("Preset export files (*.cfgx)"), - 0, - QFileDialog::DontUseNativeDialog + 0 ); if (fileName != "") @@ -497,3 +509,9 @@ void ConfigurationsDialog::deleteConfigurationGroup(const QString& groupName) } } } + +void ConfigurationsDialog::accept() +{ + on_configurationLoad_clicked(); + QDialog::accept(); +} diff --git a/sdrgui/gui/configurationsdialog.h b/sdrgui/gui/configurationsdialog.h index 6ca575d77..1d728fb52 100644 --- a/sdrgui/gui/configurationsdialog.h +++ b/sdrgui/gui/configurationsdialog.h @@ -38,7 +38,7 @@ namespace Ui { class SDRGUI_API ConfigurationsDialog : public QDialog { Q_OBJECT public: - explicit ConfigurationsDialog(QWidget* parent = nullptr); + explicit ConfigurationsDialog(bool openOnly, QWidget* parent = nullptr); ~ConfigurationsDialog(); void setConfigurations(QList* configurations) { m_configurations = configurations; } void populateTree(); @@ -71,6 +71,7 @@ private slots: void on_configurationLoad_clicked(); void on_configurationTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); void on_configurationTree_itemActivated(QTreeWidgetItem *item, int column); + void accept() override; signals: void saveConfiguration(Configuration*); diff --git a/sdrgui/gui/configurationsdialog.ui b/sdrgui/gui/configurationsdialog.ui index 23430dbf5..21cf06e35 100644 --- a/sdrgui/gui/configurationsdialog.ui +++ b/sdrgui/gui/configurationsdialog.ui @@ -6,8 +6,8 @@ 0 0 - 392 - 414 + 410 + 424 @@ -19,218 +19,207 @@ Configurations - - - - 40 - 380 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Close - - - - - - 0 - 10 - 392 - 310 - - - - - - - List of configurations - - - 5 - - - true - - - 1 - - - 5 - - - - Description + + + + + + + + Select configuration to load: + + + + + + + List of configurations + + + 5 + + + true + + + 1 + + + 5 + + + + Description + + + + + + + + + + + + + Save current workspaces configuration as new configuration - - - - - - - - - 0 - 330 - 392 - 34 - - - - - - - Save current workspaces configuration as new configuration - - - ... - - - - :/create.png:/create.png - - - - 16 - 16 - - - - - - - - Update selected configuration with current workspaces configuration - - - ... - - - - :/recycle.png:/recycle.png - - - - 16 - 16 - - - - - - - - Edit configuration details - - - - - - - :/edit.png:/edit.png - - - - - - - Export current configuration to file - - - - - - - :/export.png:/export.png - - - - - - - Import configuration from file into current group - - - - - - - :/import.png:/import.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Delete selected configuration - - - ... - - - - :/bin.png:/bin.png - - - - 16 - 16 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Load selected configuration - - - ... - - - - :/load.png:/load.png - - - - 16 - 16 - - - - - - + + ... + + + + :/create.png:/create.png + + + + 16 + 16 + + + + + + + + Update selected configuration with current workspaces configuration + + + ... + + + + :/recycle.png:/recycle.png + + + + 16 + 16 + + + + + + + + Edit configuration details + + + + + + + :/edit.png:/edit.png + + + + + + + Export current configuration to file + + + + + + + :/export.png:/export.png + + + + + + + Import configuration from file into current group + + + + + + + :/import.png:/import.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Delete selected configuration + + + ... + + + + :/bin.png:/bin.png + + + + 16 + 16 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Load selected configuration + + + ... + + + + :/load.png:/load.png + + + + 16 + 16 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + diff --git a/sdrgui/gui/devicesetpresetsdialog.cpp b/sdrgui/gui/devicesetpresetsdialog.cpp index 7e066519a..0422bbac0 100644 --- a/sdrgui/gui/devicesetpresetsdialog.cpp +++ b/sdrgui/gui/devicesetpresetsdialog.cpp @@ -292,8 +292,7 @@ void DeviceSetPresetsDialog::on_presetExport_clicked() tr("Open preset export file"), ".", tr("Preset export files (*.prex)"), - 0, - QFileDialog::DontUseNativeDialog + 0 ); if (fileName != "") @@ -342,8 +341,7 @@ void DeviceSetPresetsDialog::on_presetImport_clicked() tr("Open preset export file"), ".", tr("Preset export files (*.prex)"), - 0, - QFileDialog::DontUseNativeDialog + 0 ); if (fileName != "") diff --git a/sdrgui/gui/myposdialog.ui b/sdrgui/gui/myposdialog.ui index fde93a7b0..977ed6bda 100644 --- a/sdrgui/gui/myposdialog.ui +++ b/sdrgui/gui/myposdialog.ui @@ -7,7 +7,7 @@ 0 0 324 - 229 + 201 @@ -19,44 +19,24 @@ My Position - - + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + My Station Position - - - - - Latitude - - - - - - - Longitude - - - - - - - Longitude in decimal degrees - - - 6 - - - -180.000000000000000 - - - 180.000000000000000 - - - - + + Latitude in decimal degrees @@ -72,24 +52,14 @@ - - - - Altitude in metres - - - 50000 - - - - - + + - Altitude (m) + Latitude - + Enter the name of your station @@ -99,6 +69,20 @@ + + + + Altitude (m) + + + + + + + Longitude + + + @@ -106,19 +90,66 @@ + + + + Automatically update position using GPS (when available) + + + + + + + + + + Longitude in decimal degrees + + + 6 + + + -180.000000000000000 + + + 180.000000000000000 + + + + + + + Auto-update from GPS + + + + + + + Set position using GPS (if available) + + + + + + + :/gps.png:/gps.png + + + + + + + Altitude in metres + + + 50000 + + + - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -127,7 +158,9 @@ longitudeSpinBox altitudeSpinBox - + + + buttonBox diff --git a/sdrgui/gui/mypositiondialog.cpp b/sdrgui/gui/mypositiondialog.cpp index 58c8284a8..5f36bfafc 100644 --- a/sdrgui/gui/mypositiondialog.cpp +++ b/sdrgui/gui/mypositiondialog.cpp @@ -2,9 +2,6 @@ // Copyright (C) 2016 F4EXB // // written by Edouard Griffiths // // // -// OpenGL interface modernization. // -// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html // -// // // 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 // @@ -21,7 +18,9 @@ #include "gui/mypositiondialog.h" #include "ui_myposdialog.h" +#include "maincore.h" +#include MyPositionDialog::MyPositionDialog(MainSettings& mainSettings, QWidget* parent) : QDialog(parent), @@ -33,6 +32,7 @@ MyPositionDialog::MyPositionDialog(MainSettings& mainSettings, QWidget* parent) ui->latitudeSpinBox->setValue(m_mainSettings.getLatitude()); ui->longitudeSpinBox->setValue(m_mainSettings.getLongitude()); ui->altitudeSpinBox->setValue(m_mainSettings.getAltitude()); + ui->autoUpdatePosition->setChecked(m_mainSettings.getAutoUpdatePosition()); } MyPositionDialog::~MyPositionDialog() @@ -46,5 +46,22 @@ void MyPositionDialog::accept() m_mainSettings.setLatitude(ui->latitudeSpinBox->value()); m_mainSettings.setLongitude(ui->longitudeSpinBox->value()); m_mainSettings.setAltitude(ui->altitudeSpinBox->value()); + m_mainSettings.setAutoUpdatePosition(ui->autoUpdatePosition->isChecked()); QDialog::accept(); } + +void MyPositionDialog::on_gps_clicked() +{ + const QGeoPositionInfo& position = MainCore::instance()->getPosition(); + if (position.isValid()) + { + QGeoCoordinate coord = position.coordinate(); + ui->latitudeSpinBox->setValue(coord.latitude()); + ui->longitudeSpinBox->setValue(coord.longitude()); + ui->altitudeSpinBox->setValue(coord.altitude()); + } + else + { + qDebug() << "MyPositionDialog::on_gps_clicked: Position is not valid."; + } +} diff --git a/sdrgui/gui/mypositiondialog.h b/sdrgui/gui/mypositiondialog.h index 2f37642fa..89ce6bd43 100644 --- a/sdrgui/gui/mypositiondialog.h +++ b/sdrgui/gui/mypositiondialog.h @@ -2,9 +2,6 @@ // Copyright (C) 2016 F4EXB // // written by Edouard Griffiths // // // -// OpenGL interface modernization. // -// See: http://doc.qt.io/qt-5/qopenglshaderprogram.html // -// // // 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 // @@ -43,6 +40,7 @@ private: private slots: void accept(); + void on_gps_clicked(); }; #endif /* SDRBASE_GUI_MYPOSITIONDIALOG_H_ */ diff --git a/sdrgui/gui/samplingdevicedialog.cpp b/sdrgui/gui/samplingdevicedialog.cpp index fbbbbfec1..f9251b951 100644 --- a/sdrgui/gui/samplingdevicedialog.cpp +++ b/sdrgui/gui/samplingdevicedialog.cpp @@ -22,7 +22,7 @@ #include "samplingdevicedialog.h" #include "ui_samplingdevicedialog.h" #include "device/deviceenumerator.h" - +#include "maincore.h" SamplingDeviceDialog::SamplingDeviceDialog(int deviceType, QWidget* parent) : QDialog(parent), @@ -32,19 +32,7 @@ SamplingDeviceDialog::SamplingDeviceDialog(int deviceType, QWidget* parent) : m_hasChanged(false) { ui->setupUi(this); - - QList deviceDisplayNames; - - if (m_deviceType == 0) { // Single Rx - DeviceEnumerator::instance()->listRxDeviceNames(deviceDisplayNames, m_deviceIndexes); - } else if (m_deviceType == 1) { // Single Tx - DeviceEnumerator::instance()->listTxDeviceNames(deviceDisplayNames, m_deviceIndexes); - } else if (m_deviceType == 2) { // MIMO - DeviceEnumerator::instance()->listMIMODeviceNames(deviceDisplayNames, m_deviceIndexes); - } - - QStringList devicesNamesList(deviceDisplayNames); - ui->deviceSelect->addItems(devicesNamesList); + on_refreshDevices_clicked(); } SamplingDeviceDialog::~SamplingDeviceDialog() @@ -58,6 +46,23 @@ int SamplingDeviceDialog::exec() return QDialog::exec(); } +void SamplingDeviceDialog::displayDevices() +{ + QList deviceDisplayNames; + + m_deviceIndexes.clear(); + if (m_deviceType == 0) { // Single Rx + DeviceEnumerator::instance()->listRxDeviceNames(deviceDisplayNames, m_deviceIndexes); + } else if (m_deviceType == 1) { // Single Tx + DeviceEnumerator::instance()->listTxDeviceNames(deviceDisplayNames, m_deviceIndexes); + } else if (m_deviceType == 2) { // MIMO + DeviceEnumerator::instance()->listMIMODeviceNames(deviceDisplayNames, m_deviceIndexes); + } + + ui->deviceSelect->clear(); + ui->deviceSelect->addItems(deviceDisplayNames); +} + void SamplingDeviceDialog::setSelectedDeviceIndex(int deviceIndex) { ui->deviceSelect->blockSignals(true); @@ -77,6 +82,21 @@ void SamplingDeviceDialog::on_deviceSelect_currentIndexChanged(int index) m_hasChanged = true; } +void SamplingDeviceDialog::on_refreshDevices_clicked() +{ + PluginManager *pluginManager = MainCore::instance()->getPluginManager(); + + if (m_deviceType == 0) { + DeviceEnumerator::instance()->enumerateRxDevices(pluginManager); + } else if (m_deviceType == 1) { + DeviceEnumerator::instance()->enumerateTxDevices(pluginManager); + } else if (m_deviceType == 2) { + DeviceEnumerator::instance()->enumerateMIMODevices(pluginManager); + } + + displayDevices(); +} + void SamplingDeviceDialog::accept() { m_selectedDeviceIndex = m_deviceIndexes[ui->deviceSelect->currentIndex()]; diff --git a/sdrgui/gui/samplingdevicedialog.h b/sdrgui/gui/samplingdevicedialog.h index 7662e1cec..573212eb6 100644 --- a/sdrgui/gui/samplingdevicedialog.h +++ b/sdrgui/gui/samplingdevicedialog.h @@ -50,8 +50,11 @@ private: std::vector m_deviceIndexes; bool m_hasChanged; + void displayDevices(); + private slots: void on_deviceSelect_currentIndexChanged(int index); + void on_refreshDevices_clicked(); void accept(); void reject(); }; diff --git a/sdrgui/gui/samplingdevicedialog.ui b/sdrgui/gui/samplingdevicedialog.ui index 0b930a6bc..183a3b9a0 100644 --- a/sdrgui/gui/samplingdevicedialog.ui +++ b/sdrgui/gui/samplingdevicedialog.ui @@ -31,8 +31,8 @@ Select from list - - + + @@ -42,6 +42,20 @@ + + + + Refresh list of devices + + + + + + + :/recycle.png:/recycle.png + + + @@ -66,7 +80,9 @@ buttonBox - + + + buttonBox diff --git a/sdrgui/mainwindow.cpp b/sdrgui/mainwindow.cpp index 519f7fe9a..671e6db31 100644 --- a/sdrgui/mainwindow.cpp +++ b/sdrgui/mainwindow.cpp @@ -18,7 +18,9 @@ #include #include +#include #include +#include #include #include #include @@ -31,10 +33,11 @@ #include #include #include - +#include #include #include #include +#include #include "device/devicegui.h" #include "device/deviceapi.h" @@ -68,6 +71,8 @@ #include "gui/devicesetpresetsdialog.h" #include "gui/commandsdialog.h" #include "gui/configurationsdialog.h" +#include "gui/dialogpositioner.h" +#include "gui/welcomedialog.h" #include "dsp/dspengine.h" #include "dsp/spectrumvis.h" #include "dsp/dspcommands.h" @@ -85,6 +90,9 @@ #include "webapi/webapiserver.h" #include "webapi/webapiadapter.h" #include "commands/command.h" +#ifdef ANDROID +#include "util/android.h" +#endif #include "mainwindow.h" @@ -107,9 +115,13 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse m_mainCore(MainCore::instance()), m_dspEngine(DSPEngine::instance()), m_lastEngineState(DeviceAPI::StNotStarted), + m_dateTimeWidget(nullptr), + m_showSystemWidget(nullptr), m_commandKeyReceiver(nullptr), m_fftWisdomProcess(nullptr) { + bool showWelcome = ANDROID; + qDebug() << "MainWindow::MainWindow: start"; setWindowTitle("SDRangel"); @@ -134,10 +146,21 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse splash->showStatusMessage("starting...", Qt::white); setWindowIcon(QIcon(":/sdrangel_icon.png")); - createMenuBar(); - createStatusBar(); +#ifndef ANDROID + // To save screen space on Android, don't have menu bar. Instead menus are accessed via toolbar button + createMenuBar(nullptr); + createStatusBar(); +#endif +#ifdef ANDROID + if (screen()->isLandscape(screen()->primaryOrientation())) { + setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West); + } else { + setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::South); + } +#else setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West); +#endif setTabPosition(Qt::RightDockWidgetArea, QTabWidget::East); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); @@ -146,6 +169,12 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()), Qt::QueuedConnection); + connect(screen(), &QScreen::orientationChanged, this, &MainWindow::orientationChanged); + screen()->setOrientationUpdateMask(Qt::PortraitOrientation + | Qt::LandscapeOrientation + | Qt::InvertedPortraitOrientation + | Qt::InvertedLandscapeOrientation); + connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); m_statusTimer.start(1000); @@ -209,6 +238,16 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse { qDebug() << "MainWindow::MainWindow: no or empty current configuration, creating empty workspace..."; addWorkspace(); + + // If no configurations, load some basic examples + if (m_mainCore->m_settings.getConfigurations().size() == 0) { + loadDefaultConfigurations(); + } + } + else + { + // Only show welcome dialog first time program is run + showWelcome = false; } } @@ -240,6 +279,16 @@ MainWindow::MainWindow(qtwebapp::LoggerWithFile *logger, const MainParser& parse restoreGeometry(qUncompress(QByteArray::fromBase64(s.value("mainWindowGeometry").toByteArray()))); restoreState(qUncompress(QByteArray::fromBase64(s.value("mainWindowState").toByteArray()))); + if (showWelcome) + { + // Show welcome dialog + WelcomeDialog welcomeDialog(this); + new DialogPositioner(&welcomeDialog, true); + welcomeDialog.exec(); + // Show configurations + openConfigurationDialog(true); + } + qDebug() << "MainWindow::MainWindow: end"; } @@ -340,6 +389,11 @@ void MainWindow::sampleSourceAdd(Workspace *deviceWorkspace, Workspace *spectrum deviceWorkspace->addToMdiArea(m_deviceUIs.back()->m_deviceGUI); spectrumWorkspace->addToMdiArea(m_deviceUIs.back()->m_mainSpectrumGUI); emit m_mainCore->deviceSetAdded(deviceSetIndex, deviceAPI); + +#ifdef ANDROID + // Seemingly needed on some versions of Android, otherwise the new windows aren't always displayed?? + deviceWorkspace->repaint(); +#endif } void MainWindow::sampleSourceCreate( @@ -1165,7 +1219,9 @@ void MainWindow::loadSettings() m_mainCore->m_settings.load(); m_mainCore->m_settings.sortPresets(); m_mainCore->m_settings.sortCommands(); - m_mainCore->setLoggingOptions(); + if (m_mainCore->m_logger) { + m_mainCore->setLoggingOptions(); + } } void MainWindow::loadDeviceSetPresetSettings(const Preset* preset, int deviceSetIndex) @@ -1230,6 +1286,59 @@ void MainWindow::saveFeatureSetPresetSettings(FeatureSetPreset* preset, int feat featureUI->saveFeatureSetSettings(preset); } +void MainWindow::loadDefaultConfigurations() +{ + QDirIterator configurationsIt(":configurations", QDirIterator::Subdirectories); + while (configurationsIt.hasNext()) + { + QString group = configurationsIt.next(); + QDirIterator groupIt(group, {"*.cfgx"}, QDir::Files); + while (groupIt.hasNext()) + { + QFile file(groupIt.next()); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QByteArray base64Str; + QTextStream instream(&file); + instream >> base64Str; + file.close(); + + Configuration* configuration = MainCore::instance()->m_settings.newConfiguration("", ""); + configuration->deserialize(QByteArray::fromBase64(base64Str)); + } + else + { + qDebug() << "MainWindow::loadDefaultConfigurations: Failed to open configuration " << file.fileName(); + } + } + } + + QDirIterator presetIt(":presets", QDirIterator::Subdirectories); + while (presetIt.hasNext()) + { + QString group = presetIt.next(); + QDirIterator groupIt(group, {"*.prex"}, QDir::Files); + while (groupIt.hasNext()) + { + QFile file(groupIt.next()); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QByteArray base64Str; + QTextStream instream(&file); + instream >> base64Str; + file.close(); + + Preset* preset = MainCore::instance()->m_settings.newPreset("", ""); + preset->deserialize(QByteArray::fromBase64(base64Str)); + } + else + { + qDebug() << "MainWindow::loadDefaultConfigurations: Failed to open preset " << file.fileName(); + } + } + } +} + void MainWindow::loadConfiguration(const Configuration *configuration, bool fromDialog) { qDebug("MainWindow::loadConfiguration: configuration [%s | %s] %d workspace(s) - %d device set(s) - %d feature(s)", @@ -1240,23 +1349,24 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from configuration->getFeatureSetPreset().getFeatureCount() ); - QMessageBox *waitBox = nullptr; + QProgressDialog *waitBox = nullptr; if (fromDialog) { - waitBox = new QMessageBox(this); - waitBox->setStandardButtons(QMessageBox::NoButton); - waitBox->setWindowModality(Qt::NonModal); - waitBox->setIcon(QMessageBox::Information); - waitBox->setText("Loading configuration "); - waitBox->setInformativeText("Deleting existing..."); - waitBox->setWindowTitle("Please wait"); - waitBox->show(); - waitBox->raise(); + waitBox = new QProgressDialog("Loading configuration...", "", 0, 100, this); + waitBox->setWindowModality(Qt::WindowModal); + waitBox->setAttribute(Qt::WA_DeleteOnClose, true); + waitBox->setMinimumDuration(0); + waitBox->setCancelButton(nullptr); + waitBox->setValue(1); } // Wipe out everything first - + if (waitBox) + { + waitBox->setLabelText("Deleting existing..."); + waitBox->setValue(5); + } // Device sets while (m_deviceUIs.size() > 0) { removeLastDeviceSet(); @@ -1276,6 +1386,7 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from { addWorkspace(); m_workspaces[i]->setAutoStackOption(configuration->getWorkspaceAutoStackOptions()[i]); + m_workspaces[i]->setTabSubWindowsOption(configuration->getWorkspaceTabSubWindowsOptions()[i]); } if (m_workspaces.size() <= 0) { // cannot go further if there are no workspaces @@ -1283,8 +1394,10 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from } // Device sets - if (waitBox) { - waitBox->setInformativeText("Loading device sets..."); + if (waitBox) + { + waitBox->setLabelText("Loading device sets..."); + waitBox->setValue(25); } const QList& deviceSetPresets = configuration->getDeviceSetPresets(); @@ -1354,11 +1467,17 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from m_deviceUIs.back()->m_deviceGUI->restoreGeometry(deviceSetPreset.getDeviceGeometry()); m_deviceUIs.back()->m_mainSpectrumGUI->restoreGeometry(deviceSetPreset.getSpectrumGeometry()); m_deviceUIs.back()->loadDeviceSetSettings(&deviceSetPreset, m_pluginManager->getPluginAPI(), &m_workspaces, nullptr); + + if (waitBox) { + waitBox->setValue(waitBox->value() + 50/deviceSetPresets.size()); + } } // Features - if (waitBox) { - waitBox->setInformativeText("Loading device sets..."); + if (waitBox) + { + waitBox->setLabelText("Loading feature sets..."); + waitBox->setValue(75); } m_featureUIs[0]->loadFeatureSetSettings( @@ -1381,8 +1500,10 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from } // Lastly restore workspaces geometry - if (waitBox) { - waitBox->setInformativeText("Finalizing..."); + if (waitBox) + { + waitBox->setValue(90); + waitBox->setLabelText("Finalizing..."); } for (int i = 0; i < configuration->getNumberOfWorkspaceGeometries(); i++) @@ -1390,12 +1511,16 @@ void MainWindow::loadConfiguration(const Configuration *configuration, bool from m_workspaces[i]->restoreGeometry(configuration->getWorkspaceGeometries()[i]); m_workspaces[i]->restoreGeometry(configuration->getWorkspaceGeometries()[i]); m_workspaces[i]->adjustSubWindowsAfterRestore(); +#ifdef ANDROID + // On Android, workspaces seem to be restored to 0,20, rather than 0,0 + m_workspaces[i]->move(m_workspaces[i]->pos().x(), 0); + // Need to call updateGeometry, otherwise sometimes the layout is corrupted + m_workspaces[i]->updateGeometry(); +#endif } - if (waitBox) - { - waitBox->close(); - delete waitBox; + if (waitBox) { + waitBox->setValue(100); } } @@ -1430,6 +1555,7 @@ void MainWindow::saveConfiguration(Configuration *configuration) { configuration->getWorkspaceGeometries().push_back(workspace->saveGeometry()); configuration->getWorkspaceAutoStackOptions().push_back(workspace->getAutoStackOption()); + configuration->getWorkspaceTabSubWindowsOptions().push_back(workspace->getTabSubWindowsOption()); } } @@ -1461,24 +1587,46 @@ QString MainWindow::openGLVersion() } } -void MainWindow::createMenuBar() +void MainWindow::createMenuBar(QToolButton *button) { - QMenuBar *menuBar = this->menuBar(); + QMenu *fileMenu, *viewMenu, *workspacesMenu, *preferencesMenu, *helpMenu; + + if (button == nullptr) + { + QMenuBar *menuBar = this->menuBar(); + fileMenu = menuBar->addMenu("&File"); + viewMenu = menuBar->addMenu("&View"); + workspacesMenu = menuBar->addMenu("&Workspaces"); + preferencesMenu = menuBar->addMenu("&Preferences"); + helpMenu = menuBar->addMenu("&Help"); + } + else + { + QMenu *menu = new QMenu(); + fileMenu = new QMenu("&File"); + menu->addMenu(fileMenu); + viewMenu = new QMenu("&View"); + menu->addMenu(viewMenu); + workspacesMenu = new QMenu("&Workspaces"); + menu->addMenu(workspacesMenu); + preferencesMenu = new QMenu("&Preferences"); + menu->addMenu(preferencesMenu); + helpMenu = new QMenu("&Help"); + menu->addMenu(helpMenu); + button->setMenu(menu); + } - QMenu *fileMenu = menuBar->addMenu("&File"); QAction *exitAction = fileMenu->addAction("E&xit"); exitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); exitAction->setToolTip("Exit"); QObject::connect(exitAction, &QAction::triggered, this, &QMainWindow::close); - QMenu *viewMenu = menuBar->addMenu("&View"); QAction *fullscreenAction = viewMenu->addAction("&Fullscreen"); fullscreenAction->setShortcut(QKeySequence(Qt::Key_F11)); fullscreenAction->setToolTip("Toggle fullscreen view"); fullscreenAction->setCheckable(true); QObject::connect(fullscreenAction, &QAction::triggered, this, &MainWindow::on_action_View_Fullscreen_toggled); - QMenu *workspacesMenu = menuBar->addMenu("&Workspaces"); QAction *newWorkspaceAction = workspacesMenu->addAction("&New"); newWorkspaceAction->setToolTip("Add a new workspace"); QObject::connect(newWorkspaceAction, &QAction::triggered, this, &MainWindow::addWorkspace); @@ -1489,7 +1637,6 @@ void MainWindow::createMenuBar() removeEmptyWorkspacesAction->setToolTip("Remove empty workspaces"); QObject::connect(removeEmptyWorkspacesAction, &QAction::triggered, this, &MainWindow::removeEmptyWorkspaces); - QMenu *preferencesMenu = menuBar->addMenu("&Preferences"); QAction *configurationsAction = preferencesMenu->addAction("&Configurations..."); configurationsAction->setToolTip("Manage configurations"); QObject::connect(configurationsAction, &QAction::triggered, this, &MainWindow::on_action_Configurations_triggered); @@ -1519,7 +1666,6 @@ void MainWindow::createMenuBar() saveAllAction->setToolTip("Save all current settings"); QObject::connect(saveAllAction, &QAction::triggered, this, &MainWindow::on_action_saveAll_triggered); - QMenu *helpMenu = menuBar->addMenu("&Help"); QAction *quickStartAction = helpMenu->addAction("&Quick start..."); quickStartAction->setToolTip("Instructions for quick start"); QObject::connect(quickStartAction, &QAction::triggered, this, &MainWindow::on_action_Quick_Start_triggered); @@ -1882,7 +2028,11 @@ void MainWindow::handleWorkspaceVisibility(Workspace *workspace, bool visibility void MainWindow::addWorkspace() { int workspaceIndex = m_workspaces.size(); - m_workspaces.push_back(new Workspace(workspaceIndex)); + Workspace *workspace = new Workspace(workspaceIndex); + m_workspaces.push_back(workspace); + if (workspace->getMenuButton()) { + createMenuBar(workspace->getMenuButton()); + } QStringList featureNames; m_pluginManager->listFeatures(featureNames); m_workspaces.back()->addAvailableFeatures(featureNames); @@ -1923,6 +2073,13 @@ void MainWindow::addWorkspace() &MainWindow::openFeaturePresetsDialog ); + QObject::connect( + m_workspaces.back(), + &Workspace::configurationPresetsDialogRequested, + this, + &MainWindow::on_action_Configurations_triggered + ); + QObject::connect( m_workspaces.back(), &Workspace::startAllDevices, @@ -1951,7 +2108,7 @@ void MainWindow::addWorkspace() // tabBars.back()->setStyleSheet("QTabBar::tab:selected { background: rgb(128,70,0); }"); // change text color so it is visible // } } -} + } void MainWindow::viewAllWorkspaces() { @@ -2006,6 +2163,13 @@ void MainWindow::removeEmptyWorkspaces() } } } + +#ifdef ANDROID + // Need at least one workspace on Android, as no menus without + if (m_workspaces.size() == 0) { + addWorkspace(); + } +#endif } void MainWindow::on_action_View_Fullscreen_toggled(bool checked) @@ -2063,7 +2227,12 @@ void MainWindow::on_action_Loaded_Plugins_triggered() void MainWindow::on_action_Configurations_triggered() { - ConfigurationsDialog dialog(this); + openConfigurationDialog(false); +} + +void MainWindow::openConfigurationDialog(bool openOnly) +{ + ConfigurationsDialog dialog(openOnly, this); dialog.setConfigurations(m_mainCore->m_settings.getConfigurations()); dialog.populateTree(); QObject::connect( @@ -2078,24 +2247,28 @@ void MainWindow::on_action_Configurations_triggered() this, [=](const Configuration* configuration) { this->loadConfiguration(configuration, true); } ); + new DialogPositioner(&dialog, true); dialog.exec(); } void MainWindow::on_action_Audio_triggered() { AudioDialogX audioDialog(m_dspEngine->getAudioDeviceManager(), this); + new DialogPositioner(&audioDialog, true); audioDialog.exec(); } void MainWindow::on_action_Graphics_triggered() { GraphicsDialog graphicsDialog(m_mainCore->m_settings, this); + new DialogPositioner(&graphicsDialog, true); graphicsDialog.exec(); } void MainWindow::on_action_Logging_triggered() { LoggingDialog loggingDialog(m_mainCore->m_settings, this); + new DialogPositioner(&loggingDialog, true); loggingDialog.exec(); m_mainCore->setLoggingOptions(); } @@ -2103,6 +2276,7 @@ void MainWindow::on_action_Logging_triggered() void MainWindow::on_action_My_Position_triggered() { MyPositionDialog myPositionDialog(m_mainCore->m_settings, this); + new DialogPositioner(&myPositionDialog, true); myPositionDialog.exec(); } @@ -2110,6 +2284,7 @@ void MainWindow::on_action_DeviceUserArguments_triggered() { qDebug("MainWindow::on_action_DeviceUserArguments_triggered"); DeviceUserArgsDialog deviceUserArgsDialog(DeviceEnumerator::instance(), m_mainCore->m_settings.getDeviceUserArgs(), this); + new DialogPositioner(&deviceUserArgsDialog, true); deviceUserArgsDialog.exec(); } @@ -2121,6 +2296,7 @@ void MainWindow::on_action_commands_triggered() commandsDialog.setApiPort(m_apiServer->getPort()); commandsDialog.setCommandKeyReceiver(m_commandKeyReceiver); commandsDialog.populateTree(); + new DialogPositioner(&commandsDialog, true); commandsDialog.exec(); } @@ -2140,6 +2316,7 @@ void MainWindow::on_action_FFT_triggered() this, SLOT(fftWisdomProcessFinished(int, QProcess::ExitStatus))); FFTWisdomDialog fftWisdomDialog(m_fftWisdomProcess, this); + new DialogPositioner(&fftWisdomDialog, true); if (fftWisdomDialog.exec() == QDialog::Rejected) { @@ -2790,6 +2967,7 @@ void MainWindow::openFeaturePresetsDialog(QPoint p, Workspace *workspace) dialog.setWorkspaces(&m_workspaces); dialog.populateTree(); dialog.move(p); + new DialogPositioner(&dialog, true); dialog.exec(); if (dialog.wasPresetLoaded()) @@ -2820,6 +2998,7 @@ void MainWindow::openDeviceSetPresetsDialog(QPoint p, DeviceGUI *deviceGUI) dialog.setWorkspaces(&m_workspaces); dialog.populateTree((int) deviceGUI->getDeviceType()); dialog.move(p); + new DialogPositioner(&dialog, true); dialog.exec(); } @@ -2840,7 +3019,9 @@ void MainWindow::on_action_About_triggered() void MainWindow::updateStatus() { - m_dateTimeWidget->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss t")); + if (m_dateTimeWidget) { + m_dateTimeWidget->setText(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss t")); + } } void MainWindow::commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release) @@ -2862,3 +3043,30 @@ void MainWindow::commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifie } } } + +void MainWindow::keyPressEvent(QKeyEvent* event) +{ +#ifdef ANDROID + if (event->key() == Qt::Key_Back) + { + // On Android, we don't want to exit when back key is pressed, just run in the background + Android::moveTaskToBack(); + } + else +#endif + { + QMainWindow::keyPressEvent(event); + } +} + +void MainWindow::orientationChanged(Qt::ScreenOrientation orientation) +{ +#ifdef ANDROID + // Adjust workspace tab position, to leave max space for MDI windows + if ((orientation == Qt::LandscapeOrientation) || (orientation == Qt::InvertedLandscapeOrientation)) { + setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::West); + } else { + setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::South); + } +#endif +} diff --git a/sdrgui/mainwindow.h b/sdrgui/mainwindow.h index 102a5e861..6243a241f 100644 --- a/sdrgui/mainwindow.h +++ b/sdrgui/mainwindow.h @@ -34,6 +34,7 @@ class QLabel; class QTreeWidgetItem; class QDir; +class QToolButton; class DSPEngine; class DSPDeviceSourceEngine; @@ -136,7 +137,7 @@ private: void saveFeatureSetPresetSettings(FeatureSetPreset* preset, int featureSetIndex); QString openGLVersion(); - void createMenuBar(); + void createMenuBar(QToolButton *button); void createStatusBar(); void closeEvent(QCloseEvent*); void applySettings(); @@ -171,6 +172,9 @@ private: bool handleMessage(const Message& cmd); +protected: + virtual void keyPressEvent(QKeyEvent* event) override; + private slots: void handleMessages(); void handleWorkspaceVisibility(Workspace *workspace, bool visibility); @@ -194,6 +198,8 @@ private slots: void addWorkspace(); void viewAllWorkspaces(); void removeEmptyWorkspaces(); + void openConfigurationDialog(bool openOnly); + void loadDefaultConfigurations(); void loadConfiguration(const Configuration *configuration, bool fromDialog = false); void saveConfiguration(Configuration *configuration); void sampleSourceAdd(Workspace *deviceWorkspace, Workspace *spectrumWorkspace, int deviceIndex); @@ -215,6 +221,7 @@ private slots: void openDeviceSetPresetsDialog(QPoint p, DeviceGUI *deviceGUI); void commandKeyPressed(Qt::Key key, Qt::KeyboardModifiers keyModifiers, bool release); void fftWisdomProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); + void orientationChanged(Qt::ScreenOrientation orientation); }; #endif // INCLUDE_MAINWINDOW_H diff --git a/settings/configurations/airspyhf/radioclockeu.cfgx b/settings/configurations/airspyhf/radioclockeu.cfgx new file mode 100644 index 000000000..57c6936da --- /dev/null +++ b/settings/configurations/airspyhf/radioclockeu.cfgx @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/settings/configurations/rtlsdr/adsb.cfgx b/settings/configurations/rtlsdr/adsb.cfgx new file mode 100644 index 000000000..56fbbe0ca --- /dev/null +++ b/settings/configurations/rtlsdr/adsb.cfgx @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/settings/configurations/rtlsdr/ais.cfgx b/settings/configurations/rtlsdr/ais.cfgx new file mode 100644 index 000000000..245c71d2d --- /dev/null +++ b/settings/configurations/rtlsdr/ais.cfgx @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/settings/configurations/rtlsdr/apt.cfgx b/settings/configurations/rtlsdr/apt.cfgx new file mode 100644 index 000000000..a321e5772 --- /dev/null +++ b/settings/configurations/rtlsdr/apt.cfgx @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/settings/configurations/rtlsdr/dab.cfgx b/settings/configurations/rtlsdr/dab.cfgx new file mode 100644 index 000000000..651b9f1c7 --- /dev/null +++ b/settings/configurations/rtlsdr/dab.cfgx @@ -0,0 +1 @@ +kAABAXABB1JUTCBTRFJwAgNEQUKAAxuQAAEBcAEHZGVmYXVsdHACB25vIG5hbWUAZAAAZAEBgGVCAdnQywADAAAAAAAAAAAAAAAAAZoAAAMlAAAAAAAAAAAAAAGaAAADJQAAAAAAAAAAAZsAAAAAAAAAAAAAAZoAAAMlAMgBAYHJBB2QAAEBcAEHZGVmYXVsdHACB25vIG5hbWUwAwQNcx2AgAQAgAXikAABAQABAgQAAAIAAAMBBEAEBAAAAABABQRCjAAAYAYBAWAHAQFgCAEAYAkBAAAKAQFgCwEBAA0BEgAOAQEADwEeYBABAQARATJAEgQ/KPXDABMBAQAUAQpgFQEAcBYJMTI3LjAuMC4xEBcCIrdgGAEAYBkBAQAaATJgGwEAABwBAmAdAQAAHgBgHwEAACABA3AhBUFuZ2VsACIBAgAjAAAkAicQACUCJxAAJgInEAAnAQVgKgEBACsBBQAsAQEALQEBAC4AYC8BAGAwAQAAZAAAbgCAKAQAAAAAgCkEAAAAAGAGAQEABwBgCAEBgAlCAdnQywADAAAAABOIAAAAAAAAFQMAAAFuAAATiAAAAAAAABUDAAABbv////8AAAAAAZsAABOIAAAAAAAAFQMAAAFuAAoAgAtCAdnQywADAAAAABOIAAAAAAAAFPMAAAEEAAATiAAAAAAAABTzAAABBP////8AAAAAAZsAABOIAAAAAAAAFPMAAAEEAAwAcA0cc2RyYW5nZWwuc2FtcGxlc291cmNlLnJ0bHNkcnAOCDAwMDAwMDAxAA8AABAAABQBAXAYHHNkcmFuZ2VsLnNhbXBsZXNvdXJjZS5ydGxzZHJwGQgwMDAwMDAwMQAaAIAbXpAAAQEAAgIBpAADABAEAGAFAQBgBgEAAAcBAgAIAx9AAGAJAQBgCgEAYAsBAGAMAQAgDQAQDgMmJaBgDwEAYBABAHARCTEyNy4wLjAuMRASAiK4EBMAYBQBAWAVAQAAyAEBcMkZc2RyYW5nZWwuY2hhbm5lbC5kYWJkZW1vZIHKAZWQAAEBAAEAAAIAcAMAQAQESbufQEAFBECgAABgBgEAcAcVU3lzdGVtIGRlZmF1bHQgZGV2aWNlgAgjkAABAQABABACBP9NaRlwAw9EQUIgRGVtb2R1bGF0b3IABwAQCQT/TWkZcAoPREFCIERlbW9kdWxhdG9yYAsBAHAMCTEyNy4wLjAuMRANAiK4EA4AEA8AgBCeAAAA/wAAAAAAAAAEAAAAIgBzAGUAdAB0AGkAbgBnAHMAQwBvAG4AdABhAGkAbgBlAHIAAAABAAAAIABwAHIAbwBnAHIAYQBtAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAABwAYwB1AHIAcgBlAG4AdABQAHIAbwBnAHIAYQBtAAAAAQAAABQAcwB0AGEAdABpAHMAdABpAGMAcwAAAAEAEQCAEkIB2dDLAAMAAAAAAAAAAAAAAAABmgAAAvwAAAAAAAAAAP////7////+AAAAAAIAAAABmwAAAAAAAAAAAAABmgAAAvxgEwEAAGQAAGUBAQBmAQIAyAH/AMkB/wDKAf8EASwBAWQBLQEABAGQAQFkAZEBAQ== \ No newline at end of file diff --git a/settings/configurations/rtlsdr/isspacket.cfgx b/settings/configurations/rtlsdr/isspacket.cfgx new file mode 100644 index 000000000..88343baf2 --- /dev/null +++ b/settings/configurations/rtlsdr/isspacket.cfgx @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/settings/configurations/rtlsdr/radiosonde.cfgx b/settings/configurations/rtlsdr/radiosonde.cfgx new file mode 100644 index 000000000..2adbb104f --- /dev/null +++ b/settings/configurations/rtlsdr/radiosonde.cfgx @@ -0,0 +1 @@ +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BBAAAE4gAAAAAAAAU8wAAAQT/////AAAAAAGbAAATiAAAAAAAABTzAAABBAAMAHANHHNkcmFuZ2VsLnNhbXBsZXNvdXJjZS5ydGxzZHJwDggwMDAwMDAwMQAPAAAQAAAUAQFwGBxzZHJhbmdlbC5zYW1wbGVzb3VyY2UucnRsc2RycBkIMDAwMDAwMDEAGgCAG1+QAAEBAAICAaQAAwAQBAECYAUBAGAGAQAABwECAAgDD0JAYAkBAGAKAQBgCwEAYAwBACANABAOAyYloGAPAQBgEAEAcBEJMTI3LjAuMC4xEBICIrgQEwBgFAEBYBUBAADIAQFwySBzZHJhbmdlbC5jaGFubmVsLnJhZGlvc29uZGVkZW1vZIHKAyaQAAEBAAEDAYagQAIERhYAAEADBEUWAABABARD4QAAcAUAYAYBAHAHCTEyNy4wLjAuMRAIAicPAAoBBQALAQYQDAT/ZgBmcA0WUmFkaW9zb25kZSBEZW1vZHVsYXRvcoAOLZAAAQEAAQMBhqAQAgT/ZgBmcAMWUmFkaW9zb25kZSBEZW1vZHVsYXRvcgAHAAAPAGAQAQBwEQkxMjcuMC4wLjEQEgIiuBATABAUAIAVupAAAQEAAQEBAAIBMgADAQoABAEBAAYBAQAUAEAVBD+AAABAFgQAAAAAABgAABkAQBoEP4AAAEAbBD+AAABAHAQ+gICBEB0AACQBAUAlBD+AAABAJgQAAAAAACgAACkAQCoEP4AAAEArBD+AAABALAQ+gICBEC0AEAoBAhDIAQEAyQEwANIAANMAYNQBAWDVAQAA1gEKANcAANgAANkAQNoEAAAAAEDbBD+AAABA3AQAAAAAEN0BARDeAHAWEnJhZGlvc29uZGVfbG9nLmNzdmAXAQAAGAISwIAZgAAAAP8AAAAAAAAAAwAAACIAcwBlAHQAdABpAG4AZwBzAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAAB4AZgByAGEAbQBlAHMAQwBvAG4AdABhAGkAbgBlAHIAAAABAAAAHABzAGMAbwBwAGUAQwBvAG4AdABhAGkAbgBlAHIAAAAAABoAgBtCAdnQywADAAAAABOIAAAAAAAAFSIAAAMHAAATiAAAAAAAABUiAAADB/////8AAAAAAZsAABOIAAAAAAAAFSIAAAMHYBwBAABkAABlAQEAZgECAGcBAwBoAQQAaQEFAGoBBgBrAQcAbAEIAG0BCQBuAQoAbwELAHABDABxAQ0AcgEOAHMBDwB0ARAAdQERAHYBEgB3ARMAeAEUAHkBFQB6ARYAewEXAHwBGAB9ARkAyAH/AMkB/wDKAf8AywH/AMwB/wDNAf8AzgH/AM8B/wDQAf8A0QH/ANIB/wDTAf8A1AH/ANUB/wDWAf8A1wH/ANgB/wDZAf8A2gH/ANsB/wDcAf8A3QH/AN4B/wDfAf8A4AH/AOEB/wQBLAEBZAEtAQAEAZABAWQBkQEB \ No newline at end of file diff --git a/settings/presets/rtlsdr/noaa18.prex b/settings/presets/rtlsdr/noaa18.prex new file mode 100644 index 000000000..a573be397 --- /dev/null +++ b/settings/presets/rtlsdr/noaa18.prex @@ -0,0 +1 @@ +kAABAXABB1JUTCBTRFJwAgdOT0FBIDE4MAMECDgI0IAEAIEFAWmQAAEBAAECBAAAAgAAAwEEQAQEAAAAAEAFBEKMAABgBgEBYAcBAWAIAQBgCQEAAAoBAWALAQEADQESAA4BAQAPAR5gEAEBABEBMkASBD8o9cMAEwEBABQBCmAVAQBwFgkxMjcuMC4wLjEQFwIit2AYAQBgGQEBABoBMmAbAQAAHAECYB0BAAAeAGAfAQAAIAEDcCEFQW5nZWwAIgECACMAACQCJxAAJQInEAAmAicQACcBBWAqAQEAKwEFACwBAQAtAQEALgBgLwEAYDABAABkAABuAIAoiwAAAAMAAAAACDOcAAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADUAAAAACDgQoAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADgAAAAACCuswAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADmAKQQAAAAAYAYBAQAHAGAIAQGACUIB2dDLAAMAAAAAE4gAAAAAAAAVAwAAAW4AABOIAAAAAAAAFQMAAAFu/////wAAAAABmwAAE4gAAAAAAAAVAwAAAW4ACgCAC0IB2dDLAAMAAAAAAAAAAAAAAAABfwAAARAAAAAAAAAAFAAAAWsAAAEYAAAAAAIAAAABmwAAAAAAAAAAAAABfwAAARAADABwDRxzZHJhbmdlbC5zYW1wbGVzb3VyY2UucnRsc2RycA4IMDAwMDAwMDEADwAAEAAAFAEBcBgcc2RyYW5nZWwuc2FtcGxlc291cmNlLnJ0bHNkcnAZCDAwMDAwMDAxABoAgBtfkAABAQACAgGkAAMAEAQBA2AFAQBgBgEAAAcBAgAIAw9CQGAJAQBgCgEAYAsBAGAMAQAgDQAQDgMmJaBgDwEAYBABAHARCTEyNy4wLjAuMRASAiK4EBMAYBQBAWAVAQAAyAEBcMkZc2RyYW5nZWwuY2hhbm5lbC5hcHRkZW1vZIHKAYmQAAEBAAECVfAAAgBAAwRHHEAAQAQERoTQAGAFAQBgBgEBYAcBAGAIAQBgCQEAYAoBAAALAGAMAQBgDQEBcA4DQWxsYA8BAHAQAAARAgDIYBIBAAATARSAFCWQAAEBAAECVfAQAgT/2HCpcAMPQVBUIERlbW9kdWxhdG9yAAcAEBUE/9hwqXAWD0FQVCBEZW1vZHVsYXRvcmAXAQBwGAkxMjcuMC4wLjEQGQIiuBAaABAbAIAcWgAAAP8AAAAAAAAAAgAAACIAcwBlAHQAdABpAG4AZwBzAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAABwAaQBtAGEAZwBlAEMAbwBuAHQAYQBpAG4AZQByAAAAAWAdAQFgHgEAAB8BZAAgAgDIcCEAACIAACMBCgAkARRAJQQAAAAAQCYEAAAAAAAnAIAoQgHZ0MsAAwAAAAATiAAAAAAAABUiAAADBwAAE4gAAAAAAAAVIgAAAwf/////AAAAAAGbAAATiAAAAAAAABUiAAADB2ApAQA= \ No newline at end of file diff --git a/settings/presets/rtlsdr/noaa19.prex b/settings/presets/rtlsdr/noaa19.prex new file mode 100644 index 000000000..b46443219 --- /dev/null +++ b/settings/presets/rtlsdr/noaa19.prex @@ -0,0 +1 @@ +kAABAXABB1JUTCBTRFJwAgdOT0FBIDE5MAMECCuk8IAEAIEFAWmQAAEBAAECBAAAAgAAAwEEQAQEAAAAAEAFBEKMAABgBgEBYAcBAWAIAQBgCQEAAAoBAWALAQEADQESAA4BAQAPAR5gEAEBABEBMkASBD8o9cMAEwEBABQBCmAVAQBwFgkxMjcuMC4wLjEQFwIit2AYAQBgGQEBABoBMmAbAQAAHAECYB0BAAAeAGAfAQAAIAEDcCEFQW5nZWwAIgECACMAACQCJxAAJQInEAAmAicQACcBBWAqAQEAKwEFACwBAQAtAQEALgBgLwEAYDABAABkAABuAIAoiwAAAAMAAAAACDOcAAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADUAAAAACDgQoAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADgAAAAACCuswAAAnEAB//8rKzY2//8AAAAAAAMAAAAOAE4ATwBBAEEAIAAxADmAKQQAAAAAYAYBAQAHAGAIAQGACUIB2dDLAAMAAAAAE4gAAAAAAAAVAwAAAW4AABOIAAAAAAAAFQMAAAFu/////wAAAAABmwAAE4gAAAAAAAAVAwAAAW4ACgCAC0IB2dDLAAMAAAAAAAAAAAAAAAABfwAAARAAAAAAAAAAFAAAAWsAAAEYAAAAAAIAAAABmwAAAAAAAAAAAAABfwAAARAADABwDRxzZHJhbmdlbC5zYW1wbGVzb3VyY2UucnRsc2RycA4IMDAwMDAwMDEADwAAEAAAFAEBcBgcc2RyYW5nZWwuc2FtcGxlc291cmNlLnJ0bHNkcnAZCDAwMDAwMDAxABoAgBtfkAABAQACAgGkAAMAEAQBA2AFAQBgBgEAAAcBAgAIAw9CQGAJAQBgCgEAYAsBAGAMAQAgDQAQDgMmJaBgDwEAYBABAHARCTEyNy4wLjAuMRASAiK4EBMAYBQBAWAVAQAAyAEBcMkZc2RyYW5nZWwuY2hhbm5lbC5hcHRkZW1vZIHKAYmQAAEBAAECVfAAAgBAAwRHHEAAQAQERoTQAGAFAQBgBgEBYAcBAGAIAQBgCQEAYAoBAAALAGAMAQBgDQEBcA4DQWxsYA8BAHAQAAARAgDIYBIBAAATARSAFCWQAAEBAAECVfAQAgT/2HCpcAMPQVBUIERlbW9kdWxhdG9yAAcAEBUE/9hwqXAWD0FQVCBEZW1vZHVsYXRvcmAXAQBwGAkxMjcuMC4wLjEQGQIiuBAaABAbAIAcWgAAAP8AAAAAAAAAAgAAACIAcwBlAHQAdABpAG4AZwBzAEMAbwBuAHQAYQBpAG4AZQByAAAAAQAAABwAaQBtAGEAZwBlAEMAbwBuAHQAYQBpAG4AZQByAAAAAWAdAQFgHgEAAB8BZAAgAgDIcCEAACIAACMBCgAkARRAJQQAAAAAQCYEAAAAAAAnAIAoQgHZ0MsAAwAAAAATiAAAAAAAABUiAAADBwAAE4gAAAAAAAAVIgAAAwf/////AAAAAAGbAAATiAAAAAAAABUiAAADB2ApAQA= \ No newline at end of file diff --git a/settings/settings.qrc b/settings/settings.qrc new file mode 100644 index 000000000..b9a99934b --- /dev/null +++ b/settings/settings.qrc @@ -0,0 +1,13 @@ + + + configurations/rtlsdr/adsb.cfgx + configurations/rtlsdr/ais.cfgx + configurations/rtlsdr/apt.cfgx + configurations/rtlsdr/dab.cfgx + configurations/rtlsdr/isspacket.cfgx + configurations/rtlsdr/radiosonde.cfgx + configurations/airspyhf/radioclockeu.cfgx + presets/rtlsdr/noaa18.prex + presets/rtlsdr/noaa19.prex + +