From: IOhannes m zmölnig (Debian/GNU) Date: Tue, 5 Sep 2023 19:48:21 +0000 (+0200) Subject: New upstream version 2.0.2+ds X-Git-Tag: archive/raspbian/2.5.1+ds-1+rpi1~1^2~9^2~8 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=e1b1e6297a36159b7aca64bc8b3df1f5d6bd5713;p=jacktrip.git New upstream version 2.0.2+ds --- diff --git a/docs/Build/Linux.md b/docs/Build/Linux.md index 4b56d37..9205872 100644 --- a/docs/Build/Linux.md +++ b/docs/Build/Linux.md @@ -105,6 +105,8 @@ the following parameters: * `qtversion`: Choose to build with either Qt5 or Qt6 +* `buildinfo`: Additional info used to describe the build + For example: ```sh $ meson setup -Drtaudio=enabled builddir diff --git a/docs/changelog.yml b/docs/changelog.yml index 2419558..e61bd72 100644 --- a/docs/changelog.yml +++ b/docs/changelog.yml @@ -1,3 +1,14 @@ +- Version: "2.0.2" + Date: 2023-09-01 + Description: + - (added) VS Mode latency categories for Linux audio devices + - (added) VS Mode audio warnings for high latency Linux devices + - (updated) Improved support for Pipewire latency on Linux + - (fixed) Crash on Windows when using the JACK audio backend + - (fixed) Include ALSA support for Linux builds using meson + - (fixed) VS Mode overlapping UI elements with max scaling + - (fixed) Don't require git to be present for meson builds + - (fixed) Linux man page description and meson build errors - Version: "2.0.1" Date: 2023-08-29 Description: diff --git a/meson.build b/meson.build index d4d2c94..7b58a64 100644 --- a/meson.build +++ b/meson.build @@ -36,12 +36,20 @@ if get_option('buildtype') == 'release' c_defines += ['-DNDEBUG'] endif -git_tags_cmd = run_command('git', 'describe', '--tags', check: false) -git_hash_cmd = run_command('git', 'rev-parse', '--short', 'HEAD', check: false) -if git_tags_cmd.returncode() == 0 and git_hash_cmd.returncode() == 0 - git_tags = git_tags_cmd.stdout().strip() - git_hash = git_hash_cmd.stdout().strip() - defines += ['-DJACKTRIP_BUILD_INFO=' + git_tags + '-' + git_hash] +build_info = get_option('buildinfo') +git = find_program('git', required: false) +if build_info == '' and git.found() + git_tags_cmd = run_command(git, 'describe', '--tags', check: false) + git_hash_cmd = run_command(git, 'rev-parse', '--short', 'HEAD', check: false) + if git_tags_cmd.returncode() == 0 and git_hash_cmd.returncode() == 0 + git_tags = git_tags_cmd.stdout().strip() + git_hash = git_hash_cmd.stdout().strip() + build_info = git_tags + '-' + git_hash + endif +endif +if build_info != '' + message('Build info: ' + build_info) + defines += ['-DJACKTRIP_BUILD_INFO=' + build_info] endif src = [ 'src/DataProtocol.cpp', @@ -290,6 +298,7 @@ if (host_machine.system() == 'linux') if help2man.found() gzip = find_program('gzip', required: false) help2man_opts = [ + '--name="high-quality system for audio network performances"', '--no-info', '--section=1'] manfile = custom_target('jacktrip.1', @@ -299,8 +308,9 @@ if (host_machine.system() == 'linux') install_dir: get_option('mandir') / 'man1') if gzip.found() custom_target('jacktrip.1.gz', + input: manfile, output: 'jacktrip.1.gz', - command: [gzip, '-k', manfile], + command: [gzip, '-k', '-f', '@INPUT@'], install: true, install_dir: get_option('mandir') / 'man1') endif diff --git a/meson_options.txt b/meson_options.txt index f4753a5..ca4f707 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,4 +8,5 @@ option('vsftux', type : 'boolean', value : 'false', description: 'Build with Vir option('noupdater', type : 'boolean', value : 'false', description: 'Build without auto-update support') option('nofeedback', type : 'boolean', value : 'false', description: 'Build without feedback detection') option('profile', type: 'combo', choices: ['default', 'development'], value: 'default', description: 'Choose build profile / Sets desktop id accordingly') -option('qtversion', type : 'combo', choices: ['', '5', '6'], description: 'Choose to build with either Qt5 or Qt6') \ No newline at end of file +option('qtversion', type : 'combo', choices: ['', '5', '6'], description: 'Choose to build with either Qt5 or Qt6') +option('buildinfo', type : 'string', value : '', yield : true, description: 'Additional info used to describe the build') \ No newline at end of file diff --git a/releases/edge/mac-manifests.json b/releases/edge/mac-manifests.json index 1c78c87..c9fdcc6 100644 --- a/releases/edge/mac-manifests.json +++ b/releases/edge/mac-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.0.1", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.1", + "download": { + "date": "2023-08-30T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.0.1-macOS-x64-signed-installer.pkg", + "downloadSize": "177272934", + "sha256": "5f12f512cd372beb01c6c888c8bbbaf4c1e5cf61881db9cd91c5d2c8582531b5" + } + }, { "version": "2.0.0", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.0", diff --git a/releases/edge/win-manifests.json b/releases/edge/win-manifests.json index de0d8a4..7bc7e86 100644 --- a/releases/edge/win-manifests.json +++ b/releases/edge/win-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.0.1", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.1", + "download": { + "date": "2023-08-30T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.0.1-Windows-x64-signed-installer.msi", + "downloadSize": "95846400", + "sha256": "aeb8934b7ef5ab274a135f575b13f16e1e93b42cfc631cfefa611477ae092c23" + } + }, { "version": "2.0.0", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.0", diff --git a/releases/stable/linux-manifests.json b/releases/stable/linux-manifests.json index 6bbe9b1..955cfbc 100644 --- a/releases/stable/linux-manifests.json +++ b/releases/stable/linux-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.0.1", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.1", + "download": { + "date": "2023-08-30T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.0.1-Linux-x64-binary.zip", + "downloadSize": "1216267", + "sha256": "eb7f10108e4cd2ef09b3df8b83f67187dc9174ac632dcb0ddd61087e65c3f0cb" + } + }, { "version": "2.0.0", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.0", diff --git a/releases/stable/mac-manifests.json b/releases/stable/mac-manifests.json index 4ef3dce..72b0e18 100644 --- a/releases/stable/mac-manifests.json +++ b/releases/stable/mac-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.0.1", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.1", + "download": { + "date": "2023-08-30T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.0.1-macOS-x64-signed-installer.pkg", + "downloadSize": "177272934", + "sha256": "5f12f512cd372beb01c6c888c8bbbaf4c1e5cf61881db9cd91c5d2c8582531b5" + } + }, { "version": "2.0.0", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.0", diff --git a/releases/stable/win-manifests.json b/releases/stable/win-manifests.json index 8ab9198..019d672 100644 --- a/releases/stable/win-manifests.json +++ b/releases/stable/win-manifests.json @@ -1,6 +1,16 @@ { "app_name": "JackTrip", "releases": [ + { + "version": "2.0.1", + "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.1", + "download": { + "date": "2023-08-30T00:00:00Z", + "url": "https://files.jacktrip.org/app-builds/JackTrip-v2.0.1-Windows-x64-signed-installer.msi", + "downloadSize": "95846400", + "sha256": "aeb8934b7ef5ab274a135f575b13f16e1e93b42cfc631cfefa611477ae092c23" + } + }, { "version": "2.0.0", "changelog": "Full changelog at https://github.com/jacktrip/jacktrip/releases/tag/v2.0.0", diff --git a/src/AudioInterface.cpp b/src/AudioInterface.cpp index 15f9952..af36cfe 100644 --- a/src/AudioInterface.cpp +++ b/src/AudioInterface.cpp @@ -741,6 +741,18 @@ void AudioInterface::fromBitToSampleConversion( } } +//******************************************************************************* +void AudioInterface::setPipewireLatency(unsigned int bufferSize, unsigned int sampleRate) +{ + if (bufferSize == 0 || sampleRate == 0) + return; +#if defined(__unix__) + char latency_env[40]; + sprintf(latency_env, "%d/%d", bufferSize, sampleRate); + setenv("PIPEWIRE_LATENCY", latency_env, 1); +#endif +} + //******************************************************************************* void AudioInterface::appendProcessPluginToNetwork(ProcessPlugin* plugin) { @@ -953,6 +965,13 @@ void AudioInterface::setDevicesWarningMsg(warningMessageT msg) mWarningHelpUrl = "https://help.jacktrip.org/hc/en-us/articles/4409919243155"; mHighLatencyFlag = true; break; + case DEVICE_WARN_ALSA_LATENCY: + mWarningMsg = + "You audio device drivers may cause high latency or audio delay. Use " + "JACK backend or Linux ALSA drivers to reduce audio delays."; + mWarningHelpUrl = ""; + mHighLatencyFlag = true; + break; default: mWarningMsg = ""; mWarningHelpUrl = ""; diff --git a/src/AudioInterface.h b/src/AudioInterface.h index 80eb8a1..7511ccb 100644 --- a/src/AudioInterface.h +++ b/src/AudioInterface.h @@ -79,7 +79,8 @@ class AudioInterface enum warningMessageT { DEVICE_WARN_NONE, DEVICE_WARN_BUFFER_LATENCY, - DEVICE_WARN_ASIO_LATENCY + DEVICE_WARN_ASIO_LATENCY, + DEVICE_WARN_ALSA_LATENCY }; enum errorMessageT { @@ -192,6 +193,9 @@ class AudioInterface const int8_t* const input, sample_t* output, const AudioInterface::audioBitResolutionT sourceBitResolution); + /** \brief Sets PIPEWIRE_LATENCY environment variable on unix */ + static void setPipewireLatency(unsigned int bufferSize, unsigned int sampleRate); + //--------------SETTERS--------------------------------------------- virtual void setInputChannels(QVarLengthArray inputChans) { diff --git a/src/JackAudioInterface.cpp b/src/JackAudioInterface.cpp index 136f14d..349bd95 100644 --- a/src/JackAudioInterface.cpp +++ b/src/JackAudioInterface.cpp @@ -356,7 +356,7 @@ void JackAudioInterface::connectDefaultPorts() break; } } - std::free(ports); + jack_free(ports); } // Get physical input (playback) ports @@ -374,6 +374,6 @@ void JackAudioInterface::connectDefaultPorts() break; } } - std::free(ports); + jack_free(ports); } } diff --git a/src/RtAudioInterface.cpp b/src/RtAudioInterface.cpp index 0b63d13..890809d 100644 --- a/src/RtAudioInterface.cpp +++ b/src/RtAudioInterface.cpp @@ -60,8 +60,8 @@ void RtAudioDevice::print() const //******************************************************************************* void RtAudioDevice::printVerbose() const { - cout << "Audio Device [" << this->api << " - " << this->ID << "] : " << this->name - << endl; + cout << "Audio Device [" << RtAudio::getApiDisplayName(this->api) << " - " + << this->ID << "] : " << this->name << endl; cout << " Output Channels : " << this->outputChannels << endl; cout << " Input Channels : " << this->inputChannels << endl; cout << " Supported Sampling Rates: "; @@ -230,6 +230,13 @@ void RtAudioInterface::setup(bool verbose) AudioInterface::setDevicesWarningMsg(AudioInterface::DEVICE_WARN_NONE); AudioInterface::setDevicesErrorMsg(AudioInterface::DEVICE_ERR_SAME_ASIO); } +#else + if (in_device.api == RtAudio::LINUX_PULSE + || in_device.api == RtAudio::LINUX_OSS) { + AudioInterface::setDevicesWarningMsg( + AudioInterface::DEVICE_WARN_ALSA_LATENCY); + AudioInterface::setDevicesErrorMsg(AudioInterface::DEVICE_ERR_NONE); + } #endif } else { AudioInterface::setDevicesWarningMsg(AudioInterface::DEVICE_WARN_NONE); diff --git a/src/Settings.cpp b/src/Settings.cpp index fa0e167..ab35547 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -1125,9 +1125,7 @@ JackTrip* Settings::getConfiguredJackTrip() #if defined(__unix__) if (mChangeDefaultBS or mChangeDefaultSR) { - char latency_env[40]; - sprintf(latency_env, "%d/%d", mAudioBufferSize, mSampleRate); - setenv("PIPEWIRE_LATENCY", latency_env, 1); + AudioInterface::setPipewireLatency(mAudioBufferSize, mSampleRate); } #endif diff --git a/src/gui/AudioSettings.qml b/src/gui/AudioSettings.qml index ebf7775..469f39e 100644 --- a/src/gui/AudioSettings.qml +++ b/src/gui/AudioSettings.qml @@ -161,8 +161,8 @@ Rectangle { outputCombo.currentIndex = index outputCombo.popup.close() audio.outputDevice = modelData.text - if (modelData.category === "Low-Latency (ASIO)") { - let inputComboIdx = inputCombo.model.findIndex(it => it.category === "Low-Latency (ASIO)" && it.text === modelData.text); + if (modelData.category.startsWith("Low-Latency")) { + let inputComboIdx = inputCombo.model.findIndex(it => it.category.startsWith("Low-Latency") && it.text === modelData.text); if (inputComboIdx !== null && inputComboIdx !== undefined) { inputCombo.currentIndex = inputComboIdx; audio.inputDevice = modelData.text @@ -346,8 +346,8 @@ Rectangle { inputCombo.currentIndex = index inputCombo.popup.close() audio.inputDevice = modelData.text - if (modelData.category === "Low-Latency (ASIO)") { - let outputComboIdx = outputCombo.model.findIndex(it => it.category === "Low-Latency (ASIO)" && it.text === modelData.text); + if (modelData.category.startsWith("Low-Latency")) { + let outputComboIdx = outputCombo.model.findIndex(it => it.category.startsWith("Low-Latency") && it.text === modelData.text); if (outputComboIdx !== null && outputComboIdx !== undefined) { outputCombo.currentIndex = outputComboIdx; audio.outputDevice = modelData.text diff --git a/src/gui/ChangeDevices.qml b/src/gui/ChangeDevices.qml index 9eea3c9..76a2ae7 100644 --- a/src/gui/ChangeDevices.qml +++ b/src/gui/ChangeDevices.qml @@ -162,8 +162,8 @@ Rectangle { outputCombo.currentIndex = index outputCombo.popup.close() audio.outputDevice = modelData.text - if (modelData.category === "Low-Latency (ASIO)") { - let inputComboIdx = inputCombo.model.findIndex(it => it.category === "Low-Latency (ASIO)" && it.text === modelData.text); + if (modelData.category.startsWith("Low-Latency")) { + let inputComboIdx = inputCombo.model.findIndex(it => it.category.startsWith("Low-Latency") && it.text === modelData.text); if (inputComboIdx !== null && inputComboIdx !== undefined) { inputCombo.currentIndex = inputComboIdx; audio.inputDevice = modelData.text @@ -299,8 +299,8 @@ Rectangle { inputCombo.currentIndex = index inputCombo.popup.close() audio.inputDevice = modelData.text - if (modelData.category === "Low-Latency (ASIO)") { - let outputComboIdx = outputCombo.model.findIndex(it => it.category === "Low-Latency (ASIO)" && it.text === modelData.text); + if (modelData.category.startsWith("Low-Latency")) { + let outputComboIdx = outputCombo.model.findIndex(it => it.category.startsWith("Low-Latency") && it.text === modelData.text); if (outputComboIdx !== null && outputComboIdx !== undefined) { outputCombo.currentIndex = outputComboIdx; audio.outputDevice = modelData.text diff --git a/src/gui/DeviceControls.qml b/src/gui/DeviceControls.qml index 8dd779b..4a84c2b 100644 --- a/src/gui/DeviceControls.qml +++ b/src/gui/DeviceControls.qml @@ -68,7 +68,7 @@ Item { Component { id: inputControls - + ColumnLayout { anchors.fill: parent spacing: 2 @@ -127,7 +127,7 @@ Item { Item { Layout.fillHeight: true - Layout.preferredWidth: 100 + Layout.preferredWidth: 100 * virtualstudio.uiScale Loader { id: typeIconIndicator @@ -163,8 +163,8 @@ Item { Meter { anchors.fill: parent - anchors.topMargin: 5 * virtualstudio.uiScale - anchors.rightMargin: 8 * virtualstudio.uiScale + anchors.topMargin: 5 + anchors.rightMargin: 8 model: isInput ? audio.inputMeterLevels : audio.outputMeterLevels clipped: isInput ? audio.inputClipped : audio.outputClipped enabled: true diff --git a/src/gui/DeviceControlsGroup.qml b/src/gui/DeviceControlsGroup.qml index aaa8c0b..d0bb216 100644 --- a/src/gui/DeviceControlsGroup.qml +++ b/src/gui/DeviceControlsGroup.qml @@ -8,7 +8,7 @@ Rectangle { property string disabledButtonText: "#D3D4D4" property string saveButtonText: "#DB0A0A" property int minifiedHeight: 36 - property int fullHeight: 80 + property int fullHeight: 84 id: deviceControlsGroup width: parent.width diff --git a/src/gui/Meter.qml b/src/gui/Meter.qml index 16d0d4c..292cef9 100644 --- a/src/gui/Meter.qml +++ b/src/gui/Meter.qml @@ -6,7 +6,7 @@ Item { property int bins: Math.max(15, width/20) property int innerMargin: 2 * virtualstudio.uiScale property int boxRadius: 3 * virtualstudio.uiScale - property int boxThickness: 12 * virtualstudio.uiScale + property int boxThickness: 12 required property bool clipped property bool enabled: true property string meterColor: enabled ? (virtualstudio.darkMode ? "#5B5858" : "#D3D4D4") : (virtualstudio.darkMode ? "#7b7979" : "#EAECEC") diff --git a/src/gui/Recommendations.qml b/src/gui/Recommendations.qml index b0bf039..f6a3123 100644 --- a/src/gui/Recommendations.qml +++ b/src/gui/Recommendations.qml @@ -68,7 +68,7 @@ Item { anchors.rightMargin: 32 * virtualstudio.uiScale anchors.verticalCenter: parent.verticalCenter } - + Text { id: gettingStartedText2 visible: recommendationScreen === "fiber" @@ -449,7 +449,7 @@ Item { Item { id: acknowledgedButtonsContainer - width: 320 + width: 320 * virtualstudio.uiScale anchors.top: acknowledgedSubheader.bottom anchors.topMargin: 64 * virtualstudio.uiScale @@ -493,7 +493,6 @@ Item { } } - Button { id: acknowledgedNoButton anchors.right: parent.right diff --git a/src/gui/Settings.qml b/src/gui/Settings.qml index 312f568..0831e01 100644 --- a/src/gui/Settings.qml +++ b/src/gui/Settings.qml @@ -464,7 +464,6 @@ Item { audio.restartAudio(); } font.family: "Poppins" - enabled: audio.audioBackend != "JACK" } Text { @@ -472,7 +471,6 @@ Item { x: 48 * virtualstudio.uiScale text: "Buffer Size" font { family: "Poppins"; pixelSize: fontMedium * virtualstudio.fontScale * virtualstudio.uiScale } - visible: audio.audioBackend != "JACK" color: textColour } diff --git a/src/gui/VolumeSlider.qml b/src/gui/VolumeSlider.qml index b076199..1f2a467 100644 --- a/src/gui/VolumeSlider.qml +++ b/src/gui/VolumeSlider.qml @@ -46,8 +46,8 @@ Item { anchors.left: showLabel ? tooltip.right : parent.left anchors.leftMargin: showLabel ? 8 * virtualstudio.uiScale : 0 anchors.verticalCenter: label.verticalCenter - width: 16 * virtualstudio.uiScale - height: 16 * virtualstudio.uiScale + width: 16 + height: 16 icon.source: "quiet.svg" color: iconColor } @@ -56,8 +56,8 @@ Item { id: louderIcon anchors.right: parent.right anchors.verticalCenter: label.verticalCenter - width: 18 * virtualstudio.uiScale - height: 18 * virtualstudio.uiScale + width: 18 + height: 18 icon.source: "loud.svg" color: iconColor } @@ -110,8 +110,8 @@ Item { handle: Rectangle { x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width) y: slider.topPadding + slider.availableHeight / 2 - height / 2 - implicitWidth: 20 * virtualstudio.uiScale - implicitHeight: 20 * virtualstudio.uiScale + implicitWidth: 18 * virtualstudio.uiScale + implicitHeight: 18 * virtualstudio.uiScale radius: implicitWidth / 2 color: slider.pressed ? sliderPressedColour : "white" border.width: 3 diff --git a/src/gui/qjacktrip.cpp b/src/gui/qjacktrip.cpp index 86b6ee4..0cfbabe 100644 --- a/src/gui/qjacktrip.cpp +++ b/src/gui/qjacktrip.cpp @@ -930,11 +930,11 @@ void QJackTrip::start() #ifdef RT_AUDIO if (m_ui->backendComboBox->currentIndex() == 1) { + unsigned int bufferSize = m_ui->bufferSizeComboBox->currentText().toInt(); + unsigned int sampleRate = m_ui->sampleRateComboBox->currentText().toInt(); m_jackTrip->setAudiointerfaceMode(JackTrip::RTAUDIO); - m_jackTrip->setSampleRate( - m_ui->sampleRateComboBox->currentText().toInt()); - m_jackTrip->setAudioBufferSizeInSamples( - m_ui->bufferSizeComboBox->currentText().toInt()); + m_jackTrip->setSampleRate(sampleRate); + m_jackTrip->setAudioBufferSizeInSamples(bufferSize); // we assume that first entry is "(default)" if (m_ui->inputDeviceComboBox->currentIndex() == 0) { m_jackTrip->setInputDevice(""); @@ -948,6 +948,7 @@ void QJackTrip::start() m_jackTrip->setOutputDevice( m_ui->outputDeviceComboBox->currentText().toStdString()); } + AudioInterface::setPipewireLatency(bufferSize, sampleRate); } #endif diff --git a/src/gui/virtualstudio.cpp b/src/gui/virtualstudio.cpp index 0da9a3b..a1fd472 100644 --- a/src/gui/virtualstudio.cpp +++ b/src/gui/virtualstudio.cpp @@ -496,7 +496,6 @@ void VirtualStudio::setTestMode(bool test) m_devicePtr->disconnect(); m_devicePtr.reset(); } - m_webChannelServer->close(); m_testMode = test; @@ -512,6 +511,9 @@ void VirtualStudio::setTestMode(bool test) settings.remove(QStringLiteral("UserId")); settings.endGroup(); + // stop timers, clear data, etc. + resetState(); + // clear user data m_userMetadata = QJsonObject(); m_userId.clear(); @@ -621,9 +623,10 @@ void VirtualStudio::toStandard() m_uiMode = QJackTrip::STANDARD; settings.setValue(QStringLiteral("UiMode"), m_uiMode); - m_webChannelServer->close(); - m_refreshTimer.stop(); - m_heartbeatTimer.stop(); + // stop timers, clear data, etc. + resetState(); + setWindowState(QStringLiteral("start")); + m_auth->logout(); if (m_showFirstRun) { m_showFirstRun = false; @@ -663,8 +666,6 @@ void VirtualStudio::logout() m_devicePtr.reset(); } - m_webChannelServer->close(); - QUrl logoutURL = QUrl("https://auth.jacktrip.org/v2/logout"); QUrlQuery query; query.addQueryItem(QStringLiteral("client_id"), AUTH_CLIENT_ID); @@ -687,6 +688,9 @@ void VirtualStudio::logout() settings.remove(QStringLiteral("UserId")); settings.endGroup(); + // stop timers, clear data, etc. + resetState(); + // clear user data m_refreshToken.clear(); m_userMetadata = QJsonObject(); @@ -1081,10 +1085,9 @@ void VirtualStudio::exit() m_isExiting = true; emit isExitingChanged(); - m_startTimer.stop(); - m_refreshTimer.stop(); - m_heartbeatTimer.stop(); - m_networkOutageTimer.stop(); + // stop timers, clear data, etc. + resetState(); + if (m_onConnectedScreen) { // manually disconnect on self-managed studios if (!m_currentStudio.id().isEmpty() && !m_currentStudio.isManaged()) { @@ -1236,8 +1239,6 @@ void VirtualStudio::processError(const QString& errorMessage) } msgBox.exec(); - if (shouldSwitchToRtAudio) - m_audioConfigPtr->setAudioBackend("RtAudio"); if (m_jackTripRunning) connectionFinished(); } @@ -1331,6 +1332,16 @@ void VirtualStudio::sendHeartbeat() } } +void VirtualStudio::resetState() +{ + m_webChannelServer->close(); + m_refreshTimer.stop(); + m_heartbeatTimer.stop(); + m_startTimer.stop(); + m_networkOutageTimer.stop(); + m_firstRefresh = true; +} + void VirtualStudio::getServerList(bool signalRefresh, int index) { QMutexLocker refreshLock(&m_refreshMutex); @@ -1518,6 +1529,10 @@ void VirtualStudio::getServerList(bool signalRefresh, int index) void VirtualStudio::getSubscriptions() { + if (m_userId.isEmpty()) { + qDebug() << "Invalid user ID"; + return; + } QNetworkReply* reply = m_api->getSubscriptions(m_userId); connect(reply, &QNetworkReply::finished, this, [&, reply]() { if (reply->error() != QNetworkReply::NoError) { diff --git a/src/gui/virtualstudio.h b/src/gui/virtualstudio.h index e5b1ab2..076fa3c 100644 --- a/src/gui/virtualstudio.h +++ b/src/gui/virtualstudio.h @@ -256,6 +256,7 @@ class VirtualStudio : public QObject void exit(); private: + void resetState(); void getServerList(bool signalRefresh = false, int index = -1); void getSubscriptions(); void getRegions(); diff --git a/src/gui/vsApi.cpp b/src/gui/vsApi.cpp index a177e8f..2a50de2 100644 --- a/src/gui/vsApi.cpp +++ b/src/gui/vsApi.cpp @@ -37,6 +37,8 @@ #include "vsApi.h" +#include "../jacktrip_globals.h" + VsApi::VsApi(QNetworkAccessManager* networkAccessManager) { m_networkAccessManager = networkAccessManager; @@ -112,6 +114,8 @@ QNetworkReply* VsApi::deleteDevice(const QString& deviceId) QNetworkReply* VsApi::get(const QUrl& url) { QNetworkRequest request = QNetworkRequest(url); + request.setRawHeader(QByteArray("User-Agent"), + QString("JackTrip/%1 (Qt)").arg(gVersion).toUtf8()); request.setRawHeader(QByteArray("Authorization"), QString("Bearer %1").arg(m_accessToken).toUtf8()); @@ -122,6 +126,8 @@ QNetworkReply* VsApi::get(const QUrl& url) QNetworkReply* VsApi::post(const QUrl& url, const QByteArray& data) { QNetworkRequest request = QNetworkRequest(url); + request.setRawHeader(QByteArray("User-Agent"), + QString("JackTrip/%1 (Qt)").arg(gVersion).toUtf8()); request.setRawHeader(QByteArray("Authorization"), QString("Bearer %1").arg(m_accessToken).toUtf8()); request.setRawHeader(QByteArray("Content-Type"), @@ -134,6 +140,8 @@ QNetworkReply* VsApi::post(const QUrl& url, const QByteArray& data) QNetworkReply* VsApi::put(const QUrl& url, const QByteArray& data) { QNetworkRequest request = QNetworkRequest(url); + request.setRawHeader(QByteArray("User-Agent"), + QString("JackTrip/%1 (Qt)").arg(gVersion).toUtf8()); request.setRawHeader(QByteArray("Authorization"), QString("Bearer %1").arg(m_accessToken).toUtf8()); request.setRawHeader(QByteArray("Content-Type"), @@ -145,6 +153,8 @@ QNetworkReply* VsApi::put(const QUrl& url, const QByteArray& data) QNetworkReply* VsApi::deleteResource(const QUrl& url) { QNetworkRequest request = QNetworkRequest(url); + request.setRawHeader(QByteArray("User-Agent"), + QString("JackTrip/%1 (Qt)").arg(gVersion).toUtf8()); request.setRawHeader(QByteArray("Authorization"), QString("Bearer %1").arg(m_accessToken).toUtf8()); diff --git a/src/gui/vsAudio.cpp b/src/gui/vsAudio.cpp index f108747..4227ac4 100644 --- a/src/gui/vsAudio.cpp +++ b/src/gui/vsAudio.cpp @@ -236,7 +236,6 @@ void VsAudio::setAudioBackend(const QString& backend) if (getUseRtAudio()) return; m_backend = AudioBackendType::RTAUDIO; - refreshDevices(); } else { if (!getUseRtAudio()) return; @@ -253,7 +252,7 @@ void VsAudio::setFeedbackDetectionEnabled(bool enabled) emit feedbackDetectionEnabledChanged(); } -void VsAudio::setBufferSize([[maybe_unused]] int bufSize) +void VsAudio::setBufferSize(int bufSize) { if (m_audioBufferSize == bufSize) return; @@ -790,6 +789,10 @@ AudioInterface* VsAudio::newAudioInterface(JackTrip* jackTripPtr) { AudioInterface* ifPtr = nullptr; +#if defined(__unix__) + AudioInterface::setPipewireLatency(getBufferSize(), m_sampleRate); +#endif + // Create AudioInterface Client Object if (isBackendAvailable() && jackIsAvailable()) { // all backends area available @@ -860,9 +863,9 @@ AudioInterface* VsAudio::newAudioInterface(JackTrip* jackTripPtr) AudioInterface* VsAudio::newJackAudioInterface([[maybe_unused]] JackTrip* jackTripPtr) { - static const int numJackChannels = 2; - AudioInterface* ifPtr = nullptr; + AudioInterface* ifPtr = nullptr; #ifndef NO_JACK + static const int numJackChannels = 2; if constexpr (isBackendAvailable() || isBackendAvailable()) { QVarLengthArray inputChans; @@ -970,6 +973,7 @@ void VsAudioWorker::openAudioInterface() updateDeviceModels(); } else { m_parentPtr->setAudioBackend("RtAudio"); + updateDeviceModels(); } } #endif @@ -984,20 +988,13 @@ void VsAudioWorker::openAudioInterface() } if (m_audioInterfacePtr.isNull()) { - emit signalError(QStringLiteral("Failed to initialize audio interface")); return; } // initialize plugins and start the audio callback process m_audioInterfacePtr->initPlugins(false); m_audioInterfacePtr->startProcess(); - - if (m_parentPtr->m_backend == VsAudio::AudioBackendType::JACK) { - // this crashes on windows -#ifndef _WIN32 - m_audioInterfacePtr->connectDefaultPorts(); -#endif - } + m_audioInterfacePtr->connectDefaultPorts(); m_parentPtr->updateDeviceMessages(*m_audioInterfacePtr); m_parentPtr->setAudioReady(true); @@ -1115,24 +1112,29 @@ void VsAudioWorker::getDeviceList(const QVector& devices, channels.append(devices[n].outputChannels); } -#ifdef _WIN32 switch (devices[n].api) { case RtAudio::WINDOWS_ASIO: categories.append("Low-Latency (ASIO)"); break; case RtAudio::WINDOWS_WASAPI: - categories.append("High-Latency (Non-ASIO)"); + categories.append("High-Latency (WASAPI)"); break; case RtAudio::WINDOWS_DS: - categories.append("High-Latency (Non-ASIO)"); + categories.append("High-Latency (DirectSound)"); + break; + case RtAudio::LINUX_ALSA: + categories.append("Low-Latency (ALSA)"); + break; + case RtAudio::LINUX_PULSE: + categories.append("High-Latency (Pulse)"); + break; + case RtAudio::LINUX_OSS: + categories.append("High-Latency (OSS)"); break; default: categories.append(""); break; } -#else - categories.append(""); -#endif } } diff --git a/src/gui/vsPinger.cpp b/src/gui/vsPinger.cpp index 8e30df3..95207b6 100644 --- a/src/gui/vsPinger.cpp +++ b/src/gui/vsPinger.cpp @@ -58,8 +58,14 @@ VsPinger::VsPinger(QString scheme, QString host, QString path) connect(&mSocket, &QWebSocket::binaryMessageReceived, this, &VsPinger::onReceivePingMessage); connect(&mSocket, &QWebSocket::connected, this, &VsPinger::onConnected); +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + connect(&mSocket, + QOverload::of(&QWebSocket::errorOccurred), this, + &VsPinger::onError); +#else connect(&mSocket, QOverload::of(&QWebSocket::error), this, &VsPinger::onError); +#endif connect(&mTimer, &QTimer::timeout, this, &VsPinger::onPingTimer); } diff --git a/src/gui/vsWebSocket.cpp b/src/gui/vsWebSocket.cpp index d217cc8..87c9ab0 100644 --- a/src/gui/vsWebSocket.cpp +++ b/src/gui/vsWebSocket.cpp @@ -55,9 +55,15 @@ VsWebSocket::VsWebSocket(const QUrl& url, QString token, QString apiPrefix, connect(m_webSocket.get(), QOverload&>::of(&QWebSocket::sslErrors), this, &VsWebSocket::onSslErrors); +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + connect(m_webSocket.get(), + QOverload::of(&QWebSocket::errorOccurred), this, + &VsWebSocket::onError); +#else connect(m_webSocket.get(), QOverload::of(&QWebSocket::error), this, &VsWebSocket::onError); +#endif connect(m_webSocket.get(), &QWebSocket::textMessageReceived, this, &VsWebSocket::textMessageReceived); } diff --git a/src/jacktrip_globals.h b/src/jacktrip_globals.h index 8cee252..16bad7b 100644 --- a/src/jacktrip_globals.h +++ b/src/jacktrip_globals.h @@ -40,7 +40,7 @@ #include "AudioInterface.h" -constexpr const char* const gVersion = "2.0.1"; ///< JackTrip version +constexpr const char* const gVersion = "2.0.2"; ///< JackTrip version //******************************************************************************* /// \name Default Values