From befa4a2635d2a1660f8b68c0b920483698f04c52 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 17 Dec 2025 17:01:23 +0100 Subject: [PATCH] Add support of Jabra headsets via the hidapi library. --- Linphone/core/call/CallCore.cpp | 42 ++++++++++++++++++++++++++++++- Linphone/model/call/CallModel.cpp | 26 ++++++++++++++++++- Linphone/model/call/CallModel.hpp | 14 ++++++++++- external/linphone-sdk | 2 +- 4 files changed, 80 insertions(+), 4 deletions(-) diff --git a/Linphone/core/call/CallCore.cpp b/Linphone/core/call/CallCore.cpp index c27edab10..9aed9f56e 100644 --- a/Linphone/core/call/CallCore.cpp +++ b/Linphone/core/call/CallCore.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2024 Belledonne Communications SARL. + * Copyright (c) 2010-2026 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -28,6 +28,8 @@ #include "tool/Utils.hpp" #include "tool/thread/SafeConnection.hpp" +#include + DEFINE_ABSTRACT_OBJECT(CallCore) /***********************************************************************/ @@ -449,6 +451,44 @@ void CallCore::setSelf(QSharedPointer me) { setVideoStats(videoStats); } }); + + mCallModelConnection->makeConnectToModel(&CallModel::headsetAnswerCallRequested, [this]() { + mCallModelConnection->invokeToCore([this]() { + const auto callList = App::getInstance()->getCallList(); + const auto currentPendingCall = callList->getFirstIncommingPendingCall(); + if (!currentPendingCall.isNull()) { + const auto gui = new CallGui(currentPendingCall); + Utils::openCallsWindow(gui); + currentPendingCall->lAccept(false); + } + }); + }); + mCallModelConnection->makeConnectToModel(&CallModel::headsetEndCallRequested, [this]() { + mCallModelConnection->invokeToCore([this]() { + const auto window = Utils::getOrCreateCallsWindow(); + window->setProperty("callTerminatedByUser", true); + lTerminate(); + }); + }); + mCallModelConnection->makeConnectToModel(&CallModel::headsetHoldCallRequested, [this]() { + mCallModelConnection->invokeToCore([this]() { lSetPaused(true); }); + }); + mCallModelConnection->makeConnectToModel(&CallModel::headsetMicrophoneMuteToggled, [this](bool mute) { + mCallModelConnection->invokeToCore([this, mute]() { lSetMicrophoneMuted(mute); }); + }); + mCallModelConnection->makeConnectToModel(&CallModel::headsetRejectCallRequested, [this]() { + mCallModelConnection->invokeToCore([this]() { + const auto callList = App::getInstance()->getCallList(); + const auto currentPendingCall = callList->getFirstIncommingPendingCall(); + if (!currentPendingCall.isNull()) { + currentPendingCall->lDecline(); + } + }); + }); + mCallModelConnection->makeConnectToModel(&CallModel::headsetResumeCallRequested, [this]() { + mCallModelConnection->invokeToCore([this]() { lSetPaused(false); }); + }); + if (mShouldFindRemoteFriend) findRemoteFriend(me); } diff --git a/Linphone/model/call/CallModel.cpp b/Linphone/model/call/CallModel.cpp index b6c05cf6d..5e906d3be 100644 --- a/Linphone/model/call/CallModel.cpp +++ b/Linphone/model/call/CallModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2024 Belledonne Communications SARL. + * Copyright (c) 2010-2026 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -529,3 +529,27 @@ void CallModel::onRemoteRecording(const std::shared_ptr &call, b void CallModel::onAuthenticationTokenVerified(const std::shared_ptr &call, bool verified) { emit authenticationTokenVerified(call, verified); } + +void CallModel::onHeadsetAnswerCallRequested(const std::shared_ptr &call) { + emit headsetAnswerCallRequested(); +} + +void CallModel::onHeadsetEndCallRequested(const std::shared_ptr &call) { + emit headsetEndCallRequested(); +} + +void CallModel::onHeadsetHoldCallRequested(const std::shared_ptr &call) { + emit headsetHoldCallRequested(); +} + +void CallModel::onHeadsetMicrophoneMuteToggled(const std::shared_ptr &call, bool mute) { + emit headsetMicrophoneMuteToggled(mute); +} + +void CallModel::onHeadsetRejectCallRequested(const std::shared_ptr &call) { + emit headsetRejectCallRequested(); +} + +void CallModel::onHeadsetResumeCallRequested(const std::shared_ptr &call) { + emit headsetResumeCallRequested(); +} \ No newline at end of file diff --git a/Linphone/model/call/CallModel.hpp b/Linphone/model/call/CallModel.hpp index db5c04abe..f9549b442 100644 --- a/Linphone/model/call/CallModel.hpp +++ b/Linphone/model/call/CallModel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2024 Belledonne Communications SARL. + * Copyright (c) 2010-2026 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -156,6 +156,12 @@ private: const std::shared_ptr &audioDevice) override; virtual void onRemoteRecording(const std::shared_ptr &call, bool recording) override; virtual void onAuthenticationTokenVerified(const std::shared_ptr &call, bool verified) override; + virtual void onHeadsetAnswerCallRequested(const std::shared_ptr &call) override; + virtual void onHeadsetEndCallRequested(const std::shared_ptr &call) override; + virtual void onHeadsetHoldCallRequested(const std::shared_ptr &call) override; + virtual void onHeadsetMicrophoneMuteToggled(const std::shared_ptr &call, bool mute) override; + virtual void onHeadsetRejectCallRequested(const std::shared_ptr &call) override; + virtual void onHeadsetResumeCallRequested(const std::shared_ptr &call) override; signals: void dtmfReceived(const std::shared_ptr &call, int dtmf); @@ -185,6 +191,12 @@ signals: const std::shared_ptr &audioDevice); void remoteRecording(const std::shared_ptr &call, bool recording); void authenticationTokenVerified(const std::shared_ptr &call, bool verified); + void headsetAnswerCallRequested(); + void headsetEndCallRequested(); + void headsetHoldCallRequested(); + void headsetMicrophoneMuteToggled(bool mute); + void headsetRejectCallRequested(); + void headsetResumeCallRequested(); }; #endif diff --git a/external/linphone-sdk b/external/linphone-sdk index 48f6fdf27..dc5d0d260 160000 --- a/external/linphone-sdk +++ b/external/linphone-sdk @@ -1 +1 @@ -Subproject commit 48f6fdf27e0810b5b0011aa02d41b95da0ae6a56 +Subproject commit dc5d0d260cc5db90dc4d7dcb49780a12aaada33b