2014-07-13 09:57:25 -04:00
# include <QToolButton>
# include <QPropertyAnimation>
# include <QIcon>
# include <QLayout>
# include <gui/audiodevicehelper.h>
# include "interface/rsvoip.h"
# include "gui/SoundManager.h"
# include "util/HandleRichText.h"
# include "gui/common/StatusDefs.h"
# include "gui/chat/ChatWidget.h"
# include "VOIPChatWidgetHolder.h"
# include "VideoProcessor.h"
# include "QVideoDevice.h"
# include <retroshare/rsstatus.h>
# define CALL_START ": / images / call-start-22.png"
# define CALL_STOP ": / images / call-stop-22.png"
# define CALL_HOLD ": / images / call-hold-22.png"
VOIPChatWidgetHolder : : VOIPChatWidgetHolder ( ChatWidget * chatWidget )
: QObject ( ) , ChatWidgetHolder ( chatWidget )
{
QIcon icon ;
icon . addPixmap ( QPixmap ( " :/images/audio-volume-muted-22.png " ) ) ;
icon . addPixmap ( QPixmap ( " :/images/audio-volume-medium-22.png " ) , QIcon : : Normal , QIcon : : On ) ;
icon . addPixmap ( QPixmap ( " :/images/audio-volume-medium-22.png " ) , QIcon : : Disabled , QIcon : : On ) ;
icon . addPixmap ( QPixmap ( " :/images/audio-volume-medium-22.png " ) , QIcon : : Active , QIcon : : On ) ;
icon . addPixmap ( QPixmap ( " :/images/audio-volume-medium-22.png " ) , QIcon : : Selected , QIcon : : On ) ;
audioListenToggleButton = new QToolButton ;
audioListenToggleButton - > setIcon ( icon ) ;
audioListenToggleButton - > setIconSize ( QSize ( 22 , 22 ) ) ;
audioListenToggleButton - > setAutoRaise ( true ) ;
audioListenToggleButton - > setCheckable ( true ) ;
audioListenToggleButton - > setMinimumSize ( QSize ( 28 , 28 ) ) ;
audioListenToggleButton - > setMaximumSize ( QSize ( 28 , 28 ) ) ;
audioListenToggleButton - > setText ( QString ( ) ) ;
audioListenToggleButton - > setToolTip ( tr ( " Mute " ) ) ;
QIcon icon2 ;
icon2 . addPixmap ( QPixmap ( " :/images/call-start-22.png " ) ) ;
icon2 . addPixmap ( QPixmap ( " :/images/call-hold-22.png " ) , QIcon : : Normal , QIcon : : On ) ;
icon2 . addPixmap ( QPixmap ( " :/images/call-hold-22.png " ) , QIcon : : Disabled , QIcon : : On ) ;
icon2 . addPixmap ( QPixmap ( " :/images/call-hold-22.png " ) , QIcon : : Active , QIcon : : On ) ;
icon2 . addPixmap ( QPixmap ( " :/images/call-hold-22.png " ) , QIcon : : Selected , QIcon : : On ) ;
audioCaptureToggleButton = new QToolButton ;
audioCaptureToggleButton - > setMinimumSize ( QSize ( 28 , 28 ) ) ;
audioCaptureToggleButton - > setMaximumSize ( QSize ( 28 , 28 ) ) ;
audioCaptureToggleButton - > setText ( QString ( ) ) ;
audioCaptureToggleButton - > setToolTip ( tr ( " Start Call " ) ) ;
audioCaptureToggleButton - > setIcon ( icon2 ) ;
audioCaptureToggleButton - > setIconSize ( QSize ( 22 , 22 ) ) ;
audioCaptureToggleButton - > setAutoRaise ( true ) ;
audioCaptureToggleButton - > setCheckable ( true ) ;
QIcon icon3 ;
2014-09-21 08:31:16 -04:00
icon3 . addPixmap ( QPixmap ( " :/images/video-icon-on.png " ) ) ;
icon3 . addPixmap ( QPixmap ( " :/images/video-icon-off.png " ) , QIcon : : Normal , QIcon : : On ) ;
icon3 . addPixmap ( QPixmap ( " :/images/video-icon-off.png " ) , QIcon : : Disabled , QIcon : : On ) ;
icon3 . addPixmap ( QPixmap ( " :/images/video-icon-off.png " ) , QIcon : : Active , QIcon : : On ) ;
icon3 . addPixmap ( QPixmap ( " :/images/video-icon-off.png " ) , QIcon : : Selected , QIcon : : On ) ;
2014-07-13 09:57:25 -04:00
videoCaptureToggleButton = new QToolButton ;
videoCaptureToggleButton - > setMinimumSize ( QSize ( 28 , 28 ) ) ;
videoCaptureToggleButton - > setMaximumSize ( QSize ( 28 , 28 ) ) ;
videoCaptureToggleButton - > setText ( QString ( ) ) ;
2014-08-13 09:19:22 -04:00
videoCaptureToggleButton - > setToolTip ( tr ( " Start Video Call " ) ) ;
2014-07-13 09:57:25 -04:00
videoCaptureToggleButton - > setIcon ( icon3 ) ;
videoCaptureToggleButton - > setIconSize ( QSize ( 22 , 22 ) ) ;
videoCaptureToggleButton - > setAutoRaise ( true ) ;
videoCaptureToggleButton - > setCheckable ( true ) ;
hangupButton = new QToolButton ;
hangupButton - > setIcon ( QIcon ( " :/images/call-stop-22.png " ) ) ;
hangupButton - > setIconSize ( QSize ( 22 , 22 ) ) ;
hangupButton - > setMinimumSize ( QSize ( 28 , 28 ) ) ;
hangupButton - > setMaximumSize ( QSize ( 28 , 28 ) ) ;
hangupButton - > setCheckable ( false ) ;
hangupButton - > setAutoRaise ( true ) ;
hangupButton - > setText ( QString ( ) ) ;
hangupButton - > setToolTip ( tr ( " Hangup Call " ) ) ;
2014-09-20 12:44:26 -04:00
hangupButton - > hide ( ) ;
2014-07-13 09:57:25 -04:00
connect ( videoCaptureToggleButton , SIGNAL ( clicked ( ) ) , this , SLOT ( toggleVideoCapture ( ) ) ) ;
connect ( audioListenToggleButton , SIGNAL ( clicked ( ) ) , this , SLOT ( toggleAudioListen ( ) ) ) ;
connect ( audioCaptureToggleButton , SIGNAL ( clicked ( ) ) , this , SLOT ( toggleAudioCapture ( ) ) ) ;
connect ( hangupButton , SIGNAL ( clicked ( ) ) , this , SLOT ( hangupCall ( ) ) ) ;
mChatWidget - > addChatBarWidget ( audioListenToggleButton ) ;
mChatWidget - > addChatBarWidget ( audioCaptureToggleButton ) ;
mChatWidget - > addChatBarWidget ( videoCaptureToggleButton ) ;
mChatWidget - > addChatBarWidget ( hangupButton ) ;
outputAudioProcessor = NULL ;
outputAudioDevice = NULL ;
inputAudioProcessor = NULL ;
inputAudioDevice = NULL ;
inputVideoDevice = new QVideoInputDevice ( mChatWidget ) ; // not started yet ;-)
inputVideoProcessor = new JPEGVideoEncoder ;
outputVideoProcessor = new JPEGVideoDecoder ;
// Make a widget with two video devices, one for echo, and one for the talking peer.
videoWidget = new QWidget ( mChatWidget ) ;
videoWidget - > setLayout ( new QHBoxLayout ( ) ) ;
videoWidget - > layout ( ) - > addWidget ( echoVideoDevice = new QVideoOutputDevice ( videoWidget ) ) ;
videoWidget - > layout ( ) - > addWidget ( outputVideoDevice = new QVideoOutputDevice ( videoWidget ) ) ;
2014-09-20 12:28:26 -04:00
videoWidget - > hide ( ) ;
2014-07-13 09:57:25 -04:00
2014-07-15 16:04:31 -04:00
connect ( inputVideoDevice , SIGNAL ( networkPacketReady ( ) ) , this , SLOT ( sendVideoData ( ) ) ) ;
2014-07-13 09:57:25 -04:00
echoVideoDevice - > setMinimumSize ( 128 , 95 ) ;
outputVideoDevice - > setMinimumSize ( 128 , 95 ) ;
mChatWidget - > addChatHorizontalWidget ( videoWidget ) ;
inputVideoDevice - > setEchoVideoTarget ( echoVideoDevice ) ;
2014-07-15 16:04:31 -04:00
inputVideoDevice - > setVideoEncoder ( inputVideoProcessor ) ;
2014-07-13 09:57:25 -04:00
outputVideoProcessor - > setDisplayTarget ( outputVideoDevice ) ;
}
VOIPChatWidgetHolder : : ~ VOIPChatWidgetHolder ( )
{
if ( inputAudioDevice ! = NULL )
inputAudioDevice - > stop ( ) ;
delete inputVideoDevice ;
delete inputVideoProcessor ;
delete outputVideoProcessor ;
}
void VOIPChatWidgetHolder : : toggleAudioListen ( )
{
if ( audioListenToggleButton - > isChecked ( ) ) {
audioListenToggleButton - > setToolTip ( tr ( " Mute yourself " ) ) ;
} else {
audioListenToggleButton - > setToolTip ( tr ( " Unmute yourself " ) ) ;
//audioListenToggleButton->setChecked(false);
/*if (outputAudioDevice) {
outputAudioDevice - > stop ( ) ;
} */
}
}
void VOIPChatWidgetHolder : : hangupCall ( )
{
2014-07-20 16:50:36 -04:00
disconnect ( inputAudioProcessor , SIGNAL ( networkPacketReady ( ) ) , this , SLOT ( sendAudioData ( ) ) ) ;
if ( inputAudioDevice ) {
inputAudioDevice - > stop ( ) ;
}
if ( outputAudioDevice ) {
outputAudioDevice - > stop ( ) ;
}
audioListenToggleButton - > setChecked ( false ) ;
audioCaptureToggleButton - > setChecked ( false ) ;
2014-09-20 12:44:26 -04:00
hangupButton - > hide ( ) ;
2014-07-13 09:57:25 -04:00
}
void VOIPChatWidgetHolder : : toggleAudioCapture ( )
{
if ( audioCaptureToggleButton - > isChecked ( ) ) {
//activate audio output
audioListenToggleButton - > setChecked ( true ) ;
audioCaptureToggleButton - > setToolTip ( tr ( " Hold Call " ) ) ;
2014-09-20 12:44:26 -04:00
hangupButton - > show ( ) ;
2014-07-13 09:57:25 -04:00
//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 ) ;
if ( mChatWidget ) {
mChatWidget - > addChatMsg ( true , tr ( " VoIP Status " ) , QDateTime : : currentDateTime ( ) , QDateTime : : currentDateTime ( ) , tr ( " Outgoing Call is started... " ) , ChatWidget : : MSGTYPE_SYSTEM ) ;
}
} else {
disconnect ( inputAudioProcessor , SIGNAL ( networkPacketReady ( ) ) , this , SLOT ( sendAudioData ( ) ) ) ;
if ( inputAudioDevice ) {
inputAudioDevice - > stop ( ) ;
}
audioCaptureToggleButton - > setToolTip ( tr ( " Resume Call " ) ) ;
2014-09-20 12:44:26 -04:00
hangupButton - > hide ( ) ;
2014-07-13 09:57:25 -04:00
}
}
void VOIPChatWidgetHolder : : toggleVideoCapture ( )
{
if ( videoCaptureToggleButton - > isChecked ( ) )
{
//activate video input
//
2014-09-20 12:28:26 -04:00
videoWidget - > show ( ) ;
2014-07-13 09:57:25 -04:00
inputVideoDevice - > start ( ) ;
videoCaptureToggleButton - > setToolTip ( tr ( " Shut camera off " ) ) ;
if ( mChatWidget )
mChatWidget - > addChatMsg ( true , tr ( " VoIP Status " ) , QDateTime : : currentDateTime ( ) , QDateTime : : currentDateTime ( ) , tr ( " you're now sending video... " ) , ChatWidget : : MSGTYPE_SYSTEM ) ;
}
else
{
2014-07-17 10:13:02 -04:00
inputVideoDevice - > stop ( ) ;
2014-07-13 09:57:25 -04:00
videoCaptureToggleButton - > setToolTip ( tr ( " Activate camera " ) ) ;
2014-07-20 16:50:36 -04:00
outputVideoDevice - > showFrameOff ( ) ;
2014-09-20 12:28:26 -04:00
videoWidget - > hide ( ) ;
2014-07-13 09:57:25 -04:00
}
}
2014-07-15 16:04:31 -04:00
void VOIPChatWidgetHolder : : addVideoData ( const QString name , QByteArray * array )
{
outputVideoProcessor - > receiveEncodedData ( ( unsigned char * ) array - > data ( ) , array - > size ( ) ) ;
}
2014-07-20 16:50:36 -04:00
void VOIPChatWidgetHolder : : setAcceptedBandwidth ( const QString name , uint32_t bytes_per_sec )
{
inputVideoProcessor - > setMaximumFrameRate ( bytes_per_sec ) ;
}
2014-07-13 09:57:25 -04:00
void VOIPChatWidgetHolder : : addAudioData ( const QString name , QByteArray * array )
{
if ( ! audioCaptureToggleButton - > isChecked ( ) ) {
//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 " ) ;
anim - > setStartValue ( 1 ) ;
anim - > setKeyValueAt ( 0.5 , 0 ) ;
anim - > setEndValue ( 1 ) ;
anim - > setDuration ( 400 ) ;
anim - > start ( ) ;
}
// soundManager->play(VOIP_SOUND_INCOMING_CALL);
audioCaptureToggleButton - > setToolTip ( tr ( " Answer " ) ) ;
//TODO make a toaster and a sound for the incoming call
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 ( name , * 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 ) ;
}
}
2014-07-15 16:04:31 -04:00
void VOIPChatWidgetHolder : : sendVideoData ( )
{
RsVoipDataChunk chunk ;
while ( inputVideoDevice & & inputVideoDevice - > getNextEncodedPacket ( chunk ) )
rsVoip - > sendVoipData ( mChatWidget - > getPeerId ( ) , chunk ) ;
}
2014-07-13 09:57:25 -04:00
void VOIPChatWidgetHolder : : sendAudioData ( )
{
while ( inputAudioProcessor & & inputAudioProcessor - > hasPendingPackets ( ) ) {
QByteArray qbarray = inputAudioProcessor - > getNetworkPacket ( ) ;
RsVoipDataChunk chunk ;
chunk . size = qbarray . size ( ) ;
chunk . data = ( void * ) qbarray . constData ( ) ;
2014-07-15 16:04:31 -04:00
chunk . type = RsVoipDataChunk : : RS_VOIP_DATA_TYPE_AUDIO ;
2014-07-13 09:57:25 -04:00
rsVoip - > sendVoipData ( mChatWidget - > getPeerId ( ) , chunk ) ;
}
}
void VOIPChatWidgetHolder : : updateStatus ( int status )
{
audioListenToggleButton - > setEnabled ( true ) ;
audioCaptureToggleButton - > setEnabled ( true ) ;
hangupButton - > setEnabled ( true ) ;
switch ( status ) {
case RS_STATUS_OFFLINE :
audioListenToggleButton - > setEnabled ( false ) ;
audioCaptureToggleButton - > setEnabled ( false ) ;
hangupButton - > setEnabled ( false ) ;
break ;
}
}