mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 03:18:07 +00:00
Feature: Screen Sharing
Avoid to use SCShareableContent API because of crash on release.
This commit is contained in:
parent
559b5b13ea
commit
ca7278d51f
61 changed files with 2560 additions and 1413 deletions
|
|
@ -18,7 +18,7 @@
|
|||
echo $DEFAULT_MACOS_CMAKE_OPTIONS
|
||||
echo $CMAKE_OPTIONS
|
||||
echo $ADDITIONAL_BUILD_OPTIONS
|
||||
cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE $DEFAULT_MACOS_CMAKE_OPTIONS -DLINPHONE_BUILDER_SIGNING_IDENTITY="$MACOS_SIGNING_IDENTITY" $XCODE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $RELEASE_FILE
|
||||
cmake .. -G "$CMAKE_GENERATOR" -DCMAKE_OSX_DEPLOYMENT_TARGET=12.3 -DCMAKE_BUILD_TYPE=$CI_BUILD_TYPE $DEFAULT_MACOS_CMAKE_OPTIONS -DLINPHONE_BUILDER_SIGNING_IDENTITY="$MACOS_SIGNING_IDENTITY" $XCODE_OPTIONS $CMAKE_OPTIONS $SCHEDULE_CMAKE_OPTIONS $RELEASE_FILE
|
||||
cmake --build . --target install --config $CI_BUILD_TYPE $LBC_NODEBUG_OPTIONS -- $ADDITIONAL_BUILD_OPTIONS
|
||||
ccache -s
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ job-macosx-ninja:
|
|||
- schedules
|
||||
variables:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
CMAKE_OPTIONS: -DENABLE_PQCRYPTO=OFF
|
||||
CMAKE_OPTIONS: -DENABLE_PQCRYPTO=ON
|
||||
extends: .job-macosx-desktop
|
||||
|
||||
#################################################
|
||||
|
|
@ -60,7 +60,7 @@ job-macosx-makefile:
|
|||
- $DEPLOY_PLUGINS
|
||||
variables:
|
||||
CMAKE_GENERATOR: Unix Makefiles
|
||||
CMAKE_OPTIONS: -DENABLE_PQCRYPTO=OFF
|
||||
CMAKE_OPTIONS: -DENABLE_PQCRYPTO=ON
|
||||
ADDITIONAL_BUILD_OPTIONS: -j$MAKEFILE_JOBS
|
||||
extends: .job-macosx-desktop
|
||||
|
||||
|
|
@ -69,7 +69,7 @@ job-macosx-ninja-novideo:
|
|||
- !reference [.rules-merge-request-manual, rules]
|
||||
- if: $NIGHTLY_MASTER
|
||||
variables:
|
||||
CMAKE_OPTIONS: -DENABLE_VIDEO=OFF -DENABLE_PQCRYPTO=OFF
|
||||
CMAKE_OPTIONS: -DENABLE_VIDEO=OFF -DENABLE_PQCRYPTO=ON
|
||||
CMAKE_GENERATOR: Ninja
|
||||
extends: .job-macosx-desktop
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ job-macosx-makefile-package:
|
|||
- $PACKAGE_MACOSX
|
||||
- $DEPLOY_MACOSX
|
||||
variables:
|
||||
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=ON -DENABLE_GPL_THIRD_PARTIES=ON -DENABLE_G729=ON
|
||||
CMAKE_OPTIONS: -DENABLE_APP_PACKAGING=ON -DENABLE_GPL_THIRD_PARTIES=ON -DENABLE_G729=ON -DENABLE_PQCRYPTO=ON
|
||||
RELEASE_FILE: -DLINPHONE_SDK_MAKE_RELEASE_FILE_URL=$MAKE_RELEASE_FILE_URL/$MACOSX_PLATFORM/$APP_FOLDER
|
||||
extends: job-macosx-makefile
|
||||
script:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
### Added
|
||||
- '[ui] logs_max_size' : option to set the max size of one log file.
|
||||
- Screen Sharing
|
||||
|
||||
## 5.2.1 - 2024-02-01
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,8 @@ if( APPLE )
|
|||
set(CMAKE_INSTALL_DATAROOTDIR "${APPLICATION_NAME}.app/Contents/Resources/share")
|
||||
|
||||
if( NOT CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")#Qt: 'path' is unavailable: introduced in macOS 10.15
|
||||
#set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15")#Qt: 'path' is unavailable: introduced in macOS 10.15
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "12.3")#ScreenSharing: 'SCStreamConfiguration' has been introduced in macOS 12.3
|
||||
endif()
|
||||
set(LINPHONESDK_MACOS_ARCHS ${LINPHONEAPP_MACOS_ARCHS})
|
||||
set(CMAKE_OSX_ARCHITECTURES ${LINPHONESDK_MACOS_ARCHS} CACHE STRING "")
|
||||
|
|
@ -151,6 +152,7 @@ add_option(OPTION_LIST ENABLE_QT_KEYCHAIN "Build QtKeychain to manage VFS from S
|
|||
add_option(OPTION_LIST ENABLE_QRCODE "Enable QRCode support" OFF)#Experimental
|
||||
add_option(OPTION_LIST ENABLE_RELATIVE_PREFIX "Set Internal packages relative to the binary" ON)
|
||||
add_option(OPTION_LIST ENABLE_SANITIZER "Enable sanitizer." OFF)
|
||||
add_option(OPTION_LIST ENABLE_SCREENSHARING "Enable screen sharing." ON)
|
||||
add_option(OPTION_LIST ENABLE_STRICT "Build with strict compilator flags e.g. -Wall -Werror" OFF)
|
||||
add_option(OPTION_LIST ENABLE_TESTS "Build with testing binaries of SDK" OFF)
|
||||
add_option(OPTION_LIST ENABLE_TESTS_COMPONENTS "Build libbctoolbox-tester" OFF)
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ set(_MACOS_INSTALL_DIR "${APPLICATION_OUTPUT_DIR}/${_MACOS_INSTALL_RELATIVE_DIR}
|
|||
|
||||
#linphone_sdk_get_inherited_cmake_args(_CMAKE_CONFIGURE_ARGS _CMAKE_BUILD_ARGS)
|
||||
#linphone_sdk_get_enable_cmake_args(_MACOS_CMAKE_ARGS)
|
||||
set(_MACOS_CMAKE_ARGS ${CMAKE_OSX_DEPLOYMENT_TARGET})
|
||||
set(_MACOS_CMAKE_ARGS "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
||||
|
||||
set(_MACOS_TARGETS)
|
||||
foreach(_MACOS_ARCH IN LISTS _MACOS_ARCHS)
|
||||
|
|
|
|||
|
|
@ -259,6 +259,7 @@ set(SOURCES
|
|||
src/app/providers/ExternalImageProvider.cpp
|
||||
src/app/providers/QRCodeProvider.cpp
|
||||
src/app/providers/ThumbnailProvider.cpp
|
||||
src/app/providers/ScreenProvider.cpp
|
||||
src/app/proxyModel/ProxyListModel.cpp
|
||||
src/app/proxyModel/SortFilterProxyModel.cpp
|
||||
#src/app/proxyModel/ProxyMapModel.cpp
|
||||
|
|
@ -359,6 +360,8 @@ set(SOURCES
|
|||
src/components/recorder/RecorderModel.cpp
|
||||
src/components/recorder/RecordingListModel.cpp
|
||||
src/components/recorder/RecordingProxyModel.cpp
|
||||
src/components/screen/ScreenListModel.cpp
|
||||
src/components/screen/ScreenProxyModel.cpp
|
||||
src/components/search/SearchListener.cpp
|
||||
src/components/search/SearchResultModel.cpp
|
||||
src/components/search/SearchSipAddressesModel.cpp
|
||||
|
|
@ -380,6 +383,7 @@ set(SOURCES
|
|||
src/components/tunnel/TunnelConfigListModel.cpp
|
||||
src/components/tunnel/TunnelConfigProxyModel.cpp
|
||||
src/components/url-handlers/UrlHandlers.cpp
|
||||
src/components/videoSource/VideoSourceDescriptorModel.cpp
|
||||
src/utils/Constants.cpp
|
||||
src/utils/LinphoneEnums.cpp
|
||||
src/utils/MediastreamerUtils.cpp
|
||||
|
|
@ -404,6 +408,7 @@ set(HEADERS
|
|||
src/app/providers/ExternalImageProvider.hpp
|
||||
src/app/providers/QRCodeProvider.hpp
|
||||
src/app/providers/ThumbnailProvider.hpp
|
||||
src/app/providers/ScreenProvider.hpp
|
||||
src/app/proxyModel/ProxyAbstractListModel.hpp
|
||||
src/app/proxyModel/ProxyAbstractMapModel.hpp
|
||||
src/app/proxyModel/ProxyAbstractObject.hpp
|
||||
|
|
@ -510,6 +515,8 @@ set(HEADERS
|
|||
src/components/recorder/RecorderModel.hpp
|
||||
src/components/recorder/RecordingListModel.hpp
|
||||
src/components/recorder/RecordingProxyModel.hpp
|
||||
src/components/screen/ScreenListModel.hpp
|
||||
src/components/screen/ScreenProxyModel.hpp
|
||||
src/components/search/SearchListener.hpp
|
||||
src/components/search/SearchResultModel.hpp
|
||||
src/components/search/SearchSipAddressesModel.hpp
|
||||
|
|
@ -531,6 +538,7 @@ set(HEADERS
|
|||
src/components/tunnel/TunnelConfigListModel.hpp
|
||||
src/components/tunnel/TunnelConfigProxyModel.hpp
|
||||
src/components/url-handlers/UrlHandlers.hpp
|
||||
src/components/videoSource/VideoSourceDescriptorModel.hpp
|
||||
src/utils/Constants.hpp
|
||||
src/utils/LinphoneEnums.hpp
|
||||
src/utils/MediastreamerUtils.hpp
|
||||
|
|
@ -820,7 +828,7 @@ foreach(T ${APP_TARGETS})
|
|||
endforeach()
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(${TARGET_NAME} "-framework Cocoa" "-framework IOKit" "-framework AVFoundation")
|
||||
target_link_libraries(${TARGET_NAME} "-framework Cocoa" "-framework IOKit" "-framework AVFoundation" "-framework ScreenCaptureKit")
|
||||
endif()
|
||||
target_link_libraries(${TARGET_NAME} ${APP_PLUGIN})
|
||||
|
||||
|
|
@ -830,6 +838,13 @@ if(WIN32 AND ENABLE_LDAP)
|
|||
target_link_libraries(${TARGET_NAME} wsock32 ws2_32 ${OPENLDAP_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package(X11)
|
||||
endif()
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(${TARGET_NAME} X11::X11)
|
||||
endif()
|
||||
|
||||
add_dependencies(${APP_LIBRARY} update_translations ${APP_PLUGIN})
|
||||
# ------------------------------------------------------------------------------
|
||||
# CPack settings & RPM.
|
||||
|
|
|
|||
|
|
@ -432,7 +432,7 @@ if(${ENABLE_APP_PACKAGING})
|
|||
message(FATAL_ERROR "Could not find the macdeployqt program. Make sure it is in the PATH.")
|
||||
endif()
|
||||
endif()
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cleanCpack.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cleanCpack.cmake" @ONLY)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cleanCPack.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cleanCPack.cmake" @ONLY)
|
||||
set(CPACK_PRE_BUILD_SCRIPTS "${CMAKE_CURRENT_BINARY_DIR}/cleanCPack.cmake")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include "providers/ExternalImageProvider.hpp"
|
||||
#include "providers/QRCodeProvider.hpp"
|
||||
#include "providers/ThumbnailProvider.hpp"
|
||||
#include "providers/ScreenProvider.hpp"
|
||||
#include "translator/DefaultTranslator.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
#include "utils/Constants.hpp"
|
||||
|
|
@ -57,6 +58,7 @@
|
|||
#include "components/other/date/DateModel.hpp"
|
||||
#include "components/other/spell-checker/SpellChecker.hpp"
|
||||
|
||||
#include "components/screen/ScreenProxyModel.hpp"
|
||||
#include "components/settings/EmojisSettingsModel.hpp"
|
||||
#include "components/timeline/TimelineModel.hpp"
|
||||
#include "components/timeline/TimelineListModel.hpp"
|
||||
|
|
@ -66,6 +68,8 @@
|
|||
#include "components/participant/ParticipantListModel.hpp"
|
||||
#include "components/participant/ParticipantProxyModel.hpp"
|
||||
|
||||
#include "components/videoSource/VideoSourceDescriptorModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
using namespace std;
|
||||
|
|
@ -268,6 +272,7 @@ App::App (int &argc, char *argv[]) : SingleApplication(argc, argv, true, Mode::U
|
|||
_putenv(("TZ="+QTimeZone::systemTimeZoneId().toStdString()).c_str());
|
||||
_tzset();
|
||||
#else
|
||||
QString t = QTimeZone::systemTimeZoneId();
|
||||
setenv("TZ", QTimeZone::systemTimeZoneId().toStdString().c_str(), 1);
|
||||
tzset();
|
||||
#endif
|
||||
|
|
@ -489,6 +494,7 @@ void App::initContentApp () {
|
|||
mEngine->addImageProvider(ExternalImageProvider::ProviderId, new ExternalImageProvider());
|
||||
mEngine->addImageProvider(QRCodeProvider::ProviderId, new QRCodeProvider());
|
||||
mEngine->addImageProvider(ThumbnailProvider::ProviderId, new ThumbnailProvider());
|
||||
mEngine->addImageProvider(ScreenProvider::ProviderId, new ScreenProvider());
|
||||
|
||||
mEngine->rootContext()->setContextProperty("applicationName", APPLICATION_NAME);
|
||||
mEngine->rootContext()->setContextProperty("executableName", EXECUTABLE_NAME);
|
||||
|
|
@ -778,6 +784,7 @@ void App::registerTypes () {
|
|||
registerType<SearchSipAddressesProxyModel>("SearchSipAddressesProxyModel");
|
||||
registerType<TemporaryFile>("TemporaryFile");
|
||||
registerType<TimeZoneProxyModel>("TimeZoneProxyModel");
|
||||
registerType<VideoSourceDescriptorModel>("VideoSourceDescriptorModel");
|
||||
|
||||
registerType<CallHistoryProxyModel>("CallHistoryProxyModel");
|
||||
registerType<ColorProxyModel>("ColorProxyModel");
|
||||
|
|
@ -788,6 +795,7 @@ void App::registerTypes () {
|
|||
registerType<ParticipantDeviceProxyModel>("ParticipantDeviceProxyModel");
|
||||
registerType<SoundPlayer>("SoundPlayer");
|
||||
registerType<TelephoneNumbersModel>("TelephoneNumbersModel");
|
||||
registerType<ScreenProxyModel>("ScreenProxyModel");
|
||||
registerType<SpellChecker>("SpellChecker");
|
||||
|
||||
registerSingletonType<AudioCodecsModel>("AudioCodecsModel");
|
||||
|
|
|
|||
43
linphone-app/src/app/providers/ScreenProvider.cpp
Normal file
43
linphone-app/src/app/providers/ScreenProvider.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScreenProvider.hpp"
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
const QString ScreenProvider::ProviderId = "screen";
|
||||
|
||||
ScreenProvider::ScreenProvider () : QQuickImageProvider(
|
||||
QQmlImageProviderBase::Image,
|
||||
QQmlImageProviderBase::ForceAsynchronousImageLoading
|
||||
) {}
|
||||
|
||||
QImage ScreenProvider::requestImage (const QString &id, QSize *size, const QSize &) {
|
||||
int index = id.toInt();
|
||||
auto screens = QGuiApplication::screens();
|
||||
if(index >= 0 && index < screens.size()){
|
||||
auto image = screens[index]->grabWindow(0);
|
||||
*size = image.size();
|
||||
return image.toImage();
|
||||
}else
|
||||
return QImage();
|
||||
}
|
||||
37
linphone-app/src/app/providers/ScreenProvider.hpp
Normal file
37
linphone-app/src/app/providers/ScreenProvider.hpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCREEN_PROVIDER_H_
|
||||
#define SCREEN_PROVIDER_H_
|
||||
|
||||
#include <QQuickImageProvider>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class ScreenProvider : public QQuickImageProvider {
|
||||
public:
|
||||
ScreenProvider ();
|
||||
|
||||
QImage requestImage (const QString &id, QSize *size, const QSize &requestedSize) override;
|
||||
|
||||
static const QString ProviderId;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -315,8 +315,8 @@ bool SingleApplicationPrivate::writeConfirmedFrame( int msecs, const QByteArray
|
|||
{
|
||||
socket->write( msg );
|
||||
socket->flush();
|
||||
|
||||
bool result = socket->waitForReadyRead( msecs < 0 ? -1 : msecs ); // await ack byte
|
||||
|
||||
bool result = socket->waitForReadyRead( msecs < 0 ? -1 : msecs ); // await ack byte
|
||||
if (result) {
|
||||
socket->read( 1 );
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -37,4 +37,4 @@ CallListener::CallListener(QObject* parent) : QObject(parent){
|
|||
void CallListener::onRemoteRecording(const std::shared_ptr<linphone::Call> & call, bool recording){
|
||||
qDebug() << "onRemoteRecording: " << recording;
|
||||
emit remoteRecording(call, recording);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright (c) 2010-2020 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
#include "components/settings/AccountSettingsModel.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "components/timeline/TimelineListModel.hpp"
|
||||
#include "components/videoSource/VideoSourceDescriptorModel.hpp"
|
||||
#include "utils/MediastreamerUtils.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ CallModel::CallModel (shared_ptr<linphone::Call> call){
|
|||
connect(this, &CallModel::isPQZrtpChanged, this, &CallModel::securityUpdated);
|
||||
connect(this, &CallModel::securityUpdated, this, &CallModel::onSecurityUpdated);
|
||||
|
||||
|
||||
mCall = call;
|
||||
if(mCall)
|
||||
mCall->setData("call-model", *this);
|
||||
|
|
@ -120,12 +122,14 @@ CallModel::CallModel (shared_ptr<linphone::Call> call){
|
|||
if(mCall->getConference()) {
|
||||
mConferenceModel = ConferenceModel::create(mCall->getConference());
|
||||
connect(mConferenceModel.get(), &ConferenceModel::participantAdminStatusChanged, this, &CallModel::onParticipantAdminStatusChanged);
|
||||
connect(mConferenceModel.get(), &ConferenceModel::localScreenSharingChanged, this, &CallModel::onLocalScreenSharingChanged);
|
||||
}
|
||||
auto conferenceInfo = CoreManager::getInstance()->getCore()->findConferenceInformationFromUri(getConferenceAddress());
|
||||
if( conferenceInfo ){
|
||||
mConferenceInfoModel = ConferenceInfoModel::create(conferenceInfo);
|
||||
}
|
||||
mMagicSearch->getContactsListAsync(mRemoteAddress->getUsername(),mRemoteAddress->getDomain(), (int)linphone::MagicSearch::Source::LdapServers | (int)linphone::MagicSearch::Source::Friends, linphone::MagicSearch::Aggregation::Friend);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -248,6 +252,7 @@ QSharedPointer<ConferenceModel> CallModel::getConferenceSharedModel(){
|
|||
if(mCall->getState() != linphone::Call::State::End && mCall->getConference() && !mConferenceModel){
|
||||
mConferenceModel = ConferenceModel::create(mCall->getConference());
|
||||
connect(mConferenceModel.get(), &ConferenceModel::participantAdminStatusChanged, this, &CallModel::onParticipantAdminStatusChanged);
|
||||
connect(mConferenceModel.get(), &ConferenceModel::localScreenSharingChanged, this, &CallModel::onLocalScreenSharingChanged);
|
||||
emit conferenceModelChanged();
|
||||
}
|
||||
return mConferenceModel;
|
||||
|
|
@ -570,7 +575,6 @@ void CallModel::handleCallStateChanged (const shared_ptr<linphone::Call> &call,
|
|||
case linphone::Call::State::PushIncomingReceived:
|
||||
break;
|
||||
}
|
||||
|
||||
emit statusChanged(getStatus());
|
||||
}
|
||||
|
||||
|
|
@ -1031,6 +1035,12 @@ void CallModel::onSecurityUpdated(){
|
|||
model->updateSecurityLevel();
|
||||
}
|
||||
|
||||
void CallModel::onLocalScreenSharingChanged(bool enabled) {
|
||||
qDebug() << "onLocalScreenSharingChanged" << enabled;
|
||||
if(!enabled)
|
||||
setVideoSource(nullptr);
|
||||
}
|
||||
|
||||
void CallModel::setRemoteDisplayName(const std::string& name){
|
||||
mRemoteAddress->setDisplayName(name);
|
||||
if(mCall) {
|
||||
|
|
@ -1081,6 +1091,9 @@ void CallModel::changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layo
|
|||
shared_ptr<linphone::CallParams> params = coreManager->getCore()->createCallParams(mCall);
|
||||
params->setConferenceVideoLayout(LinphoneEnums::toLinphone(layout));
|
||||
params->enableVideo(layout != LinphoneEnums::ConferenceLayoutAudioOnly);
|
||||
if (!params->videoEnabled() && params->screenSharingEnabled()) {
|
||||
params->enableScreenSharing(false); // Deactivate screensharing if going to audio only.
|
||||
}
|
||||
mCall->update(params);
|
||||
}
|
||||
|
||||
|
|
@ -1105,6 +1118,45 @@ void CallModel::updateConferenceVideoLayout(){
|
|||
}
|
||||
}
|
||||
|
||||
void CallModel::setVideoSource(std::shared_ptr<linphone::VideoSourceDescriptor> videoDesc){
|
||||
//auto videoSource = mCall->getVideoSource();
|
||||
//if(!videoDesc) {
|
||||
// auto oldDesc = linphone::Factory::get()->createVideoSourceDescriptor();
|
||||
// oldDesc->setCameraId(CoreManager::getInstance()->getCore()->getVideoDevice());
|
||||
// mCall->setVideoSource(oldDesc);
|
||||
// mCall->setVideoSource(videoDesc);
|
||||
//}else
|
||||
mCall->setVideoSource(videoDesc);
|
||||
|
||||
emit videoDescriptorChanged();
|
||||
}
|
||||
|
||||
LinphoneEnums::VideoSourceScreenSharingType CallModel::getVideoSourceType() const{
|
||||
auto videoSource = mCall->getVideoSource();
|
||||
return LinphoneEnums::fromLinphone(videoSource ? videoSource->getScreenSharingType() : linphone::VideoSourceScreenSharingType::Display);
|
||||
}
|
||||
int CallModel::getScreenSharingIndex() const{
|
||||
auto videoSource = mCall->getVideoSource();
|
||||
if(videoSource && videoSource->getScreenSharingType() == linphone::VideoSourceScreenSharingType::Display) {
|
||||
void * t = videoSource->getScreenSharing();
|
||||
return *(int*)(&t);
|
||||
}else
|
||||
return -1;
|
||||
}
|
||||
|
||||
VideoSourceDescriptorModel *CallModel::getVideoSourceDescriptorModel() const {
|
||||
auto videoSource = mCall->getVideoSource();
|
||||
return new VideoSourceDescriptorModel(videoSource ? videoSource->clone() : nullptr);
|
||||
}
|
||||
|
||||
void CallModel::setVideoSourceDescriptorModel(VideoSourceDescriptorModel *model) {
|
||||
if(model)
|
||||
setVideoSource(model->mDesc);
|
||||
else {
|
||||
setVideoSource(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
CallModel::CallEncryption CallModel::getEncryption () const {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class ConferenceInfoModel;
|
|||
class ConferenceModel;
|
||||
class ContactModel;
|
||||
class ChatRoomModel;
|
||||
class VideoSourceDescriptorModel;
|
||||
|
||||
class CallModel : public QObject {
|
||||
Q_OBJECT
|
||||
|
|
@ -97,7 +98,9 @@ class CallModel : public QObject {
|
|||
|
||||
Q_PROPERTY(LinphoneEnums::ConferenceLayout conferenceVideoLayout READ getConferenceVideoLayout WRITE changeConferenceVideoLayout NOTIFY conferenceVideoLayoutChanged)
|
||||
|
||||
|
||||
Q_PROPERTY(LinphoneEnums::VideoSourceScreenSharingType screenSharingType READ getVideoSourceType NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(bool screenSharingIndex READ getScreenSharingIndex NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(VideoSourceDescriptorModel *videoSourceDescriptorModel READ getVideoSourceDescriptorModel WRITE setVideoSourceDescriptorModel NOTIFY videoDescriptorChanged)
|
||||
|
||||
public:
|
||||
enum CallStatus {
|
||||
|
|
@ -194,6 +197,13 @@ public:
|
|||
void changeConferenceVideoLayout(LinphoneEnums::ConferenceLayout layout); // Make a call request
|
||||
void updateConferenceVideoLayout(); // Called from call state changed ater the new layout has been set.
|
||||
|
||||
void setVideoSource(std::shared_ptr<linphone::VideoSourceDescriptor> videoDesc);
|
||||
LinphoneEnums::VideoSourceScreenSharingType getVideoSourceType() const;
|
||||
int getScreenSharingIndex() const;
|
||||
Q_INVOKABLE VideoSourceDescriptorModel *getVideoSourceDescriptorModel() const;
|
||||
Q_INVOKABLE void setVideoSourceDescriptorModel(VideoSourceDescriptorModel *model = nullptr);
|
||||
|
||||
|
||||
static constexpr int DtmfSoundDelay = 200;
|
||||
|
||||
std::shared_ptr<linphone::Call> mCall;
|
||||
|
|
@ -210,6 +220,7 @@ public slots:
|
|||
void onChatRoomInitialized(int state);
|
||||
void onParticipantAdminStatusChanged(const std::shared_ptr<const linphone::Participant> & participant);
|
||||
void onSecurityUpdated();
|
||||
void onLocalScreenSharingChanged(bool enabled);
|
||||
|
||||
signals:
|
||||
void meAdminChanged();
|
||||
|
|
@ -241,8 +252,7 @@ signals:
|
|||
void transferAddressChanged (const QString &transferAddress);
|
||||
|
||||
void conferenceVideoLayoutChanged();
|
||||
|
||||
|
||||
void videoDescriptorChanged();
|
||||
public:
|
||||
void handleCallEncryptionChanged (const std::shared_ptr<linphone::Call> &call);
|
||||
void handleCallStateChanged (const std::shared_ptr<linphone::Call> &call, linphone::Call::State state);
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ void Camera::updateWindowIdLocation(){
|
|||
if(mIsPreview)
|
||||
setWindowIdLocation( WindowIdLocation::CorePreview);
|
||||
else{
|
||||
|
||||
if(mCallModel){
|
||||
auto call = mCallModel->getCall();
|
||||
if(call){
|
||||
|
|
@ -180,6 +181,7 @@ void Camera::removeLinphonePlayer(){
|
|||
|
||||
QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
|
||||
QQuickFramebufferObject::Renderer * renderer = NULL;
|
||||
resetWindowId();
|
||||
if(mWindowIdLocation == CorePreview){
|
||||
qInfo() << "[Camera] (" << mQmlName << ") Setting Camera to Preview";
|
||||
renderer=(QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->createNativePreviewWindowId();
|
||||
|
|
@ -334,8 +336,10 @@ void Camera::isNotReady(){
|
|||
|
||||
void Camera::activatePreview(){
|
||||
mPreviewCounterMutex.lock();
|
||||
if (++mPreviewCounter == 1)
|
||||
if (++mPreviewCounter == 1) {
|
||||
CoreManager::getInstance()->getCore()->enableVideoPreview(true);
|
||||
CoreManager::getInstance()->getSettingsModel()->setCaptureWindowId();
|
||||
}
|
||||
mPreviewCounterMutex.unlock();
|
||||
}
|
||||
|
||||
|
|
@ -355,4 +359,4 @@ void Camera::onCallStateChanged(){
|
|||
disconnect(mCallModel, &CallModel::statusChanged, this, &Camera::onCallStateChanged);
|
||||
mCallModel = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ void ConferenceListener::onActiveSpeakerParticipantDevice(const std::shared_ptr<
|
|||
emit activeSpeakerParticipantDevice(participantDevice);
|
||||
}
|
||||
|
||||
void ConferenceListener::onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant){
|
||||
void ConferenceListener::onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<linphone::Participant> & participant){
|
||||
qDebug() << "onParticipantAdded: " << participant->getAddress()->asString().c_str();
|
||||
emit participantAdded(participant);
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ void ConferenceListener::onParticipantRemoved(const std::shared_ptr<linphone::Co
|
|||
qDebug() << "onParticipantRemoved";
|
||||
emit participantRemoved(participant);
|
||||
}
|
||||
void ConferenceListener::onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
||||
void ConferenceListener::onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<linphone::ParticipantDevice> & participantDevice){
|
||||
qDebug() << "onParticipantDeviceAdded";
|
||||
qDebug() << "Me devices : " << conference->getMe()->getDevices().size();
|
||||
if( conference->getMe()->getDevices().size() > 1)
|
||||
|
|
@ -87,6 +87,10 @@ void ConferenceListener::onParticipantDeviceIsSpeakingChanged(const std::shared_
|
|||
//qDebug() << "onParticipantDeviceIsSpeakingChanged: " << participantDevice->getAddress()->asString().c_str() << ". Speaking:" << isSpeaking;
|
||||
emit participantDeviceIsSpeakingChanged(participantDevice, isSpeaking);
|
||||
}
|
||||
void ConferenceListener::onParticipantDeviceScreenSharingChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device, bool enabled) {
|
||||
qDebug() << "onParticipantDeviceScreenSharingChanged: " << device->getAddress()->asString().c_str() << ". Enabled:" << enabled;
|
||||
emit participantDeviceScreenSharingChanged(device,enabled);
|
||||
}
|
||||
void ConferenceListener::onStateChanged(const std::shared_ptr<linphone::Conference> & conference, linphone::Conference::State newState){
|
||||
qDebug() << "onStateChanged:" << (int)newState;
|
||||
emit conferenceStateChanged(newState);
|
||||
|
|
|
|||
|
|
@ -36,15 +36,16 @@ public:
|
|||
|
||||
// LINPHONE LISTENERS
|
||||
virtual void onActiveSpeakerParticipantDevice(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
|
||||
virtual void onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
|
||||
virtual void onParticipantAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<linphone::Participant> & participant) override;
|
||||
virtual void onParticipantRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
|
||||
virtual void onParticipantAdminStatusChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::Participant> & participant) override;
|
||||
virtual void onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
|
||||
virtual void onParticipantDeviceAdded(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<linphone::ParticipantDevice> & participantDevice) override;
|
||||
virtual void onParticipantDeviceRemoved(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice) override;
|
||||
virtual void onParticipantDeviceStateChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device, linphone::ParticipantDevice::State state) override;
|
||||
virtual void onParticipantDeviceMediaCapabilityChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
|
||||
virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device) override;
|
||||
virtual void onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice, bool isSpeaking) override;
|
||||
virtual void onParticipantDeviceScreenSharingChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device, bool enabled) override;
|
||||
virtual void onStateChanged(const std::shared_ptr<linphone::Conference> & conference, linphone::Conference::State newState) override;
|
||||
virtual void onSubjectChanged(const std::shared_ptr<linphone::Conference> & conference, const std::string & subject) override;
|
||||
virtual void onAudioDeviceChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::AudioDevice> & audioDevice) override;
|
||||
|
|
@ -61,7 +62,9 @@ signals:
|
|||
void participantDeviceMediaCapabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
|
||||
void participantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
|
||||
void participantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice, bool isSpeaking);
|
||||
void participantDeviceScreenSharingChanged( const std::shared_ptr<const linphone::ParticipantDevice> & device, bool enabled);
|
||||
void conferenceStateChanged(linphone::Conference::State newState);
|
||||
|
||||
void subjectChanged(const std::string & subject);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "app/App.hpp"
|
||||
#include "components/participant/ParticipantListModel.hpp"
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "utils/Utils.hpp"
|
||||
|
||||
|
||||
|
|
@ -42,6 +44,7 @@ void ConferenceModel::connectTo(ConferenceListener * listener){
|
|||
connect(listener, &ConferenceListener::participantDeviceMediaCapabilityChanged, this, &ConferenceModel::onParticipantDeviceMediaCapabilityChanged);
|
||||
connect(listener, &ConferenceListener::participantDeviceMediaAvailabilityChanged, this, &ConferenceModel::onParticipantDeviceMediaAvailabilityChanged);
|
||||
connect(listener, &ConferenceListener::participantDeviceIsSpeakingChanged, this, &ConferenceModel::onParticipantDeviceIsSpeakingChanged);
|
||||
connect(listener, &ConferenceListener::participantDeviceScreenSharingChanged, this, &ConferenceModel::onParticipantDeviceScreenSharingChanged);
|
||||
connect(listener, &ConferenceListener::conferenceStateChanged, this, &ConferenceModel::onConferenceStateChanged);
|
||||
connect(listener, &ConferenceListener::subjectChanged, this, &ConferenceModel::onSubjectChanged);
|
||||
}
|
||||
|
|
@ -61,7 +64,9 @@ ConferenceModel::ConferenceModel (std::shared_ptr<linphone::Conference> conferen
|
|||
mConference->addListener(mConferenceListener);
|
||||
connect(this, &ConferenceModel::participantDeviceAdded, this, &ConferenceModel::participantDeviceCountChanged);
|
||||
connect(this, &ConferenceModel::participantDeviceRemoved, this, &ConferenceModel::participantDeviceCountChanged);
|
||||
connect(this, &ConferenceModel::isScreenSharingEnabledChanged, this, &ConferenceModel::onIsScreenSharingEnabledChanged);
|
||||
connect(mParticipantListModel.get(), &ParticipantListModel::participantsChanged, this, &ConferenceModel::participantDeviceCountChanged);
|
||||
connect(this, &ConferenceModel::participantDeviceCountChanged, this, &ConferenceModel::updateLayout);
|
||||
onConferenceStateChanged(mConference->getState());// Is it already Created like for local conference?
|
||||
}
|
||||
|
||||
|
|
@ -87,6 +92,42 @@ bool ConferenceModel::updateLocalParticipant(){
|
|||
return changed;
|
||||
}
|
||||
|
||||
void ConferenceModel::updateLayout(){
|
||||
if(getParticipantDeviceCount() > CoreManager::getInstance()->getSettingsModel()->getConferenceMaxThumbnails()+1) {
|
||||
auto call = mConference->getCall();
|
||||
std::shared_ptr<linphone::CallParams> params = CoreManager::getInstance()->getCore()->createCallParams(call);
|
||||
if( params->getConferenceVideoLayout() == linphone::Conference::Layout::Grid && params->videoEnabled()) {
|
||||
params->setConferenceVideoLayout(linphone::Conference::Layout::ActiveSpeaker);
|
||||
call->update(params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ConferenceModel::toggleScreenSharing() {
|
||||
auto device = mConference->getScreenSharingParticipantDevice();
|
||||
|
||||
if(!device || Utils::isLocal(mConference, device)) {
|
||||
bool enable = !device;
|
||||
auto params = CoreManager::getInstance()->getCore()->createCallParams(mConference->getCall());
|
||||
params->enableScreenSharing(enable);
|
||||
if(enable) {
|
||||
params->setConferenceVideoLayout(linphone::Conference::Layout::ActiveSpeaker);
|
||||
params->enableVideo(true);
|
||||
}
|
||||
if(params->isValid())
|
||||
mConference->getCall()->update(params);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConferenceModel::isLocalScreenSharingEnabled() const{
|
||||
auto device = mConference->getScreenSharingParticipantDevice();
|
||||
return device && Utils::isLocal(mConference, device);
|
||||
}
|
||||
|
||||
bool ConferenceModel::isScreenSharingEnabled() const{
|
||||
return mConference && mConference->getScreenSharingParticipant();
|
||||
}
|
||||
|
||||
std::shared_ptr<linphone::Conference> ConferenceModel::getConference()const{
|
||||
return mConference;
|
||||
}
|
||||
|
|
@ -157,11 +198,14 @@ void ConferenceModel::onParticipantAdminStatusChanged(const std::shared_ptr<cons
|
|||
|
||||
void ConferenceModel::onParticipantDeviceAdded(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
||||
qDebug() << "Me devices : " << mConference->getMe()->getDevices().size();
|
||||
updateLayout();
|
||||
updateLocalParticipant();
|
||||
emit participantDeviceAdded(participantDevice);
|
||||
}
|
||||
void ConferenceModel::onParticipantDeviceRemoved(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
||||
qDebug() << "Me devices : " << mConference->getMe()->getDevices().size();
|
||||
if( participantDevice->screenSharingEnabled())
|
||||
emit isScreenSharingEnabledChanged();
|
||||
emit participantDeviceRemoved(participantDevice);
|
||||
}
|
||||
|
||||
|
|
@ -182,10 +226,21 @@ void ConferenceModel::onParticipantDeviceMediaAvailabilityChanged(const std::sha
|
|||
void ConferenceModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice, bool isSpeaking){
|
||||
emit participantDeviceIsSpeakingChanged(participantDevice, isSpeaking);
|
||||
}
|
||||
void ConferenceModel::onParticipantDeviceScreenSharingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device, bool enabled){
|
||||
emit participantDeviceScreenSharingChanged(device, enabled);
|
||||
if(Utils::isLocal(mConference, device)){
|
||||
emit localScreenSharingChanged(enabled);
|
||||
}
|
||||
emit isScreenSharingEnabledChanged();
|
||||
}
|
||||
|
||||
|
||||
void ConferenceModel::onConferenceStateChanged(linphone::Conference::State newState){
|
||||
if(newState == linphone::Conference::State::Created){
|
||||
setIsReady(true);
|
||||
emit participantDeviceCountChanged();
|
||||
if(mConference->getScreenSharingParticipant())
|
||||
emit isScreenSharingEnabledChanged();
|
||||
}
|
||||
updateLocalParticipant();
|
||||
emit conferenceStateChanged(newState);
|
||||
|
|
@ -193,6 +248,13 @@ void ConferenceModel::onConferenceStateChanged(linphone::Conference::State newSt
|
|||
void ConferenceModel::onSubjectChanged(const std::string& string){
|
||||
emit subjectChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConferenceModel::onIsScreenSharingEnabledChanged(){
|
||||
auto call = mConference->getCall();
|
||||
std::shared_ptr<linphone::CallParams> params = CoreManager::getInstance()->getCore()->createCallParams(call);
|
||||
if(params->getConferenceVideoLayout() == linphone::Conference::Layout::Grid && params->videoEnabled()) {
|
||||
params->setConferenceVideoLayout(linphone::Conference::Layout::ActiveSpeaker);
|
||||
}
|
||||
call->update(params);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
class ConferenceListener;
|
||||
class ParticipantListModel;
|
||||
class VideoSourceDescriptorModel;
|
||||
|
||||
class ConferenceModel : public QObject{
|
||||
Q_OBJECT
|
||||
|
|
@ -43,12 +44,18 @@ public:
|
|||
Q_PROPERTY(ParticipantModel* localParticipant READ getLocalParticipant NOTIFY localParticipantChanged)
|
||||
Q_PROPERTY(bool isReady MEMBER mIsReady WRITE setIsReady NOTIFY isReadyChanged)
|
||||
Q_PROPERTY(int participantDeviceCount READ getParticipantDeviceCount NOTIFY participantDeviceCountChanged)
|
||||
Q_PROPERTY(bool isLocalScreenSharingEnabled READ isLocalScreenSharingEnabled NOTIFY localScreenSharingChanged)
|
||||
Q_PROPERTY(bool isScreenSharingEnabled READ isScreenSharingEnabled NOTIFY isScreenSharingEnabledChanged)
|
||||
|
||||
|
||||
static QSharedPointer<ConferenceModel> create(std::shared_ptr<linphone::Conference> chatRoom, QObject *parent = Q_NULLPTR);
|
||||
ConferenceModel(std::shared_ptr<linphone::Conference> content, QObject *parent = Q_NULLPTR);
|
||||
virtual ~ConferenceModel();
|
||||
bool updateLocalParticipant(); // true if changed
|
||||
void updateLayout();
|
||||
Q_INVOKABLE void toggleScreenSharing();
|
||||
bool isLocalScreenSharingEnabled() const;
|
||||
bool isScreenSharingEnabled() const;
|
||||
|
||||
std::shared_ptr<linphone::Conference> getConference()const;
|
||||
|
||||
|
|
@ -71,9 +78,12 @@ public:
|
|||
virtual void onParticipantDeviceMediaCapabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device);
|
||||
virtual void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device);
|
||||
virtual void onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device, bool isSpeaking);
|
||||
virtual void onParticipantDeviceScreenSharingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device, bool enabled);
|
||||
virtual void onParticipantDeviceStateChanged(const std::shared_ptr<linphone::Conference> & conference, const std::shared_ptr<const linphone::ParticipantDevice> & device, linphone::ParticipantDevice::State state);
|
||||
virtual void onConferenceStateChanged(linphone::Conference::State newState);
|
||||
virtual void onSubjectChanged(const std::string& subject);
|
||||
|
||||
void onIsScreenSharingEnabledChanged();
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
signals:
|
||||
|
|
@ -87,11 +97,14 @@ signals:
|
|||
void participantDeviceMediaCapabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
|
||||
void participantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
|
||||
void participantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device, bool isSpeaking);
|
||||
void participantDeviceScreenSharingChanged( const std::shared_ptr<const linphone::ParticipantDevice> & device, bool enabled);
|
||||
void participantDeviceStateChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device, linphone::ParticipantDevice::State state);
|
||||
void conferenceStateChanged(linphone::Conference::State newState);
|
||||
void subjectChanged();
|
||||
void isReadyChanged();
|
||||
void participantDeviceCountChanged();
|
||||
void localScreenSharingChanged(bool enabled);
|
||||
void isScreenSharingEnabledChanged();
|
||||
|
||||
private:
|
||||
void connectTo(ConferenceListener * listener);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ ContactModel::ContactModel (VcardModel *vcardModel, QObject * parent) : QObject(
|
|||
Q_CHECK_PTR(vcardModel);
|
||||
Q_CHECK_PTR(vcardModel->mVcard);
|
||||
Q_ASSERT(!vcardModel->mIsReadOnly);
|
||||
|
||||
mLinphoneFriend = CoreManager::getInstance()->getCore()->createFriendFromVcard(vcardModel->mVcard);
|
||||
mLinphoneFriend->setData("contact-model", *this);
|
||||
if(mLinphoneFriend)
|
||||
|
|
|
|||
|
|
@ -115,4 +115,4 @@ void CallHistoryProxyModel::handleIsActiveChanged (QWindow *window) {
|
|||
if (window->isActive() && getParentWindow(this) == window) {
|
||||
CoreManager::getInstance()->resetMissedCallsCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,23 +20,103 @@
|
|||
|
||||
#include "DesktopToolsLinux.hpp"
|
||||
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "components/videoSource/VideoSourceDescriptorModel.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <X11/Xlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
// #include <X11/Xutil.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
// =============================================================================
|
||||
|
||||
DesktopTools::~DesktopTools () {
|
||||
setScreenSaverStatus(true);
|
||||
DesktopTools::~DesktopTools() {
|
||||
setScreenSaverStatus(true);
|
||||
}
|
||||
|
||||
bool DesktopTools::getScreenSaverStatus () const {
|
||||
return mScreenSaverStatus;
|
||||
bool DesktopTools::getScreenSaverStatus() const {
|
||||
return mScreenSaverStatus;
|
||||
}
|
||||
|
||||
void DesktopTools::setScreenSaverStatus (bool status) {
|
||||
screenSaverDBus.setScreenSaverStatus(status);
|
||||
screenSaverXdg.setScreenSaverStatus(status);
|
||||
void DesktopTools::setScreenSaverStatus(bool status) {
|
||||
screenSaverDBus.setScreenSaverStatus(status);
|
||||
screenSaverXdg.setScreenSaverStatus(status);
|
||||
|
||||
bool newStatus = screenSaverDBus.getScreenSaverStatus() || screenSaverXdg.getScreenSaverStatus();
|
||||
if (newStatus != mScreenSaverStatus) {
|
||||
mScreenSaverStatus = newStatus;
|
||||
emit screenSaverStatusChanged(mScreenSaverStatus);
|
||||
}
|
||||
bool newStatus = screenSaverDBus.getScreenSaverStatus() || screenSaverXdg.getScreenSaverStatus();
|
||||
if (newStatus != mScreenSaverStatus) {
|
||||
mScreenSaverStatus = newStatus;
|
||||
emit screenSaverStatusChanged(mScreenSaverStatus);
|
||||
}
|
||||
}
|
||||
class T : public QThread {
|
||||
public:
|
||||
Display *mDisplay;
|
||||
Window mWindow;
|
||||
VideoSourceDescriptorModel *mVideoSourceDescriptorModel = nullptr;
|
||||
DesktopTools *mParent;
|
||||
T() {
|
||||
}
|
||||
virtual void run() {
|
||||
bool endLoop = false;
|
||||
unsigned char data[3];
|
||||
const char *pDevice = "/dev/input/event6";
|
||||
int fd = open(pDevice, O_RDONLY), bytes;
|
||||
XEvent event;
|
||||
endLoop = (fd == -1);
|
||||
int left, middle, right;
|
||||
XEvent report;
|
||||
XButtonEvent *xb = (XButtonEvent *)&report;
|
||||
|
||||
auto cursor = XCreateFontCursor(mDisplay, XC_crosshair);
|
||||
auto i = XGrabPointer(mDisplay, mWindow, False, ButtonReleaseMask | ButtonPressMask | Button1MotionMask,
|
||||
GrabModeSync, GrabModeAsync, mWindow, cursor, CurrentTime);
|
||||
|
||||
endLoop = (i != GrabSuccess);
|
||||
if (endLoop) qCritical() << "Cannot open mouse events";
|
||||
while (!endLoop) {
|
||||
XAllowEvents(mDisplay, SyncPointer, CurrentTime);
|
||||
XWindowEvent(mDisplay, mWindow, ButtonPressMask | ButtonReleaseMask, &report);
|
||||
if (report.type == ButtonPress) {
|
||||
printf("Press @ (%d, %d)\n", xb->x_root, xb->y_root);
|
||||
XQueryPointer(mDisplay, mWindow, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root,
|
||||
&event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
|
||||
auto id = event.xbutton.subwindow;
|
||||
QMetaObject::invokeMethod(CoreManager::getInstance(), [id, this]() mutable {
|
||||
mVideoSourceDescriptorModel->setScreenSharingWindow(reinterpret_cast<void*>(id));
|
||||
});
|
||||
endLoop = true;
|
||||
}
|
||||
}
|
||||
XFlush(mDisplay);
|
||||
XUngrabServer(mDisplay);
|
||||
XCloseDisplay(mDisplay);
|
||||
deleteLater();
|
||||
}
|
||||
};
|
||||
void DesktopTools::getWindowIdFromMouse(VideoSourceDescriptorModel *model) {
|
||||
const char *displayStr = getenv("DISPLAY");
|
||||
if (displayStr == NULL) displayStr = ":0";
|
||||
Display *display = XOpenDisplay(displayStr); // QX11Info::display();
|
||||
if (display == NULL) {
|
||||
qCritical() << "Can't open X display!";
|
||||
return;
|
||||
}
|
||||
emit windowIdSelectionStarted();
|
||||
T *t = new T();
|
||||
connect(t, &QThread::finished, this, &DesktopTools::windowIdSelectionEnded);
|
||||
t->mVideoSourceDescriptorModel = model;
|
||||
t->mDisplay = display;
|
||||
auto screen = DefaultScreen(display); // QX11Info::appScreen();
|
||||
t->mWindow = RootWindow(display, screen); // QX11Info::appRootWindow(m_x11_screen);
|
||||
t->mParent = this;
|
||||
t->start();
|
||||
}
|
||||
|
||||
uintptr_t DesktopTools::getDisplayIndex(void* screenSharing){
|
||||
return *(uintptr_t*)(&screenSharing);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,30 +25,44 @@
|
|||
#include "components/other/desktop-tools/screen-saver/ScreenSaverXdg.hpp"
|
||||
|
||||
// =============================================================================
|
||||
class VideoSourceDescriptorModel;
|
||||
|
||||
class DesktopTools : public QObject {
|
||||
Q_OBJECT;
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool screenSaverStatus READ getScreenSaverStatus WRITE setScreenSaverStatus NOTIFY screenSaverStatusChanged);
|
||||
Q_PROPERTY(
|
||||
bool screenSaverStatus READ getScreenSaverStatus WRITE setScreenSaverStatus NOTIFY screenSaverStatusChanged)
|
||||
|
||||
public:
|
||||
DesktopTools (QObject *parent = Q_NULLPTR) : QObject(parent) {}
|
||||
~DesktopTools ();
|
||||
DesktopTools(QObject *parent = Q_NULLPTR) : QObject(parent) {
|
||||
}
|
||||
~DesktopTools();
|
||||
|
||||
bool getScreenSaverStatus () const;
|
||||
void setScreenSaverStatus (bool status);
|
||||
bool getScreenSaverStatus() const;
|
||||
void setScreenSaverStatus(bool status);
|
||||
|
||||
static void init(){}
|
||||
static void applicationStateChanged(Qt::ApplicationState){};
|
||||
static void init() {
|
||||
}
|
||||
static void applicationStateChanged(Qt::ApplicationState){};
|
||||
|
||||
Q_INVOKABLE void getWindowIdFromMouse(VideoSourceDescriptorModel *model);
|
||||
static void *getDisplay(uintptr_t screenIndex){return reinterpret_cast<void*>(screenIndex);}
|
||||
static uintptr_t getDisplayIndex(void* screenSharing);
|
||||
|
||||
signals:
|
||||
void screenSaverStatusChanged (bool status);
|
||||
void screenSaverStatusChanged(bool status);
|
||||
void windowIdSelectionStarted();
|
||||
void windowIdSelectionEnded();
|
||||
|
||||
private:
|
||||
bool mScreenSaverStatus = true;
|
||||
bool mScreenSaverStatus = true;
|
||||
|
||||
ScreenSaverDBus screenSaverDBus;
|
||||
ScreenSaverXdg screenSaverXdg;
|
||||
ScreenSaverDBus screenSaverDBus;
|
||||
ScreenSaverXdg screenSaverXdg;
|
||||
|
||||
// X11 headers cannot be used in hpp. moc don't' compile.
|
||||
void *mDisplay = nullptr; // Display
|
||||
unsigned int mWindow = 0; // Window
|
||||
};
|
||||
|
||||
#endif // DESKTOP_TOOLS_LINUX_H_
|
||||
|
|
|
|||
|
|
@ -23,28 +23,34 @@
|
|||
|
||||
#include <QObject>
|
||||
// =============================================================================
|
||||
class VideoSourceDescriptorModel;
|
||||
|
||||
class DesktopTools : public QObject {
|
||||
Q_OBJECT;
|
||||
Q_OBJECT;
|
||||
|
||||
Q_PROPERTY(bool screenSaverStatus READ getScreenSaverStatus WRITE setScreenSaverStatus NOTIFY screenSaverStatusChanged);
|
||||
Q_PROPERTY(
|
||||
bool screenSaverStatus READ getScreenSaverStatus WRITE setScreenSaverStatus NOTIFY screenSaverStatusChanged);
|
||||
|
||||
public:
|
||||
DesktopTools (QObject *parent = Q_NULLPTR);
|
||||
~DesktopTools ();
|
||||
DesktopTools(QObject *parent = Q_NULLPTR);
|
||||
~DesktopTools();
|
||||
|
||||
bool getScreenSaverStatus () const;
|
||||
void setScreenSaverStatus (bool status);
|
||||
|
||||
static void init(); // Do first initialization
|
||||
static void applicationStateChanged(Qt::ApplicationState currentState);
|
||||
bool getScreenSaverStatus() const;
|
||||
void setScreenSaverStatus(bool status);
|
||||
|
||||
static void init(); // Do first initialization
|
||||
static void applicationStateChanged(Qt::ApplicationState currentState);
|
||||
static void *getDisplay(int screenIndex);
|
||||
static int getDisplayIndex(void *screenSharing);
|
||||
Q_INVOKABLE void getWindowIdFromMouse(VideoSourceDescriptorModel *model);
|
||||
|
||||
signals:
|
||||
void screenSaverStatusChanged (bool status);
|
||||
void screenSaverStatusChanged(bool status);
|
||||
void windowIdSelectionStarted();
|
||||
void windowIdSelectionEnded();
|
||||
|
||||
private:
|
||||
bool mScreenSaverStatus = true;
|
||||
bool mScreenSaverStatus = true;
|
||||
};
|
||||
|
||||
#endif // DESKTOP_TOOLS_MAC_OS_H_
|
||||
|
|
|
|||
|
|
@ -1,12 +1,71 @@
|
|||
#include "DesktopToolsMacOs.hpp"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <ScreenCaptureKit/ScreenCaptureKit.h>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include "components/videoSource/VideoSourceDescriptorModel.hpp"
|
||||
|
||||
void DesktopTools::init(){
|
||||
// Request permissions
|
||||
if( @available(macOS 10.14, *) ) {
|
||||
if([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] == AVAuthorizationStatusNotDetermined)
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL) {}];
|
||||
if([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio] == AVAuthorizationStatusNotDetermined)
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL) {}];
|
||||
}
|
||||
if([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo] != AVAuthorizationStatusAuthorized) {
|
||||
qDebug() << "Requesting Video permission";
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL) {}];
|
||||
}
|
||||
if([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio] != AVAuthorizationStatusAuthorized){
|
||||
qDebug() << "Requesting Audio permission";
|
||||
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL) {}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *DesktopTools::getDisplay(int screenIndex){
|
||||
CGDirectDisplayID displays[screenIndex+1];
|
||||
CGDisplayCount displayCount;
|
||||
CGGetOnlineDisplayList(screenIndex+1, displays, &displayCount);
|
||||
CGDirectDisplayID display = 0;
|
||||
if(displayCount > screenIndex)
|
||||
display = displays[screenIndex];
|
||||
return reinterpret_cast<void*>(display);
|
||||
}
|
||||
|
||||
int DesktopTools::getDisplayIndex(void* screenSharing){
|
||||
CGDirectDisplayID displayId = *(CGDirectDisplayID*)&screenSharing;
|
||||
int maxDisplayCount = 10;
|
||||
CGDisplayCount displayCount;
|
||||
do {
|
||||
CGDirectDisplayID displays[maxDisplayCount];
|
||||
CGGetOnlineDisplayList(maxDisplayCount, displays, &displayCount);
|
||||
for(int i = 0 ; i < displayCount ; ++i)
|
||||
if( displays[i] == displayId) {
|
||||
return i;
|
||||
}
|
||||
maxDisplayCount *= 2;
|
||||
}while(displayCount == maxDisplayCount/2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DesktopTools::getWindowIdFromMouse(VideoSourceDescriptorModel *model) {
|
||||
__block id globalMonitorId;
|
||||
__block id localMonitorId;
|
||||
__block DesktopTools * tools = this;
|
||||
emit windowIdSelectionStarted();
|
||||
globalMonitorId = [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown
|
||||
handler:^(NSEvent *event){
|
||||
CGWindowID windowID = (CGWindowID)[event windowNumber];
|
||||
if(event.type == NSEventTypeLeftMouseDown)
|
||||
model->setScreenSharingWindow(reinterpret_cast<void *>(windowID));
|
||||
[NSEvent removeMonitor:globalMonitorId];
|
||||
[NSEvent removeMonitor:localMonitorId];
|
||||
emit tools->windowIdSelectionEnded();
|
||||
}];
|
||||
localMonitorId = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown | NSEventMaskRightMouseDown
|
||||
handler:^NSEvent *(NSEvent *event){
|
||||
CGWindowID windowID = (CGWindowID)[event windowNumber];
|
||||
if(event.type == NSEventTypeLeftMouseDown)
|
||||
model->setScreenSharingWindow(reinterpret_cast<void *>(windowID));
|
||||
[NSEvent removeMonitor:globalMonitorId];
|
||||
[NSEvent removeMonitor:localMonitorId];
|
||||
emit tools->windowIdSelectionEnded();
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,32 +18,64 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "DesktopToolsWindows.hpp"
|
||||
|
||||
#include "components/core/CoreManager.hpp"
|
||||
#include "components/settings/SettingsModel.hpp"
|
||||
#include "components/videoSource/VideoSourceDescriptorModel.hpp"
|
||||
|
||||
#include <QDebug>
|
||||
#include <Windows.h>
|
||||
// =============================================================================
|
||||
|
||||
DesktopTools::DesktopTools (QObject *parent) : QObject(parent) {}
|
||||
|
||||
DesktopTools::~DesktopTools () {
|
||||
setScreenSaverStatus(true);
|
||||
DesktopTools::DesktopTools(QObject *parent) : QObject(parent) {
|
||||
}
|
||||
|
||||
bool DesktopTools::getScreenSaverStatus () const {
|
||||
return mScreenSaverStatus;
|
||||
DesktopTools::~DesktopTools() {
|
||||
setScreenSaverStatus(true);
|
||||
}
|
||||
|
||||
void DesktopTools::setScreenSaverStatus (bool status) {
|
||||
if (status == mScreenSaverStatus)
|
||||
return;
|
||||
|
||||
if (status)
|
||||
SetThreadExecutionState(ES_CONTINUOUS);
|
||||
else
|
||||
SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
|
||||
|
||||
mScreenSaverStatus = status;
|
||||
emit screenSaverStatusChanged(status);
|
||||
bool DesktopTools::getScreenSaverStatus() const {
|
||||
return mScreenSaverStatus;
|
||||
}
|
||||
|
||||
void DesktopTools::setScreenSaverStatus(bool status) {
|
||||
if (status == mScreenSaverStatus) return;
|
||||
|
||||
if (status) SetThreadExecutionState(ES_CONTINUOUS);
|
||||
else SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
|
||||
|
||||
mScreenSaverStatus = status;
|
||||
emit screenSaverStatusChanged(status);
|
||||
}
|
||||
|
||||
HHOOK hMouseHook;
|
||||
DesktopTools *gTools = nullptr;
|
||||
LRESULT CALLBACK mouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
MOUSEHOOKSTRUCT *pMouseStruct = (MOUSEHOOKSTRUCT *)lParam;
|
||||
if (pMouseStruct != NULL) {
|
||||
if (wParam == WM_LBUTTONDOWN) {
|
||||
printf("clicked");
|
||||
auto id = WindowFromPoint(pMouseStruct->pt);
|
||||
UnhookWindowsHookEx(hMouseHook);
|
||||
QMetaObject::invokeMethod(CoreManager::getInstance(), [id]() {
|
||||
gTools->mVideoSourceDescriptorModel->setScreenSharingWindow(reinterpret_cast<void *>(id));
|
||||
});
|
||||
emit gTools->windowIdSelectionEnded();
|
||||
}
|
||||
qDebug() << "Mouse position X = " << pMouseStruct->pt.x << " Mouse Position Y = " << pMouseStruct->pt.y;
|
||||
}
|
||||
return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
void DesktopTools::getWindowIdFromMouse(VideoSourceDescriptorModel *model) {
|
||||
gTools = this;
|
||||
gTools->mVideoSourceDescriptorModel = model;
|
||||
emit windowIdSelectionStarted();
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, mouseProc, hInstance, NULL);
|
||||
}
|
||||
|
||||
uintptr_t DesktopTools::getDisplayIndex(void* screenSharing) {
|
||||
return *(uintptr_t*)(&screenSharing);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,29 +22,43 @@
|
|||
#define DESKTOP_TOOLS_WINDOWS_H_
|
||||
|
||||
#include <QObject>
|
||||
#include <windows.h>
|
||||
|
||||
class VideoSourceDescriptorModel;
|
||||
// =============================================================================
|
||||
|
||||
class DesktopTools : public QObject {
|
||||
Q_OBJECT;
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool screenSaverStatus READ getScreenSaverStatus WRITE setScreenSaverStatus NOTIFY screenSaverStatusChanged);
|
||||
Q_PROPERTY(
|
||||
bool screenSaverStatus READ getScreenSaverStatus WRITE setScreenSaverStatus NOTIFY screenSaverStatusChanged)
|
||||
|
||||
public:
|
||||
DesktopTools (QObject *parent = Q_NULLPTR);
|
||||
~DesktopTools ();
|
||||
DesktopTools(QObject *parent = Q_NULLPTR);
|
||||
~DesktopTools();
|
||||
|
||||
bool getScreenSaverStatus () const;
|
||||
void setScreenSaverStatus (bool status);
|
||||
bool getScreenSaverStatus() const;
|
||||
void setScreenSaverStatus(bool status);
|
||||
|
||||
static void init(){}
|
||||
static void applicationStateChanged(Qt::ApplicationState){};
|
||||
static void init() {
|
||||
}
|
||||
static void applicationStateChanged(Qt::ApplicationState){};
|
||||
|
||||
Q_INVOKABLE void getWindowIdFromMouse(VideoSourceDescriptorModel *model);
|
||||
static void *getDisplay(uintptr_t screenIndex) {
|
||||
return reinterpret_cast<void *>(screenIndex);
|
||||
}
|
||||
static uintptr_t getDisplayIndex(void *screenSharing);
|
||||
HWND mWindowId = 0; // Window
|
||||
VideoSourceDescriptorModel *mVideoSourceDescriptorModel = nullptr;
|
||||
|
||||
signals:
|
||||
void screenSaverStatusChanged (bool status);
|
||||
void screenSaverStatusChanged(bool status);
|
||||
void windowIdSelectionStarted();
|
||||
void windowIdSelectionEnded();
|
||||
|
||||
private:
|
||||
bool mScreenSaverStatus = true;
|
||||
bool mScreenSaverStatus = true;
|
||||
};
|
||||
|
||||
#endif // DESKTOP_TOOLS_WINDOWS_H_
|
||||
|
|
|
|||
|
|
@ -70,7 +70,13 @@ void ParticipantDeviceListModel::initConferenceModel(){
|
|||
connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaCapabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaCapabilityChanged);
|
||||
connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged);
|
||||
connect(conferenceModel.get(), &ConferenceModel::participantDeviceIsSpeakingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged);
|
||||
mActiveSpeaker = get(conferenceModel->getConference()->getActiveSpeakerParticipantDevice());
|
||||
connect(conferenceModel.get(), &ConferenceModel::participantDeviceScreenSharingChanged, this, &ParticipantDeviceListModel::onParticipantDeviceScreenSharingChanged);
|
||||
|
||||
// TODO activeSpeaker
|
||||
//auto activeSpeaker = conferenceModel->getConference()->getScreenSharingParticipantDevice();
|
||||
//if(!activeSpeaker)
|
||||
auto activeSpeaker = conferenceModel->getConference()->getActiveSpeakerParticipantDevice();
|
||||
mActiveSpeaker = get(activeSpeaker);
|
||||
mInitialized = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -102,6 +108,13 @@ void ParticipantDeviceListModel::updateDevices(const std::list<std::shared_ptr<l
|
|||
}
|
||||
}
|
||||
|
||||
void ParticipantDeviceListModel::setActiveSpeaker(QSharedPointer<ParticipantDeviceModel> activeSpeaker) {
|
||||
if( mActiveSpeaker != activeSpeaker) {
|
||||
mActiveSpeaker = activeSpeaker;
|
||||
emit activeSpeakerChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool ParticipantDeviceListModel::add(std::shared_ptr<linphone::ParticipantDevice> deviceToAdd){
|
||||
auto deviceToAddAddr = deviceToAdd->getAddress();
|
||||
int row = 0;
|
||||
|
|
@ -135,8 +148,14 @@ bool ParticipantDeviceListModel::add(std::shared_ptr<linphone::ParticipantDevice
|
|||
if( addMe){
|
||||
qDebug() << "Added a me device";
|
||||
emit meChanged();
|
||||
}else if(mList.size() == 1 || (mList.size() == 2 && isMe(mList.front().objectCast<ParticipantDeviceModel>()->getDevice()))){
|
||||
mActiveSpeaker = mList.back().objectCast<ParticipantDeviceModel>();
|
||||
}else{
|
||||
// Todo ActiveSpeaker
|
||||
//if(deviceToAdd->screenSharingEnabled())
|
||||
// mActiveSpeaker = deviceModel;
|
||||
//else
|
||||
mActiveSpeaker = get(mCallModel->getConferenceSharedModel()->getConference()->getActiveSpeakerParticipantDevice());
|
||||
if(!mActiveSpeaker && (mList.size() == 1 || (mList.size() == 2 && isMe(mList.front().objectCast<ParticipantDeviceModel>()->getDevice()))))
|
||||
mActiveSpeaker = mList.back().objectCast<ParticipantDeviceModel>();
|
||||
emit activeSpeakerChanged();
|
||||
}
|
||||
return true;
|
||||
|
|
@ -239,6 +258,8 @@ void ParticipantDeviceListModel::onParticipantDeviceAdded(const std::shared_ptr<
|
|||
qDebug() << "Adding new device : " << mList.count();
|
||||
auto conferenceModel = mCallModel->getConferenceSharedModel();
|
||||
std::list<std::shared_ptr<linphone::ParticipantDevice>> devices;
|
||||
|
||||
|
||||
for(int i = 0 ; i < 2 ; ++i){
|
||||
if( i == 0)
|
||||
devices = conferenceModel->getConference()->getParticipantDeviceList();// Active devices.
|
||||
|
|
@ -296,11 +317,12 @@ void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(con
|
|||
onParticipantDeviceAdded(participantDevice);
|
||||
}
|
||||
void ParticipantDeviceListModel::onActiveSpeakerParticipantDevice(const std::shared_ptr<const linphone::ParticipantDevice>& participantDevice){
|
||||
auto device = get(participantDevice);
|
||||
if( device){
|
||||
mActiveSpeaker = device;
|
||||
emit activeSpeakerChanged();
|
||||
}
|
||||
// TODO activeSpeaker
|
||||
//auto activeSpeaker = get(mCallModel->getConferenceSharedModel()->getConference()->getScreenSharingParticipantDevice());
|
||||
//if(!activeSpeaker)
|
||||
auto activeSpeaker = get(participantDevice);
|
||||
qDebug() << "onActiveSpeakerParticipantDevice " << participantDevice.get() << " == " << get(participantDevice) << " : " << (participantDevice ? participantDevice->getAddress()->asStringUriOnly().c_str() : "");
|
||||
setActiveSpeaker(activeSpeaker);
|
||||
}
|
||||
|
||||
void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice, bool isSpeaking){
|
||||
|
|
@ -308,6 +330,16 @@ void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std:
|
|||
if( device)
|
||||
emit participantSpeaking(device.get());
|
||||
}
|
||||
void ParticipantDeviceListModel::onParticipantDeviceScreenSharingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice){
|
||||
// TODO activeSpeaker
|
||||
//auto activeSpeaker = mCallModel->getConferenceSharedModel()->getConference()->getScreenSharingParticipantDevice();
|
||||
//if(!activeSpeaker)
|
||||
auto activeSpeaker = mCallModel->getConferenceSharedModel()->getConference()->getActiveSpeakerParticipantDevice();
|
||||
qDebug() << "onParticipantDeviceScreenSharingChanged " << participantDevice.get() << " == " << get(participantDevice) << " ; "
|
||||
<< activeSpeaker.get() << " == " << get(activeSpeaker) << " : " << (activeSpeaker ? activeSpeaker->getAddress()->asStringUriOnly().c_str() : "")
|
||||
<< ", ScreenShared:" << participantDevice->screenSharingEnabled();
|
||||
setActiveSpeaker(get(activeSpeaker));
|
||||
}
|
||||
|
||||
void ParticipantDeviceListModel::onParticipantDeviceSpeaking(){
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
void initConferenceModel();
|
||||
void updateDevices(std::shared_ptr<linphone::Participant> participant);
|
||||
void updateDevices(const std::list<std::shared_ptr<linphone::ParticipantDevice>>& devices, const bool& isMe);
|
||||
void setActiveSpeaker(QSharedPointer<ParticipantDeviceModel> activeSpeaker);
|
||||
|
||||
bool add(std::shared_ptr<linphone::ParticipantDevice> deviceToAdd);
|
||||
bool remove(std::shared_ptr<const linphone::ParticipantDevice> deviceToAdd);
|
||||
|
|
@ -65,6 +66,7 @@ public slots:
|
|||
void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
|
||||
void onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & device, bool isSpeaking);
|
||||
void onParticipantDeviceSpeaking();
|
||||
void onParticipantDeviceScreenSharingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice);
|
||||
|
||||
signals:
|
||||
void activeSpeakerChanged();
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@ void ParticipantDeviceListener::onIsMuted(const std::shared_ptr<linphone::Partic
|
|||
emit isMuted(participantDevice, isMutedVar);
|
||||
}
|
||||
|
||||
void ParticipantDeviceListener::onScreenSharingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isScreenSharing) {
|
||||
emit isScreenSharingChanged(participantDevice, isScreenSharing);
|
||||
}
|
||||
|
||||
void ParticipantDeviceListener::onStateChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::ParticipantDevice::State state){
|
||||
qDebug() << "onStateChanged: " << participantDevice->getAddress()->asString().c_str() << " " << (int)state;
|
||||
emit stateChanged(participantDevice, state);
|
||||
|
|
@ -51,4 +55,4 @@ void ParticipantDeviceListener::onStreamCapabilityChanged(const std::shared_ptr<
|
|||
void ParticipantDeviceListener::onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) {
|
||||
qDebug() << "onStreamAvailabilityChanged: " << participantDevice->getAddress()->asString().c_str() << " " << available<< " / " << (int)streamType;
|
||||
emit streamAvailabilityChanged(participantDevice, available, streamType);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,12 +38,14 @@ public:
|
|||
|
||||
virtual void onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking) override;
|
||||
virtual void onIsMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted) override;
|
||||
virtual void onScreenSharingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isScreenSharing) override;
|
||||
virtual void onStateChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::ParticipantDevice::State state) override;
|
||||
virtual void onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) override;
|
||||
virtual void onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) override;
|
||||
signals:
|
||||
void isSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking);
|
||||
void isMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted);
|
||||
void isScreenSharingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isScreenSharing);
|
||||
void stateChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::ParticipantDevice::State state);
|
||||
void streamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType);
|
||||
void streamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
void ParticipantDeviceModel::connectTo(ParticipantDeviceListener * listener){
|
||||
connect(listener, &ParticipantDeviceListener::isSpeakingChanged, this, &ParticipantDeviceModel::onIsSpeakingChanged);
|
||||
connect(listener, &ParticipantDeviceListener::isMuted, this, &ParticipantDeviceModel::onIsMuted);
|
||||
connect(listener, &ParticipantDeviceListener::isScreenSharingChanged, this, &ParticipantDeviceModel::onScreenSharingChanged);
|
||||
connect(listener, &ParticipantDeviceListener::stateChanged, this, &ParticipantDeviceModel::onStateChanged);
|
||||
connect(listener, &ParticipantDeviceListener::streamCapabilityChanged, this, &ParticipantDeviceModel::onStreamCapabilityChanged);
|
||||
connect(listener, &ParticipantDeviceListener::streamAvailabilityChanged, this, &ParticipantDeviceModel::onStreamAvailabilityChanged);
|
||||
|
|
@ -108,6 +109,10 @@ bool ParticipantDeviceModel::getIsMuted() const{
|
|||
return mParticipantDevice ? mParticipantDevice->getIsMuted() : false;
|
||||
}
|
||||
|
||||
bool ParticipantDeviceModel::getIsScreenSharingEnabled() const {
|
||||
return mParticipantDevice ? mParticipantDevice->screenSharingEnabled() : false;
|
||||
}
|
||||
|
||||
LinphoneEnums::ParticipantDeviceState ParticipantDeviceModel::getState() const{
|
||||
return LinphoneEnums::fromLinphone(mState);
|
||||
}
|
||||
|
|
@ -120,6 +125,10 @@ bool ParticipantDeviceModel::isVideoEnabled() const{
|
|||
return mIsVideoEnabled;
|
||||
}
|
||||
|
||||
bool ParticipantDeviceModel::isThumbnailVideoEnabled() const{
|
||||
return mIsThumbnailVideoEnabled;
|
||||
}
|
||||
|
||||
void ParticipantDeviceModel::setPaused(bool paused){
|
||||
if(mIsPaused != paused){
|
||||
mIsPaused = paused;
|
||||
|
|
@ -149,16 +158,51 @@ void ParticipantDeviceModel::setState(LinphoneEnums::ParticipantDeviceState stat
|
|||
}
|
||||
}
|
||||
|
||||
void ParticipantDeviceModel::updateVideoEnabled(){
|
||||
bool enabled = (mParticipantDevice && mParticipantDevice->isInConference() && mParticipantDevice->getStreamAvailability(linphone::StreamType::Video) &&
|
||||
( mParticipantDevice->getStreamCapability(linphone::StreamType::Video) == linphone::MediaDirection::SendRecv
|
||||
|| mParticipantDevice->getStreamCapability(linphone::StreamType::Video) == linphone::MediaDirection::SendOnly
|
||||
)
|
||||
|| (isMe() && isLocal())) && !mIsPaused;
|
||||
if( mIsVideoEnabled != enabled && mCall && mCall->getCall()->getState() == linphone::Call::State::StreamsRunning) {
|
||||
qDebug() << "VideoEnabled: " << enabled << ", old=" << mIsVideoEnabled << (mParticipantDevice ? mParticipantDevice->getAddress()->asString().c_str() : "") << ", me=" << isMe() << ", isLocal=" << isLocal() << ", CallState=" << (mCall ? (int)mCall->getCall()->getState() : -1);
|
||||
mIsVideoEnabled = enabled;
|
||||
emit videoEnabledChanged();
|
||||
void ParticipantDeviceModel::updateVideoEnabled() {
|
||||
if (mCall && mCall->getCall()->getState() == linphone::Call::State::StreamsRunning) {
|
||||
bool enabled = (mParticipantDevice && mParticipantDevice->isInConference()
|
||||
&& mParticipantDevice->getStreamAvailability(linphone::StreamType::Video)
|
||||
|| (isMe() && isLocal()))
|
||||
&& !mIsPaused;
|
||||
if (mIsVideoEnabled != enabled) {
|
||||
qDebug() << "VideoEnabled: " << enabled << ", old=" << mIsVideoEnabled
|
||||
<< (mParticipantDevice ? mParticipantDevice->getAddress()->asString().c_str()
|
||||
: "")
|
||||
<< ", me=" << isMe() << ", isLocal=" << isLocal() << ", inConf="
|
||||
<< (mParticipantDevice ? mParticipantDevice->isInConference() : false)
|
||||
<< ", CallState=" << (mCall ? (int) mCall->getCall()->getState() : -1)
|
||||
<< ", StreamAvailability:"
|
||||
<< (mParticipantDevice
|
||||
? mParticipantDevice->getStreamAvailability(linphone::StreamType::Video)
|
||||
: false)
|
||||
<< ", StreamDir="
|
||||
<< (mParticipantDevice ? (int) mParticipantDevice->getStreamCapability(
|
||||
linphone::StreamType::Video)
|
||||
: -1);
|
||||
mIsVideoEnabled = enabled;
|
||||
emit videoEnabledChanged();
|
||||
}
|
||||
enabled = (mParticipantDevice && mParticipantDevice->isInConference()
|
||||
&& mParticipantDevice->getThumbnailStreamAvailability()
|
||||
|| (isMe() && isLocal()))
|
||||
&& !mIsPaused;
|
||||
if (mIsThumbnailVideoEnabled != enabled) {
|
||||
qDebug() << "ThumbnailVideoEnabled: " << enabled << ", old=" << mIsThumbnailVideoEnabled
|
||||
<< (mParticipantDevice ? mParticipantDevice->getAddress()->asString().c_str()
|
||||
: "")
|
||||
<< ", me=" << isMe() << ", isLocal=" << isLocal() << ", inConf="
|
||||
<< (mParticipantDevice ? mParticipantDevice->isInConference() : false)
|
||||
<< ", CallState=" << (mCall ? (int) mCall->getCall()->getState() : -1)
|
||||
<< ", StreamAvailability:"
|
||||
<< (mParticipantDevice ? mParticipantDevice->getThumbnailStreamAvailability()
|
||||
: false)
|
||||
<< ", StreamDir="
|
||||
<< (mParticipantDevice
|
||||
? (int) mParticipantDevice->getThumbnailStreamCapability()
|
||||
: -1);
|
||||
mIsThumbnailVideoEnabled = enabled;
|
||||
emit thumbnailVideoEnabledChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -189,6 +233,9 @@ void ParticipantDeviceModel::onCallStatusChanged(){
|
|||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
void ParticipantDeviceModel::onScreenSharingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isScreenSharing) {
|
||||
emit isScreenSharingEnabledChanged();
|
||||
}
|
||||
void ParticipantDeviceModel::onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking) {
|
||||
setIsSpeaking(isSpeaking);
|
||||
}
|
||||
|
|
@ -216,4 +263,4 @@ void ParticipantDeviceModel::onStreamCapabilityChanged(const std::shared_ptr<lin
|
|||
}
|
||||
void ParticipantDeviceModel::onStreamAvailabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool available, linphone::StreamType streamType) {
|
||||
updateVideoEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,11 +50,13 @@ public:
|
|||
Q_PROPERTY(int securityLevel READ getSecurityLevel NOTIFY securityLevelChanged)
|
||||
Q_PROPERTY(time_t timeOfJoining READ getTimeOfJoining CONSTANT)
|
||||
Q_PROPERTY(bool videoEnabled READ isVideoEnabled NOTIFY videoEnabledChanged)
|
||||
Q_PROPERTY(bool thumbnailVideoEnabled READ isThumbnailVideoEnabled NOTIFY thumbnailVideoEnabledChanged)
|
||||
Q_PROPERTY(bool isMe READ isMe CONSTANT)
|
||||
Q_PROPERTY(bool isLocal READ isLocal WRITE setIsLocal NOTIFY isLocalChanged)// Can change on call update. Not really used but it just in case as Object can be initialized with empty call/device.
|
||||
Q_PROPERTY(bool isPaused READ getPaused WRITE setPaused NOTIFY isPausedChanged)
|
||||
Q_PROPERTY(bool isSpeaking READ getIsSpeaking WRITE setIsSpeaking NOTIFY isSpeakingChanged)
|
||||
Q_PROPERTY(bool isMuted READ getIsMuted NOTIFY isMutedChanged)
|
||||
Q_PROPERTY(bool isScreenSharingEnabled READ getIsScreenSharingEnabled NOTIFY isScreenSharingEnabledChanged)
|
||||
Q_PROPERTY(LinphoneEnums::ParticipantDeviceState state READ getState WRITE setState NOTIFY stateChanged)
|
||||
|
||||
QString getName() const;
|
||||
|
|
@ -63,11 +65,13 @@ public:
|
|||
int getSecurityLevel() const;
|
||||
time_t getTimeOfJoining() const;
|
||||
bool isVideoEnabled() const;
|
||||
bool isThumbnailVideoEnabled() const;
|
||||
bool isMe() const;
|
||||
bool isLocal()const;
|
||||
bool getPaused() const;
|
||||
bool getIsSpeaking() const;
|
||||
bool getIsMuted() const;
|
||||
bool getIsScreenSharingEnabled() const;
|
||||
LinphoneEnums::ParticipantDeviceState getState() const;
|
||||
|
||||
std::shared_ptr<linphone::ParticipantDevice> getDevice();
|
||||
|
|
@ -77,6 +81,7 @@ public:
|
|||
void setIsLocal(bool local);
|
||||
void setState(LinphoneEnums::ParticipantDeviceState state);
|
||||
|
||||
virtual void onScreenSharingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isScreenSharing);
|
||||
virtual void onIsSpeakingChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isSpeaking);
|
||||
virtual void onIsMuted(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, bool isMuted);
|
||||
virtual void onStateChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::ParticipantDevice::State state);
|
||||
|
|
@ -93,9 +98,11 @@ public slots:
|
|||
signals:
|
||||
void securityLevelChanged();
|
||||
void videoEnabledChanged();
|
||||
void thumbnailVideoEnabledChanged();
|
||||
void isPausedChanged();
|
||||
void isSpeakingChanged();
|
||||
void isMutedChanged();
|
||||
void isScreenSharingEnabledChanged();
|
||||
void isLocalChanged();
|
||||
void stateChanged();
|
||||
|
||||
|
|
@ -103,7 +110,8 @@ private:
|
|||
|
||||
bool mIsMe = false;
|
||||
bool mIsLocal = false;
|
||||
bool mIsVideoEnabled;
|
||||
bool mIsVideoEnabled = false;
|
||||
bool mIsThumbnailVideoEnabled = false;
|
||||
bool mIsPaused = false;
|
||||
bool mIsSpeaking = false;
|
||||
linphone::ParticipantDevice::State mState;
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){
|
|||
sort(0);
|
||||
emit countChanged();
|
||||
emit meChanged();
|
||||
emit activeSpeakerChanged();
|
||||
}
|
||||
|
||||
void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant){
|
||||
|
|
@ -112,6 +113,7 @@ void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant)
|
|||
sort(0);
|
||||
emit countChanged();
|
||||
emit meChanged();
|
||||
emit activeSpeakerChanged();
|
||||
}
|
||||
|
||||
void ParticipantDeviceProxyModel::setShowMe(const bool& show){
|
||||
|
|
|
|||
44
linphone-app/src/components/screen/ScreenListModel.cpp
Normal file
44
linphone-app/src/components/screen/ScreenListModel.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScreenListModel.hpp"
|
||||
#include <QGuiApplication>
|
||||
#include <QPixmap>
|
||||
#include <QScreen>
|
||||
|
||||
ScreenListModel::ScreenListModel(QObject *parent) : ProxyAbstractListModel(parent) {
|
||||
mList = QGuiApplication::screens();
|
||||
}
|
||||
|
||||
ScreenListModel::~ScreenListModel() {
|
||||
}
|
||||
|
||||
QVariant ScreenListModel::data(const QModelIndex &index, int role) const {
|
||||
int row = index.row();
|
||||
if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant();
|
||||
if (role == Qt::DisplayRole) {
|
||||
auto screen = mList[row];
|
||||
QVariantMap data;
|
||||
data["name"] = screen->name();
|
||||
data["screenshot"] = QVariant::fromValue(screen->grabWindow(0));
|
||||
return data;
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
39
linphone-app/src/components/screen/ScreenListModel.hpp
Normal file
39
linphone-app/src/components/screen/ScreenListModel.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCREEN_LIST_MODEL_H_
|
||||
#define SCREEN_LIST_MODEL_H_
|
||||
|
||||
#include "app/proxyModel/ProxyListModel.hpp"
|
||||
|
||||
#include <QScreen>
|
||||
|
||||
class ScreenListModel : public ProxyAbstractListModel<QScreen*> {
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScreenListModel(QObject *parent = Q_NULLPTR);
|
||||
virtual ~ScreenListModel();
|
||||
|
||||
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
30
linphone-app/src/components/screen/ScreenProxyModel.cpp
Normal file
30
linphone-app/src/components/screen/ScreenProxyModel.cpp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QQuickWindow>
|
||||
|
||||
#include "ScreenListModel.hpp"
|
||||
#include "ScreenProxyModel.hpp"
|
||||
// =============================================================================
|
||||
|
||||
ScreenProxyModel::ScreenProxyModel(QObject *parent) : SortFilterProxyModel(parent) {
|
||||
setSourceModel(new ScreenListModel(this));
|
||||
sort(0);
|
||||
}
|
||||
39
linphone-app/src/components/screen/ScreenProxyModel.hpp
Normal file
39
linphone-app/src/components/screen/ScreenProxyModel.hpp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2024 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCREEN_PROXY_MODEL_H_
|
||||
#define SCREEN_PROXY_MODEL_H_
|
||||
|
||||
#include "app/proxyModel/SortFilterProxyModel.hpp"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
class QWindow;
|
||||
|
||||
class ScreenProxyModel : public SortFilterProxyModel {
|
||||
class ScreenModelFilter;
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScreenProxyModel(QObject *parent = Q_NULLPTR);
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "VideoSourceDescriptorModel.hpp"
|
||||
#include "components/other/desktop-tools/DesktopTools.hpp"
|
||||
// =============================================================================
|
||||
VideoSourceDescriptorModel::VideoSourceDescriptorModel() {
|
||||
|
||||
}
|
||||
VideoSourceDescriptorModel::VideoSourceDescriptorModel(std::shared_ptr<linphone::VideoSourceDescriptor> desc) {
|
||||
mDesc = desc;
|
||||
if(mDesc && mDesc->getScreenSharingType() == linphone::VideoSourceScreenSharingType::Display)
|
||||
mScreenIndex = DesktopTools::getDisplayIndex(mDesc->getScreenSharing());
|
||||
}
|
||||
|
||||
void VideoSourceDescriptorModel::setScreenSharingDisplay(int index) {
|
||||
if(!mDesc) mDesc = linphone::Factory::get()->createVideoSourceDescriptor();
|
||||
mScreenIndex = index;
|
||||
mDesc->setScreenSharing(linphone::VideoSourceScreenSharingType::Display, DesktopTools::getDisplay(index));
|
||||
emit videoDescriptorChanged();
|
||||
}
|
||||
|
||||
void VideoSourceDescriptorModel::setScreenSharingWindow(void *window){ // Get data from DesktopTools.
|
||||
if(!mDesc) mDesc = linphone::Factory::get()->createVideoSourceDescriptor();
|
||||
else if(getVideoSourceType() == LinphoneEnums::VideoSourceScreenSharingTypeWindow && window == getScreenSharing())
|
||||
return;
|
||||
mDesc->setScreenSharing(linphone::VideoSourceScreenSharingType::Window, window);
|
||||
emit videoDescriptorChanged();
|
||||
}
|
||||
|
||||
void * VideoSourceDescriptorModel::getScreenSharing() const{
|
||||
if(!mDesc)
|
||||
return nullptr;
|
||||
else
|
||||
return mDesc->getScreenSharing();
|
||||
}
|
||||
|
||||
bool VideoSourceDescriptorModel::isScreenSharing() const{
|
||||
return mDesc && mDesc->getType() == linphone::VideoSourceType::ScreenSharing;
|
||||
}
|
||||
|
||||
LinphoneEnums::VideoSourceScreenSharingType VideoSourceDescriptorModel::getVideoSourceType() const{
|
||||
return mDesc ? LinphoneEnums::fromLinphone(mDesc->getScreenSharingType()) : LinphoneEnums::VideoSourceScreenSharingType::VideoSourceScreenSharingTypeDisplay;
|
||||
}
|
||||
|
||||
int VideoSourceDescriptorModel::getScreenSharingIndex() const{
|
||||
if(mDesc && mDesc->getScreenSharingType() == linphone::VideoSourceScreenSharingType::Display) {
|
||||
return mScreenIndex;
|
||||
}else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-desktop
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* 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, either 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VIDEO_SOURCE_DESCRIPTOR_MODEL_H_
|
||||
#define VIDEO_SOURCE_DESCRIPTOR_MODEL_H_
|
||||
|
||||
|
||||
#include <linphone++/linphone.hh>
|
||||
// =============================================================================
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "utils/LinphoneEnums.hpp"
|
||||
|
||||
class VideoSourceDescriptorModel : public QObject{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool isScreenSharing READ isScreenSharing NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(LinphoneEnums::VideoSourceScreenSharingType screenSharingType READ getVideoSourceType NOTIFY videoDescriptorChanged)
|
||||
Q_PROPERTY(int screenSharingIndex READ getScreenSharingIndex WRITE setScreenSharingDisplay NOTIFY videoDescriptorChanged)
|
||||
public:
|
||||
VideoSourceDescriptorModel();
|
||||
VideoSourceDescriptorModel(std::shared_ptr<linphone::VideoSourceDescriptor> desc);
|
||||
void setScreenSharingDisplay(int index);
|
||||
void setScreenSharingWindow(void *window); // Get data from DesktopTools.
|
||||
void *getScreenSharing() const;
|
||||
|
||||
bool isScreenSharing() const;
|
||||
LinphoneEnums::VideoSourceScreenSharingType getVideoSourceType() const;
|
||||
int getScreenSharingIndex() const;
|
||||
|
||||
|
||||
std::shared_ptr<linphone::VideoSourceDescriptor> mDesc;
|
||||
int mScreenIndex = 0;
|
||||
|
||||
signals:
|
||||
void videoDescriptorChanged();
|
||||
};
|
||||
#endif
|
||||
|
|
@ -38,6 +38,7 @@ void LinphoneEnums::registerMetaTypes(){
|
|||
qRegisterMetaType<LinphoneEnums::RecorderState>();
|
||||
qRegisterMetaType<LinphoneEnums::TunnelMode>();
|
||||
qRegisterMetaType<LinphoneEnums::TransportType>();
|
||||
qRegisterMetaType<LinphoneEnums::VideoSourceScreenSharingType>();
|
||||
|
||||
qRegisterMetaType<std::shared_ptr<linphone::Call>>();
|
||||
qRegisterMetaType<linphone::Call::State>();
|
||||
|
|
@ -171,3 +172,11 @@ void LinphoneEnums::fromString(const QString& transportType, LinphoneEnums::Tran
|
|||
else
|
||||
*transport = TransportTypeDtls;
|
||||
}
|
||||
|
||||
linphone::VideoSourceScreenSharingType LinphoneEnums::toLinphone(const LinphoneEnums::VideoSourceScreenSharingType& type){
|
||||
return static_cast<linphone::VideoSourceScreenSharingType>(type);
|
||||
}
|
||||
LinphoneEnums::VideoSourceScreenSharingType LinphoneEnums::fromLinphone(const linphone::VideoSourceScreenSharingType& type){
|
||||
return static_cast<LinphoneEnums::VideoSourceScreenSharingType>(type);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,6 +214,17 @@ linphone::TransportType toLinphone(const LinphoneEnums::TransportType& type);
|
|||
LinphoneEnums::TransportType fromLinphone(const linphone::TransportType& type);
|
||||
QString toString(const LinphoneEnums::TransportType& type);
|
||||
void fromString(const QString& transportType, LinphoneEnums::TransportType *transport);
|
||||
|
||||
enum VideoSourceScreenSharingType{
|
||||
VideoSourceScreenSharingTypeArea = int(linphone::VideoSourceScreenSharingType::Area),
|
||||
VideoSourceScreenSharingTypeDisplay = int(linphone::VideoSourceScreenSharingType::Display),
|
||||
VideoSourceScreenSharingTypeWindow = int(linphone::VideoSourceScreenSharingType::Window)
|
||||
};
|
||||
Q_ENUM_NS(VideoSourceScreenSharingType)
|
||||
|
||||
linphone::VideoSourceScreenSharingType toLinphone(const LinphoneEnums::VideoSourceScreenSharingType& type);
|
||||
LinphoneEnums::VideoSourceScreenSharingType fromLinphone(const linphone::VideoSourceScreenSharingType& type);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -230,6 +241,7 @@ Q_DECLARE_METATYPE(LinphoneEnums::ParticipantDeviceState)
|
|||
Q_DECLARE_METATYPE(LinphoneEnums::RecorderState)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::TunnelMode)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::TransportType)
|
||||
Q_DECLARE_METATYPE(LinphoneEnums::VideoSourceScreenSharingType)
|
||||
|
||||
Q_DECLARE_METATYPE(std::shared_ptr<linphone::Call>)
|
||||
Q_DECLARE_METATYPE(linphone::Call::State)
|
||||
|
|
|
|||
|
|
@ -680,6 +680,12 @@ bool Utils::isMe(const std::shared_ptr<const linphone::Address>& address){
|
|||
}else
|
||||
return address ? CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddress()->weakEqual(address) : false;
|
||||
}
|
||||
bool Utils::isLocal(const std::shared_ptr<linphone::Conference>& conference, const std::shared_ptr<const linphone::ParticipantDevice>& device) {
|
||||
auto deviceAddress = device->getAddress();
|
||||
auto callAddress = conference->getMe()->getAddress();
|
||||
auto gruuAddress = CoreManager::getInstance()->getAccountSettingsModel()->findAccount(callAddress)->getContactAddress();
|
||||
return deviceAddress->equal(gruuAddress);
|
||||
}
|
||||
|
||||
bool Utils::isAnimatedImage(const QString& path){
|
||||
if(path.isEmpty()) return false;
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ public:
|
|||
static QString computeUserAgent(const std::shared_ptr<linphone::Config>& config);
|
||||
|
||||
static bool isMe(const std::shared_ptr<const linphone::Address>& address);
|
||||
static bool isLocal(const std::shared_ptr<linphone::Conference>& conference, const std::shared_ptr<const linphone::ParticipantDevice>& device);
|
||||
|
||||
|
||||
static void deleteAllUserData();
|
||||
static void deleteAllUserDataOffline();// When we are out of all events and core is not running (aka in main())
|
||||
|
|
|
|||
|
|
@ -26,10 +26,12 @@ Item {
|
|||
property color borderColorPressed
|
||||
|
||||
property alias text: button.text
|
||||
property alias textColor: button.textColor
|
||||
property bool enabled: true
|
||||
property bool showBorder : false
|
||||
property alias toggled : button.checked
|
||||
|
||||
property alias button: button
|
||||
property alias radius: button.radius
|
||||
property alias capitalization : button.capitalization
|
||||
|
||||
//Additional size around text
|
||||
|
|
@ -81,16 +83,18 @@ Item {
|
|||
Button {
|
||||
id: button
|
||||
property int capitalization
|
||||
property color textColor: _getTextColor()
|
||||
property int radius: AbstractTextButtonStyle.background.radius
|
||||
|
||||
background: Rectangle {
|
||||
color: _getBackgroundColor()
|
||||
radius: AbstractTextButtonStyle.background.radius
|
||||
radius: button.radius
|
||||
border.color: _getBorderColor()
|
||||
border.width: (showBorder ? 1 : 0)
|
||||
}
|
||||
|
||||
contentItem: Text {
|
||||
color: _getTextColor()
|
||||
color: button.textColor
|
||||
font {
|
||||
bold: true
|
||||
pointSize: AbstractTextButtonStyle.text.pointSize
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ Control.RadioButton{
|
|||
font.weight: checked ? RadioButtonStyle.selectedWeight : RadioButtonStyle.weight
|
||||
font.pointSize: RadioButtonStyle.pointSize
|
||||
spacing: 10
|
||||
FontMetrics{id: fontMetrics}
|
||||
FontMetrics{
|
||||
id: fontMetrics
|
||||
font: radio.font
|
||||
}
|
||||
|
||||
MouseArea{
|
||||
anchors.fill:parent
|
||||
|
|
@ -29,7 +32,8 @@ Control.RadioButton{
|
|||
height: fontMetrics.height - 5
|
||||
width: height
|
||||
x: parent.leftPadding
|
||||
y: parent.height / 2 - height / 2
|
||||
//y: parent.height / 2 - (textItem.lineCount > 1 ? height / 2 : 0)
|
||||
y: height / 2
|
||||
radius: width/2
|
||||
border.color: RadioButtonStyle.colorModel.color
|
||||
property bool checked: parent.checked
|
||||
|
|
@ -44,14 +48,15 @@ Control.RadioButton{
|
|||
}
|
||||
}
|
||||
contentItem: Text{
|
||||
id: textItem
|
||||
text: parent.text
|
||||
font: parent.font
|
||||
width: parent.width - (parent.indicator.width + parent.spacing)
|
||||
height: implicitHeight
|
||||
y:0
|
||||
//height: implicitHeight
|
||||
//y:0
|
||||
// Override unwanted auto changes
|
||||
onYChanged: y = 0
|
||||
onHeightChanged: height=implicitHeight
|
||||
//onYChanged: y = 0
|
||||
//onHeightChanged: height=implicitHeight
|
||||
//---------------------------------------
|
||||
color: RadioButtonStyle.colorModel.color
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
|
@ -59,4 +64,4 @@ Control.RadioButton{
|
|||
wrapMode: Text.WordWrap
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,13 @@ Item {
|
|||
property color backgroundColor: '#00000000'
|
||||
property color foregroundColor: '#00000000'
|
||||
readonly property alias status: image.status
|
||||
property int radius: width/2
|
||||
|
||||
Rectangle {
|
||||
id: backgroundArea
|
||||
anchors.fill: parent
|
||||
color: item.backgroundColor
|
||||
radius: width/2
|
||||
radius: item.radius
|
||||
}
|
||||
Image {
|
||||
id: image
|
||||
|
|
@ -36,6 +37,6 @@ Item {
|
|||
anchors.fill: parent
|
||||
visible: color != 'transparent'
|
||||
color: item.foregroundColor
|
||||
radius: width/2
|
||||
radius: item.radius
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,13 +25,15 @@ Item {
|
|||
property bool hideCamera: false
|
||||
property bool isPaused: false
|
||||
property bool deactivateCamera: true
|
||||
property bool isThumbnail: false
|
||||
property bool isDeviceVideoEnabled: container.currentDevice && (isThumbnail ? container.currentDevice.thumbnailVideoEnabled : container.currentDevice.videoEnabled)
|
||||
property bool isVideoEnabled: !deactivateCamera && (!callModel || callModel.videoEnabled)
|
||||
&& (!container.currentDevice || ( callModel && container.currentDevice &&
|
||||
( (! (container.currentDevice.isMe && container.currentDevice.isLocal) && container.currentDevice.videoEnabled)
|
||||
( (! (container.currentDevice.isMe && container.currentDevice.isLocal) && isDeviceVideoEnabled)
|
||||
|| (container.currentDevice.isMe && container.currentDevice.isLocal && callModel.cameraEnabled))))
|
||||
|
||||
property bool a : callModel && callModel.videoEnabled
|
||||
property bool b: container.currentDevice && container.currentDevice.videoEnabled
|
||||
property bool b: isDeviceVideoEnabled
|
||||
property bool c: container.currentDevice && container.currentDevice.isMe && container.currentDevice.isLocal
|
||||
property bool d : callModel && callModel.cameraEnabled
|
||||
property bool isReady: cameraLoader.item && cameraLoader.item.isReady
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Item{
|
|||
property alias isPreview: camera.isPreview
|
||||
property alias isFullscreen: camera.isFullscreen
|
||||
property alias isCameraFromDevice: camera.isCameraFromDevice
|
||||
property alias isThumbnail: camera.isThumbnail
|
||||
property alias qmlName: camera.qmlName
|
||||
property bool showCloseButton: false
|
||||
property bool showActiveSpeakerOverlay: true
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import Linphone.Styles 1.0
|
|||
import LinphoneEnums 1.0
|
||||
|
||||
import UtilsCpp 1.0
|
||||
import DesktopTools 1.0
|
||||
|
||||
import App.Styles 1.0
|
||||
|
||||
|
|
@ -23,6 +24,8 @@ Rectangle{
|
|||
property ParticipantModel me: conferenceModel ? conferenceModel.localParticipant : null
|
||||
property bool isMeAdmin: me && me.adminStatus
|
||||
property bool isParticipantsMenu: false
|
||||
property bool isScreenSharingMenu: false
|
||||
property bool screenSharingAvailable: conferenceModel && (!conferenceModel.isScreenSharingEnabled || conferenceModel.isLocalScreenSharingEnabled)
|
||||
signal close()
|
||||
signal layoutChanging(int layoutMode)
|
||||
|
||||
|
|
@ -40,13 +43,18 @@ Rectangle{
|
|||
//: 'Invite participants' : Menu title to invite participants in admin mode.
|
||||
mainItem.isMeAdmin ? qsTr('incallMenuInvite')
|
||||
//: 'Participants list' : Menu title to show participants in non-admin mode.
|
||||
: qsTr('incallMenuParticipants')
|
||||
: qsTr('incallMenuParticipants'),
|
||||
"Partage d'écran"
|
||||
]
|
||||
|
||||
function showParticipantsMenu(){
|
||||
contentsStack.push(participantsMenu, {title:Qt.binding(function() { return mainItem.menuTitles[2]})})
|
||||
visible = true
|
||||
}
|
||||
function showScreenSharingMenu(){
|
||||
contentsStack.push(screenSharingMenu, {title:Qt.binding(function() { return mainItem.menuTitles[3]})})
|
||||
visible = true
|
||||
}
|
||||
onVisibleChanged: if(!visible && contentsStack.nViews > 1) {
|
||||
contentsStack.pop()
|
||||
}
|
||||
|
|
@ -59,6 +67,7 @@ Rectangle{
|
|||
}
|
||||
}
|
||||
ButtonGroup{id: modeGroup}
|
||||
ButtonGroup{id: screenSharingGroup}
|
||||
ColumnLayout{
|
||||
anchors.fill: parent
|
||||
// HEADER
|
||||
|
|
@ -134,7 +143,12 @@ Rectangle{
|
|||
{ titleIndex: 2
|
||||
, icon: IncallMenuStyle.settingsIcons.participantsIcon
|
||||
, nextPage:participantsMenu
|
||||
, visible: mainItem.callModel && mainItem.callModel.isConference}
|
||||
, visible: mainItem.callModel && mainItem.callModel.isConference},
|
||||
|
||||
{ titleIndex: 3
|
||||
, icon: IncallMenuStyle.settingsIcons.screenSharingIcon
|
||||
, nextPage: screenSharingMenu
|
||||
, visible: mainItem.screenSharingAvailable && SettingsModel.videoAvailable}
|
||||
]
|
||||
delegate:
|
||||
Borders{
|
||||
|
|
@ -226,11 +240,12 @@ Rectangle{
|
|||
Layout.fillWidth: true
|
||||
Repeater{
|
||||
//: 'Mosaic mode' : Grid layout for video conference.
|
||||
model: [{text: qsTr('incallMenuGridLayout'), icon: IncallMenuStyle.modeIcons.gridIcon, value:LinphoneEnums.ConferenceLayoutGrid}
|
||||
model: [{text: qsTr('incallMenuGridLayout'), icon: IncallMenuStyle.modeIcons.gridIcon, value:LinphoneEnums.ConferenceLayoutGrid, enabled: (!mainItem.conferenceModel
|
||||
|| (mainItem.conferenceModel.participantDeviceCount <= SettingsModel.conferenceMaxThumbnails+1 && !mainItem.conferenceModel.isScreenSharingEnabled))}
|
||||
//: 'Active speaker mode' : Active speaker layout for video conference.
|
||||
, {text: qsTr('incallMenuActiveSpeakerLayout'), icon: IncallMenuStyle.modeIcons.activeSpeakerIcon, value:LinphoneEnums.ConferenceLayoutActiveSpeaker}
|
||||
, {text: qsTr('incallMenuActiveSpeakerLayout'), icon: IncallMenuStyle.modeIcons.activeSpeakerIcon, value:LinphoneEnums.ConferenceLayoutActiveSpeaker, enabled: true}
|
||||
//: 'Audio only mode' : Audio only layout for video conference.
|
||||
, {text: qsTr('incallMenuAudioLayout'), icon: IncallMenuStyle.modeIcons.audioOnlyIcon, value:LinphoneEnums.ConferenceLayoutAudioOnly}
|
||||
, {text: qsTr('incallMenuAudioLayout'), icon: IncallMenuStyle.modeIcons.audioOnlyIcon, value:LinphoneEnums.ConferenceLayoutAudioOnly, enabled: true}
|
||||
]
|
||||
delegate:
|
||||
Borders{
|
||||
|
|
@ -238,7 +253,8 @@ Rectangle{
|
|||
bottomWidth: IncallMenuStyle.list.border.width
|
||||
Layout.preferredHeight: Math.max(layoutIcon.height, radio.contentItem.implicitHeight) + 20
|
||||
Layout.fillWidth: true
|
||||
enabled: mainItem.callModel && !mainItem.callModel.updating
|
||||
enabled: mainItem.callModel && !mainItem.callModel.updating && modelData.enabled
|
||||
opacity: enabled ? 1.0 : 0.5
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: radio.clicked()
|
||||
|
|
@ -310,5 +326,130 @@ Rectangle{
|
|||
Component.onDestruction: mainItem.isParticipantsMenu = false
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------------------------
|
||||
Component{
|
||||
id: screenSharingMenu
|
||||
ColumnLayout{
|
||||
id: screenSharingItem
|
||||
property VideoSourceDescriptorModel desc: mainItem.callModel.videoSourceDescriptorModel
|
||||
property string title
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
RadioButton{
|
||||
id: displayRadioButton
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 15
|
||||
text: "Partager l'intégralité de l'écran"
|
||||
font.pointSize: IncallMenuStyle.list.pointSize
|
||||
ButtonGroup.group: screenSharingGroup
|
||||
//checked: screenList.selectedIndex >= 0
|
||||
checked: screenSharingItem.desc && screenSharingItem.desc.isScreenSharing && screenSharingItem.desc.screenSharingType == LinphoneEnums.VideoSourceScreenSharingTypeDisplay
|
||||
onClicked: {
|
||||
screenSharingItem.desc.screenSharingIndex = 0
|
||||
if( mainItem.conferenceModel.isLocalScreenSharingEnabled)
|
||||
mainItem.callModel.setVideoSourceDescriptorModel(screenSharingItem.desc)
|
||||
}
|
||||
}
|
||||
|
||||
ListView{
|
||||
id: screenList
|
||||
property int selectedIndex: displayRadioButton.checked ? screenSharingItem.desc.screenSharingIndex : -1
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 15
|
||||
Layout.preferredWidth: parent.width
|
||||
Layout.preferredHeight: 100
|
||||
orientation: ListView.Horizontal
|
||||
model: ScreenProxyModel{}
|
||||
spacing: 10
|
||||
delegate:Rectangle{
|
||||
width: 114 + 10
|
||||
height: 100
|
||||
border.color: 'red'
|
||||
border.width: index == screenList.selectedIndex ? 1 : 0
|
||||
radius: 10
|
||||
ColumnLayout{
|
||||
anchors.fill: parent
|
||||
anchors.margins: 5
|
||||
RoundedImage{
|
||||
Layout.preferredWidth: 114
|
||||
Layout.preferredHeight: 64
|
||||
backgroundColor: 'white'
|
||||
source: 'image://screen/'+index
|
||||
radius: 10
|
||||
}
|
||||
Text{
|
||||
Layout.fillWidth: true
|
||||
text: modelData.name
|
||||
font.pointSize: IncallMenuStyle.list.pointSize
|
||||
color: IncallMenuStyle.list.colorModel.color
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
}
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
screenSharingItem.desc.screenSharingIndex = index
|
||||
if( mainItem.conferenceModel.isLocalScreenSharingEnabled)
|
||||
mainItem.callModel.setVideoSourceDescriptorModel(screenSharingItem.desc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: IncallMenuStyle.list.border.width
|
||||
color: IncallMenuStyle.list.border.colorModel.color
|
||||
}
|
||||
RadioButton{
|
||||
id: windowSharingRadioButton
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 15
|
||||
text: "Partager une fenêtre"
|
||||
font.pointSize: IncallMenuStyle.list.pointSize
|
||||
ButtonGroup.group: screenSharingGroup
|
||||
checked: screenSharingItem.desc && screenSharingItem.desc.isScreenSharing && screenSharingItem.desc.screenSharingType == LinphoneEnums.VideoSourceScreenSharingTypeWindow//screenList.selectedIndex < 0
|
||||
onClicked: DesktopTools.getWindowIdFromMouse(screenSharingItem.desc)
|
||||
Connections{
|
||||
target: DesktopTools
|
||||
onWindowIdSelectionEnded: if( mainItem.conferenceModel.isLocalScreenSharingEnabled)
|
||||
mainItem.callModel.setVideoSourceDescriptorModel(screenSharingItem.desc)
|
||||
}
|
||||
}
|
||||
Rectangle{
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: IncallMenuStyle.list.border.width
|
||||
color: IncallMenuStyle.list.border.colorModel.color
|
||||
}
|
||||
Item{// Spacer
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
Item{// Item encapsulation because of a bug on width update when changing text
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: screenSharingButton.fitHeight
|
||||
Layout.margins: 20
|
||||
TextButtonB{
|
||||
id: screenSharingButton
|
||||
anchors.fill: parent
|
||||
visible: mainItem.screenSharingAvailable
|
||||
enabled: displayRadioButton.checked || windowSharingRadioButton.checked
|
||||
text: mainItem.conferenceModel && mainItem.conferenceModel.isLocalScreenSharingEnabled
|
||||
//: 'Stop' : Text button to stop the screen sharing.
|
||||
? qsTr('incallMenuScreenSharingStop')
|
||||
//: 'Share' : Text button to start the screen sharing.
|
||||
: qsTr('incallMenuScreenSharingStart')
|
||||
capitalization: Font.AllUppercase
|
||||
onClicked: mainItem.conferenceModel.toggleScreenSharing()
|
||||
Connections{
|
||||
target: mainItem.conferenceModel
|
||||
onLocalScreenSharingChanged: (enabled) => {if(enabled) mainItem.callModel.setVideoSourceDescriptorModel(screenSharingItem.desc) }
|
||||
}
|
||||
}
|
||||
}
|
||||
Component.onCompleted: mainItem.isScreenSharingMenu = true
|
||||
Component.onDestruction: mainItem.isScreenSharingMenu = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ DecorationSticker{
|
|||
property alias isCameraFromDevice: camera.isCameraFromDevice
|
||||
property alias isReady: camera.isReady
|
||||
property alias isVideoEnabled: camera.isVideoEnabled
|
||||
property alias isThumbnail: camera.isThumbnail
|
||||
property alias cameraQmlName: camera.qmlName
|
||||
property bool showCloseButton: false
|
||||
property bool showActiveSpeakerOverlay: true
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ Item{
|
|||
property alias deactivateCamera: camera.deactivateCamera
|
||||
readonly property alias isVideoEnabled: camera.isVideoEnabled
|
||||
property alias cameraQmlName: camera.cameraQmlName
|
||||
property alias isThumbnail: camera.isThumbnail
|
||||
|
||||
property alias image: avatar.image
|
||||
property alias avatarBackgroundColor: avatar.avatarBackgroundColor
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ QtObject {
|
|||
property string audioOnlyIcon: 'conference_audio_only_custom'
|
||||
property string mediaIcon: 'micro_on_custom'
|
||||
property string participantsIcon: 'participants_custom'
|
||||
property string screenSharingIcon: 'screen_sharing_custom'
|
||||
|
||||
property int width: 40
|
||||
property int height: 40
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import Linphone 1.0
|
|||
|
||||
import LinphoneEnums 1.0
|
||||
import UtilsCpp 1.0
|
||||
import DesktopTools 1.0
|
||||
|
||||
import App.Styles 1.0
|
||||
|
||||
|
|
@ -28,6 +29,8 @@ Rectangle {
|
|||
property bool previewIsReady : false
|
||||
property bool isFullScreen: false // Use this variable to test if we are in fullscreen. Do not test _fullscreen : we need to clean memory before having the window (see .js file)
|
||||
property bool layoutChanging: false
|
||||
property bool isLocalScreenSharingEnabled: conferenceModel && conferenceModel.isLocalScreenSharingEnabled
|
||||
property bool isScreenSharingEnabled: conferenceModel && conferenceModel.isScreenSharingEnabled
|
||||
|
||||
property var _fullscreen: null
|
||||
on_FullscreenChanged: if( !_fullscreen) isFullScreen = false
|
||||
|
|
@ -251,12 +254,41 @@ Rectangle {
|
|||
}
|
||||
}
|
||||
// Mode buttons
|
||||
TextButtonB{
|
||||
id: screenSharingButton
|
||||
visible: mainItem.isScreenSharingEnabled
|
||||
Layout.preferredWidth: fitWidth
|
||||
Icon{
|
||||
id: screenSharingIcon
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 10
|
||||
icon: IncallStyle.buttons.screenSharing.icon
|
||||
iconSize: IncallStyle.buttons.screenSharing.iconSize
|
||||
overwriteColor: screenSharingButton.textColor
|
||||
}
|
||||
button.leftPadding: screenSharingIcon.width
|
||||
addHeight: 15
|
||||
addWidth: 75
|
||||
radius: height/4
|
||||
text: mainItem.isLocalScreenSharingEnabled ? "Arrêter la présentation" : "Présentation en cours"
|
||||
onClicked: if(mainItem.isLocalScreenSharingEnabled) conferenceModel.toggleScreenSharing()
|
||||
}
|
||||
ActionButton{
|
||||
visible: !screenSharingButton.visible && callModel && mainItem.conferenceModel && callModel.videoEnabled
|
||||
isCustom: true
|
||||
backgroundRadius: width/2
|
||||
colorSet: IncallStyle.buttons.screenSharing
|
||||
visible: false //TODO
|
||||
toggled: rightMenu.visible && rightMenu.isScreenSharingMenu
|
||||
|
||||
onClicked: {
|
||||
if(toggled)
|
||||
rightMenu.visible = false
|
||||
else
|
||||
rightMenu.showScreenSharingMenu()
|
||||
}
|
||||
}
|
||||
|
||||
ActionButton {
|
||||
id: recordingSwitch
|
||||
isCustom: true
|
||||
|
|
@ -637,10 +669,20 @@ Rectangle {
|
|||
onClicked: rightMenu.visible = !rightMenu.visible
|
||||
}
|
||||
}
|
||||
Connections{
|
||||
target: DesktopTools
|
||||
onWindowIdSelectionStarted: window.attachVirtualWindow(Utils.buildCommonDialogUri('ConfirmDialog'), {
|
||||
descriptionText: "Click on the window that you want to share."
|
||||
, showButtonOnly: 42
|
||||
, buttonTexts : ['']
|
||||
})
|
||||
onWindowIdSelectionEnded: window.detachVirtualWindow()
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TelKeypad.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CallStatistics {
|
||||
id: callStatistics
|
||||
|
||||
|
|
|
|||
|
|
@ -27,14 +27,15 @@ Item {
|
|||
property bool cameraEnabled: true
|
||||
property bool isConference: callModel && callModel.isConference
|
||||
property bool isConferenceReady: isConference && callModel.conferenceModel && callModel.conferenceModel.isReady
|
||||
|
||||
property ConferenceModel conferenceModel: callModel && callModel.conferenceModel
|
||||
property bool isScreenSharingEnabled: conferenceModel && conferenceModel.isScreenSharingEnabled
|
||||
property bool isLocalScreenSharingEnabled: conferenceModel && conferenceModel.isLocalScreenSharingEnabled
|
||||
property int participantCount: isConference ? allDevices.count + 1 : 2 // +me. allDevices==0 if !conference
|
||||
|
||||
property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel {
|
||||
id: allDevices
|
||||
callModel: mainItem.callModel
|
||||
showMe: false
|
||||
|
||||
showMe: false
|
||||
onConferenceCreated: cameraView.resetCamera()
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +60,7 @@ Item {
|
|||
|| !mainItem.isConferenceReady
|
||||
: (callModel && (callModel.pausedByUser || callModel.status === CallModel.CallStatusPaused || !callModel.videoEnabled) )
|
||||
|| currentDevice && !currentDevice.videoEnabled
|
||||
isPreview: !preview.visible && mainItem.participantCount == 1
|
||||
isPreview: !preview.visible && mainItem.participantCount == 1 && !isScreenSharingEnabled
|
||||
onIsPreviewChanged: {cameraView.resetCamera() }
|
||||
isCameraFromDevice: isPreview
|
||||
isPaused: isPreview && callModel.pausedByUser
|
||||
|
|
@ -86,7 +87,7 @@ Item {
|
|||
height: visible ? miniViews.cellHeight : 0
|
||||
width: 16 * height / 9
|
||||
|
||||
visible: mainItem.isConferenceReady && allDevices.count >= 1
|
||||
visible: mainItem.isConferenceReady && (allDevices.count >= 1 || mainItem.isLocalScreenSharingEnabled)
|
||||
|| (!mainItem.isConference && mainItem.callModel && mainItem.callModel.cameraEnabled)// use videoEnabled if we want to show the preview sticker
|
||||
|
||||
Loader{
|
||||
|
|
@ -152,7 +153,7 @@ Item {
|
|||
id: miniViews
|
||||
property int cellHeight: 150
|
||||
anchors.fill: parent
|
||||
model : mainItem.isConference && mainItem.participantDevices.count > 1 ? mainItem.participantDevices : []
|
||||
model : /*mainItem.isConference && mainItem.participantDevices.count > 1 ? */mainItem.participantDevices //: []
|
||||
spacing: 0
|
||||
verticalLayoutDirection: ListView.BottomToTop
|
||||
fitCacheToContent: false
|
||||
|
|
@ -162,7 +163,7 @@ Item {
|
|||
delegate:Item{
|
||||
height: visible ? miniViews.cellHeight + 15 : 0
|
||||
width: visible ? miniViews.width : 0
|
||||
visible: cameraView.currentDevice != modelData
|
||||
visible: cameraView.currentDevice != modelData || mainItem.isScreenSharingEnabled
|
||||
clip:false
|
||||
Sticker{
|
||||
id: miniView
|
||||
|
|
@ -172,8 +173,9 @@ Item {
|
|||
anchors.rightMargin: 3
|
||||
anchors.bottomMargin: 18
|
||||
cameraQmlName: 'S_'+index
|
||||
isThumbnail: true
|
||||
deactivateCamera: (!mainItem.isConferenceReady || !mainItem.isConference)
|
||||
&& (index <0 || !mainItem.cameraEnabled || (!modelData.videoEnabled) || (callModel && callModel.pausedByUser) )
|
||||
&& (index <0 || !mainItem.cameraEnabled || (!modelData.thumbnailVideoEnabled) || (callModel && callModel.pausedByUser) )
|
||||
currentDevice: modelData.isPreview ? null : modelData
|
||||
callModel: modelData.isPreview ? null : mainItem.callModel
|
||||
isCameraFromDevice: mainItem.isConference
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ Window {
|
|||
console.info('[QML] Call becomes not ready : exit fullscreen')
|
||||
window.exit()
|
||||
}
|
||||
property bool isLocalScreenSharingEnabled: conferenceModel && conferenceModel.isLocalScreenSharingEnabled
|
||||
property bool isScreenSharingEnabled: conferenceModel && conferenceModel.isScreenSharingEnabled
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function exit (cb) {
|
||||
|
|
@ -223,11 +225,39 @@ Window {
|
|||
font.pointSize: IncallStyle.title.pointSize
|
||||
}
|
||||
// Mode buttons
|
||||
TextButtonB{
|
||||
id: screenSharingButton
|
||||
visible: window.isScreenSharingEnabled
|
||||
Layout.preferredWidth: fitWidth
|
||||
Icon{
|
||||
id: screenSharingIcon
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.leftMargin: 10
|
||||
icon: IncallStyle.buttons.screenSharing.icon
|
||||
iconSize: IncallStyle.buttons.screenSharing.iconSize
|
||||
overwriteColor: screenSharingButton.textColor
|
||||
}
|
||||
button.leftPadding: screenSharingIcon.width
|
||||
addHeight: 15
|
||||
addWidth: 75
|
||||
radius: height/4
|
||||
text: window.isLocalScreenSharingEnabled ? "Arrêter la présentation" : "Présentation en cours"
|
||||
onClicked: if(window.isLocalScreenSharingEnabled) conferenceModel.toggleScreenSharing()
|
||||
}
|
||||
ActionButton{
|
||||
visible: !screenSharingButton.visible && callModel && window.conferenceModel && callModel.videoEnabled
|
||||
isCustom: true
|
||||
backgroundRadius: width/2
|
||||
colorSet: IncallStyle.buttons.screenSharing
|
||||
visible: false //TODO
|
||||
toggled: rightMenu.visible && rightMenu.isScreenSharingMenu
|
||||
|
||||
onClicked: {
|
||||
if(toggled)
|
||||
rightMenu.visible = false
|
||||
else
|
||||
rightMenu.showScreenSharingMenu()
|
||||
}
|
||||
}
|
||||
ActionButton {
|
||||
id: recordingSwitch
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import QtGraphicalEffects 1.12
|
|||
|
||||
import Common 1.0
|
||||
import Linphone 1.0
|
||||
import DesktopTools 1.0
|
||||
|
||||
import App.Styles 1.0
|
||||
|
||||
|
|
@ -11,6 +12,8 @@ import App.Styles 1.0
|
|||
DialogPlus {
|
||||
id: dialog
|
||||
|
||||
|
||||
|
||||
buttons: [
|
||||
TextButtonB {
|
||||
text: qsTr('confirm')
|
||||
|
|
@ -26,8 +29,9 @@ DialogPlus {
|
|||
width: SettingsVideoPreviewStyle.width
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
Item{
|
||||
MouseArea{
|
||||
anchors.fill: parent
|
||||
onClicked: DesktopTools.getWindowIdFromMouse()
|
||||
CameraView{
|
||||
id: previewLoader
|
||||
anchors.centerIn: parent
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import Common 1.0
|
|||
import Linphone 1.0
|
||||
import LinphoneEnums 1.0
|
||||
import Utils 1.0
|
||||
import Units 1.0
|
||||
import DesktopTools 1.0
|
||||
|
||||
import App.Styles 1.0
|
||||
|
||||
|
|
@ -288,6 +290,7 @@ TabContainer {
|
|||
}
|
||||
}
|
||||
FormLine {
|
||||
width: parent.width
|
||||
FormGroup {
|
||||
//: 'Default video layout' : Label to choose the default layout in video conference.
|
||||
label: qsTr('videoLayout')
|
||||
|
|
@ -303,6 +306,17 @@ TabContainer {
|
|||
onActivated: SettingsModel.videoConferenceLayout = model[index].value
|
||||
}
|
||||
}
|
||||
FormGroup {
|
||||
label: 'Maximum thumbnails'
|
||||
|
||||
NumericField {
|
||||
maxValue: 60
|
||||
minValue: 0
|
||||
text: SettingsModel.conferenceMaxThumbnails
|
||||
|
||||
onEditingFinished: SettingsModel.conferenceMaxThumbnails = text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,9 +226,12 @@ QtObject {
|
|||
property var backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 's_n_b_bg')
|
||||
property var backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 's_h_b_bg')
|
||||
property var backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 's_p_b_bg')
|
||||
property var backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_c', icon, 's_p_b_bg')
|
||||
property var foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 's_n_b_fg')
|
||||
property var foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 's_h_b_fg')
|
||||
property var foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 's_p_b_fg')
|
||||
property var foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_c', icon, 's_p_b_fg')
|
||||
|
||||
}
|
||||
property QtObject record: QtObject {
|
||||
property int iconSize: 40
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e310a060639474dd333239810d86d14db5f9c83d
|
||||
Subproject commit 119c43076dbfc48ee25642c3bff52b975b08194e
|
||||
Loading…
Add table
Reference in a new issue