source: qutecom-2.2/wengophone/src/presentation/qt/phonecall/QtPhoneCall.cpp @ 340:17fdf00a13b0

Last change on this file since 340:17fdf00a13b0 was 340:17fdf00a13b0, checked in by vadim@…, 4 years ago

Fix include file name to QtCallBar? to avoid comilation problem on Linux

File size: 24.1 KB
Line 
1/*
2 * WengoPhone, a voice over Internet phone
3 * Copyright (C) 2004-2007  Wengo
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20#include "QtPhoneCall.h"
21
22#include "ui_PhoneCallWidget.h"
23
24#ifdef XV_HWACCEL
25        #include "QtVideoXV.h"
26#endif
27
28#include "QtVideoQt.h"
29#include "QtPhoneCallEventFilter.h"
30#include "../toaster/QtCallToaster.h"
31#include "../QtDialpad.h"
32
33#include "QtAudioSmileysWindow.h"
34
35#include <presentation/qt/QtWengoPhone.h>
36#include <presentation/qt/QtToolBar.h>
37#include <presentation/qt/callbar/QtCallBar.h>
38#include <presentation/qt/statusbar/QtStatusBar.h>
39#include <presentation/qt/contactlist/QtContactList.h>
40#include <presentation/qt/profile/QtProfileDetails.h>
41#include <presentation/qt/conference/QtConferenceCallWidget.h>
42
43#include <control/CWengoPhone.h>
44#include <control/profile/CUserProfile.h>
45#include <control/profile/CUserProfileHandler.h>
46#include <control/phonecall/CPhoneCall.h>
47
48#include <model/config/Config.h>
49#include <model/config/ConfigManager.h>
50#include <model/contactlist/ContactProfile.h>
51#include <model/phonecall/ConferenceCall.h>
52#include <model/phonecall/PhoneCall.h>
53#include <model/phoneline/PhoneLine.h>
54#include <model/profile/AvatarList.h>
55
56#include <sipwrapper/CodecList.h>
57#include <sipwrapper/SipWrapper.h>
58
59#include <cutil/global.h>
60
61#include <util/Logger.h>
62#include <util/SafeDelete.h>
63
64#include <qtutil/SafeConnect.h>
65#include <qtutil/WidgetRatioEnforcer.h>
66#include <qtutil/WidgetUtils.h>
67
68#include <QtCore/QMutex>
69#include <QtCore/QTime>
70#include <QtCore/QTimer>
71
72#include <QtGui/QMenu>
73#include <QtGui/QMessageBox>
74#include <QtGui/QPainter>
75
76// If a PSTN number is shorter than this length, we assume it's a special sip
77// account, like 333 for Wengo
78static const int PSTN_NUMBER_MIN_LENGTH = 4;
79
80static const int LOCAL_FRAME_WIDTH = 64;
81static const int LOCAL_FRAME_HEIGHT = 64;
82static const int LOCAL_FRAME_MARGIN = 7;
83
84// See wifo/phapi/phmedia-video.c
85static const int NOWEBCAM_FILL_VALUE = 128;
86
87static const int NOWEBCAM_SAMPLE_COUNT = 200;
88
89// Minimum width of buttons shown when we are in "talking" state. Defined to avoid square buttons
90// under MacOS X
91static const int TALKING_BUTTON_MIN_WIDTH = 50;
92
93/**
94 * Helper function to determine if image is a real webcam or not:
95 * If the remote user has no webcam, then wifo will send us a yuv image filled
96 * with NOWEBCAM_FILL_VALUE bytes.
97 */
98static bool isRealWebcamVideoFrame(piximage* image) {
99        if (image->palette != PIX_OSI_YUV420P) {
100                return true;
101        }
102
103        int step = (image->width * image->height * 3 / 2) / NOWEBCAM_SAMPLE_COUNT;
104
105        for (int sample=0; sample < NOWEBCAM_SAMPLE_COUNT; ++sample) {
106                if (image->data[sample * step] != NOWEBCAM_FILL_VALUE) {
107                        return true;
108                }
109        }
110
111        return false;
112}
113
114static void setButtonAction(QPushButton* button, QAction* action) {
115        button->disconnect();
116        SAFE_CONNECT_RECEIVER(button, SIGNAL(clicked()), action, SLOT(trigger()));
117        button->setIcon(action->icon());
118        button->setEnabled(action->isEnabled());
119        button->setToolTip(action->toolTip());
120}
121
122static void flashMainWindow(QWidget* window) {
123        if (window->isActiveWindow()) {
124                return;
125        }
126
127        if (!window->isVisible()) {
128                // Make sure the window appears on the taskbar,
129                // otherwise it won't flash...
130                window->showMinimized();
131        }
132
133        WidgetUtils::flashWindow(window);
134}
135
136QtPhoneCall::QtPhoneCall(CPhoneCall & cPhoneCall)
137        : QObject(NULL),
138        _cPhoneCall(cPhoneCall) {
139
140        _qtWengoPhone = (QtWengoPhone *) _cPhoneCall.getCWengoPhone().getPresentation();
141        _videoWindow = NULL;
142        _closed = false;
143        _duration = 0;
144
145        _callToaster = NULL;
146        _remoteVideoFrame = NULL;
147        _localVideoFrame = NULL;
148        _hold = false;
149        _videoMode = VM_None;
150
151        _mutex = new QMutex(QMutex::Recursive);
152
153        _phoneCallWidget = new QWidget(NULL);
154
155        _ui = new Ui::PhoneCallWidget();
156        _ui->setupUi(_phoneCallWidget);
157        _ui->encryptionFrame->hide();
158        //_ui->videoContainer->hide();
159        _ui->labelStack->setCurrentWidget(_ui->avatarPage);
160        _ui->buttonStack->setCurrentWidget(_ui->ringingPage);
161
162        _phoneCallWidget->setAutoFillBackground(true);
163
164        std::string tmpDisplayName = _cPhoneCall.getPhoneCall().getPeerSipAddress().getDisplayName();
165        QString userName = QString::fromUtf8(tmpDisplayName.c_str());
166
167        if (userName.isEmpty()) {
168                userName = QString::fromStdString(_cPhoneCall.getPhoneCall().getPeerSipAddress().getUserName());
169        }
170        QPixmap avatarPixmap = loadContactAvatar(userName);
171        initAvatarLabel(avatarPixmap);
172
173
174        Config & config = ConfigManager::getInstance().getCurrentConfig();
175
176        // On MacOSX getVideoEnable causes quite a lot of work, like listing the
177        // available devices. Therefore we keep the result instead of asking it
178        // everytime it's needed.
179        _videoEnabledInConfig = config.getVideoEnable();
180
181        //init flip
182        PhoneLine & phoneLine = dynamic_cast < PhoneLine & > (_cPhoneCall.getPhoneCall().getPhoneLine());
183        phoneLine.flipVideoImage(config.getVideoFlipEnable());
184        ////
185
186        userName = getDisplayName(userName);
187
188#ifndef OS_MACOSX
189        //With Qt4.2, the button background is set to _phoneCallWidget background
190        //color on Windows and Linux, setting autoFillBackground to true prevents
191        //this.
192        //We don't want to do this on OSX, because on this platform setting
193        //autoFillBackground to true paints horizontal stripes behind the buttons.
194        Q_FOREACH(QPushButton* button, _phoneCallWidget->findChildren<QPushButton*>()) {
195                button->setAutoFillBackground(true);
196        }
197        ////
198#endif
199
200        Q_FOREACH(QPushButton* button, _ui->talkingPage->findChildren<QPushButton*>()) {
201                button->setMinimumWidth(TALKING_BUTTON_MIN_WIDTH);
202        }
203
204        // Set bold ourself: if we do it from Designer it alters the font name (at
205        // least with Qt 4.1)
206        QFont font(_ui->nickNameLabel->font());
207        font.setBold(true);
208        _ui->nickNameLabel->setFont(font);
209
210        _ui->nickNameLabel->setText(userName);
211        updateNickNameToolTip();
212
213        _ui->statusLabel->setToolTip(tr("Status"));
214
215        // Accept call
216        SAFE_CONNECT(_ui->acceptButton, SIGNAL(clicked()), SLOT(acceptCall()));
217
218        // Reject call
219        SAFE_CONNECT(_ui->rejectButton, SIGNAL(clicked()), SLOT(rejectCall()));
220
221        // Tweak ui when we are the caller
222        if (!isIncoming()) {
223                _ui->acceptButton->hide();
224                _ui->rejectButton->setText(tr("Ca&ncel"));
225        }
226
227        // Hang up
228        _actionHangupCall = new QAction(QIcon(":/pics/actions/hangup-phone.png"), tr("Hang-up"), _phoneCallWidget);
229        SAFE_CONNECT(_actionHangupCall, SIGNAL(triggered()), SLOT(rejectCall()));
230        setButtonAction(_ui->hangupButton, _actionHangupCall);
231
232        //Hold
233        _actionHold = new QAction(_phoneCallWidget);
234        SAFE_CONNECT(_actionHold, SIGNAL(triggered()), SLOT(holdOrResume()));
235
236#ifndef DISABLE_MANUAL_CALL_FORWARD
237        //Call forward
238        SAFE_CONNECT(_ui->forwardButton, SIGNAL(clicked()), SLOT(callTransfer()) );
239        _ui->forwardButton->setToolTip(tr("Transfert call"));
240#else
241        _ui->forwardButton->hide();
242#endif
243
244        //Add contact
245        _actionAddContact = new QAction(QIcon(":/pics/actions/add-contact.png"), tr("Add contact"), _phoneCallWidget);
246        SAFE_CONNECT(_actionAddContact, SIGNAL(triggered()), SLOT(addContact()));
247        setButtonAction(_ui->addContactButton, _actionAddContact);
248        ////
249
250        SAFE_CONNECT(_ui->dialpadButton, SIGNAL(toggled(bool)), SLOT(toggleDialpad(bool)) );
251        SAFE_CONNECT(_ui->smileysButton, SIGNAL(toggled(bool)), SLOT(toggleSmileys(bool)) );
252        SAFE_CONNECT(_ui->createConf, SIGNAL(clicked()), SLOT(createConf()) );
253
254
255        //Computes the call duration
256        _callTimer = new QTimer(_phoneCallWidget);
257        SAFE_CONNECT(_callTimer, SIGNAL(timeout()), SLOT(updateCallDuration()));
258
259        QtPhoneCallEventFilter * filter = new QtPhoneCallEventFilter(_phoneCallWidget);
260        _phoneCallWidget->installEventFilter(filter);
261
262        flashMainWindow(_qtWengoPhone->getWidget());
263        showToaster(userName, avatarPixmap);
264
265        if (!_cPhoneCall.getPhoneCall().getConferenceCall()) {
266                _qtWengoPhone->addPhoneCall(this);
267        } else {
268                hideConfButton();
269                _qtWengoPhone->addToConference(this);
270        }
271
272        updateStatusLabel();
273        updateHoldAction();
274
275        //update toolbar (menus)
276        if (_qtWengoPhone) {
277                _qtWengoPhone->getQtToolBar().updateMenuActions();
278        }
279        ////
280
281        _ui->acceptButton->setFocus();
282}
283
284QtPhoneCall::~QtPhoneCall() {
285        if (_remoteVideoFrame) {
286                pix_free(_remoteVideoFrame);
287        }
288        if (_localVideoFrame) {
289                pix_free(_localVideoFrame);
290        }
291
292        OWSAFE_DELETE(_ui);
293        OWSAFE_DELETE(_mutex);
294}
295
296void QtPhoneCall::initAvatarLabel(const QPixmap& pixmap) {
297        if (pixmap.hasAlpha()) {
298                // Paint avatar over a background if it's transparent (doing so for
299                // full opaque images looks ugly)
300                QPixmap bg(":/pics/phonecall/avatar_background.png");
301                QPainter painter(&bg);
302                painter.drawPixmap(
303                        (bg.width() - pixmap.width()) / 2,
304                        (bg.height() - pixmap.height()) / 2,
305                        pixmap);
306                painter.end();
307                _ui->avatarLabel->setPixmap(bg);
308        } else {
309                _ui->avatarLabel->setPixmap(pixmap);
310        }
311
312        _ui->labelStack->setCurrentWidget(_ui->avatarPage);
313}
314
315QPixmap QtPhoneCall::loadContactAvatar(const QString& userName) {
316
317        QPixmap pixmap;
318
319        QtContactList * qtContactList = _qtWengoPhone->getQtContactList();
320        if (qtContactList) {
321                CContactList & cContactList = qtContactList->getCContactList();
322
323                IMContact imContact(EnumIMProtocol::IMProtocolWengo, userName.toStdString());
324                std::string contactId = cContactList.findContactThatOwns(imContact);
325                ContactProfile contactProfile = cContactList.getContactProfile(contactId);
326
327                std::string data = contactProfile.getIcon().getData();
328                if (!data.empty()) {
329                        pixmap.loadFromData((uchar *) data.c_str(), data.size());
330                }
331        }
332
333        if (pixmap.isNull()) {
334                // User is not in contact list, or has no avatar defined, use default
335                // avatar instead
336                std::string data = AvatarList::getInstance().getDefaultAvatarPicture().getData();
337                pixmap.loadFromData((uchar*) data.c_str(), data.size());
338        }
339
340        return pixmap;
341}
342
343
344void QtPhoneCall::updateHoldAction() {
345        if (_hold) {
346                _actionHold->setToolTip(tr("Resume"));
347                _actionHold->setIcon(QIcon(":/pics/actions/resume-phone.png"));
348        } else {
349                _actionHold->setToolTip(tr("Hold"));
350                _actionHold->setIcon(QIcon(":/pics/actions/hold-phone.png"));
351        }
352        setButtonAction(_ui->holdButton, _actionHold);
353}
354
355
356void QtPhoneCall::updateNickNameToolTip() {
357        QString toolTip = QString::fromStdString(_cPhoneCall.getPeerSipAddress());
358        if (!_codecs.isEmpty()) {
359                toolTip += QString(" (%1)").arg(_codecs);
360        }
361        _ui->nickNameLabel->setToolTip(toolTip);
362}
363
364
365QString QtPhoneCall::getDisplayName(QString str) 
366{
367        QString tmpUserName = str;
368
369        CWengoPhone & cWengoPhone = _cPhoneCall.getCWengoPhone();
370        CUserProfile* cUserProfile =  cWengoPhone.getCUserProfileHandler().getCUserProfile();
371        if(cUserProfile)
372        {
373                std::string  uuid = cUserProfile->getCContactList().findContactThatOwns(str.toStdString());
374                if(!uuid.empty())
375                {
376                        ContactProfile contactProfile = cUserProfile->getCContactList().getContactProfile(uuid);
377                        if(!contactProfile.getShortDisplayName().empty())
378                                tmpUserName = QString::fromStdString(contactProfile.getShortDisplayName());
379                }
380        }
381        return tmpUserName;
382}
383
384void QtPhoneCall::stateChangedEvent(EnumPhoneCallState::PhoneCallState state) {
385        std::string codecs;
386        if (_cPhoneCall.getAudioCodecUsed() != CodecList::AudioCodecError) {
387                codecs += CodecList::toString(_cPhoneCall.getAudioCodecUsed());
388        }
389        if (_cPhoneCall.getVideoCodecUsed() != CodecList::VideoCodecError) {
390                codecs += "/" + CodecList::toString(_cPhoneCall.getVideoCodecUsed());
391        }
392        _codecs = QString::fromStdString(codecs);
393        updateNickNameToolTip();
394
395        updateStatusLabel();
396
397        //update toolbar (menus)
398        if (_qtWengoPhone) {
399                _qtWengoPhone->getQtToolBar().updateMenuActions();
400        }
401
402        switch (state) {
403        case EnumPhoneCallState::PhoneCallStateTalking:
404                _ui->buttonStack->setCurrentWidget(_ui->talkingPage);
405                _duration = 0;
406                _callTimer->start(1000);
407                _actionHangupCall->setEnabled(true);
408
409                _ui->encryptionFrame->setVisible(isCallEncrypted());
410
411                startedTalking(this);
412                break;
413
414        case EnumPhoneCallState::PhoneCallStateDialing:
415        case EnumPhoneCallState::PhoneCallStateRinging:
416        case EnumPhoneCallState::PhoneCallStateRingingStart:
417        case EnumPhoneCallState::PhoneCallStateRingingStop:
418        case EnumPhoneCallState::PhoneCallStateIncoming:
419                _actionHangupCall->setEnabled(true);
420                break;
421
422        case EnumPhoneCallState::PhoneCallStateHold:
423                _hold = true;
424                updateHoldAction();
425                break;
426
427        case EnumPhoneCallState::PhoneCallStateResumed:
428                _hold = false;
429                updateHoldAction();
430                break;
431
432        case EnumPhoneCallState::PhoneCallStateUnknown:
433        case EnumPhoneCallState::PhoneCallStateError:
434        case EnumPhoneCallState::PhoneCallStateMissed:
435        case EnumPhoneCallState::PhoneCallStateRedirected:
436                break;
437
438        case EnumPhoneCallState::PhoneCallStateClosed:
439                LOG_FATAL("should never reach this case since PPhoneCall::close() is done for this purpose");
440                break;
441
442        default:
443                LOG_FATAL("unknown PhoneCallState=" + EnumPhoneCallState::toString(state));
444        }
445}
446
447void QtPhoneCall::initVideo(piximage* remoteVideoFrame, piximage* localVideoFrame) {
448        _remoteVideoFrame = remoteVideoFrame;
449        _localVideoFrame = localVideoFrame;
450
451        if (!isRealWebcamVideoFrame(remoteVideoFrame)) {
452                if (_videoEnabledInConfig) {
453                        _videoMode = VM_LocalOnly;
454                } else {
455                        _videoMode = VM_None;
456                }
457                return;
458        }
459
460        // We only get there if we receive a real video from the remote user
461
462        if (_videoEnabledInConfig) {
463                _videoMode = VM_Both;
464        } else {
465                _videoMode = VM_RemoteOnly;
466        }
467        // Hide avatar label to save space for the video
468        //_ui->avatarLabel->hide();
469
470#ifdef XV_HWACCEL
471        if (config.getXVideoEnable()) {
472                _videoWindow = new QtVideoXV(_phoneCallWidget, remoteVideoFrame->width, remoteVideoFrame->height,
473                        localVideoFrame->width, localVideoFrame->height);
474                if (!_videoWindow->isInitialized()) {
475                        OWSAFE_DELETE(_videoWindow);
476                }
477        }
478#endif
479
480        // We can fallback from a failure in QtVideoXV
481        if (!_videoWindow) {
482                _videoWindow = new QtVideoQt(_ui->videoContainer);
483                SAFE_CONNECT(_videoWindow, SIGNAL(toggleFlipVideoImageSignal()), SLOT(toggleFlipVideoImage()));
484        }
485
486        // Init videoContainer
487        double ratio = remoteVideoFrame->width / double(remoteVideoFrame->height);
488        _ui->videoContainer->setRatio(ratio);
489        _ui->videoContainer->setChild(_videoWindow->getWidget());
490        QTimer::singleShot(0, _videoWindow->getWidget(), SLOT(show()));
491        //_ui->videoContainer->show();
492        _ui->labelStack->setCurrentWidget(_ui->videoPage);
493}
494
495void QtPhoneCall::videoFrameReceivedEvent(piximage * remoteVideoFrame, piximage * localVideoFrame) {
496
497        QMutexLocker locker(_mutex);
498
499        //FIXME hack to prevent a crash
500        if (_closed) {
501                return;
502        }
503
504        if (_videoMode == VM_None) {
505                initVideo(remoteVideoFrame, localVideoFrame);
506        }
507
508        if (_videoMode == VM_RemoteOnly || _videoMode == VM_Both) {
509                _videoWindow->showImage(remoteVideoFrame, localVideoFrame);
510        }
511
512        if (_videoMode == VM_LocalOnly) {
513                QImage image;
514                QSize size(_localVideoFrame->width, _localVideoFrame->height);
515                size.scale(LOCAL_FRAME_WIDTH, LOCAL_FRAME_HEIGHT, Qt::KeepAspectRatio);
516                if (size.width() & 1) {
517                        size.setWidth(size.width() + 1);
518                }
519                if (size.height() & 1) {
520                        size.setHeight(size.height() + 1);
521                }
522                QtVideoQt::convertPixImageToQImage(_localVideoFrame, size, &image);
523                QPixmap avatarPix = *_ui->avatarLabel->pixmap();
524                QPainter painter(&avatarPix);
525                painter.drawImage(
526                        avatarPix.width() - size.width() - LOCAL_FRAME_MARGIN,
527                        avatarPix.height() - size.height() - LOCAL_FRAME_MARGIN,
528                        image);
529                painter.end();
530                _ui->avatarLabel->setPixmap(avatarPix);
531        }
532}
533
534void QtPhoneCall::acceptCall() {
535        _ui->statusLabel->setText(tr("Initialization..."));
536        _cPhoneCall.accept();
537        if (_callToaster) {
538                _callToaster->close();
539        }
540}
541
542void QtPhoneCall::rejectCall() {
543        LOG_DEBUG("phone call hangup");
544        switch (_cPhoneCall.getState()) {
545        case EnumPhoneCallState::PhoneCallStateClosed:
546        case EnumPhoneCallState::PhoneCallStateError:
547        case EnumPhoneCallState::PhoneCallStateResumed:
548        case EnumPhoneCallState::PhoneCallStateTalking:
549        case EnumPhoneCallState::PhoneCallStateDialing:
550        case EnumPhoneCallState::PhoneCallStateRinging:
551        case EnumPhoneCallState::PhoneCallStateRingingStart:
552        case EnumPhoneCallState::PhoneCallStateRingingStop:
553        case EnumPhoneCallState::PhoneCallStateIncoming:
554        case EnumPhoneCallState::PhoneCallStateHold:
555        case EnumPhoneCallState::PhoneCallStateRedirected:
556                _cPhoneCall.hangUp();
557                break;
558        default:
559                LOG_DEBUG("call rejected");
560        }
561}
562
563//--start my dirty hack
564void QtPhoneCall::callTransfer() {
565
566        std::string forwardNumber = _qtWengoPhone->getQtCallBar().getPhoneComboBoxCurrentText();
567        if (forwardNumber.length()>0){
568                _cPhoneCall.blindTransfer(forwardNumber);
569                _qtWengoPhone->getQtCallBar().clearPhoneComboBoxEditText();
570        }
571        else {
572                QString titel = tr("QuteCom - Information");
573                QString message = tr("You must enter a phone number before forwarding");
574                QMessageBox::information(_qtWengoPhone->getWidget(), titel, message );
575        }
576}
577//-- end my dirty hack
578
579void QtPhoneCall::holdOrResume() {
580        if (_hold) {
581                _cPhoneCall.resume();
582        } else {
583                _cPhoneCall.hold();
584        }
585        updateHoldAction();
586}
587
588void QtPhoneCall::updateCallDuration() {
589        _duration++;
590        updateStatusLabel();
591}
592
593void QtPhoneCall::updateStatusLabel() {
594        QString text;
595        switch (_cPhoneCall.getState()) {
596        case EnumPhoneCallState::PhoneCallStateError:
597                text = tr("Error");
598                break;
599
600        case EnumPhoneCallState::PhoneCallStateResumed:
601        case EnumPhoneCallState::PhoneCallStateTalking:
602                if (_cPhoneCall.getPhoneCall().getConferenceCall()) {
603                        text = tr("Talking - Conference");
604                } else {
605                        text = tr("Talking");
606                }
607                break;
608
609        case EnumPhoneCallState::PhoneCallStateDialing:
610                text = tr("Dialing");
611                break;
612
613        case EnumPhoneCallState::PhoneCallStateRinging:
614                text = tr("Ringing");
615                break;
616
617        case EnumPhoneCallState::PhoneCallStateRingingStart:
618                text = tr("Ringing");
619                break;
620
621        case EnumPhoneCallState::PhoneCallStateIncoming:
622                text = tr("Incoming Call");
623                break;
624
625        case EnumPhoneCallState::PhoneCallStateHold:
626                text = tr("Hold");
627                break;
628
629        case EnumPhoneCallState::PhoneCallStateRedirected:
630                text = tr("Redirected");
631                break;
632
633        default:
634                break;
635        }
636        _ui->statusLabel->setText(text);
637
638        QTime time;
639        time = time.addSecs(_duration);
640        _ui->durationLabel->setText(time.toString(Qt::TextDate));
641}
642
643bool QtPhoneCall::isIncoming() const {
644        return (_cPhoneCall.getState() == EnumPhoneCallState::PhoneCallStateIncoming);
645}
646
647void QtPhoneCall::showToaster(const QString & userName, const QPixmap& pixmap) {
648        Config & config = ConfigManager::getInstance().getCurrentConfig();
649
650        if (!isIncoming()) {
651                return;
652        }
653
654        //Shows toaster for incoming chats?
655        if (!config.getNotificationShowToasterOnIncomingCall()) {
656                return;
657        }
658
659        OWSAFE_DELETE(_callToaster);
660        _callToaster = new QtCallToaster();
661        _callToaster->setMessage(userName);
662        _callToaster->setPixmap(pixmap);
663
664        SAFE_CONNECT(_callToaster, SIGNAL(pickUpButtonClicked()), SLOT(acceptCall()));
665        SAFE_CONNECT(_callToaster, SIGNAL(hangUpButtonClicked()), SLOT(rejectCall()));
666        _callToaster->show();
667}
668
669void QtPhoneCall::close() {
670        //FIXME hack to prevent a crash
671        _closed = true;
672
673        if (_callToaster) {
674                _callToaster->close();
675        }
676
677        _callTimer->disconnect();
678        _callTimer->stop();
679        OWSAFE_DELETE(_callTimer);
680
681        _actionHangupCall->setEnabled(false);
682        _ui->statusLabel->setText(tr("Closed"));
683        if (_videoWindow) {
684                if (_videoWindow->isFullScreen()) {
685                        _videoWindow->unFullScreen();
686                }
687        }
688
689        //update toolbar (menus)
690        if (_qtWengoPhone) {
691                _qtWengoPhone->getQtToolBar().updateMenuActions();
692        }
693        ////
694
695        //TODO: disconnect from flipWebcamButtonClicked
696        OWSAFE_DELETE(_videoWindow);
697        OWSAFE_DELETE(_phoneCallWidget);
698        deleteLater();
699}
700
701void QtPhoneCall::toggleFlipVideoImage() {
702        Config & config = ConfigManager::getInstance().getCurrentConfig();
703        PhoneLine & phoneLine = dynamic_cast < PhoneLine & > (_cPhoneCall.getPhoneCall().getPhoneLine());
704        bool flip = !config.getVideoFlipEnable();
705        phoneLine.flipVideoImage(flip);
706        config.set(Config::VIDEO_ENABLE_FLIP_KEY, flip);
707}
708
709/**
710 * Helper function trying to determine if a username is a PSTN number.
711 */
712static bool isPSTNUserName(const QString& userName) {
713        for (int pos=0; pos < userName.size(); ++pos) {
714                if (!userName[0].isDigit()) {
715                        return false;
716                }
717        }
718
719        return userName.size() >= PSTN_NUMBER_MIN_LENGTH;
720}
721
722void QtPhoneCall::addContact() {
723        CWengoPhone & cWengoPhone = _cPhoneCall.getCWengoPhone();
724        CUserProfile* cUserProfile =  cWengoPhone.getCUserProfileHandler().getCUserProfile();
725        if (!cUserProfile) {
726                LOG_WARN("No user profile defined. This should not happen");
727                return;
728        }
729
730        ContactProfile contactProfile;
731        QtProfileDetails qtProfileDetails(*cUserProfile, contactProfile, _phoneCallWidget->window(), tr("Add a Contact"));
732
733        // Fill some QtProfileDetails fields
734        PhoneCall& call = _cPhoneCall.getPhoneCall();
735        SipAddress sipAddress = call.getPeerSipAddress();
736
737        QString rawSipAddress = QString::fromStdString(sipAddress.getRawSipAddress());
738        Config & config = ConfigManager::getInstance().getCurrentConfig();
739        QString wengoRealm = QString::fromStdString( config.getWengoRealm() );
740        if (rawSipAddress.contains(wengoRealm)) {
741                // Wengo server
742                QString userName;
743                userName = QString::fromUtf8(sipAddress.getDisplayName().c_str());
744                if (userName.isEmpty()) {
745                        userName = QString::fromUtf8(sipAddress.getUserName().c_str());
746                }
747                if (isPSTNUserName(userName)) {
748                        // User name is the phone number
749                        qtProfileDetails.setHomePhone(userName);
750                } else {
751                        // User name is the name of the Wengo account
752                        qtProfileDetails.setWengoName(userName);
753                }
754        } else {
755                // External SIP server
756                QString address = QString::fromStdString(sipAddress.getSipAddress());
757                if (address.startsWith("sip:")) {
758                        address = address.mid(4);
759                }
760                qtProfileDetails.setSipAddress(address);
761        }
762        ////
763
764        if (qtProfileDetails.show()) {
765                // WARNING: if the user hang up while the dialog is shown, 'this' won't
766                // be valid anymore. Therefore we must not use any field of 'this'
767                // here.
768                cUserProfile->getCContactList().addContact(contactProfile);
769        }
770}
771
772bool QtPhoneCall::isCallEncrypted() {
773        return _cPhoneCall.isCallEncrypted();
774}
775
776
777/**
778 * Hide the other audio smileys window if it's open and uncheck its button
779 */
780static void hideOtherPopupWindow(QPushButton* button, QtAudioSmileysWindow* window) {
781        button->blockSignals(true);
782        button->setChecked(false);
783        button->blockSignals(false);
784        if (window) {
785                window->hide();
786        }
787}
788
789/**
790 * Show an audio smileys window
791 */
792static void togglePopupWindow(QtAudioSmileysWindow* window, bool on) {
793        if (on) {
794                window->show();
795        } else {
796                if (window) {
797                        window->hide();
798                }
799        }
800}
801
802void QtPhoneCall::toggleDialpad(bool on) {
803        if (_ui->smileysButton->isChecked()) {
804                hideOtherPopupWindow(_ui->smileysButton, _smileysWindow.get());
805        }
806        if (on) {
807                if (!_dialpadWindow.get()) {
808                        CDtmfThemeManager& manager = _qtWengoPhone->getCWengoPhone().getCDtmfThemeManager();
809                        _dialpadWindow.reset( new QtAudioSmileysWindow(manager, _qtWengoPhone) );
810                        _dialpadWindow->dialpad()->setThemeMode(QtDialpad::ThemeModeDefaultOnly);
811                        _dialpadWindow->setButton(_ui->dialpadButton);
812                }
813        }
814
815        togglePopupWindow(_dialpadWindow.get(), on);
816}
817
818void QtPhoneCall::toggleSmileys(bool on) {
819        if (_ui->dialpadButton->isChecked()) {
820                hideOtherPopupWindow(_ui->dialpadButton, _dialpadWindow.get());
821        }
822        if (on) {
823                if (!_smileysWindow.get()) {
824                        CDtmfThemeManager& manager = _qtWengoPhone->getCWengoPhone().getCDtmfThemeManager();
825                        _smileysWindow.reset( new QtAudioSmileysWindow(manager, _qtWengoPhone) );
826                        _smileysWindow->dialpad()->setThemeMode(QtDialpad::ThemeModeAudioSmileysOnly);
827                        _smileysWindow->setButton(_ui->smileysButton);
828                }
829        }
830
831        togglePopupWindow(_smileysWindow.get(), on);
832}
833
834void QtPhoneCall::createConf()
835{
836        QString address = QString::fromStdString(_cPhoneCall.getPeerSipAddress());
837       
838        if(address.contains("@"))
839                address = address.section("@",0,0);
840
841        if (address.startsWith("sip:")) {
842                address = address.mid(4);
843        }
844
845        //
846
847        QtConferenceCallWidget conferenceDialog(_qtWengoPhone->getWidget(), _qtWengoPhone->getCWengoPhone(), &_cPhoneCall.getPhoneCall().getPhoneLine(),false);
848        conferenceDialog.setFirstPeer(address.toStdString());
849        if(conferenceDialog.exec())
850        {
851                if(address != conferenceDialog.getSecondPeer())
852                {
853                        _ui->createConf->hide();
854                        _qtWengoPhone->addToConference(conferenceDialog.getSecondPeer(),&_cPhoneCall.getPhoneCall());
855                }
856        }
857}
858
859void QtPhoneCall::hideConfButton()
860{
861        _ui->createConf->hide();
862}
Note: See TracBrowser for help on using the repository browser.