mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-26 16:09:35 -05:00
1183 lines
46 KiB
C++
1183 lines
46 KiB
C++
/****************************************************************
|
|
* RetroShare is distributed under the following license:
|
|
*
|
|
* Copyright (C) 2015
|
|
*
|
|
* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
****************************************************************/
|
|
//C++
|
|
#include <time.h>
|
|
//Qt
|
|
#include <QIcon>
|
|
#include <QLayout>
|
|
#include <QPropertyAnimation>
|
|
#include <QToolButton>
|
|
//VOIP
|
|
#include <gui/audiodevicehelper.h>
|
|
#include "interface/rsVOIP.h"
|
|
#include "VOIPChatWidgetHolder.h"
|
|
#include "VideoProcessor.h"
|
|
#include "QVideoDevice.h"
|
|
//retroshare GUI
|
|
#include "gui/SoundManager.h"
|
|
#include "util/HandleRichText.h"
|
|
#include "gui/common/StatusDefs.h"
|
|
#include "gui/chat/ChatWidget.h"
|
|
//libretroshare
|
|
#include <retroshare/rsstatus.h>
|
|
#include <retroshare/rspeers.h>
|
|
|
|
#define CALL_START ":/images/call-start.png"
|
|
#define CALL_STOP ":/images/call-stop.png"
|
|
#define CALL_HOLD ":/images/call-hold.png"
|
|
|
|
|
|
VOIPChatWidgetHolder::VOIPChatWidgetHolder(ChatWidget *chatWidget, VOIPNotify *notify)
|
|
: QObject(), ChatWidgetHolder(chatWidget), mVOIPNotify(notify)
|
|
{
|
|
int S = QFontMetricsF(chatWidget->font()).height() ;
|
|
QSize iconSize = QSize(3*S,3*S);
|
|
QSize buttonSize = QSize(iconSize + QSize(3,3));
|
|
|
|
QIcon iconaudioListenToggleButton ;
|
|
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker_mute.png")) ;
|
|
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Normal,QIcon::On) ;
|
|
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Disabled,QIcon::On) ;
|
|
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Active,QIcon::On) ;
|
|
iconaudioListenToggleButton.addPixmap(QPixmap(":/images/speaker.png"),QIcon::Selected,QIcon::On) ;
|
|
|
|
audioListenToggleButton = new QToolButton ;
|
|
audioListenToggleButton->setIcon(iconaudioListenToggleButton) ;
|
|
audioListenToggleButton->setIconSize(iconSize) ;
|
|
audioListenToggleButton->setMinimumSize(buttonSize) ;
|
|
audioListenToggleButton->setMaximumSize(buttonSize) ;
|
|
audioListenToggleButton->setCheckable(true);
|
|
audioListenToggleButton->setAutoRaise(true) ;
|
|
audioListenToggleButton->setText(QString()) ;
|
|
audioListenToggleButton->setToolTip(tr("Mute"));
|
|
audioListenToggleButton->setEnabled(false);
|
|
|
|
QIcon iconaudioCaptureToggleButton ;
|
|
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/phone.png")) ;
|
|
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Normal,QIcon::On) ;
|
|
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Disabled,QIcon::On) ;
|
|
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Active,QIcon::On) ;
|
|
iconaudioCaptureToggleButton.addPixmap(QPixmap(":/images/microphone_mute.png"),QIcon::Selected,QIcon::On) ;
|
|
|
|
audioCaptureToggleButton = new QToolButton ;
|
|
audioCaptureToggleButton->setIcon(iconaudioCaptureToggleButton) ;
|
|
audioCaptureToggleButton->setIconSize(iconSize) ;
|
|
audioCaptureToggleButton->setMinimumSize(buttonSize) ;
|
|
audioCaptureToggleButton->setMaximumSize(buttonSize) ;
|
|
audioCaptureToggleButton->setCheckable(true) ;
|
|
audioCaptureToggleButton->setAutoRaise(true) ;
|
|
audioCaptureToggleButton->setText(QString()) ;
|
|
audioCaptureToggleButton->setToolTip(tr("Start Call"));
|
|
|
|
QIcon iconvideoCaptureToggleButton ;
|
|
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam.png")) ;
|
|
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Normal,QIcon::On) ;
|
|
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Disabled,QIcon::On) ;
|
|
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Active,QIcon::On) ;
|
|
iconvideoCaptureToggleButton.addPixmap(QPixmap(":/images/filmcam-off.png"),QIcon::Selected,QIcon::On) ;
|
|
|
|
videoCaptureToggleButton = new QToolButton ;
|
|
videoCaptureToggleButton->setIcon(iconvideoCaptureToggleButton) ;
|
|
videoCaptureToggleButton->setIconSize(iconSize) ;
|
|
videoCaptureToggleButton->setMinimumSize(buttonSize) ;
|
|
videoCaptureToggleButton->setMaximumSize(buttonSize) ;
|
|
videoCaptureToggleButton->setCheckable(true) ;
|
|
videoCaptureToggleButton->setAutoRaise(true) ;
|
|
videoCaptureToggleButton->setText(QString()) ;
|
|
videoCaptureToggleButton->setToolTip(tr("Start Video Call"));
|
|
|
|
hangupButton = new QToolButton ;
|
|
hangupButton->setIcon(QIcon(":/images/phone_hangup.png")) ;
|
|
hangupButton->setIconSize(iconSize) ;
|
|
hangupButton->setMinimumSize(buttonSize) ;
|
|
hangupButton->setMaximumSize(buttonSize) ;
|
|
hangupButton->setCheckable(false) ;
|
|
hangupButton->setAutoRaise(true) ;
|
|
hangupButton->setText(QString()) ;
|
|
hangupButton->setToolTip(tr("Hangup Call"));
|
|
hangupButton->hide();
|
|
|
|
QIcon iconhideChatTextToggleButton ;
|
|
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png")) ;
|
|
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Normal,QIcon::On) ;
|
|
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Disabled,QIcon::On) ;
|
|
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Active,QIcon::On) ;
|
|
iconhideChatTextToggleButton.addPixmap(QPixmap(":/images/chat-bubble.png"),QIcon::Selected,QIcon::On) ;
|
|
|
|
hideChatTextToggleButton = new QToolButton ;
|
|
hideChatTextToggleButton->setIcon(iconhideChatTextToggleButton) ;
|
|
hideChatTextToggleButton->setIconSize(iconSize) ;
|
|
hideChatTextToggleButton->setMinimumSize(buttonSize) ;
|
|
hideChatTextToggleButton->setMaximumSize(buttonSize) ;
|
|
hideChatTextToggleButton->setCheckable(true) ;
|
|
hideChatTextToggleButton->setAutoRaise(true) ;
|
|
hideChatTextToggleButton->setText(QString()) ;
|
|
hideChatTextToggleButton->setToolTip(tr("Hide Chat Text"));
|
|
hideChatTextToggleButton->setEnabled(false) ;
|
|
|
|
QIcon iconfullscreenToggleButton ;
|
|
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen_arrows.png")) ;
|
|
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Normal,QIcon::On) ;
|
|
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Disabled,QIcon::On) ;
|
|
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Active,QIcon::On) ;
|
|
iconfullscreenToggleButton.addPixmap(QPixmap(":/images/fullscreen.png"),QIcon::Selected,QIcon::On) ;
|
|
|
|
fullscreenToggleButton = new QToolButton ;
|
|
fullscreenToggleButton->setIcon(iconfullscreenToggleButton) ;
|
|
fullscreenToggleButton->setIconSize(iconSize) ;
|
|
fullscreenToggleButton->setMinimumSize(buttonSize) ;
|
|
fullscreenToggleButton->setMaximumSize(buttonSize) ;
|
|
fullscreenToggleButton->setCheckable(true) ;
|
|
fullscreenToggleButton->setAutoRaise(true) ;
|
|
fullscreenToggleButton->setText(QString()) ;
|
|
fullscreenToggleButton->setToolTip(tr("Fullscreen mode"));
|
|
fullscreenToggleButton->setEnabled(false) ;
|
|
|
|
connect(audioListenToggleButton, SIGNAL(clicked()), this , SLOT(toggleAudioListen()));
|
|
connect(audioCaptureToggleButton, SIGNAL(clicked()), this , SLOT(toggleAudioCapture()));
|
|
connect(videoCaptureToggleButton, SIGNAL(clicked()), this , SLOT(toggleVideoCapture()));
|
|
connect(hangupButton, SIGNAL(clicked()), this , SLOT(hangupCall()));
|
|
connect(hideChatTextToggleButton, SIGNAL(clicked()), this , SLOT(toggleHideChatText()));
|
|
connect(fullscreenToggleButton, SIGNAL(clicked()), this , SLOT(toggleFullScreen()));
|
|
|
|
mChatWidget->addTitleBarWidget(audioListenToggleButton) ;
|
|
mChatWidget->addTitleBarWidget(audioCaptureToggleButton) ;
|
|
mChatWidget->addTitleBarWidget(videoCaptureToggleButton) ;
|
|
mChatWidget->addTitleBarWidget(hangupButton) ;
|
|
mChatWidget->addTitleBarWidget(hideChatTextToggleButton) ;
|
|
mChatWidget->addTitleBarWidget(fullscreenToggleButton) ;
|
|
|
|
outputAudioProcessor = NULL ;
|
|
outputAudioDevice = NULL ;
|
|
inputAudioProcessor = NULL ;
|
|
inputAudioDevice = NULL ;
|
|
|
|
inputVideoDevice = new QVideoInputDevice(mChatWidget) ; // not started yet ;-)
|
|
videoProcessor = new VideoProcessor ;
|
|
|
|
// Make a widget with two video devices, one for echo, and one for the talking peer.
|
|
videoWidget = new QWidget(mChatWidget) ;
|
|
videoWidget->setLayout(new QVBoxLayout()) ;
|
|
videoWidget->layout()->addWidget(outputVideoDevice = new QVideoOutputDevice(videoWidget)) ;
|
|
videoWidget->layout()->addWidget(echoVideoDevice = new QVideoOutputDevice(videoWidget)) ;
|
|
videoWidget->hide();
|
|
|
|
connect(inputVideoDevice, SIGNAL(networkPacketReady()), this, SLOT(sendVideoData()));
|
|
|
|
echoVideoDevice->setMinimumSize(320,240) ;//4/3
|
|
outputVideoDevice->setMinimumSize(320,240) ;//4/3
|
|
|
|
echoVideoDevice->showFrameOff();
|
|
outputVideoDevice->showFrameOff();
|
|
|
|
echoVideoDevice->setStyleSheet("border: 4px solid #CCCCCC; border-radius: 4px;");
|
|
outputVideoDevice->setStyleSheet("border: 4px solid #CCCCCC; border-radius: 4px;");
|
|
|
|
/// FULLSCREEN ///
|
|
fullScreenFrame = new QFrame();
|
|
|
|
outputVideoDeviceFS = new QVideoOutputDevice(fullScreenFrame);
|
|
outputVideoDeviceFS->setGeometry(QRect(QPoint(0,0),fullScreenFrame->geometry().size()));
|
|
outputVideoDeviceFS->showFrameOff();
|
|
|
|
echoVideoDeviceFS = new QVideoOutputDevice(fullScreenFrame);
|
|
echoVideoDeviceFS->setGeometry(QRect(QPoint(fullScreenFrame->width(), fullScreenFrame->height()) - QPoint(320,240), QSize(320,240)));
|
|
echoVideoDeviceFS->showFrameOff();
|
|
|
|
toolBarFS = new QFrame(fullScreenFrame);
|
|
QHBoxLayout *toolBarFSLayout = new QHBoxLayout(toolBarFS);
|
|
|
|
audioListenToggleButtonFS = new QToolButton(fullScreenFrame) ;
|
|
audioListenToggleButtonFS->setIcon(iconaudioListenToggleButton) ;
|
|
audioListenToggleButtonFS->setIconSize(iconSize) ;
|
|
audioListenToggleButtonFS->setMinimumSize(buttonSize) ;
|
|
audioListenToggleButtonFS->setMaximumSize(buttonSize) ;
|
|
audioListenToggleButtonFS->setCheckable(true);
|
|
audioListenToggleButtonFS->setAutoRaise(true) ;
|
|
audioListenToggleButtonFS->setText(QString()) ;
|
|
audioListenToggleButtonFS->setToolTip(tr("Mute"));
|
|
|
|
audioCaptureToggleButtonFS = new QToolButton(fullScreenFrame) ;
|
|
audioCaptureToggleButtonFS->setIcon(iconaudioCaptureToggleButton) ;
|
|
audioCaptureToggleButtonFS->setIconSize(iconSize) ;
|
|
audioCaptureToggleButtonFS->setMinimumSize(buttonSize) ;
|
|
audioCaptureToggleButtonFS->setMaximumSize(buttonSize) ;
|
|
audioCaptureToggleButtonFS->setCheckable(true) ;
|
|
audioCaptureToggleButtonFS->setAutoRaise(true) ;
|
|
audioCaptureToggleButtonFS->setText(QString()) ;
|
|
audioCaptureToggleButtonFS->setToolTip(tr("Start Call"));
|
|
|
|
videoCaptureToggleButtonFS = new QToolButton(fullScreenFrame) ;
|
|
videoCaptureToggleButtonFS->setIcon(iconvideoCaptureToggleButton) ;
|
|
videoCaptureToggleButtonFS->setIconSize(iconSize) ;
|
|
videoCaptureToggleButtonFS->setMinimumSize(buttonSize) ;
|
|
videoCaptureToggleButtonFS->setMaximumSize(buttonSize) ;
|
|
videoCaptureToggleButtonFS->setCheckable(true) ;
|
|
videoCaptureToggleButtonFS->setAutoRaise(true) ;
|
|
videoCaptureToggleButtonFS->setText(QString()) ;
|
|
videoCaptureToggleButtonFS->setToolTip(tr("Start Video Call"));
|
|
|
|
hangupButtonFS = new QToolButton(fullScreenFrame) ;
|
|
hangupButtonFS->setIcon(QIcon(":/images/phone_hangup.png")) ;
|
|
hangupButtonFS->setIconSize(iconSize) ;
|
|
hangupButtonFS->setMinimumSize(buttonSize) ;
|
|
hangupButtonFS->setMaximumSize(buttonSize) ;
|
|
hangupButtonFS->setCheckable(false) ;
|
|
hangupButtonFS->setAutoRaise(true) ;
|
|
hangupButtonFS->setText(QString()) ;
|
|
hangupButtonFS->setToolTip(tr("Hangup Call"));
|
|
hangupButtonFS->hide();
|
|
|
|
fullscreenToggleButtonFS = new QToolButton(fullScreenFrame);
|
|
fullscreenToggleButtonFS->setIcon(iconfullscreenToggleButton);
|
|
fullscreenToggleButtonFS->setIconSize(iconSize);
|
|
fullscreenToggleButtonFS->setMinimumSize(buttonSize);
|
|
fullscreenToggleButtonFS->setMaximumSize(buttonSize);
|
|
fullscreenToggleButtonFS->setCheckable(true);
|
|
fullscreenToggleButtonFS->setAutoRaise(true);
|
|
fullscreenToggleButtonFS->setText(QString());
|
|
fullscreenToggleButtonFS->setToolTip(tr("Fullscreen mode"));
|
|
fullscreenToggleButtonFS->setEnabled(false);
|
|
|
|
connect(audioListenToggleButtonFS, SIGNAL(clicked()), this , SLOT(toggleAudioListenFS()));
|
|
connect(audioCaptureToggleButtonFS, SIGNAL(clicked()), this , SLOT(toggleAudioCaptureFS()));
|
|
connect(videoCaptureToggleButtonFS, SIGNAL(clicked()), this , SLOT(toggleVideoCaptureFS()));
|
|
connect(hangupButtonFS, SIGNAL(clicked()), this , SLOT(hangupCall()));
|
|
connect(fullscreenToggleButtonFS, SIGNAL(clicked()), this , SLOT(toggleFullScreenFS()));
|
|
|
|
toolBarFSLayout->setDirection(QBoxLayout::LeftToRight);
|
|
toolBarFSLayout->setSpacing(2);
|
|
toolBarFSLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
|
toolBarFSLayout->addWidget(audioListenToggleButtonFS);
|
|
toolBarFSLayout->addWidget(audioCaptureToggleButtonFS);
|
|
toolBarFSLayout->addWidget(videoCaptureToggleButtonFS);
|
|
toolBarFSLayout->addWidget(hangupButtonFS);
|
|
toolBarFSLayout->addWidget(fullscreenToggleButtonFS);
|
|
toolBarFS->setLayout(toolBarFSLayout);
|
|
|
|
fullScreenFrame->setParent(0);
|
|
fullScreenFrame->setWindowFlags(Qt::WindowStaysOnTopHint);
|
|
fullScreenFrame->setFocusPolicy(Qt::StrongFocus);
|
|
fullScreenFrame->setWindowState(Qt::WindowFullScreen);
|
|
fullScreenFrame->hide();
|
|
fullScreenFrame->installEventFilter(this);
|
|
|
|
mChatWidget->addChatHorizontalWidget(videoWidget) ;
|
|
|
|
inputVideoDevice->setEchoVideoTarget(echoVideoDevice) ;
|
|
inputVideoDevice->setVideoProcessor(videoProcessor) ;
|
|
videoProcessor->setDisplayTarget(outputVideoDevice) ;
|
|
|
|
//Ring
|
|
pbAudioRing = new QProgressBar();
|
|
pbAudioRing->setOrientation(Qt::Horizontal);
|
|
pbAudioRing->setRange(0, 99);
|
|
pbAudioRing->setTextVisible(false);
|
|
pbAudioRing->setHidden(true);
|
|
pbVideoRing = new QProgressBar();
|
|
pbVideoRing->setOrientation(Qt::Horizontal);
|
|
pbVideoRing->setRange(0, 99);
|
|
pbVideoRing->setTextVisible(false);
|
|
pbVideoRing->setHidden(true);
|
|
mChatWidget->addChatBarWidget(pbAudioRing);
|
|
mChatWidget->addChatBarWidget(pbVideoRing);
|
|
|
|
sendAudioRingTime = -1;
|
|
sendVideoRingTime = -1;
|
|
recAudioRingTime = -1;
|
|
recVideoRingTime = -1;
|
|
|
|
timerAudioRing = new QTimer(this);
|
|
timerAudioRing->setInterval(300);
|
|
timerAudioRing->setSingleShot(true);
|
|
connect(timerAudioRing, SIGNAL(timeout()), this, SLOT(timerAudioRingTimeOut()));
|
|
timerVideoRing = new QTimer(this);
|
|
timerVideoRing->setInterval(300);
|
|
timerVideoRing->setSingleShot(true);
|
|
connect(timerVideoRing, SIGNAL(timeout()), this, SLOT(timerVideoRingTimeOut()));
|
|
|
|
lastTimePlayOccurs = time(NULL);
|
|
}
|
|
|
|
VOIPChatWidgetHolder::~VOIPChatWidgetHolder()
|
|
{
|
|
hangupCall();
|
|
|
|
if(inputAudioDevice != NULL)
|
|
inputAudioDevice->stop() ;
|
|
|
|
delete inputVideoDevice ;
|
|
delete videoProcessor ;
|
|
deleteButtonMap();
|
|
|
|
// stop and delete timers
|
|
timerAudioRing->stop();
|
|
delete(timerAudioRing);
|
|
timerVideoRing->stop();
|
|
delete(timerVideoRing);
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::deleteButtonMap(int flags)
|
|
{
|
|
button_map::iterator it = buttonMapTakeCall.begin();
|
|
while (it != buttonMapTakeCall.end()) {
|
|
if (((it.key().left(1) == "a") && (flags & RS_VOIP_FLAGS_AUDIO_DATA))
|
|
|| ((it.key().left(1) == "v") && (flags & RS_VOIP_FLAGS_VIDEO_DATA)) ) {
|
|
QPair<RSButtonOnText*,RSButtonOnText*> pair = it.value();
|
|
delete pair.second;
|
|
delete pair.first;
|
|
if (flags & RS_VOIP_FLAGS_AUDIO_DATA) recAudioRingTime = -1;
|
|
if (flags & RS_VOIP_FLAGS_VIDEO_DATA) recVideoRingTime = -1;
|
|
it = buttonMapTakeCall.erase(it);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::addNewAudioButtonMap(const RsPeerId &peer_id)
|
|
{
|
|
if (mChatWidget) {
|
|
recAudioRingTime = 0;
|
|
timerAudioRingTimeOut();
|
|
|
|
QString buttonName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
if (buttonName.isEmpty()) buttonName = QString::fromStdString(peer_id.toStdString().c_str());
|
|
if (buttonName.isEmpty()) buttonName = "VoIP";
|
|
button_map::iterator it = buttonMapTakeCall.find(QString("a").append(buttonName));
|
|
if (it == buttonMapTakeCall.end()){
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 is inviting you to start an audio conversation. Do you want to Accept or Decline the invitation?").arg(buttonName), ChatWidget::MSGTYPE_SYSTEM);
|
|
|
|
RSButtonOnText *buttonT = mChatWidget->getNewButtonOnTextBrowser(tr("Accept Audio Call"));
|
|
buttonT->setToolTip(tr("Activate audio"));
|
|
buttonT->setStyleSheet(QString("border: 1px solid #199909;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(122, 230, 110, 255),"
|
|
"stop:0.494318 rgba(36, 191, 16, 255), stop:0.505682 rgba(26, 162, 9, 255), stop:1 rgba(17, 106, 6, 255));")
|
|
);
|
|
|
|
buttonT->updateImage();
|
|
|
|
connect(buttonT,SIGNAL(clicked()),this,SLOT(startAudioCapture()));
|
|
connect(buttonT,SIGNAL(mouseEnter()),this,SLOT(botMouseEnterTake()));
|
|
connect(buttonT,SIGNAL(mouseLeave()),this,SLOT(botMouseLeaveTake()));
|
|
|
|
RSButtonOnText *buttonD = mChatWidget->getNewButtonOnTextBrowser(tr("Decline Audio Call"));
|
|
buttonD->setToolTip(tr("Refuse audio call"));
|
|
buttonD->setStyleSheet(QString("border: 1px solid #6a1106;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(230, 124, 110, 255), stop:0.494318 rgba(191, 35, 16, 255), "
|
|
"stop:0.505682 rgba(162, 26, 9, 255), stop:1 rgba(106, 17, 6, 255));")
|
|
);
|
|
|
|
buttonD->updateImage();
|
|
|
|
connect(buttonD,SIGNAL(clicked()),this,SLOT(hangupCallAudio()));
|
|
connect(buttonD,SIGNAL(mouseEnter()),this,SLOT(botMouseEnterDecline()));
|
|
connect(buttonD,SIGNAL(mouseLeave()),this,SLOT(botMouseLeaveDecline()));
|
|
|
|
buttonMapTakeCall.insert(QString("a").append(buttonName), QPair<RSButtonOnText*, RSButtonOnText*>(buttonT, buttonD));
|
|
}
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::addNewVideoButtonMap(const RsPeerId &peer_id)
|
|
{
|
|
if (mChatWidget) {
|
|
recVideoRingTime = 0;
|
|
timerVideoRingTimeOut();
|
|
|
|
QString buttonName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
if (buttonName.isEmpty()) buttonName = QString::fromStdString(peer_id.toStdString().c_str());
|
|
if (buttonName.isEmpty()) buttonName = "VoIP";
|
|
button_map::iterator it = buttonMapTakeCall.find(QString("v").append(buttonName));
|
|
if (it == buttonMapTakeCall.end()){
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 is inviting you to start a video conversation. Do you want to Accept or Decline the invitation?").arg(buttonName), ChatWidget::MSGTYPE_SYSTEM);
|
|
|
|
RSButtonOnText *buttonT = mChatWidget->getNewButtonOnTextBrowser(tr("Accept Video Call"));
|
|
buttonT->setToolTip(tr("Activate camera"));
|
|
buttonT->setStyleSheet(QString("border: 1px solid #199909;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(122, 230, 110, 255),"
|
|
"stop:0.494318 rgba(36, 191, 16, 255), stop:0.505682 rgba(26, 162, 9, 255), stop:1 rgba(17, 106, 6, 255));")
|
|
);
|
|
|
|
buttonT->updateImage();
|
|
|
|
connect(buttonT,SIGNAL(clicked()),this,SLOT(startVideoCapture()));
|
|
connect(buttonT,SIGNAL(mouseEnter()),this,SLOT(botMouseEnterTake()));
|
|
connect(buttonT,SIGNAL(mouseLeave()),this,SLOT(botMouseLeaveTake()));
|
|
|
|
RSButtonOnText *buttonD = mChatWidget->getNewButtonOnTextBrowser(tr("Decline Video Call"));
|
|
buttonD->setToolTip(tr("Refuse video call"));
|
|
buttonD->setStyleSheet(QString("border: 1px solid #6a1106;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(230, 124, 110, 255), stop:0.494318 rgba(191, 35, 16, 255), "
|
|
"stop:0.505682 rgba(162, 26, 9, 255), stop:1 rgba(106, 17, 6, 255));")
|
|
);
|
|
|
|
buttonD->updateImage();
|
|
|
|
connect(buttonD,SIGNAL(clicked()),this,SLOT(hangupCallVideo()));
|
|
connect(buttonD,SIGNAL(mouseEnter()),this,SLOT(botMouseEnterDecline()));
|
|
connect(buttonD,SIGNAL(mouseLeave()),this,SLOT(botMouseLeaveDecline()));
|
|
|
|
buttonMapTakeCall.insert(QString("v").append(buttonName), QPair<RSButtonOnText*, RSButtonOnText*>(buttonT, buttonD));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool VOIPChatWidgetHolder::eventFilter(QObject *obj, QEvent *event)
|
|
{
|
|
if (obj == fullScreenFrame) {
|
|
if (event->type() == QEvent::Close || event->type() == QEvent::MouseButtonDblClick) {
|
|
showNormalView();
|
|
}
|
|
if (event->type() == QEvent::Resize) {
|
|
replaceFullscreenWidget();
|
|
}
|
|
|
|
}
|
|
// pass the event on to the parent class
|
|
return QObject::eventFilter(obj, event);
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::hangupCall()
|
|
{
|
|
hangupCallAudio();
|
|
hangupCallVideo();
|
|
hangupButton->hide();
|
|
hangupButtonFS->hide();
|
|
deleteButtonMap();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::hangupCallAudio()
|
|
{
|
|
bool atLeastOneChecked = false;
|
|
if (audioCaptureToggleButton->isChecked()) {
|
|
audioCaptureToggleButton->setChecked(false);
|
|
toggleAudioCapture();
|
|
atLeastOneChecked = true;
|
|
}
|
|
if (!atLeastOneChecked) {
|
|
//Decline button ,Friend hang up or chat close
|
|
if (recAudioRingTime != -1) {
|
|
rsVOIP->sendVoipHangUpCall(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_AUDIO_DATA);
|
|
deleteButtonMap(RS_VOIP_FLAGS_AUDIO_DATA);
|
|
}
|
|
sendAudioRingTime = -1;
|
|
recAudioRingTime = -1;
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::hangupCallVideo()
|
|
{
|
|
bool atLeastOneChecked = false;
|
|
if (videoCaptureToggleButton->isChecked()) {
|
|
videoCaptureToggleButton->setChecked(false);
|
|
toggleVideoCapture();
|
|
atLeastOneChecked = true;
|
|
}
|
|
if (fullscreenToggleButton->isChecked()) {
|
|
fullscreenToggleButton->setChecked(false);
|
|
toggleFullScreen();
|
|
atLeastOneChecked = true;
|
|
}
|
|
if (hideChatTextToggleButton->isChecked()) {
|
|
hideChatTextToggleButton->setChecked(false);
|
|
toggleHideChatText();
|
|
atLeastOneChecked = true;
|
|
}
|
|
if (!atLeastOneChecked) {
|
|
//Decline button ,Friend hang up or chat close
|
|
if (recVideoRingTime != -1) {
|
|
rsVOIP->sendVoipHangUpCall(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_VIDEO_DATA);
|
|
deleteButtonMap(RS_VOIP_FLAGS_VIDEO_DATA);
|
|
}
|
|
sendVideoRingTime = -1;
|
|
recVideoRingTime = -1;
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleAudioListenFS()
|
|
{
|
|
audioListenToggleButton->setChecked(audioListenToggleButtonFS->isChecked());
|
|
toggleAudioListen();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleAudioListen()
|
|
{
|
|
if (audioListenToggleButton->isChecked()) {
|
|
audioListenToggleButton->setToolTip(tr("Mute yourself"));
|
|
} else {
|
|
audioListenToggleButton->setToolTip(tr("Unmute yourself"));
|
|
//audioListenToggleButton->setChecked(false);
|
|
/*if (outputAudioDevice) {
|
|
outputAudioDevice->stop();
|
|
}*/
|
|
}
|
|
audioListenToggleButtonFS->setChecked(audioListenToggleButton->isChecked());
|
|
audioListenToggleButtonFS->setToolTip(audioListenToggleButton->toolTip());
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::startAudioCapture()
|
|
{
|
|
recAudioRingTime = -2;
|
|
audioCaptureToggleButton->setChecked(true);
|
|
toggleAudioCapture();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleAudioCaptureFS()
|
|
{
|
|
audioCaptureToggleButton->setChecked(audioCaptureToggleButtonFS->isChecked());
|
|
toggleAudioCapture();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleAudioCapture()
|
|
{
|
|
if (audioCaptureToggleButton->isChecked()) {
|
|
if (recAudioRingTime == -1) {
|
|
if (sendAudioRingTime == -1) {
|
|
sendAudioRingTime = 0;
|
|
timerAudioRingTimeOut();
|
|
rsVOIP->sendVoipRinging(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_AUDIO_DATA);
|
|
return; //Start Audio when accept received
|
|
}
|
|
}
|
|
if (recAudioRingTime != -1)
|
|
rsVOIP->sendVoipAcceptCall(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_AUDIO_DATA);
|
|
recAudioRingTime = -1; //Stop ringing
|
|
|
|
//activate buttons
|
|
audioListenToggleButton->setEnabled(true);
|
|
audioListenToggleButton->setChecked(true);
|
|
audioListenToggleButtonFS->setEnabled(true);
|
|
audioListenToggleButtonFS->setChecked(true);
|
|
audioCaptureToggleButton->setToolTip(tr("Hold Call"));
|
|
hangupButton->show();
|
|
hangupButtonFS->show();
|
|
|
|
//activate audio input
|
|
if (!inputAudioProcessor) {
|
|
inputAudioProcessor = new QtSpeex::SpeexInputProcessor();
|
|
if (outputAudioProcessor) {
|
|
connect(outputAudioProcessor, SIGNAL(playingFrame(QByteArray*)), inputAudioProcessor, SLOT(addEchoFrame(QByteArray*)));
|
|
}
|
|
inputAudioProcessor->open(QIODevice::WriteOnly | QIODevice::Unbuffered);
|
|
}
|
|
if (!inputAudioDevice) {
|
|
inputAudioDevice = AudioDeviceHelper::getPreferedInputDevice();
|
|
}
|
|
connect(inputAudioProcessor, SIGNAL(networkPacketReady()), this, SLOT(sendAudioData()));
|
|
inputAudioDevice->start(inputAudioProcessor);
|
|
|
|
//send system message
|
|
if (mChatWidget)
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime(), tr("Outgoing Call is started..."), ChatWidget::MSGTYPE_SYSTEM);
|
|
|
|
deleteButtonMap(RS_VOIP_FLAGS_AUDIO_DATA);
|
|
} else {
|
|
//desactivate buttons
|
|
audioListenToggleButton->setEnabled(false);
|
|
audioListenToggleButton->setChecked(false);
|
|
audioListenToggleButtonFS->setEnabled(false);
|
|
audioListenToggleButtonFS->setChecked(false);
|
|
audioCaptureToggleButton->setToolTip(tr("Resume Call"));
|
|
if (!videoCaptureToggleButton->isChecked()) {
|
|
hangupButton->hide();
|
|
hangupButtonFS->hide();
|
|
}
|
|
|
|
if (recAudioRingTime <= -1){
|
|
//desactivate audio input
|
|
disconnect(inputAudioProcessor, SIGNAL(networkPacketReady()), this, SLOT(sendAudioData()));
|
|
if (inputAudioDevice) {
|
|
inputAudioDevice->stop();
|
|
}
|
|
|
|
//send system message
|
|
if (mChatWidget)
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("Outgoing Audio Call stopped."), ChatWidget::MSGTYPE_SYSTEM);
|
|
|
|
rsVOIP->sendVoipHangUpCall(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_AUDIO_DATA);
|
|
}
|
|
|
|
sendAudioRingTime = -1;
|
|
recAudioRingTime = -1;
|
|
|
|
}
|
|
audioCaptureToggleButtonFS->setChecked(audioCaptureToggleButton->isChecked());
|
|
audioCaptureToggleButtonFS->setToolTip(audioCaptureToggleButton->toolTip());
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::startVideoCapture()
|
|
{
|
|
recVideoRingTime = -2;
|
|
videoCaptureToggleButton->setChecked(true);
|
|
toggleVideoCapture();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleVideoCaptureFS()
|
|
{
|
|
videoCaptureToggleButton->setChecked(videoCaptureToggleButtonFS->isChecked());
|
|
toggleVideoCapture();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleVideoCapture()
|
|
{
|
|
if (videoCaptureToggleButton->isChecked())
|
|
{
|
|
if (recVideoRingTime == -1) {
|
|
if (sendVideoRingTime == -1) {
|
|
sendVideoRingTime = 0;
|
|
timerVideoRingTimeOut();
|
|
rsVOIP->sendVoipRinging(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_VIDEO_DATA);
|
|
return; //Start Video when accept received
|
|
}
|
|
}
|
|
if (recVideoRingTime != -1)
|
|
rsVOIP->sendVoipAcceptCall(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_VIDEO_DATA);
|
|
recVideoRingTime = -1; //Stop ringing
|
|
|
|
//activate buttons
|
|
hideChatTextToggleButton->setEnabled(true);
|
|
fullscreenToggleButton->setEnabled(true);
|
|
fullscreenToggleButtonFS->setEnabled(true);
|
|
videoCaptureToggleButton->setToolTip(tr("Shut camera off"));
|
|
hangupButton->show();
|
|
hangupButtonFS->show();
|
|
|
|
//activate video input
|
|
videoWidget->show();
|
|
inputVideoDevice->start() ;
|
|
|
|
//send system message
|
|
if (mChatWidget)
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("You're now sending video..."), ChatWidget::MSGTYPE_SYSTEM);
|
|
|
|
deleteButtonMap(RS_VOIP_FLAGS_VIDEO_DATA);
|
|
} else {
|
|
//desactivate buttons
|
|
hideChatTextToggleButton->setEnabled(false);
|
|
hideChatTextToggleButton->setChecked(false);
|
|
toggleHideChatText();
|
|
fullscreenToggleButton->setEnabled(false);
|
|
fullscreenToggleButton->setChecked(false);
|
|
fullscreenToggleButtonFS->setEnabled(false);
|
|
fullscreenToggleButtonFS->setChecked(false);
|
|
toggleFullScreen();
|
|
videoCaptureToggleButton->setToolTip(tr("Activate camera"));
|
|
if (!audioCaptureToggleButton->isChecked()) {
|
|
hangupButton->hide();
|
|
hangupButtonFS->hide();
|
|
}
|
|
|
|
if (recVideoRingTime<=-1){
|
|
//desactivate video input
|
|
inputVideoDevice->stop() ;
|
|
outputVideoDevice->showFrameOff();
|
|
videoWidget->hide();
|
|
|
|
//send system message
|
|
if (mChatWidget)
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("Video call stopped"), ChatWidget::MSGTYPE_SYSTEM);
|
|
|
|
rsVOIP->sendVoipHangUpCall(mChatWidget->getChatId().toPeerId(), RS_VOIP_FLAGS_VIDEO_DATA);
|
|
}
|
|
|
|
sendVideoRingTime = -1;
|
|
recVideoRingTime = -1;
|
|
|
|
}
|
|
videoCaptureToggleButtonFS->setChecked(videoCaptureToggleButton->isChecked());
|
|
videoCaptureToggleButtonFS->setToolTip(videoCaptureToggleButton->toolTip());
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::addVideoData(const RsPeerId &peer_id, QByteArray* array)
|
|
{
|
|
sendVideoRingTime = -2;//Receive Video so Accepted
|
|
if (!videoCaptureToggleButton->isChecked()) {
|
|
addNewVideoButtonMap(peer_id);
|
|
return;
|
|
}
|
|
|
|
RsVOIPDataChunk chunk ;
|
|
chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ;
|
|
chunk.size = array->size() ;
|
|
chunk.data = array->data() ;
|
|
|
|
videoProcessor->receiveEncodedData(chunk) ;
|
|
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleHideChatText()
|
|
{
|
|
QBoxLayout *layout = static_cast<QBoxLayout*>(videoWidget->layout());
|
|
|
|
if (hideChatTextToggleButton->isChecked()) {
|
|
mChatWidget->hideChatText(true);
|
|
if (layout) layout->setDirection(QBoxLayout::LeftToRight);
|
|
hideChatTextToggleButton->setToolTip(tr("Show Chat Text"));
|
|
} else {
|
|
mChatWidget->hideChatText(false);
|
|
if (layout) layout->setDirection(QBoxLayout::TopToBottom);
|
|
hideChatTextToggleButton->setToolTip(tr("Hide Chat Text"));
|
|
fullscreenToggleButton->setChecked(false);
|
|
toggleFullScreen();
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleFullScreenFS()
|
|
{
|
|
fullscreenToggleButton->setChecked(fullscreenToggleButtonFS->isChecked());
|
|
toggleFullScreen();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::toggleFullScreen()
|
|
{
|
|
if (fullscreenToggleButton->isChecked()) {
|
|
fullscreenToggleButton->setToolTip(tr("Return to normal view."));
|
|
inputVideoDevice->setEchoVideoTarget(echoVideoDeviceFS) ;
|
|
videoProcessor->setDisplayTarget(outputVideoDeviceFS) ;
|
|
fullScreenFrame->show();
|
|
} else {
|
|
mChatWidget->hideChatText(false);
|
|
fullscreenToggleButton->setToolTip(tr("Fullscreen mode"));
|
|
inputVideoDevice->setEchoVideoTarget(echoVideoDevice) ;
|
|
videoProcessor->setDisplayTarget(outputVideoDevice) ;
|
|
fullScreenFrame->hide();
|
|
}
|
|
fullscreenToggleButtonFS->setChecked(fullscreenToggleButton->isChecked());
|
|
fullscreenToggleButtonFS->setToolTip(fullscreenToggleButton->toolTip());
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::replaceFullscreenWidget()
|
|
{
|
|
if (QSize(toolBarFS->geometry().size() - fullScreenFrame->geometry().size()).isValid()){
|
|
QRect fsRect = fullScreenFrame->geometry();
|
|
fsRect.setSize(toolBarFS->geometry().size());
|
|
fullScreenFrame->setGeometry(fsRect);
|
|
}
|
|
|
|
outputVideoDeviceFS->setGeometry(QRect(QPoint(0,0),fullScreenFrame->geometry().size()));
|
|
echoVideoDeviceFS->setGeometry(QRect(QPoint(fullScreenFrame->width(), fullScreenFrame->height()) - QPoint(320,240), QSize(320,240)));
|
|
QRect toolBarFSGeo = QRect( (fullScreenFrame->width() - toolBarFS->geometry().width()) / 2
|
|
, fullScreenFrame->height() - (toolBarFS->geometry().height() * 2)
|
|
, toolBarFS->geometry().width(), toolBarFS->geometry().height());
|
|
toolBarFS->setGeometry(toolBarFSGeo);
|
|
|
|
if (!videoCaptureToggleButton->isChecked()) {
|
|
outputVideoDeviceFS->showFrameOff();
|
|
echoVideoDeviceFS->showFrameOff();
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::showNormalView()
|
|
{
|
|
hideChatTextToggleButton->setChecked(false);
|
|
toggleHideChatText();
|
|
fullscreenToggleButton->setChecked(false);
|
|
fullscreenToggleButtonFS->setChecked(false);
|
|
toggleFullScreen();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::botMouseEnterTake()
|
|
{
|
|
RSButtonOnText *source = qobject_cast<RSButtonOnText *>(QObject::sender());
|
|
if (source){
|
|
source->setStyleSheet(QString("border: 1px solid #333333;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.67, "
|
|
"stop: 0 #444444, stop: 1 #222222);")
|
|
|
|
);
|
|
//source->setDown(true);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::botMouseLeaveTake()
|
|
{
|
|
RSButtonOnText *source = qobject_cast<RSButtonOnText *>(QObject::sender());
|
|
if (source){
|
|
source->setStyleSheet(QString("border: 1px solid #116a06;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(153, 240, 143, 255),"
|
|
"stop:0.494318 rgba(59, 201, 40, 255), stop:0.505682 rgba(46, 172, 29, 255), stop:1 rgba(30, 116, 20, 255));")
|
|
);
|
|
//source->setDown(false);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::botMouseEnterDecline()
|
|
{
|
|
RSButtonOnText *source = qobject_cast<RSButtonOnText *>(QObject::sender());
|
|
if (source){
|
|
source->setStyleSheet(QString("border: 1px solid #333333;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.67, "
|
|
"stop: 0 #444444, stop: 1 #222222);")
|
|
);
|
|
//source->setDown(true);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::botMouseLeaveDecline()
|
|
{
|
|
RSButtonOnText *source = qobject_cast<RSButtonOnText *>(QObject::sender());
|
|
if (source){
|
|
source->setStyleSheet(QString("border: 1px solid #6a1106;")
|
|
.append("font-size: 12pt; color: white;")
|
|
.append("min-width: 128px; min-height: 24px;")
|
|
.append("border-radius: 6px;")
|
|
.append("padding: 3px;")
|
|
.append("background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(240, 154, 143, 255), "
|
|
"stop:0.494318 rgba(201, 57, 40, 255), stop:0.505682 rgba(172, 45, 29, 255), stop:1 rgba(116, 30, 20, 255));")
|
|
);
|
|
//source->setDown(false);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::setAcceptedBandwidth(uint32_t bytes_per_sec)
|
|
{
|
|
videoProcessor->setMaximumBandwidth(bytes_per_sec) ;
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::addAudioData(const RsPeerId &peer_id, QByteArray* array)
|
|
{
|
|
sendAudioRingTime = -2;//Receive Audio so Accepted
|
|
if (!audioCaptureToggleButton->isChecked()) {
|
|
addNewAudioButtonMap(peer_id);
|
|
return;
|
|
}
|
|
|
|
if (!outputAudioDevice) {
|
|
outputAudioDevice = AudioDeviceHelper::getDefaultOutputDevice();
|
|
}
|
|
|
|
if (!outputAudioProcessor) {
|
|
//start output audio device
|
|
outputAudioProcessor = new QtSpeex::SpeexOutputProcessor();
|
|
if (inputAudioProcessor) {
|
|
connect(outputAudioProcessor, SIGNAL(playingFrame(QByteArray*)), inputAudioProcessor, SLOT(addEchoFrame(QByteArray*)));
|
|
}
|
|
outputAudioProcessor->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
|
|
outputAudioDevice->start(outputAudioProcessor);
|
|
}
|
|
|
|
if (outputAudioDevice && outputAudioDevice->error() != QAudio::NoError) {
|
|
std::cerr << "Restarting output device. Error before reset " << outputAudioDevice->error() << " buffer size : " << outputAudioDevice->bufferSize() << std::endl;
|
|
outputAudioDevice->stop();
|
|
outputAudioDevice->reset();
|
|
if (outputAudioDevice->error() == QAudio::UnderrunError)
|
|
outputAudioDevice->setBufferSize(20);
|
|
outputAudioDevice->start(outputAudioProcessor);
|
|
}
|
|
outputAudioProcessor->putNetworkPacket(QString::fromStdString(peer_id.toStdString()), *array);
|
|
|
|
//check the input device for errors
|
|
if (inputAudioDevice && inputAudioDevice->error() != QAudio::NoError) {
|
|
std::cerr << "Restarting input device. Error before reset " << inputAudioDevice->error() << std::endl;
|
|
inputAudioDevice->stop();
|
|
inputAudioDevice->reset();
|
|
inputAudioDevice->start(inputAudioProcessor);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::sendVideoData()
|
|
{
|
|
RsVOIPDataChunk chunk ;
|
|
|
|
while(inputVideoDevice && inputVideoDevice->getNextEncodedPacket(chunk))
|
|
rsVOIP->sendVoipData(mChatWidget->getChatId().toPeerId(),chunk) ;
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::sendAudioData()
|
|
{
|
|
while(inputAudioProcessor && inputAudioProcessor->hasPendingPackets()) {
|
|
QByteArray qbarray = inputAudioProcessor->getNetworkPacket();
|
|
RsVOIPDataChunk chunk;
|
|
chunk.size = qbarray.size();
|
|
chunk.data = (void*)qbarray.constData();
|
|
chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_AUDIO ;
|
|
rsVOIP->sendVoipData(mChatWidget->getChatId().toPeerId(),chunk);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::updateStatus(int status)
|
|
{
|
|
bool enabled = (status != RS_STATUS_OFFLINE);
|
|
|
|
audioListenToggleButton->setEnabled(audioCaptureToggleButton->isChecked() && enabled);
|
|
audioListenToggleButtonFS->setEnabled(audioCaptureToggleButton->isChecked() && enabled);
|
|
audioCaptureToggleButton->setEnabled(enabled);
|
|
audioCaptureToggleButtonFS->setEnabled(enabled);
|
|
videoCaptureToggleButton->setEnabled(enabled);
|
|
videoCaptureToggleButtonFS->setEnabled(enabled);
|
|
hideChatTextToggleButton->setEnabled(videoCaptureToggleButton->isChecked() && enabled);
|
|
fullscreenToggleButton->setEnabled(videoCaptureToggleButton->isChecked() && enabled);
|
|
fullscreenToggleButtonFS->setEnabled(videoCaptureToggleButton->isChecked() && enabled);
|
|
hangupButton->setEnabled(enabled);
|
|
hangupButtonFS->setEnabled(enabled);
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::ReceivedInvitation(const RsPeerId &peer_id, int flags)
|
|
{
|
|
switch(flags){
|
|
case RS_VOIP_FLAGS_AUDIO_DATA: {
|
|
if (audioCaptureToggleButton->isChecked()) {
|
|
if (recAudioRingTime != -1)
|
|
toggleAudioCapture();
|
|
} else {
|
|
addNewAudioButtonMap(peer_id);
|
|
}
|
|
}
|
|
break;
|
|
case RS_VOIP_FLAGS_VIDEO_DATA: {
|
|
if (videoCaptureToggleButton->isChecked()) {
|
|
if (recVideoRingTime != -1)
|
|
toggleVideoCapture();
|
|
} else {
|
|
addNewVideoButtonMap(peer_id);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
std::cerr << "VOIPChatWidgetHolder::ReceivedInvitation(): Received unknown flags item # " << flags << ": not handled yet ! Sorry" << std::endl;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::ReceivedVoipHangUp(const RsPeerId &peer_id, int flags)
|
|
{
|
|
switch(flags){
|
|
case RS_VOIP_FLAGS_AUDIO_DATA | RS_VOIP_FLAGS_VIDEO_DATA: {
|
|
if (mChatWidget) {
|
|
if (videoCaptureToggleButton->isChecked() || audioCaptureToggleButton->isChecked()) {
|
|
QString peerName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 hang up. Your call is closed.").arg(peerName), ChatWidget::MSGTYPE_SYSTEM);
|
|
}
|
|
hangupCall();
|
|
}
|
|
}
|
|
break;
|
|
case RS_VOIP_FLAGS_AUDIO_DATA: {
|
|
if (mChatWidget) {
|
|
if (audioCaptureToggleButton->isChecked()) {
|
|
QString peerName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 hang up. Your audio call is closed.").arg(peerName), ChatWidget::MSGTYPE_SYSTEM);
|
|
}
|
|
hangupCallAudio();
|
|
}
|
|
}
|
|
break;
|
|
case RS_VOIP_FLAGS_VIDEO_DATA: {
|
|
if (mChatWidget) {
|
|
if (videoCaptureToggleButton->isChecked()) {
|
|
QString peerName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 hang up. Your video call is closed.").arg(peerName), ChatWidget::MSGTYPE_SYSTEM);
|
|
}
|
|
hangupCallVideo();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
std::cerr << "VOIPChatWidgetHolder::ReceivedVoipHangUp(): Received unknown flags item # " << flags << ": not handled yet ! Sorry" << std::endl;
|
|
break ;
|
|
}
|
|
//deleteButtonMap();
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::ReceivedVoipAccept(const RsPeerId &peer_id, int flags)
|
|
{
|
|
switch(flags){
|
|
case RS_VOIP_FLAGS_AUDIO_DATA: {
|
|
if (mChatWidget) {
|
|
sendAudioRingTime = -2;
|
|
QString peerName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 accepted your audio call.").arg(peerName), ChatWidget::MSGTYPE_SYSTEM);
|
|
if (audioCaptureToggleButton->isChecked())
|
|
toggleAudioCapture();
|
|
}
|
|
}
|
|
break;
|
|
case RS_VOIP_FLAGS_VIDEO_DATA: {
|
|
if (mChatWidget) {
|
|
sendVideoRingTime = -2;
|
|
QString peerName = QString::fromUtf8(rsPeers->getPeerName(peer_id).c_str());
|
|
mChatWidget->addChatMsg(true, tr("VoIP Status"), QDateTime::currentDateTime(), QDateTime::currentDateTime()
|
|
, tr("%1 accepted your video call.").arg(peerName), ChatWidget::MSGTYPE_SYSTEM);
|
|
if (videoCaptureToggleButton->isChecked())
|
|
toggleVideoCapture();
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
std::cerr << "VOIPChatWidgetHolder::ReceivedVoipHangUp(): Received unknown flags item # " << flags << ": not handled yet ! Sorry" << std::endl;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::timerAudioRingTimeOut()
|
|
{
|
|
//Sending or receiving (-2 connected, -1 reseted, >=0 in progress)
|
|
if (sendAudioRingTime >= 0) {
|
|
//Sending
|
|
++sendAudioRingTime;
|
|
if (sendAudioRingTime == 100) sendAudioRingTime = 0;
|
|
pbAudioRing->setValue(sendAudioRingTime);
|
|
pbAudioRing->setToolTip(tr("Waiting for your friend to respond to your audio call."));
|
|
pbAudioRing->setVisible(true);
|
|
|
|
if (time(NULL) > lastTimePlayOccurs) {
|
|
soundManager->play(VOIP_SOUND_OUTGOING_AUDIO_CALL);
|
|
lastTimePlayOccurs = time(NULL) + 1;
|
|
}
|
|
|
|
timerAudioRing->start();
|
|
} else if(recAudioRingTime >= 0) {
|
|
//Receiving
|
|
++recAudioRingTime;
|
|
if (recAudioRingTime == 100) recAudioRingTime = 0;
|
|
pbAudioRing->setValue(recAudioRingTime);
|
|
pbAudioRing->setToolTip(tr("Your friend is calling you for audio. Respond."));
|
|
pbAudioRing->setVisible(true);
|
|
|
|
//launch an animation. Don't launch it if already animating
|
|
if (!audioCaptureToggleButton->graphicsEffect()
|
|
|| (audioCaptureToggleButton->graphicsEffect()->inherits("QGraphicsOpacityEffect")
|
|
&& ((QGraphicsOpacityEffect*)audioCaptureToggleButton->graphicsEffect())->opacity() == 1)
|
|
) {
|
|
QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(audioListenToggleButton);
|
|
audioCaptureToggleButton->setGraphicsEffect(effect);
|
|
QPropertyAnimation *anim = new QPropertyAnimation(effect, "opacity", effect);
|
|
anim->setStartValue(1);
|
|
anim->setKeyValueAt(0.5,0);
|
|
anim->setEndValue(1);
|
|
anim->setDuration(timerAudioRing->interval());
|
|
anim->start();
|
|
}
|
|
audioCaptureToggleButton->setToolTip(tr("Answer"));
|
|
|
|
if (time(NULL) > lastTimePlayOccurs) {
|
|
soundManager->play(VOIP_SOUND_INCOMING_AUDIO_CALL);
|
|
lastTimePlayOccurs = time(NULL) + 1;
|
|
}
|
|
|
|
if (mVOIPNotify) mVOIPNotify->notifyReceivedVoipAudioCall(mChatWidget->getChatId().toPeerId());
|
|
|
|
timerAudioRing->start();
|
|
} else {
|
|
//Nothing to do, reset stat
|
|
pbAudioRing->setHidden(true);
|
|
pbAudioRing->setValue(0);
|
|
pbAudioRing->setToolTip("");
|
|
audioCaptureToggleButton->setGraphicsEffect(0);
|
|
}
|
|
}
|
|
|
|
void VOIPChatWidgetHolder::timerVideoRingTimeOut()
|
|
{
|
|
//Sending or receiving (-2 connected, -1 reseted, >=0 in progress)
|
|
if (sendVideoRingTime >= 0) {
|
|
//Sending
|
|
++sendVideoRingTime;
|
|
if (sendVideoRingTime == 100) sendVideoRingTime = 0;
|
|
pbVideoRing->setValue(sendVideoRingTime);
|
|
pbVideoRing->setToolTip(tr("Waiting for your friend to respond to your video call."));
|
|
pbVideoRing->setVisible(true);
|
|
|
|
if (time(NULL) > lastTimePlayOccurs) {
|
|
soundManager->play(VOIP_SOUND_OUTGOING_VIDEO_CALL);
|
|
lastTimePlayOccurs = time(NULL) + 1;
|
|
}
|
|
|
|
timerVideoRing->start();
|
|
} else if(recVideoRingTime >= 0) {
|
|
//Receiving
|
|
++recVideoRingTime;
|
|
if (recVideoRingTime == 100) recVideoRingTime = 0;
|
|
pbVideoRing->setValue(recVideoRingTime);
|
|
pbVideoRing->setToolTip(tr("Your friend is calling you for video. Respond."));
|
|
pbVideoRing->setVisible(true);
|
|
|
|
//launch an animation. Don't launch it if already animating
|
|
if (!videoCaptureToggleButton->graphicsEffect()
|
|
|| (videoCaptureToggleButton->graphicsEffect()->inherits("QGraphicsOpacityEffect")
|
|
&& ((QGraphicsOpacityEffect*)videoCaptureToggleButton->graphicsEffect())->opacity() == 1)
|
|
) {
|
|
QGraphicsOpacityEffect *effect = new QGraphicsOpacityEffect(audioListenToggleButton);
|
|
videoCaptureToggleButton->setGraphicsEffect(effect);
|
|
QPropertyAnimation *anim = new QPropertyAnimation(effect, "opacity", effect);
|
|
anim->setStartValue(1);
|
|
anim->setKeyValueAt(0.5,0);
|
|
anim->setEndValue(1);
|
|
anim->setDuration(timerVideoRing->interval());
|
|
anim->start();
|
|
}
|
|
videoCaptureToggleButton->setToolTip(tr("Answer"));
|
|
|
|
if (time(NULL) > lastTimePlayOccurs) {
|
|
soundManager->play(VOIP_SOUND_INCOMING_VIDEO_CALL);
|
|
lastTimePlayOccurs = time(NULL) + 1;
|
|
}
|
|
|
|
if (mVOIPNotify) mVOIPNotify->notifyReceivedVoipVideoCall(mChatWidget->getChatId().toPeerId());
|
|
|
|
timerVideoRing->start();
|
|
} else {
|
|
//Nothing to do, reset stat
|
|
pbVideoRing->setHidden(true);
|
|
pbVideoRing->setValue(0);
|
|
pbVideoRing->setToolTip("");
|
|
videoCaptureToggleButton->setGraphicsEffect(0);
|
|
}
|
|
}
|