- Fix Mac build on unsupported XCFramework.

- Change layout icons.
- Allow to change layout in prepare room.
- Add a status to Camera when Ready : print waiting message if conference is not ready (call created and have participants).
- Display avatar if camera is not ready.
- Change Active Speaker to use call stream and not participant device.
- Change avatar colors.
- Active speaker mode have scrollable miniatures (16/9 format).
- Move close preview icon.
- Change layout icon on selection.
This commit is contained in:
Julien Wadel 2022-04-29 17:23:18 +02:00
parent efcb67944e
commit b8d0fb5e46
25 changed files with 363 additions and 322 deletions

1
.gitignore vendored
View file

@ -13,6 +13,7 @@ WORK
OUTPUT
Makefile
CMakeLists.txt.user
build*
build-*-Debug
build-*-Default
prepare.conf.user

View file

@ -174,6 +174,8 @@ endif()
if(UNIX AND NOT APPLE)
set(CMAKE_INSTALL_RPATH "$ORIGIN:$ORIGIN/lib64:$ORIGIN/../lib64:$ORIGIN/lib:$ORIGIN/../lib:${LINPHONE_OUTPUT_DIR}/${CMAKE_INSTALL_LIBDIR}")
list(APPEND APP_OPTIONS "-DCMAKE_INSTALL_RPATH=${CMAKE_INSTALL_RPATH}")
elseif(APPLE)
list(APPEND APP_OPTIONS "-DENABLE_FAT_BINARY=ON") #Disable XCFrameworks as it is not supported.
endif()
if(CMAKE_OSX_DEPLOYMENT_TARGET)
list(APPEND APP_OPTIONS "-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")

View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="80"
height="80"
viewBox="0 0 80 80"
version="1.1"
id="svg16"
sodipodi:docname="conference_layout_active_speaker_custom.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview18"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
width="80px"
inkscape:zoom="5.6283784"
inkscape:cx="74"
inkscape:cy="74.088836"
inkscape:window-width="1920"
inkscape:window-height="1163"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg16" />
<defs
id="defs6">
<rect
id="6lujqo9djb"
x="0"
y="0"
width="42"
height="70"
rx="5" />
<rect
id="pr4awmy6kd"
x="0"
y="0"
width="27"
height="33"
rx="5" />
<path
id="h4d9168nsa"
d="M 0,0 H 42 V 70 H 0 Z" />
<path
id="30xwhu0i0c"
d="M 0,0 H 27 V 33 H 0 Z" />
</defs>
<g
fill="none"
fill-rule="evenodd"
id="g14"
transform="matrix(0.68737767,0,0,0.70608441,-10.931995,-12.537292)">
<rect
stroke="#000000"
stroke-width="4"
x="2"
y="2"
width="38"
height="66"
rx="5"
transform="translate(45,39)"
id="rect8" />
<g
id="g12">
<rect
stroke="#000000"
stroke-width="4"
x="2"
y="2"
width="23"
height="29"
rx="5"
transform="translate(76,76)"
id="rect10" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -4,16 +4,15 @@
height="80"
viewBox="0 0 80 80"
version="1.1"
id="svg90"
sodipodi:docname="conference_layout_grid.svg"
id="svg26"
sodipodi:docname="conference_layout_grid_custom.svg"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview92"
id="namedview28"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
@ -22,286 +21,108 @@
inkscape:pagecheckerboard="0"
showgrid="false"
width="80px"
inkscape:zoom="5.20625"
inkscape:cx="15.270108"
inkscape:cy="18.631453"
inkscape:zoom="5.6283784"
inkscape:cx="74"
inkscape:cy="74.088835"
inkscape:window-width="1920"
inkscape:window-height="1043"
inkscape:window-x="1920"
inkscape:window-height="1163"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg90" />
inkscape:current-layer="svg26" />
<defs
id="defs62">
id="defs10">
<rect
id="7d73pidfgb"
id="nrceunfdkb"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="2.766" />
width="27"
height="33"
rx="5" />
<rect
id="yz4p2363vc"
id="xmkteln59d"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="1" />
width="27"
height="33"
rx="5" />
<rect
id="0ixe1p4o1e"
id="bdnudj63cf"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="2.766" />
width="27"
height="33"
rx="5" />
<rect
id="gqqj4bqr3f"
id="0qs35dlrmh"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="1" />
<rect
id="ei3bofohqh"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="2.766" />
<rect
id="fw8jktzkci"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="1" />
<rect
id="5kuxk18otk"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="2.766" />
<rect
id="j81y1lwafl"
x="0"
y="0"
width="9.5240002"
height="5.533"
rx="1" />
<filter
x="-0.062998739"
y="-0.10844027"
width="1.1259975"
height="1.2168805"
filterUnits="objectBoundingBox"
id="1w3vu8nnia">
<feOffset
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset10" />
<feGaussianBlur
stdDeviation=".25"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur12" />
<feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
in="shadowBlurOuter1"
result="shadowMatrixOuter1"
id="feColorMatrix14" />
<feMerge
id="feMerge20">
<feMergeNode
in="shadowMatrixOuter1"
id="feMergeNode16" />
<feMergeNode
in="SourceGraphic"
id="feMergeNode18" />
</feMerge>
</filter>
<filter
x="-0.062998739"
y="-0.10844027"
width="1.1259975"
height="1.2168805"
filterUnits="objectBoundingBox"
id="46vopj45hd">
<feOffset
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset23" />
<feGaussianBlur
stdDeviation=".25"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur25" />
<feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
in="shadowBlurOuter1"
result="shadowMatrixOuter1"
id="feColorMatrix27" />
<feMerge
id="feMerge33">
<feMergeNode
in="shadowMatrixOuter1"
id="feMergeNode29" />
<feMergeNode
in="SourceGraphic"
id="feMergeNode31" />
</feMerge>
</filter>
<filter
x="-0.062998739"
y="-0.10844027"
width="1.1259975"
height="1.2168805"
filterUnits="objectBoundingBox"
id="jnauojodeg">
<feOffset
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset36" />
<feGaussianBlur
stdDeviation=".25"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur38" />
<feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
in="shadowBlurOuter1"
result="shadowMatrixOuter1"
id="feColorMatrix40" />
<feMerge
id="feMerge46">
<feMergeNode
in="shadowMatrixOuter1"
id="feMergeNode42" />
<feMergeNode
in="SourceGraphic"
id="feMergeNode44" />
</feMerge>
</filter>
<filter
x="-0.062998739"
y="-0.10844027"
width="1.1259975"
height="1.2168805"
filterUnits="objectBoundingBox"
id="kc22z3ksgj">
<feOffset
in="SourceAlpha"
result="shadowOffsetOuter1"
id="feOffset49" />
<feGaussianBlur
stdDeviation=".25"
in="shadowOffsetOuter1"
result="shadowBlurOuter1"
id="feGaussianBlur51" />
<feColorMatrix
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0"
in="shadowBlurOuter1"
result="shadowMatrixOuter1"
id="feColorMatrix53" />
<feMerge
id="feMerge59">
<feMergeNode
in="shadowMatrixOuter1"
id="feMergeNode55" />
<feMergeNode
in="SourceGraphic"
id="feMergeNode57" />
</feMerge>
</filter>
width="27"
height="33"
rx="5" />
<path
id="rdfobamz0a"
d="M 0,0 H 27 V 33 H 0 Z" />
<path
id="4g0468k0zc"
d="M 0,0 H 27 V 33 H 0 Z" />
<path
id="g1ydbc0vje"
d="M 0,0 H 27 V 33 H 0 Z" />
<path
id="bcq9c9r9xg"
d="M 0,0 H 27 V 33 H 0 Z" />
</defs>
<g
fill="none"
fill-rule="evenodd"
id="g88"
transform="matrix(1.9811369,0,0,1.9721192,-0.6226868,-0.42639723)">
id="g24"
transform="matrix(0.59895046,0,0,0.70984408,-4.4527707,-12.683919)">
<rect
stroke="#000000"
stroke-width="4"
x="2"
y="2"
width="23"
height="29"
rx="5"
transform="translate(76,39)"
id="rect12" />
<rect
stroke="#000000"
stroke-width="4"
x="2"
y="2"
width="23"
height="29"
rx="5"
transform="translate(45,39)"
id="rect14" />
<g
filter="url(#1w3vu8nnia)"
transform="translate(20.476,20.455)"
id="g68">
<use
fill="#000000"
xlink:href="#7d73pidfgb"
id="use64"
x="0"
y="0"
width="100%"
height="100%" />
<use
fill="#000000"
xlink:href="#yz4p2363vc"
id="use66"
x="0"
y="0"
width="100%"
height="100%" />
id="g18">
<rect
stroke="#000000"
stroke-width="4"
x="2"
y="2"
width="23"
height="29"
rx="5"
transform="translate(45,76)"
id="rect16" />
</g>
<g
filter="url(#46vopj45hd)"
transform="translate(20.476,14)"
id="g74">
<use
fill="#000000"
xlink:href="#0ixe1p4o1e"
id="use70"
x="0"
y="0"
width="100%"
height="100%" />
<use
fill="#000000"
xlink:href="#gqqj4bqr3f"
id="use72"
x="0"
y="0"
width="100%"
height="100%" />
</g>
<g
filter="url(#jnauojodeg)"
transform="translate(10,20.455)"
id="g80">
<use
fill="#000000"
xlink:href="#ei3bofohqh"
id="use76"
x="0"
y="0"
width="100%"
height="100%" />
<use
fill="#000000"
xlink:href="#fw8jktzkci"
id="use78"
x="0"
y="0"
width="100%"
height="100%" />
</g>
<g
filter="url(#kc22z3ksgj)"
transform="translate(10,14)"
id="g86">
<use
fill="#000000"
xlink:href="#5kuxk18otk"
id="use82"
x="0"
y="0"
width="100%"
height="100%" />
<use
fill="#000000"
xlink:href="#j81y1lwafl"
id="use84"
x="0"
y="0"
width="100%"
height="100%" />
id="g22">
<rect
stroke="#000000"
stroke-width="4"
x="2"
y="2"
width="23"
height="29"
rx="5"
transform="translate(76,76)"
id="rect20" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -56,7 +56,7 @@
<file>assets/images/conference_custom.svg</file>
<file>assets/images/conference_layout_grid_custom.svg</file>
<file>assets/images/conference_layout_grid.svg</file>
<file>assets/images/conference_layout_active_speaker.svg</file>
<file>assets/images/conference_layout_active_speaker_custom.svg</file>
<file>assets/images/contact_add_custom.svg</file>
<file>assets/images/contact_card_photo_custom.svg</file>
<file>assets/images/contact_custom.svg</file>

View file

@ -184,7 +184,7 @@ void CallsListModel::launchVideoCall (const QString &sipAddress, const QString&
shared_ptr<linphone::CallParams> params = core->createCallParams(nullptr);
params->setConferenceVideoLayout(linphone::ConferenceLayout::Grid);
params->setConferenceVideoLayout(options.contains("layout") ? LinphoneEnums::toLinphone((LinphoneEnums::ConferenceLayout)options["layout"].toInt()) : linphone::ConferenceLayout::Grid);
params->enableMic(options.contains("micro") ? options["micro"].toBool() : true);
bool enableVideo = options.contains("video") ? options["video"].toBool() : true;

View file

@ -80,8 +80,9 @@ void Camera::resetWindowId() {
QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
QQuickFramebufferObject::Renderer * renderer = NULL;
bool useDefaultWindow = false;
bool useDefaultWindow = true;
if(mIsPreview){
qWarning() << "Setting Camera to Preview";
renderer = (QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativePreviewWindowId();
if(renderer)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(NULL);// Reset
@ -92,17 +93,19 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
if(mCallModel){
auto call = mCallModel->getCall();
if(call){
qWarning() << "Setting Camera to CallModel";
renderer = (QQuickFramebufferObject::Renderer *) call->getNativeVideoWindowId();
if(renderer)
call->setNativeVideoWindowId(NULL);// Reset
renderer = (QQuickFramebufferObject::Renderer *) call->createNativeVideoWindowId();
if(renderer)
call->setNativeVideoWindowId(renderer);
}else
useDefaultWindow = true;
useDefaultWindow = false;
}
}else if( mParticipantDeviceModel){
auto participantDevice = mParticipantDeviceModel->getDevice();
if(participantDevice){
qWarning() << "Setting Camera to Participant Device";
renderer = (QQuickFramebufferObject::Renderer *)participantDevice->getNativeVideoWindowId();
if(renderer)
participantDevice->setNativeVideoWindowId(NULL);// Reset
@ -110,10 +113,11 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
renderer = (QQuickFramebufferObject::Renderer *) participantDevice->createNativeVideoWindowId();
if(renderer)
participantDevice->setNativeVideoWindowId(renderer);
}else
useDefaultWindow = true;
useDefaultWindow = false;
}
}
if(useDefaultWindow){
qWarning() << "Setting Camera to Defaul tWindow";
renderer = (QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->getNativeVideoWindowId();
if(renderer)
CoreManager::getInstance()->getCore()->setNativeVideoWindowId(NULL);
@ -123,10 +127,13 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
}
}
if( !renderer){
QTimer::singleShot(1, this, &Camera::isNotReady);// Workaround for const createRenderer
qWarning() << "Camera stream couldn't start for Rendering. Retrying in 1s";
renderer = new CameraDummy();
QTimer::singleShot(1000, this, &Camera::requestNewRenderer);
}else{
QTimer::singleShot(1, this, &Camera::isReady);// Workaround for const createRenderer
}
return renderer;
}
@ -141,6 +148,10 @@ bool Camera::getIsPreview () const {
return mIsPreview;
}
bool Camera::getIsReady () const {
return mIsReady;
}
ParticipantDeviceModel * Camera::getParticipantDeviceModel() const{
return mParticipantDeviceModel;
}
@ -167,6 +178,13 @@ void Camera::setIsPreview (bool status) {
}
}
void Camera::setIsReady(bool status) {
if (mIsReady != status) {
mIsReady = status;
emit isReadyChanged();
}
}
void Camera::setParticipantDeviceModel(ParticipantDeviceModel * participantDeviceModel){
if (mParticipantDeviceModel != participantDeviceModel) {
mParticipantDeviceModel = participantDeviceModel;
@ -175,6 +193,13 @@ if (mParticipantDeviceModel != participantDeviceModel) {
}
}
void Camera::isReady(){
setIsReady(true);
}
void Camera::isNotReady(){
setIsReady(false);
}
void Camera::activatePreview(){
mPreviewCounterMutex.lock();
if (++mPreviewCounter == 1)

View file

@ -43,6 +43,7 @@ class Camera : public QQuickFramebufferObject {
Q_PROPERTY(CallModel * call READ getCallModel WRITE setCallModel NOTIFY callChanged);
Q_PROPERTY(ParticipantDeviceModel * participantDeviceModel READ getParticipantDeviceModel WRITE setParticipantDeviceModel NOTIFY participantDeviceModelChanged)
Q_PROPERTY(bool isPreview READ getIsPreview WRITE setIsPreview NOTIFY isPreviewChanged);
Q_PROPERTY(bool isReady READ getIsReady WRITE setIsReady NOTIFY isReadyChanged);
public:
Camera (QQuickItem *parent = Q_NULLPTR);
@ -55,25 +56,32 @@ public:
static QMutex mPreviewCounterMutex;
static int mPreviewCounter;
void isReady();
void isNotReady();
signals:
void callChanged (CallModel *callModel);
void isPreviewChanged (bool isPreview);
void isReadyChanged();
void participantDeviceModelChanged(ParticipantDeviceModel *participantDeviceModel);
void requestNewRenderer();
private:
CallModel *getCallModel () const;
bool getIsPreview () const;
bool getIsReady () const;
ParticipantDeviceModel * getParticipantDeviceModel() const;
void setCallModel (CallModel *callModel);
void setIsPreview (bool status);
void setIsReady(bool status);
void setParticipantDeviceModel(ParticipantDeviceModel * participantDeviceModel);
void activatePreview();
void deactivatePreview();
bool mIsPreview = false;
bool mIsReady = false;
CallModel *mCallModel = nullptr;
ParticipantDeviceModel *mParticipantDeviceModel = nullptr;

View file

@ -113,7 +113,10 @@ class ColorListModel : public ProxyListModel {
ADD_COLOR("event_in", "#96C11F", "Event colors that are incoming")
ADD_COLOR("event_out", "#18A7AF", "Event colors that are outgoing")
ADD_COLOR("conference_bg", "#D0D8DE", "Conferences : Background entry")
ADD_COLOR("conference_entry_bg", "#D0D8DE", "Conferences : Background entry")
ADD_COLOR("conference_out_avatar_bg", "#A1A1A1", "Conferences: Background avatar")
ADD_COLOR("conference_bg", "#798791", "Conferences: Background")
// Standard actions
//

View file

@ -95,6 +95,7 @@ void ParticipantDeviceProxyModel::setShowMe(const bool& show){
if( mShowMe != show) {
mShowMe = show;
emit showMeChanged();
invalidate();
}
}

View file

@ -66,7 +66,7 @@ protected:
QSharedPointer<ParticipantDeviceListModel> mDevices;
CallModel * mCallModel;
bool mShowMe = false;
bool mShowMe = true;
};
#endif

View file

@ -17,35 +17,22 @@ import 'qrc:/ui/scripts/Utils/utils.js' as Utils
Item {
id: container
property ParticipantDeviceModel currentDevice
property bool isPreview: !container.currentDevice || container.currentDevice.isMe
property CallModel callModel
property bool isPreview: !callModel && ( !container.currentDevice || container.currentDevice.isMe)
property bool isFullscreen: false
property bool hideCamera: false //callModel.pausedByUser
property bool isPaused: false
property bool isVideoEnabled: enabled && (!container.currentDevice || (container.currentDevice && container.currentDevice.videoEnabled))
property bool isReady: cameraLoader.item && cameraLoader.item.isReady
onCurrentDeviceChanged: resetActive()
function resetActive(){
resetTimer.resetActive()
}
Component {
id: avatar
IncallAvatar {
participantDeviceModel: container.currentDevice
height: Utils.computeAvatarSize(container, CallStyle.container.avatar.maxSize)
width: height
}
}
Loader {
anchors.centerIn: parent
active: container.currentDevice && !container.currentDevice.isMe && (!container.currentDevice.videoEnabled || container.isFullscreen)
sourceComponent: avatar
}
Loader {
id: cameraLoader
property bool resetActive: false
anchors.fill: parent
active: container.enabled && !resetActive && container.isVideoEnabled //avatarCell.currentDevice && (avatarCell.currentDevice.videoEnabled && !conference._fullscreen)
@ -70,13 +57,13 @@ Item {
id: camera
Camera {
participantDeviceModel: container.currentDevice
call: container.callModel
anchors.fill: parent
isPreview: container.isPreview
onRequestNewRenderer: {resetTimer.resetActive()}
Component.onDestruction: {resetWindowId(); console.log("Destroyed Camera [" + isPreview + "] : " + camera)}
Component.onCompleted: console.log("Completed Camera [" + isPreview + "] : " + camera)
}
}
}

View file

@ -2,20 +2,25 @@ import QtQuick 2.7
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.12
import App.Styles 1.0
import Common 1.0
import Common.Styles 1.0
import Linphone 1.0
import Linphone.Styles 1.0
import 'qrc:/ui/scripts/Utils/utils.js' as Utils
// =============================================================================
Item{
id: mainItem
property alias currentDevice: camera.currentDevice
property alias callModel: camera.callModel
property alias hideCamera: camera.hideCamera
property alias isPaused: camera.isPaused
property alias isPreview: camera.isPreview
property alias isFullscreen: camera.isFullscreen
property bool showCloseButton: true
property color color : CameraViewStyle.backgroundColor
property color color : CameraViewStyle.outBackgroundColor
signal closeRequested()
MouseArea{
@ -36,10 +41,27 @@ Item{
color: mainItem.color
anchors.fill: parent
radius: CameraViewStyle.radius
Component {
id: avatar
IncallAvatar {
participantDeviceModel: mainItem.currentDevice
height: Utils.computeAvatarSize(mainItem, CallStyle.container.avatar.maxSize)
width: height
backgroundColor: CameraViewStyle.inAvatarBackgroundColor
}
}
Loader {
anchors.centerIn: parent
active: mainItem.currentDevice && !camera.isReady //&& !mainItem.currentDevice.isMe && (!mainItem.currentDevice.videoEnabled || mainItem.isFullscreen)
sourceComponent: avatar
}
}
Rectangle{
id: showArea
anchors.fill: parent
radius: CameraViewStyle.radius
visible: false
@ -47,14 +69,15 @@ Item{
}
CameraItem{
id: camera
anchors.centerIn: parent
anchors.fill: parent
visible: true
visible: false
}
OpacityMask{
id: renderedCamera
anchors.fill: parent
source: camera
maskSource: backgroundArea
maskSource: showArea
invert:false
visible: true
@ -99,7 +122,7 @@ Item{
}
Text{
id: username
visible: mainItem.currentDevice
visible: mainItem.currentDevice
anchors.right: parent.right
anchors.left: parent.left
anchors.bottom: parent.bottom
@ -132,8 +155,8 @@ Item{
visible: mainItem.showCloseButton && camera.isPreview
anchors.right: parent.right
anchors.top: parent.top
anchors.rightMargin: 15
anchors.topMargin: 15
anchors.rightMargin: 5
anchors.topMargin: 5
isCustom: true
colorSet: CameraViewStyle.closePreview
onClicked: mainItem.closeRequested()

View file

@ -10,8 +10,10 @@ import ColorsList 1.0
QtObject {
property string sectionName: 'CameraView'
property color backgroundColor: ColorsList.add(sectionName+'_description', '', '', '#798791').color
property int radius : 8
property color outBackgroundColor: ColorsList.add(sectionName+'_out_bg', 'conference_out_avatar_bg').color
property color inAvatarBackgroundColor: ColorsList.add(sectionName+'_in_bg', 'conference_bg').color
property int radius : 10
property QtObject contactDescription: QtObject {
property color color: ColorsList.add(sectionName+'_username', 'q').color

View file

@ -24,7 +24,7 @@ QtObject {
property int lineHeight: 20
property QtObject backgroundColor: QtObject {
property color normal: ColorsList.add(sectionName+'_conference_bg_n', 'conference_bg').color
property color normal: ColorsList.add(sectionName+'_conference_bg_n', 'conference_entry_bg').color
property color hovered: ColorsList.add(sectionName+'_conference_bg_h', 'g10').color
}

View file

@ -168,8 +168,6 @@ Rectangle {
anchors.right: parent.right
anchors.bottom: actionsButtons.top
anchors.leftMargin: 70
anchors.rightMargin: rightMenu.visible ? 70 : 15
anchors.topMargin: 15
anchors.bottomMargin: 20
onClicked: {
@ -178,10 +176,13 @@ Rectangle {
+Math.floor(Math.random()*255).toString(16)
+Math.floor(Math.random()*255).toString(16)})
}
Component{
id: gridComponent
VideoConferenceGrid{
id: grid
anchors.leftMargin: 70
anchors.rightMargin: rightMenu.visible ? 15 : 70
callModel: conference.callModel
}
}
@ -190,22 +191,43 @@ Rectangle {
VideoConferenceActiveSpeaker{
id: activeSpeaker
callModel: conference.callModel
isRightReducedLayout: rightMenu.visible
isLeftReducedLayout: conference.listCallsOpened
}
}
RowLayout{
anchors.fill: parent
Loader{
id: conferenceLayout
Layout.fillHeight: true
Layout.fillWidth: true
Layout.fillWidth: true
sourceComponent: conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid ? gridComponent : activeSpeakerComponent
onSourceComponentChanged: console.log(conference.callModel.conferenceVideoLayout)
active: conference.callModel
ColumnLayout {
anchors.fill: parent
visible: !conference.callModel || !conferenceLayout.item || conferenceLayout.item.participantCount == 0
BusyIndicator{
Layout.preferredHeight: 50
Layout.preferredWidth: 50
Layout.alignment: Qt.AlignCenter
running: parent.visible
color: VideoConferenceStyle.buzyColor
}
Text{
Layout.alignment: Qt.AlignCenter
text: "Video conference is not ready. Please Wait..."
color: VideoConferenceStyle.buzyColor
}
}
}
VideoConferenceMenu{
id: rightMenu
Layout.fillHeight: true
Layout.preferredWidth: 400
Layout.rightMargin: 30
callModel: conference.callModel
visible: false
onClose: rightMenu.visible = !rightMenu.visible
}
}

View file

@ -20,24 +20,61 @@ import 'qrc:/ui/scripts/Utils/utils.js' as Utils
// =============================================================================
Item {
id: grid
property alias callModel: participantDevices.callModel
anchors.fill: parent
id: mainItem
property alias callModel: allDevices.callModel
property bool isRightReducedLayout: false
property bool isLeftReducedLayout: false
property alias showMe : allDevices.showMe
property int participantCount: allDevices.count
anchors.fill: parent
property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel {
id: participantDevices
id: allDevices
showMe: true
onParticipantSpeaking: cameraView.currentDevice = speakingDevice
}
CameraView{
id: cameraView
enabled: index >=0
callModel: mainItem.callModel
anchors.fill: parent
anchors.leftMargin: isRightReducedLayout || isLeftReducedLayout? 30 : 140
anchors.rightMargin: isRightReducedLayout ? 10 : 140
isPaused: callModel.pausedByUser || currentDevice && currentDevice.isPaused //callModel.pausedByUser
showCloseButton: false
// onCloseRequested: grid.remove( index)
color: 'black'
}
ScrollableListView{
id: miniViews
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.rightMargin: 30
anchors.topMargin: 30
anchors.bottomMargin: 30
//property int maxShowedCount: 4
property int cellHeight: 150
width: 16 * cellHeight / 9
onCountChanged: {console.log("Delegate count = "+count+"/"+mainItem.participantDevices.count)}
model: mainItem.participantDevices
spacing: 15
verticalLayoutDirection: ItemView.BottomToTop
delegate:Item{
height: miniViews.cellHeight
width: miniViews.width
CameraView{
id: miniView
anchors.centerIn: parent
height: miniViews.cellHeight - 6
width: miniViews.width - 6
enabled: index >=0
currentDevice: modelData
isPaused: mainItem.callModel.pausedByUser || currentDevice && currentDevice.isPaused //callModel.pausedByUser
onCloseRequested: mainItem.showMe = false
//color: 'black'
}
}
}
}

View file

@ -22,6 +22,7 @@ import 'qrc:/ui/scripts/Utils/utils.js' as Utils
Mosaic {
id: grid
property alias callModel: participantDevices.callModel
property int participantCount: gridModel.count
anchors.fill: parent
squaredDisplay: true
@ -71,9 +72,9 @@ Mosaic {
enabled: index >=0
anchors.fill: parent
currentDevice: avatarCell.currentDevice
isPaused: callModel.pausedByUser || avatarCell.currentDevice && avatarCell.currentDevice.isPaused //callModel.pausedByUser
isPaused: grid.callModel.pausedByUser || avatarCell.currentDevice && avatarCell.currentDevice.isPaused //callModel.pausedByUser
onCloseRequested: grid.remove( index)
color: 'black'
//color: 'black'
}
}
}

View file

@ -85,7 +85,9 @@ Rectangle{
Layout.fillHeight: true
Layout.fillWidth: true
Repeater{
model: [{text: 'Modifier la mise en page', icon: VideoConferenceMenuStyle.settingsIcons.gridIcon, nextPage:layoutMenu}
model: [{text: 'Modifier la mise en page'
, icon: (mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid ? VideoConferenceMenuStyle.settingsIcons.gridIcon : VideoConferenceMenuStyle.settingsIcons.activeSpeakerIcon)
, nextPage:layoutMenu}
]
delegate:
Borders{

View file

@ -4,6 +4,7 @@ import QtGraphicalEffects 1.12
import Common 1.0
import Linphone 1.0
import LinphoneEnums 1.0
import Common.Styles 1.0
import App.Styles 1.0
@ -93,9 +94,15 @@ Rectangle {
}
RowLayout{
ActionButton{
id: layoutChoice
property int selectedLayout: LinphoneEnums.ConferenceLayoutGrid
isCustom: true
backgroundRadius: width/2
colorSet: WaitingRoomStyle.buttons.gridLayout
colorSet: selectedLayout == LinphoneEnums.ConferenceLayoutGrid ? WaitingRoomStyle.buttons.gridLayout : WaitingRoomStyle.buttons.activeSpeakerLayout
onClicked: if( selectedLayout == LinphoneEnums.ConferenceLayoutGrid )
selectedLayout = LinphoneEnums.ConferenceLayoutActiveSpeaker
else
selectedLayout = LinphoneEnums.ConferenceLayoutGrid
/*
colorSet: callModel.pausedByUser ? WaitingRoomStyle.buttons.play : WaitingRoomStyle.buttons.pause
onClicked: callModel.pausedByUser = !callModel.pausedByUser
@ -121,7 +128,7 @@ Rectangle {
TextButtonB {
text: 'DEMARRER'
onClicked: {mainItem.close(); CallsListModel.launchVideoCall(conferenceInfoModel.uri, '', 0, {video: camera.cameraEnabled, micro:!micro.microMuted, audio:!speaker.speakerMuted}) }
onClicked: {mainItem.close(); CallsListModel.launchVideoCall(conferenceInfoModel.uri, '', 0, {video: camera.cameraEnabled, micro:!micro.microMuted, audio:!speaker.speakerMuted, layout: layoutChoice.selectedLayout}) }
}
}

View file

@ -33,16 +33,16 @@ QtObject {
}
property QtObject modeIcons: QtObject{
property string gridIcon: 'conference_layout_grid'
property string activeSpeakerIcon: 'conference_layout_active_speaker'
property int width: 80
property int height: 50
property string gridIcon: 'conference_layout_grid_custom'
property string activeSpeakerIcon: 'conference_layout_active_speaker_custom'
property int width: 40
property int height: 40
}
property QtObject settingsIcons: QtObject{
property string gridIcon: 'conference_layout_grid_custom'
property string activeSpeakerIcon: 'conference_layout_active_speaker'
property int width: 50
property int height: 50
property string activeSpeakerIcon: 'conference_layout_active_speaker_custom'
property int width: 40
property int height: 40
}
//------------------------------------------------------------------------------

View file

@ -9,7 +9,8 @@ import ColorsList 1.0
QtObject {
property string sectionName: 'VideoConference'
property color backgroundColor: ColorsList.add(sectionName+'_description', '', '', '#798791').color
property color backgroundColor: ColorsList.add(sectionName+'_description', 'conference_bg').color
property color buzyColor: ColorsList.add(sectionName+'_indicator', 'i').color
property QtObject title: QtObject {
property color color: ColorsList.add(sectionName+'_title', 'q').color

View file

@ -210,6 +210,19 @@ QtObject {
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 's_p_b_fg').color
property color foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 's_p_b_fg').color
}
property QtObject activeSpeakerLayout: QtObject {
property int iconSize: 40
property string icon : 'conference_layout_active_speaker_custom'
property string name : 'activeSpeakerLayout'
property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_n', icon, 's_n_b_bg').color
property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_h', icon, 's_h_b_bg').color
property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_p', icon, 's_p_b_bg').color
property color backgroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_bg_u', icon, 's_p_b_bg').color
property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_n', icon, 's_n_b_fg').color
property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 's_n_b_fg').color
property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 's_p_b_fg').color
property color foregroundUpdatingColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_u', icon, 's_p_b_fg').color
}
/*
property QtObject callsList: QtObject {
property int iconSize: 40

View file

@ -40,7 +40,7 @@ QtObject {
property int spacing: 15
property QtObject backgroundColor: QtObject {
property color ended: ColorsList.add(sectionName+'_conference_ended_bg', 'conference_bg').color
property color ended: ColorsList.add(sectionName+'_conference_ended_bg', 'conference_entry_bg').color
property color scheduled: ColorsList.add(sectionName+'_conference_scheduled_bg', 'e').color
property color hovered: ColorsList.add(sectionName+'_conference_bg_h', 'g10').color
}

@ -1 +1 @@
Subproject commit 45009739fe36bba8f70647e526d354cbcf8c06a4
Subproject commit 01e12c490219965084a16b6dccda107c45d80bc2