ActiveSpeaker details (display name) is now based on the last of speaker (and not based on speaking events).

Fix Qml errors.
Update SDK.
This commit is contained in:
Julien Wadel 2022-06-27 12:24:09 +02:00
parent cdbc52f7a2
commit 93021ec567
12 changed files with 78 additions and 52 deletions

View file

@ -61,7 +61,7 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
}
Camera::~Camera(){
qDebug() << "Camera destructor" << this;
qDebug() << "[Camera] Camera destructor" << this;
if(mIsPreview)
deactivatePreview();
setWindowIdLocation(None);
@ -97,7 +97,7 @@ void Camera::resetWindowId() const{
if(oldRenderer)
CoreManager::getInstance()->getCore()->setNativeVideoWindowId(NULL);
}
qDebug() << "Removed " << oldRenderer << " at " << mWindowIdLocation << " for " << this;
qDebug() << "[Camera] Removed " << oldRenderer << " at " << mWindowIdLocation << " for " << this;
mIsWindowIdSet = false;
}
}
@ -141,14 +141,14 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
QQuickFramebufferObject::Renderer * renderer = NULL;
if(mWindowIdLocation == CorePreview){
qDebug() << "Setting Camera to Preview";
qDebug() << "[Camera] Setting Camera to Preview";
renderer=(QQuickFramebufferObject::Renderer *)CoreManager::getInstance()->getCore()->createNativePreviewWindowId();
if(renderer)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(renderer);
}else if(mWindowIdLocation == Call){
auto call = mCallModel->getCall();
if(call){
qDebug() << "Setting Camera to CallModel";
qDebug() << "[Camera] Setting Camera to CallModel";
renderer = (QQuickFramebufferObject::Renderer *) call->createNativeVideoWindowId();
if(renderer)
call->setNativeVideoWindowId(renderer);
@ -156,27 +156,27 @@ QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
}else if( mWindowIdLocation == Device) {
auto participantDevice = mParticipantDeviceModel->getDevice();
if(participantDevice){
qDebug() << "Setting Camera to Participant Device";
qDebug() << "Trying to create new window ID for " << participantDevice->getName().c_str() << ", addr=" << participantDevice->getAddress()->asString().c_str();
qDebug() << "[Camera] Setting Camera to Participant Device";
qDebug() << "[Camera] Trying to create new window ID for " << participantDevice->getName().c_str() << ", addr=" << participantDevice->getAddress()->asString().c_str();
renderer = (QQuickFramebufferObject::Renderer *) participantDevice->createNativeVideoWindowId();
if(renderer)
participantDevice->setNativeVideoWindowId(renderer);
}
}else if( mWindowIdLocation == Core){
qDebug() << "Setting Camera to Default Window";
qDebug() << "[Camera] Setting Camera to Default Window";
renderer = (QQuickFramebufferObject::Renderer *) CoreManager::getInstance()->getCore()->createNativeVideoWindowId();
if(renderer)
CoreManager::getInstance()->getCore()->setNativeVideoWindowId(renderer);
}
if( !renderer){
QTimer::singleShot(1, this, &Camera::isNotReady);// Workaround for const createRenderer
qWarning() << "Camera stream couldn't start for Rendering. Retrying in 1s";
qWarning() << "[Camera] Stream couldn't start for Rendering. Retrying in 1s";
renderer = new CameraDummy();
QTimer::singleShot(1000, this, &Camera::requestNewRenderer);
}else{
mIsWindowIdSet = true;
qDebug() << "Added " << renderer << " at " << mWindowIdLocation << " for " << this;
qDebug() << "[Camera] Added " << renderer << " at " << mWindowIdLocation << " for " << this;
QTimer::singleShot(1, this, &Camera::isReady);// Workaround for const createRenderer
}
return renderer;

View file

@ -245,13 +245,12 @@ void ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged(con
}
void ParticipantDeviceListModel::onParticipantDeviceIsSpeakingChanged(const std::shared_ptr<const linphone::ParticipantDevice> & participantDevice, bool isSpeaking){
if( isSpeaking){
auto device = get(participantDevice);
if( device)
emit participantSpeaking(device.get());
}
auto device = get(participantDevice);
if( device)
emit participantSpeaking(device.get());
}
void ParticipantDeviceListModel::onParticipantDeviceSpeaking(){
emit participantSpeaking(qobject_cast<ParticipantDeviceModel*>(sender()));
auto deviceModel = qobject_cast<ParticipantDeviceModel*>(sender());
emit participantSpeaking(deviceModel);
}

View file

@ -47,9 +47,11 @@ void ParticipantDeviceListener::onConferenceLeft(const std::shared_ptr<linphone:
emit conferenceLeft(participantDevice);
}
void ParticipantDeviceListener::onStreamCapabilityChanged(const std::shared_ptr<linphone::ParticipantDevice> & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) {
qDebug() << "onStreamCapabilityChanged: " << participantDevice->getAddress()->asString().c_str() << " " << (int)direction << " / " << (int)streamType;
emit streamCapabilityChanged(participantDevice, direction, streamType);
}
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);
}

View file

@ -59,6 +59,13 @@ ParticipantDeviceModel *ParticipantDeviceProxyModel::getAt(int row){
return sourceModel()->data(sourceIndex).value<ParticipantDeviceModel *>();
}
ParticipantDeviceModel* ParticipantDeviceProxyModel::getLastActiveSpeaking(){
if( mActiveSpeakers.size() == 0)
return nullptr;
else
return mActiveSpeakers.first();
}
CallModel * ParticipantDeviceProxyModel::getCallModel() const{
return mCallModel;
}
@ -72,7 +79,7 @@ void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){
mCallModel = callModel;
auto sourceModel = new ParticipantDeviceListModel(mCallModel);
connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::onCountChanged);
connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::participantSpeaking);
connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking);
setSourceModel(sourceModel);
emit countChanged();
}
@ -81,7 +88,7 @@ void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant)
setFilterType(0);
auto sourceModel = participant->getParticipantDevices().get();
connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged);
connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::participantSpeaking);
connect(sourceModel, &ParticipantDeviceListModel::participantSpeaking, this, &ParticipantDeviceProxyModel::onParticipantSpeaking);
setSourceModel(sourceModel);
emit countChanged();
}
@ -95,4 +102,14 @@ void ParticipantDeviceProxyModel::setShowMe(const bool& show){
}
void ParticipantDeviceProxyModel::onCountChanged(){
}
void ParticipantDeviceProxyModel::onParticipantSpeaking(ParticipantDeviceModel * speakingDevice){
bool changed = (mActiveSpeakers.removeAll(speakingDevice) > 0);
if( speakingDevice->getIsSpeaking()) {
mActiveSpeakers.push_front(speakingDevice);
changed = true;
}
if(changed)
emit participantSpeaking(speakingDevice);
}

View file

@ -45,6 +45,7 @@ public:
ParticipantDeviceProxyModel (QObject *parent = nullptr);
Q_INVOKABLE ParticipantDeviceModel* getAt(int row);
Q_INVOKABLE ParticipantDeviceModel* getLastActiveSpeaking();
CallModel * getCallModel() const;
bool isShowMe() const;
@ -55,6 +56,7 @@ public:
public slots:
void onCountChanged();
void onParticipantSpeaking(ParticipantDeviceModel * speakingDevice);
signals:
void callModelChanged();
@ -68,6 +70,7 @@ protected:
QSharedPointer<ParticipantDeviceListModel> mDevices;
CallModel * mCallModel;
bool mShowMe = true;
QList<ParticipantDeviceModel*> mActiveSpeakers;// First item is last speaker
};
#endif

View file

@ -20,7 +20,7 @@ Rectangle{
id: mainItem
property CallModel callModel
property ConferenceModel conferenceModel: callModel.conferenceModel
property ParticipantModel me: conferenceModel.localParticipant
property ParticipantModel me: conferenceModel ? conferenceModel.localParticipant : null
property bool isMeAdmin: me && me.adminStatus
property bool isParticipantsMenu: false
signal close()
@ -109,7 +109,7 @@ Rectangle{
, nextPage:mediaMenu},
{titleIndex: 1
, icon: (mainItem.callModel.videoEnabled ?
, icon: (mainItem.callModel && mainItem.callModel.videoEnabled ?
(mainItem.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid ? VideoConferenceMenuStyle.settingsIcons.gridIcon : VideoConferenceMenuStyle.settingsIcons.activeSpeakerIcon)
: VideoConferenceMenuStyle.settingsIcons.audioOnlyIcon)
, nextPage:layoutMenu},

View file

@ -52,12 +52,11 @@ function handleCameraFirstFrameReceived (width, height) {
window.setHeight(window.height + diff)
}
function handleStatusChanged (status) {
function handleStatusChanged (status, isFullscreen) {
if (status === Linphone.CallModel.CallStatusEnded) {
var fullscreen = incall._fullscreen
if (fullscreen) {
if (isFullscreen) {
// Timeout => Avoid dead lock on mac.
Utils.setTimeout(window, 0, fullscreen.exit)
Utils.setTimeout(window, 0, isFullscreen.exit)
}
telKeypad.visible = false

View file

@ -46,7 +46,7 @@ Rectangle {
target: call
onCameraFirstFrameReceived: Logic.handleCameraFirstFrameReceived(width, height)
onStatusChanged: Logic.handleStatusChanged (status)
onStatusChanged: Logic.handleStatusChanged (status, incall._fullscreen)
onVideoRequested: Logic.handleVideoRequested(call)
}

View file

@ -41,7 +41,7 @@ Rectangle {
target: callModel
onCameraFirstFrameReceived: Logic.handleCameraFirstFrameReceived(width, height)
onStatusChanged: Logic.handleStatusChanged (status)
onStatusChanged: Logic.handleStatusChanged (status, conference._fullscreen)
onVideoRequested: Logic.handleVideoRequested(callModel)
}

View file

@ -30,7 +30,11 @@ Item {
property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel {
id: allDevices
showMe: true
onParticipantSpeaking: cameraView.currentDevice = speakingDevice
onParticipantSpeaking: {
var device = getLastActiveSpeaking()
if(device) // Get
cameraView.currentDevice = device
}
property bool cameraEnabled: callModel && callModel.cameraEnabled
onCameraEnabledChanged: showMe = cameraEnabled // Do it on changed to ignore hard bindings (that can be override)
}

View file

@ -81,14 +81,14 @@ Window {
target: callModel
onCameraFirstFrameReceived: Logic.handleCameraFirstFrameReceived(width, height)
onStatusChanged: Logic.handleStatusChanged (status)
onStatusChanged: Logic.handleStatusChanged (status, conference._fullscreen)
onVideoRequested: Logic.handleVideoRequested(callModel)
}
// ---------------------------------------------------------------------------
Rectangle{
anchors.fill: parent
visible: callModel.pausedByUser
visible: callModel && callModel.pausedByUser
color: VideoConferenceStyle.pauseArea.backgroundColor
z: 1
ColumnLayout{
@ -103,7 +103,7 @@ Window {
isCustom: true
colorSet: VideoConferenceStyle.pauseArea.play
backgroundRadius: width/2
onClicked: callModel.pausedByUser = !callModel.pausedByUser
onClicked: if(callModel) callModel.pausedByUser = !callModel.pausedByUser
}
Text{
Layout.alignment: Qt.AlignCenter
@ -183,9 +183,9 @@ Window {
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.record
property CallModel callModel: conference.callModel
onCallModelChanged: if(!callModel) callModel.stopRecording()
onCallModelChanged: if(callModel) callModel.stopRecording()
visible: SettingsModel.callRecorderEnabled && callModel
toggled: callModel.recording
toggled: callModel && callModel.recording
onClicked: {
return !toggled
@ -201,8 +201,8 @@ Window {
isCustom: true
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.screenshot
visible: conference.callModel.snapshotEnabled
onClicked: conference.callModel.takeSnapshot()
visible: conference.callModel && conference.callModel.snapshotEnabled
onClicked: conference.callModel && conference.callModel.takeSnapshot()
//: 'Take Snapshot' : Tooltip for takking snapshot.
tooltipText: qsTr('videoConferenceSnapshotTooltip')
}
@ -260,7 +260,7 @@ Window {
id: conferenceLayout
Layout.fillHeight: true
Layout.fillWidth: true
sourceComponent: conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid || !conference.callModel.videoEnabled? gridComponent : activeSpeakerComponent
sourceComponent: conference.callModel ? (conference.callModel.conferenceVideoLayout == LinphoneEnums.ConferenceLayoutGrid || !conference.callModel.videoEnabled? gridComponent : activeSpeakerComponent) : null
onSourceComponentChanged: console.log(conference.callModel.conferenceVideoLayout)
active: conference.callModel
ColumnLayout {
@ -328,7 +328,7 @@ Window {
Row {
spacing: 2
visible: SettingsModel.muteMicrophoneEnabled
property bool microMuted: callModel.microMuted
property bool microMuted: callModel && callModel.microMuted
VuMeter {
enabled: !parent.microMuted
@ -337,7 +337,7 @@ Window {
repeat: true
running: parent.enabled
onTriggered: parent.value = callModel.microVu
onTriggered: if(callModel) parent.value = callModel.microVu
}
}
ActionSwitch {
@ -345,12 +345,12 @@ Window {
isCustom: true
backgroundRadius: 90
colorSet: parent.microMuted ? VideoConferenceStyle.buttons.microOff : VideoConferenceStyle.buttons.microOn
onClicked: callModel.microMuted = !parent.microMuted
onClicked: if(callModel) callModel.microMuted = !parent.microMuted
}
}
Row {
spacing: 2
property bool speakerMuted: callModel.speakerMuted
property bool speakerMuted: callModel && callModel.speakerMuted
VuMeter {
enabled: !parent.speakerMuted
Timer {
@ -365,7 +365,7 @@ Window {
isCustom: true
backgroundRadius: 90
colorSet: parent.speakerMuted ? VideoConferenceStyle.buttons.speakerOff : VideoConferenceStyle.buttons.speakerOn
onClicked: callModel.speakerMuted = !parent.speakerMuted
onClicked: if(callModel) callModel.speakerMuted = !parent.speakerMuted
}
}
ActionSwitch {
@ -373,8 +373,8 @@ Window {
isCustom: true
backgroundRadius: 90
colorSet: callModel && callModel.cameraEnabled ? VideoConferenceStyle.buttons.cameraOn : VideoConferenceStyle.buttons.cameraOff
updating: callModel.videoEnabled && callModel.updating
enabled: callModel.videoEnabled
updating: callModel && callModel.videoEnabled && callModel.updating
enabled: callModel && callModel.videoEnabled
onClicked: if(callModel) callModel.cameraEnabled = !callModel.cameraEnabled
}
}
@ -384,16 +384,16 @@ Window {
isCustom: true
backgroundRadius: width/2
visible: SettingsModel.callPauseEnabled
updating: callModel.updating
colorSet: callModel.pausedByUser ? VideoConferenceStyle.buttons.play : VideoConferenceStyle.buttons.pause
onClicked: callModel.pausedByUser = !callModel.pausedByUser
updating: callModel && callModel.updating
colorSet: callModel && callModel.pausedByUser ? VideoConferenceStyle.buttons.play : VideoConferenceStyle.buttons.pause
onClicked: if(callModel) callModel.pausedByUser = !callModel.pausedByUser
}
ActionButton{
isCustom: true
backgroundRadius: width/2
colorSet: VideoConferenceStyle.buttons.hangup
onClicked: callModel.terminate()
onClicked: if(callModel) callModel.terminate()
}
}
}
@ -433,12 +433,14 @@ Window {
running: true
triggeredOnStart: true
onTriggered: {
// Note: `quality` is in the [0, 5] interval and -1.
var quality = callModel.quality
if(quality >= 0)
callQuality.percentageDisplayed = quality * 100 / 5
else
callQuality.percentageDisplayed = 0
if(callModel) {
// Note: `quality` is in the [0, 5] interval and -1.
var quality = callModel.quality
if(quality >= 0)
callQuality.percentageDisplayed = quality * 100 / 5
else
callQuality.percentageDisplayed = 0
}
}
}
}

@ -1 +1 @@
Subproject commit baeed5ae055e519284f7314d3a9bace134c3ecb5
Subproject commit 1e4bdbdcf843b5c0b4cea23c0b27ee031bdaf08f