diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml new file mode 100644 index 000000000..df580c66d --- /dev/null +++ b/.github/workflows/mac.yml @@ -0,0 +1,127 @@ +name: SDRangel Mac release build + +on: + push: + branches: + - mac_ci + tags: + - 'v*' + +jobs: + build_mac_x64: + runs-on: macos-13 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + - name: Update brew + run: brew update + - name: Install brew packages + run: brew install nasm subversion + - name: Install SDRplay API + run: | + wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.15.0.pkg + sudo installer -pkg SDRplayAPI-macos-installer-universal-3.15.0.pkg -target / + - name: Install python + run: | + wget https://www.python.org/ftp/python/3.12.7/python-3.12.7-macos11.pkg + sudo installer -pkg python-3.12.7-macos11.pkg -target / + - name: Install python packages for UHD + run: | + /usr/local/bin/python3.12 -m pip install numpy mako requests Cheetah3 setuptools + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.3' + host: 'mac' + arch: 'clang_64' + modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel' + - name: Configure SDRangel + run: | + mkdir build && cd build + cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DARCH_OPT=nehalem -DDEBUG_OUTPUT=ON -DENABLE_USRP=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=ON -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DPYTHON_EXECUTABLE=/usr/local/bin/python3.12 + - name: Build SDRangel on Mac + run: | + cd build + make -j4 package + - name: Get version + id: get_version + run: | + if [[ "${{github.ref_name}}" == "mac_ci" ]]; then + echo "version=$(echo ${{github.sha}} | cut -c1-7)" >> $GITHUB_OUTPUT + else + echo "version=$(echo ${{github.ref_name}} | cut -c2-)" >> $GITHUB_OUTPUT + fi + - name: Get filename + id: get_filename + run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: sdrangel-${{ steps.get_version.outputs.version }}-macx64.dmg + path: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg + - name: Upload release + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v2 + with: + files: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg + + build_mac_arm64: + runs-on: macos-14 + steps: + - uses: actions/checkout@v4 + with: + submodules: true + fetch-depth: 0 + - name: Update brew + run: brew update + - name: Install brew packages + run: brew install nasm subversion + - name: Install SDRplay API + run: | + wget https://www.sdrplay.com/software/SDRplayAPI-macos-installer-universal-3.15.0.pkg + sudo installer -pkg SDRplayAPI-macos-installer-universal-3.15.0.pkg -target / + - name: Install python + run: | + wget https://www.python.org/ftp/python/3.12.7/python-3.12.7-macos11.pkg + sudo installer -pkg python-3.12.7-macos11.pkg -target / + - name: Install python packages for UHD + run: | + /usr/local/bin/python3.12 -m pip install numpy mako requests Cheetah3 setuptools + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: '6.7.3' + host: 'mac' + arch: 'clang_64' + modules: 'qtcharts qtscxml qt5compat qtlocation qtmultimedia qtpositioning qtserialport qtspeech qtwebsockets qtwebengine qtshadertools qtwebchannel' + - name: Configure SDRangel + run: | + mkdir build && cd build + cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DDEBUG_OUTPUT=ON -DENABLE_USRP=ON -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=ON -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DPYTHON_EXECUTABLE=/usr/local/bin/python3.12 + - name: Build SDRangel on Mac + run: | + cd build + make -j3 package + - name: Get version + id: get_version + run: | + if [[ "${{github.ref_name}}" == "mac_ci" ]]; then + echo "version=$(echo ${{github.sha}} | cut -c1-7)" >> $GITHUB_OUTPUT + else + echo "version=$(echo ${{github.ref_name}} | cut -c2-)" >> $GITHUB_OUTPUT + fi + - name: Get filename + id: get_filename + run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: sdrangel-${{ steps.get_version.outputs.version }}-macarm64.dmg + path: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg + - name: Upload release + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v2 + with: + files: ${{ github.workspace }}/build/${{ steps.get_filename.outputs.filename }}.dmg diff --git a/.github/workflows/sdrangel.yml b/.github/workflows/sdrangel.yml index ac770c5d5..817ff7013 100644 --- a/.github/workflows/sdrangel.yml +++ b/.github/workflows/sdrangel.yml @@ -101,7 +101,7 @@ jobs: files: ${{ github.workspace }}/build/sdrangel-${{ steps.get_version.outputs.version }}-win64.exe build_mac: - runs-on: macos-13 + runs-on: macos-14 steps: - uses: actions/checkout@v4 with: @@ -126,10 +126,7 @@ jobs: - name: Configure SDRangel run: | mkdir build && cd build - cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DARCH_OPT=nehalem -DDEBUG_OUTPUT=ON -DENABLE_CHANNELRX_DEMODDATV=OFF -DENABLE_CHANNELTX_MODDATV=OFF -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=AUTO -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DCMAKE_PREFIX_PATH="/usr/local/opt/ffmpeg@5/" - - name: Get filename - id: get_filename - run: echo "filename=$(grep CPACK_PACKAGE_FILE_NAME build/CMakeCache.txt | cut -d "=" -f2)" >> $GITHUB_OUTPUT + cmake .. -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_QT6=ON -DCMAKE_BUILD_TYPE=Release -DDEBUG_OUTPUT=ON -DENABLE_CHANNELRX_DEMODDATV=OFF -DENABLE_CHANNELTX_MODDATV=OFF -DENABLE_MIRISDR=OFF -DBUILD_SERVER=OFF -DENABLE_EXTERNAL_LIBRARIES=AUTO -DBUNDLE=ON -DPKG_CONFIG_USE_CMAKE_PREFIX_PATH=TRUE -DCMAKE_PREFIX_PATH="/usr/local/opt/ffmpeg@5/" - name: Build SDRangel on Mac run: | cd build diff --git a/cmake/cpack/deploy_mac.cmake.in b/cmake/cpack/deploy_mac.cmake.in index 20b45a21d..d6015e85a 100644 --- a/cmake/cpack/deploy_mac.cmake.in +++ b/cmake/cpack/deploy_mac.cmake.in @@ -1,14 +1,15 @@ # This CPACK_PRE_BUILD_SCRIPTS script is used to copy all required Qt and other 3rd party libraries (SDR drivers and codecs) in to the .app bundle # It is run in a staging area (${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app) after all targets have been installed (E.g. sdrangel exe and plugins) # The copying of frameworks and libraries is mostly done by 'macdeployqt', however, in order for 'macdeployqt' to copy libraries built by external/CMakeLists.txt, -# we first need to add RPATHs into the libraries giving the locations of any libraries they might depend on. +# we first need to add RPATHs into the libraries giving the locations of any libraries they might depend on. # These paths are in the variable MACOS_EXTERNAL_LIBS_FIXUP set in externals/CMakeLists.txt # Is there an easier way to this? # Copy executable that will be run when icon in /Applications is clicked message ("Copying default executable to SDRangel.app/Contents/MacOS/SDRangel") execute_process (COMMAND mkdir ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app/Contents/MacOS/) -execute_process (COMMAND cp /opt/build/sdrangel/build/sdrangel ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app/Contents/MacOS/SDRangel) +execute_process (COMMAND pwd) +execute_process (COMMAND cp sdrangel ${CPACK_TEMPORARY_INSTALL_DIRECTORY}/SDRangel.app/Contents/MacOS/SDRangel) # Add RPATHS to libraries so macdeployqt can find out and copy all dependencies diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 137e77f26..619bbe7bc 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -31,15 +31,9 @@ set(SOAPYSDR_REMOTE_TAG "soapy-remote-0.5.1") set(AIRSPY_TAG "37c768ce9997b32e7328eb48972a7fda0a1f8554") set(HACKRF_TAG "v2022.09.1") set(LIBXML2_TAG "v2.10.4") -set(UHD_TAG "v4.6.0.0") -if (APPLE AND (CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64)) - # UHD fails to load with 1.80+ - set(BOOST_TAG "1.78.0") - set(BOOST_TAG2 "1_78_0") -else() - set(BOOST_TAG "1.83.0") - set(BOOST_TAG2 "1_83_0") -endif() +set(UHD_TAG "v4.7.0.0") +set(BOOST_TAG "1.86.0") +set(BOOST_TAG2 "1_86_0") # For some external project macros include(ExternalProject) @@ -546,7 +540,7 @@ endif (NOT FFMPEG_FOUND AND NOT USE_PRECOMPILED_LIBS) if (NOT OpenCV_FOUND AND NOT USE_PRECOMPILED_LIBS AND ENABLE_CHANNELTX_MODATV) ExternalProject_Add(opencv GIT_REPOSITORY https://github.com/opencv/opencv.git - GIT_TAG 4.5.5 + GIT_TAG 4.10.0 DEPENDS "${FFMPEG_DEPENDS}" PREFIX "${EXTERNAL_BUILD_LIBRARIES}/opencv" CMAKE_ARGS ${COMMON_CMAKE_ARGS} -DWITH_FFMPEG=ON -DCMAKE_PREFIX_PATH=${FFMPEG_INSTALL_DIR} @@ -1578,6 +1572,8 @@ if (WIN32 OR APPLE) -DLIBUSB_LIBRARIES=${LIBUSB_LIBRARIES} -DLIBUSB_INCLUDE_DIR=${LIBUSB_INCLUDE_DIR} ${UHD_PYTHON_ARGS} + -DPython3_FIND_FRAMEWORK=NEVER + -DENABLE_PYTHON_API=OFF -DCMAKE_INSTALL_NAME_DIR=/lib TEST_COMMAND "" ) diff --git a/plugins/channelrx/remotetcpsink/remotetcpsink.cpp b/plugins/channelrx/remotetcpsink/remotetcpsink.cpp index 7d0ff2a43..75bea4183 100644 --- a/plugins/channelrx/remotetcpsink/remotetcpsink.cpp +++ b/plugins/channelrx/remotetcpsink/remotetcpsink.cpp @@ -149,6 +149,9 @@ void RemoteTCPSink::start() m_basebandSink->setBasebandSampleRate(m_basebandSampleRate); } + MsgConfigureRemoteTCPSink* msg = MsgConfigureRemoteTCPSink::create(m_settings, QStringList(), true, true); + m_basebandSink->getInputMessageQueue()->push(msg); + updatePublicListing(); } diff --git a/plugins/channelrx/remotetcpsink/remotetcpsinkbaseband.cpp b/plugins/channelrx/remotetcpsink/remotetcpsinkbaseband.cpp index 6fc3d26a4..d27dc13b7 100644 --- a/plugins/channelrx/remotetcpsink/remotetcpsinkbaseband.cpp +++ b/plugins/channelrx/remotetcpsink/remotetcpsinkbaseband.cpp @@ -43,6 +43,7 @@ RemoteTCPSinkBaseband::~RemoteTCPSinkBaseband() void RemoteTCPSinkBaseband::reset() { QMutexLocker mutexLocker(&m_mutex); + m_inputMessageQueue.clear(); m_sampleFifo.reset(); m_sink.init(); } diff --git a/plugins/channelrx/remotetcpsink/remotetcpsinksettingsdialog.cpp b/plugins/channelrx/remotetcpsink/remotetcpsinksettingsdialog.cpp index 599bec544..0b45356aa 100644 --- a/plugins/channelrx/remotetcpsink/remotetcpsinksettingsdialog.cpp +++ b/plugins/channelrx/remotetcpsink/remotetcpsinksettingsdialog.cpp @@ -32,7 +32,16 @@ RemoteTCPSinkSettingsDialog::RemoteTCPSinkSettingsDialog(RemoteTCPSinkSettings * ui->maxClients->setValue(m_settings->m_maxClients); ui->timeLimit->setValue(m_settings->m_timeLimit); ui->maxSampleRate->setValue(m_settings->m_maxSampleRate); - ui->iqOnly->setChecked(m_settings->m_iqOnly); + if (m_settings->m_protocol == RemoteTCPSinkSettings::RTL0) + { + ui->iqOnly->setChecked(true); + ui->iqOnlyLabel->setEnabled(false); + ui->iqOnly->setEnabled(false); + } + else + { + ui->iqOnly->setChecked(m_settings->m_iqOnly); + } ui->compressor->setCurrentIndex((int) m_settings->m_compression); ui->compressionLevel->setValue(m_settings->m_compressionLevel); @@ -40,6 +49,9 @@ RemoteTCPSinkSettingsDialog::RemoteTCPSinkSettingsDialog(RemoteTCPSinkSettings * ui->certificate->setText(m_settings->m_certificate); ui->key->setText(m_settings->m_key); + if (m_settings->m_protocol != RemoteTCPSinkSettings::SDRA_WSS) { + ui->sslSettingsGroup->setEnabled(false); + } ui->publicListing->setChecked(m_settings->m_public); ui->publicAddress->setText(m_settings->m_publicAddress); @@ -94,10 +106,13 @@ void RemoteTCPSinkSettingsDialog::accept() m_settings->m_maxSampleRate = ui->maxSampleRate->value(); m_settingsKeys.append("maxSampleRate"); } - if (ui->iqOnly->isChecked() != m_settings->m_iqOnly) + if (m_settings->m_protocol != RemoteTCPSinkSettings::RTL0) { - m_settings->m_iqOnly = ui->iqOnly->isChecked(); - m_settingsKeys.append("iqOnly"); + if (ui->iqOnly->isChecked() != m_settings->m_iqOnly) + { + m_settings->m_iqOnly = ui->iqOnly->isChecked(); + m_settingsKeys.append("iqOnly"); + } } RemoteTCPSinkSettings::Compressor compressor = (RemoteTCPSinkSettings::Compressor) ui->compressor->currentIndex(); if (compressor != m_settings->m_compression) diff --git a/plugins/channelrx/remotetcpsink/remotetcpsinksink.cpp b/plugins/channelrx/remotetcpsink/remotetcpsinksink.cpp index d5977e32b..5697422fd 100644 --- a/plugins/channelrx/remotetcpsink/remotetcpsinksink.cpp +++ b/plugins/channelrx/remotetcpsink/remotetcpsinksink.cpp @@ -269,7 +269,7 @@ void RemoteTCPSinkSink::processOneSample(Complex &ci) } } - if (!m_settings.m_iqOnly && (m_settings.m_compression == RemoteTCPSinkSettings::FLAC)) + if (!m_settings.m_iqOnly && (m_settings.m_compression == RemoteTCPSinkSettings::FLAC) && (m_settings.m_protocol != RemoteTCPSinkSettings::RTL0)) { // Compress using FLAC FLAC__int32 iqBuf[2]; @@ -360,7 +360,7 @@ void RemoteTCPSinkSink::processOneSample(Complex &ci) int bytes = 2 * m_settings.m_sampleBits / 8; m_bytesUncompressed += bytes; - if (!m_settings.m_iqOnly && (m_settings.m_compression == RemoteTCPSinkSettings::ZLIB)) + if (!m_settings.m_iqOnly && (m_settings.m_compression == RemoteTCPSinkSettings::ZLIB) && (m_settings.m_protocol != RemoteTCPSinkSettings::RTL0)) { if (m_zStreamInitialised) { @@ -1027,12 +1027,12 @@ void RemoteTCPSinkSink::acceptConnection(Socket *client) client->flush(); // Inform client if they are in a queue - if (!m_settings.m_iqOnly && (m_clients.size() > m_settings.m_maxClients)) { + if (!m_settings.m_iqOnly && (m_clients.size() > m_settings.m_maxClients) && (m_settings.m_protocol != RemoteTCPSinkSettings::RTL0)) { sendQueuePosition(client, m_clients.size() - m_settings.m_maxClients); } // Send existing FLAC header to new client - if (!m_settings.m_iqOnly && (m_settings.m_compression == RemoteTCPSinkSettings::FLAC) && (m_flacHeader.size() == m_flacHeaderSize)) + if (!m_settings.m_iqOnly && (m_settings.m_compression == RemoteTCPSinkSettings::FLAC) && (m_flacHeader.size() == m_flacHeaderSize) && (m_settings.m_protocol != RemoteTCPSinkSettings::RTL0)) { char header[1+4]; diff --git a/plugins/samplesink/usrpoutput/CMakeLists.txt b/plugins/samplesink/usrpoutput/CMakeLists.txt index b0bd6dc8f..6808a8f71 100644 --- a/plugins/samplesink/usrpoutput/CMakeLists.txt +++ b/plugins/samplesink/usrpoutput/CMakeLists.txt @@ -45,14 +45,14 @@ else() set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) endif() -if(UHD_EXTERNAL) - add_dependencies(${TARGET_NAME} uhd) -endif() if(NOT Qt6_FOUND) add_library(${TARGET_NAME} ${usrpoutput_SOURCES}) else() qt_add_plugin(${TARGET_NAME} CLASS_NAME USRPOutputPlugin ${usrpoutput_SOURCES}) endif() +if(UHD_EXTERNAL) + add_dependencies(${TARGET_NAME} uhd) +endif() if(NOT BUILD_SHARED_LIBS) set_property(GLOBAL APPEND PROPERTY STATIC_PLUGINS_PROPERTY ${TARGET_NAME}) diff --git a/sdrsrv/mainserver.cpp b/sdrsrv/mainserver.cpp index 4e517ecac..da7723ce4 100644 --- a/sdrsrv/mainserver.cpp +++ b/sdrsrv/mainserver.cpp @@ -578,8 +578,8 @@ void MainServer::changeSampleSink(int deviceSetIndex, int selectedDeviceIndex) // wait for sample source to be set, before loading settings auto connection = new QMetaObject::Connection(); *connection = connect( - deviceSet->m_deviceSourceEngine, - &DSPDeviceSourceEngine::sampleSet, + deviceSet->m_deviceSinkEngine, + &DSPDeviceSinkEngine::sampleSet, this, [=]() { deviceSet->m_deviceAPI->loadSamplingDeviceSettings(m_mainCore->m_settings.getWorkingPreset()); // load new API settings @@ -644,8 +644,8 @@ void MainServer::changeSampleMIMO(int deviceSetIndex, int selectedDeviceIndex) // wait for sample source to be set, before loading settings auto connection = new QMetaObject::Connection(); *connection = connect( - deviceSet->m_deviceSourceEngine, - &DSPDeviceSourceEngine::sampleSet, + deviceSet->m_deviceMIMOEngine, + &DSPDeviceMIMOEngine::sampleSet, this, [=]() { deviceSet->m_deviceAPI->loadSamplingDeviceSettings(m_mainCore->m_settings.getWorkingPreset()); // load new API settings