00001
00002
00003
00004
00005
00006
00007
00008 #include <qapplication.h>
00009 #include <qfile.h>
00010 #include <qdialog.h>
00011 #include <qcursor.h>
00012 #include <qdir.h>
00013 #include <qimage.h>
00014 #include <qbitmap.h>
00015
00016 #include <stdlib.h>
00017 #include <unistd.h>
00018 #include <iostream>
00019 using namespace std;
00020
00021 #include <linux/videodev.h>
00022 #include <mythtv/mythcontext.h>
00023 #include <mythtv/mythwidgets.h>
00024 #include <mythtv/lcddevice.h>
00025
00026 #include "config.h"
00027 #include "webcam.h"
00028 #include "sipfsm.h"
00029 #include "phoneui.h"
00030 #include "vxml.h"
00031
00032
00033
00034
00035
00036 PhoneUIBox::PhoneUIBox(MythMainWindow *parent, QString window_name,
00037 QString theme_filename, const char *name)
00038
00039 : MythThemedDialog(parent, window_name, theme_filename, name)
00040 {
00041
00042 h263 = new H263Container();
00043
00044
00045 SelectHit = false;
00046 VideoOn = false;
00047
00048 wireUpTheme();
00049 phoneUIStatusBar = new PhoneUIStatusBar(getUITextType("caller_text"),
00050 getUITextType("audio_stats_text"),
00051 getUITextType("video_stats_text"),
00052 getUITextType("bw_stats_text"),
00053 getUITextType("call_time_text"),
00054 getUITextType("status_msg_text"));
00055
00056 bool reg;
00057 QString regAs;
00058 QString regTo;
00059 sipStack->GetRegistrationStatus(reg, regTo, regAs);
00060 if (reg)
00061 phoneUIStatusBar->DisplayNotification(QString(tr("Registered to ") + regTo + tr(" as ") + regAs), 5);
00062 else
00063 phoneUIStatusBar->DisplayNotification(tr("Not Registered"), 5);
00064
00065
00066 DirContainer = new DirectoryContainer();
00067 DirContainer->Load();
00068 DirContainer->createTree();
00069
00070 DirectoryList->setVisualOrdering(2);
00071 DirectoryList->setTreeOrdering(2);
00072 DirectoryList->setIconSelector(3);
00073
00074 DirContainer->writeTree();
00075 DirectoryList->assignTreeData(DirContainer->getTreeRoot());
00076
00077
00078 DirectoryList->showWholeTree(true);
00079 DirectoryList->colorSelectables(true);
00080
00081 QValueList <int> branches_to_current_node;
00082 branches_to_current_node.append(0);
00083 branches_to_current_node.append(0);
00084 DirectoryList->moveToNodesFirstChild(branches_to_current_node);
00085 DirectoryList->refresh();
00086
00087 updateForeground();
00088
00089
00090 sipStack->UiOpened(this);
00091 sipStack->UiWatch(DirContainer->ListAllEntries(true));
00092
00093
00094
00095 volume_display_timer = new QTimer(this);
00096 VolumeMode = VOL_VOLUME;
00097 volume_icon->SetImage(gContext->FindThemeDir("default") + "/mp_volume_icon.png");
00098 volume_icon->LoadImage();
00099
00100 connect(volume_display_timer, SIGNAL(timeout()), this, SLOT(hideVolume()));
00101
00102 rtpAudio = 0;
00103 rtpVideo = 0;
00104 loopbackMode = false;
00105
00106 powerDispTimer = new QTimer(this);
00107 connect(powerDispTimer, SIGNAL(timeout()), this, SLOT(DisplayMicSpkPower()));
00108
00109 OnScreenClockTimer = new QTimer(this);
00110 connect(OnScreenClockTimer, SIGNAL(timeout()), this, SLOT(OnScreenClockTick()));
00111 ConnectTime.start();
00112
00113
00114 webcam = new Webcam();
00115 QString WebcamDevice = gContext->GetSetting("WebcamDevice");
00116 getResolution("CaptureResolution", wcWidth, wcHeight);
00117 getResolution("TxResolution", txWidth, txHeight);
00118 txVideoMode = videoResToCifMode(txWidth);
00119
00120 screenwidth = 0;
00121 screenheight = 0;
00122 float wmult = 0, hmult = 0;
00123 gContext->GetScreenSettings(screenwidth, wmult, screenheight, hmult);
00124 fullScreen = false;
00125 rxVideoArea = receivedWebcamArea->getScreenArea();
00126
00127 camBrightness = 32768;
00128 camColour = 32768;
00129 camContrast = 32768;
00130 localClient = 0;
00131 txClient = 0;
00132 wcDeliveredFrames = 0;
00133 wcDroppedFrames = 0;
00134 txFps = atoi((const char *)gContext->GetSetting("TransmitFPS"));
00135 if (WebcamDevice.length() > 0)
00136 {
00137 if (webcam->camOpen(WebcamDevice, wcWidth, wcHeight))
00138 {
00139 webcam->GetCurSize(&wcWidth, &wcHeight);
00140 camBrightness = webcam->GetBrightness();
00141 camContrast = webcam->GetContrast();
00142 camColour = webcam->GetColour();
00143 localClient = webcam->RegisterClient(VIDEO_PALETTE_RGB32, 20, this);
00144 }
00145 }
00146
00147 zoomFactor = 10;
00148 zoomWidth = wcWidth;
00149 zoomHeight = wcHeight;
00150 hPan = wPan = 0;
00151
00152 State = -1;
00153 menuPopup = NULL;
00154 urlPopup = NULL;
00155 addEntryPopup = NULL;
00156 addDirectoryPopup = NULL;
00157 incallPopup = NULL;
00158 statsPopup = NULL;
00159 audioPkInOutLabel = audioPlayoutLabel = audioPkRtcpLabel = 0;
00160 videoResLabel = videoPkOutLabel = videoPkInLabel = videoPkRtcpLabel = videoFramesInOutDiscLabel = videoAvgFpsLabel = videoWebcamFpsLabel = 0;
00161 currentCallEntry = 0;
00162
00163
00164 vmail = 0;
00165
00166
00167 QApplication::postEvent(this, new SipEvent(SipEvent::SipStateChange));
00168
00169 }
00170
00171
00172 void PhoneUIBox::getResolution(QString setting, int &width, int &height)
00173 {
00174 width = 352;
00175 height = 288;
00176
00177
00178 QString resolution = gContext->GetSetting(setting);
00179 if (resolution.length() > 0)
00180 {
00181 width = atoi((const char *)resolution);
00182 QString heightString = resolution.mid(resolution.find('x')+1);
00183 height = atoi((const char *)heightString);
00184 }
00185 }
00186
00187 const char *PhoneUIBox::videoResToCifMode(int w)
00188 {
00189 switch (w)
00190 {
00191 case 704: return "4CIF";
00192 case 352: return "CIF";
00193 case 176: return "QCIF";
00194 case 128: return "SQCIF";
00195 }
00196 return "AUDIOONLY";
00197 }
00198
00199 void PhoneUIBox::videoCifModeToRes(QString cifMode, int &w, int &h)
00200 {
00201 w = 176;
00202 h = 144;
00203 if (cifMode == "QCIF")
00204 {
00205 w = 176;
00206 h = 144;
00207 }
00208 if (cifMode == "SQCIF")
00209 {
00210 w = 128;
00211 h = 96;
00212 }
00213 if (cifMode == "CIF")
00214 {
00215 w = 352;
00216 h = 288;
00217 }
00218 if (cifMode == "4CIF")
00219 {
00220 w = 704;
00221 h = 576;
00222 }
00223 }
00224
00225 void PhoneUIBox::keyPressEvent(QKeyEvent *e)
00226 {
00227 bool handled = false;
00228 QStringList actions;
00229 gContext->GetMainWindow()->TranslateKeyPress("Phone", e, actions);
00230
00231 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00232 {
00233 QString action = actions[i];
00234 handled = true;
00235
00236 if (action == "1")
00237 keypadPressed('1');
00238 else if (action == "2")
00239 keypadPressed('2');
00240 else if (action == "3")
00241 keypadPressed('3');
00242 else if (action == "4")
00243 keypadPressed('4');
00244 else if (action == "5")
00245 keypadPressed('5');
00246 else if (action == "6")
00247 keypadPressed('6');
00248 else if (action == "7")
00249 keypadPressed('7');
00250 else if (action == "8")
00251 keypadPressed('8');
00252 else if (action == "9")
00253 keypadPressed('9');
00254 else if (action == "0")
00255 keypadPressed('0');
00256 else if (action == "HASH")
00257 keypadPressed('#');
00258 else if (action == "STAR")
00259 keypadPressed('*');
00260 else if (action == "MENU")
00261 MenuButtonPushed();
00262 else if (action == "INFO")
00263 InfoButtonPushed();
00264 else if (action == "LOOPBACK")
00265 LoopbackButtonPushed();
00266
00267 else if (action == "VOLUMEDOWN")
00268 changeVolume(false);
00269 else if (action == "VOLUMEUP")
00270 changeVolume(true);
00271 else if (action == "MUTE")
00272 toggleMute();
00273
00274 else if (action == "FULLSCRN")
00275 {
00276 setUpdatesEnabled(fullScreen);
00277 if (fullScreen)
00278 {
00279 rxVideoArea = receivedWebcamArea->getScreenArea();
00280 updateForeground();
00281 }
00282 else
00283 {
00284 rxVideoArea = QRect(0, 0, screenwidth, screenheight);
00285
00286 QPixmap Pixmap(screenwidth, screenheight);
00287 Pixmap.fill(Qt::black);
00288 bitBlt(this, 0, 0, &Pixmap);
00289 }
00290 fullScreen = !fullScreen;
00291 }
00292
00293
00294 else if ((action == "ZOOMOUT") && (VideoOn))
00295 {
00296 if (zoomFactor < 10)
00297 {
00298 zoomFactor++;
00299 zoomWidth = ((wcWidth-128) * zoomFactor / 10) + 128;
00300 zoomWidth = (zoomWidth >> 3) << 3;
00301 zoomHeight = ((wcHeight-96) * zoomFactor / 10) + 96;
00302 zoomHeight = (zoomHeight >> 3) << 3;
00303 }
00304 }
00305 else if ((action == "ZOOMIN") && (VideoOn))
00306 {
00307 if (zoomFactor > 0)
00308 {
00309 zoomFactor--;
00310 zoomWidth = ((wcWidth-128) * zoomFactor / 10) + 128;
00311 zoomWidth = (zoomWidth >> 3) << 3;
00312 zoomHeight = ((wcHeight-96) * zoomFactor / 10) + 96;
00313 zoomHeight = (zoomHeight >> 3) << 3;
00314 }
00315 }
00316
00317
00318 else if ((action == "LEFT") && (VideoOn) && ((!volume_status) || (volume_status->getOrder() == -1)))
00319 {
00320 if (wPan > -10)
00321 wPan--;
00322 }
00323 else if ((action == "RIGHT") && (VideoOn) && ((!volume_status) || (volume_status->getOrder() == -1)))
00324 {
00325 if (wPan < 10)
00326 wPan++;
00327 }
00328 else if ((action == "UP") && (VideoOn) && ((!volume_status) || (volume_status->getOrder() == -1)))
00329 {
00330 if (hPan > -10)
00331 hPan--;
00332 }
00333 else if ((action == "DOWN") && (VideoOn) && ((!volume_status) || (volume_status->getOrder() == -1)))
00334 {
00335 if (hPan < 10)
00336 hPan++;
00337 }
00338
00339 else if ((action == "DOWN") && (volume_status) && (volume_status->getOrder() != -1))
00340 changeVolumeControl(false);
00341 else if ((action == "UP") && (volume_status) && (volume_status->getOrder() != -1))
00342 changeVolumeControl(true);
00343 else if ((action == "RIGHT") && (volume_status) && (volume_status->getOrder() != -1))
00344 changeVolume(true);
00345 else if ((action == "LEFT") && (volume_status) && (volume_status->getOrder() != -1))
00346 changeVolume(false);
00347
00348 else if (action == "UP")
00349 DirectoryList->moveUp();
00350 else if (action == "DOWN")
00351 DirectoryList->moveDown();
00352 else if (action == "LEFT")
00353 DirectoryList->popUp();
00354 else if (action == "RIGHT")
00355 DirectoryList->pushDown();
00356 else if ((action == "SELECT") && (State == SIP_IDLE))
00357 {
00358 SelectHit = true;
00359 DirectoryList->select();
00360 }
00361 else if (action == "REFRESH")
00362 {
00363 DirectoryList->syncCurrentWithActive();
00364 DirectoryList->forceLastBin();
00365 DirectoryList->refresh();
00366 }
00367 else if (action == "HANGUP")
00368 {
00369 HangUp();
00370 }
00371 else if (action == "ESCAPE")
00372 {
00373 HangUp();
00374 handled = false;
00375 }
00376 else
00377 handled = false;
00378 }
00379
00380 if (!handled)
00381 MythThemedDialog::keyPressEvent(e);
00382 }
00383
00384
00385 void PhoneUIBox::customEvent(QCustomEvent *event)
00386 {
00387 QString spk;
00388 switch ((int)event->type())
00389 {
00390 case WebcamEvent::FrameReady:
00391 {
00392 WebcamEvent *we = (WebcamEvent *)event;
00393 if (we->getClient() == localClient)
00394 DrawLocalWebcamImage();
00395 else if (we->getClient() == txClient)
00396 TransmitLocalWebcamImage();
00397 }
00398 break;
00399
00400 case RtpEvent::RxVideoFrame:
00401 ProcessRxVideoFrame();
00402 break;
00403
00404 case RtpEvent::RtpStatisticsEv:
00405 {
00406 RtpEvent *re = (RtpEvent *)event;
00407 if (re->owner() == rtpAudio)
00408 ProcessAudioRtpStatistics(re);
00409 else if (re->owner() == rtpVideo)
00410 ProcessVideoRtpStatistics(re);
00411 }
00412 break;
00413
00414 case RtpEvent::RtpRtcpStatsEv:
00415 {
00416 RtpEvent *re = (RtpEvent *)event;
00417 if (re->owner() == rtpAudio)
00418 ProcessAudioRtcpStatistics(re);
00419 else if (re->owner() == rtpVideo)
00420 ProcessVideoRtcpStatistics(re);
00421 }
00422 break;
00423
00424 case SipEvent::SipStateChange:
00425 ProcessSipStateChange();
00426 break;
00427
00428 case SipEvent::SipNotification:
00429 ProcessSipNotification();
00430 break;
00431
00432 case SipEvent::SipStartMedia:
00433 {
00434 SipEvent *se = (SipEvent *)event;
00435 startRTP(se->getAudioPayload(),
00436 se->getVideoPayload(),
00437 se->getDTMFPayload(),
00438 se->getAudioPort(),
00439 se->getVideoPort(),
00440 se->getRemoteIp(),
00441 se->getAudioCodec(),
00442 se->getVideoCodec(),
00443 se->getVideoRes());
00444 }
00445 break;
00446
00447 case SipEvent::SipStopMedia:
00448 stopRTP();
00449 break;
00450
00451 case SipEvent::SipChangeMedia:
00452 {
00453 SipEvent *se = (SipEvent *)event;
00454 stopRTP(audioCodecInUse != se->getAudioCodec(), videoCodecInUse != se->getVideoCodec());
00455 startRTP(se->getAudioPayload(),
00456 se->getVideoPayload(),
00457 se->getDTMFPayload(),
00458 se->getAudioPort(),
00459 se->getVideoPort(),
00460 se->getRemoteIp(),
00461 se->getAudioCodec(),
00462 se->getVideoCodec(),
00463 se->getVideoRes());
00464 }
00465 break;
00466
00467 case SipEvent::SipAlertUser:
00468 {
00469 SipEvent *se = (SipEvent *)event;
00470 alertUser(se->getCallerUser(), se->getCallerName(), se->getCallerUrl(), se->getCallIsAudioOnly());
00471 }
00472 break;
00473
00474 case SipEvent::SipCeaseAlertUser:
00475 closeCallPopup();
00476 break;
00477
00478 case SipEvent::SipRingbackTone:
00479 spk = gContext->GetSetting("AudioOutputDevice");
00480 Tones.TTone(TelephonyTones::TONE_RINGBACK)->Play(spk, true);
00481 break;
00482
00483 case SipEvent::SipCeaseRingbackTone:
00484 if (Tones.TTone(TelephonyTones::TONE_RINGBACK)->Playing())
00485 Tones.TTone(TelephonyTones::TONE_RINGBACK)->Stop();
00486 break;
00487 }
00488
00489 QWidget::customEvent(event);
00490 }
00491
00492 void PhoneUIBox::PlaceCall(QString url, QString name, QString Mode, bool onLocalLan)
00493 {
00494 sipStack->PlaceNewCall(Mode, url, name, onLocalLan);
00495
00496
00497 if (currentCallEntry)
00498 delete currentCallEntry;
00499 currentCallEntry = new CallRecord(name, url, false, (QDateTime::currentDateTime()).toString());
00500 phoneUIStatusBar->updateMidCallCaller(((name != 0) && (name.length() > 0)) ? name : url);
00501 }
00502
00503 void PhoneUIBox::AnswerCall(QString Mode, bool onLocalLan)
00504 {
00505 sipStack->AnswerRingingCall(Mode, onLocalLan);
00506 }
00507
00508 void PhoneUIBox::keypadPressed(char k)
00509 {
00510
00511
00512 if (rtpAudio)
00513 {
00514 rtpAudio->sendDtmf(k);
00515 int id=0;
00516 if (k == '*')
00517 id = 10;
00518 else if (k == '#')
00519 id = 11;
00520 else
00521 id = k - '0';
00522 if (Tones.dtmf(id))
00523 rtpAudio->PlayToneToSpeaker(Tones.dtmf(id)->getAudio(), Tones.dtmf(id)->getSamples());
00524 }
00525
00526 else if (State == SIP_IDLE)
00527 {
00528 doUrlPopup(k, true);
00529 }
00530 }
00531
00532
00533 void PhoneUIBox::HangUp()
00534 {
00535 sipStack->HangupCall();
00536 }
00537
00538
00539 void PhoneUIBox::StartVideo(int lPort, QString remoteIp, int remoteVideoPort, int videoPayload, QString rxVidRes)
00540 {
00541 videoCifModeToRes(rxVidRes, rxWidth, rxHeight);
00542
00543 rtpVideo = new rtp (this, lPort, remoteIp, remoteVideoPort, videoPayload, -1, -1, "", "", RTP_TX_VIDEO, RTP_RX_VIDEO);
00544
00545 if (h263->H263StartEncoder(txWidth, txHeight, txFps) &&
00546 h263->H263StartDecoder(rxWidth, rxHeight))
00547 {
00548 txClient = webcam->RegisterClient(VIDEO_PALETTE_YUV420P, txFps, this);
00549 wcDeliveredFrames = 0;
00550 wcDroppedFrames = 0;
00551 VideoOn = true;
00552 }
00553 else
00554 {
00555 h263->H263StopEncoder();
00556 h263->H263StopDecoder();
00557 }
00558 }
00559
00560 void PhoneUIBox::StopVideo()
00561 {
00562 if (VideoOn)
00563 {
00564 h263->H263StopEncoder();
00565 h263->H263StopDecoder();
00566
00567 VideoOn = false;
00568 }
00569 if (txClient)
00570 webcam->UnregisterClient(txClient);
00571 txClient = 0;
00572
00573 if (rtpVideo)
00574 delete rtpVideo;
00575 rtpVideo = 0;
00576 videoCodecInUse = "";
00577 }
00578
00579
00580 void PhoneUIBox::ChangeVideoTxResolution()
00581 {
00582 if (VideoOn)
00583 {
00584 h263->H263StopEncoder();
00585 h263->H263StartEncoder(txWidth, txHeight, txFps);
00586 }
00587 }
00588
00589
00590 void PhoneUIBox::ChangeVideoRxResolution()
00591 {
00592 if (VideoOn)
00593 {
00594 h263->H263StopDecoder();
00595 h263->H263StartDecoder(rxWidth, rxHeight);
00596 }
00597 }
00598
00599
00600 void PhoneUIBox::MenuButtonPushed()
00601 {
00602 if (rtpAudio != 0)
00603 showVolume(true);
00604 else
00605 doMenuPopup();
00606 }
00607
00608
00609 void PhoneUIBox::InfoButtonPushed()
00610 {
00611 if (rtpAudio != 0)
00612 showStatistics(rtpVideo != 0);
00613 }
00614
00615
00616 void PhoneUIBox::LoopbackButtonPushed()
00617 {
00618 if ((!loopbackMode) && (rtpAudio == 0) && (rtpVideo == 0))
00619 {
00620 DialogCode loop = MythPopupBox::Show2ButtonPopup(
00621 gContext->GetMainWindow(),
00622 "AskLoopback", tr("Loopback Audio and video at ..."),
00623 tr("Socket on this machine"), tr("NAT Device"),
00624 kDialogCodeButton0);
00625 QString loopIp;
00626 switch (loop)
00627 {
00628 default:
00629 case kDialogCodeRejected:
00630 return;
00631 case kDialogCodeButton0:
00632 loopIp = sipStack->getLocalIpAddress();
00633 break;
00634 case kDialogCodeButton1:
00635 loopIp = sipStack->getNatIpAddress();
00636 break;
00637 }
00638 phoneUIStatusBar->DisplayCallState(QString(tr("Audio and Video Looped to ") + loopIp));
00639 int lvPort = atoi((const char *)gContext->GetSetting("VideoLocalPort"));
00640 int laPort = atoi((const char *)gContext->GetSetting("AudioLocalPort"));
00641 int playout = atoi((const char *)gContext->GetSetting("PlayoutVideoCall"));
00642 rtpAudio = new rtp (this, laPort, loopIp, laPort, 0, playout, -1,
00643 gContext->GetSetting("MicrophoneDevice"),
00644 gContext->GetSetting("AudioOutputDevice"));
00645 powerDispTimer->start(100);
00646 StartVideo(lvPort, loopIp, lvPort, 34, videoResToCifMode(txWidth));
00647 loopbackMode = true;
00648 }
00649 else if (loopbackMode)
00650 {
00651 phoneUIStatusBar->DisplayCallState(tr("No Active Calls"));
00652 powerDispTimer->stop();
00653 micAmplitude->setRepeat(0);
00654 spkAmplitude->setRepeat(0);
00655 delete rtpAudio;
00656 rtpAudio = 0;
00657 StopVideo();
00658 loopbackMode = false;
00659 }
00660 }
00661
00662
00663 void PhoneUIBox::DrawLocalWebcamImage()
00664 {
00665 unsigned char *rgb32Frame = webcam->GetVideoFrame(localClient);
00666 if (rgb32Frame != 0)
00667 {
00668
00669 int zx = (wcWidth-zoomWidth)/2;
00670 zx += (zx*wPan/10);
00671 zx = (zx >> 1) << 1;
00672 int zy = (wcHeight-zoomHeight)/2;
00673 zy += (zy*hPan/10);
00674 zy = (zy >> 1) << 1;
00675
00676 QImage ScaledImage;
00677
00678 QImage Image(rgb32Frame, wcWidth, wcHeight, 32, (QRgb *)0, 0, QImage::LittleEndian);
00679
00680 QRect puthere;
00681 if (!fullScreen)
00682 puthere = localWebcamArea->getScreenArea();
00683 else
00684 puthere = QRect(screenwidth-WC_INSET_WIDTH, screenheight-WC_INSET_HEIGHT,
00685 WC_INSET_WIDTH, WC_INSET_HEIGHT);
00686 if (zoomFactor == 10)
00687 {
00688 ScaledImage = Image.scale(puthere.width(), puthere.height(), QImage::ScaleMin);
00689 }
00690 else
00691 {
00692 QImage zoomedImage = Image.copy(zx, zy, zoomWidth, zoomHeight);
00693 ScaledImage = zoomedImage.scale(puthere.width(), puthere.height(), QImage::ScaleMin);
00694 }
00695
00696
00697 if (!fullScreen)
00698 bitBlt(this, puthere.x(), puthere.y(), &ScaledImage);
00699 else
00700 savedLocalWebcam = ScaledImage;
00701 webcam->FreeVideoBuffer(localClient, rgb32Frame);
00702 }
00703 }
00704
00705
00706
00707 void PhoneUIBox::TransmitLocalWebcamImage()
00708 {
00709 unsigned char *yuvFrame = webcam->GetVideoFrame(txClient);
00710 if (yuvFrame != 0)
00711 {
00712 wcDeliveredFrames++;
00713
00714 if (VideoOn && rtpVideo)
00715 {
00716 if (rtpVideo->readyForVideo())
00717 {
00718
00719 int zx = (wcWidth-zoomWidth)/2;
00720 zx += (zx*wPan/10);
00721 zx = (zx >> 1) << 1;
00722 int zy = (wcHeight-zoomHeight)/2;
00723 zy += (zy*hPan/10);
00724 zy = (zy >> 1) << 1;
00725
00726 int encLen;
00727 if (zoomFactor == 10)
00728 {
00729 scaleYuvImage(yuvFrame, wcWidth, wcHeight, txWidth, txHeight, yuvBuffer2);
00730 }
00731 else
00732 {
00733 cropYuvImage(yuvFrame, wcWidth, wcHeight, zx, zy, zoomWidth, zoomHeight, yuvBuffer1);
00734 scaleYuvImage(yuvBuffer1, zoomWidth, zoomHeight, txWidth, txHeight, yuvBuffer2);
00735 }
00736 uchar *encFrame = h263->H263EncodeFrame(yuvBuffer2, &encLen);
00737 VIDEOBUFFER *vb = rtpVideo->getVideoBuffer(encLen);
00738 if (vb)
00739 {
00740 if (encLen > (int)sizeof(vb->video))
00741 {
00742 cout << "SIP: Encoded H.323 frame size is " << encLen << "; too big for buffer\n";
00743 rtpVideo->freeVideoBuffer(vb);
00744 }
00745 else if (encFrame && encLen >= 0)
00746 {
00747 memcpy(vb->video, encFrame, encLen);
00748 vb->len = encLen;
00749 vb->w = txWidth;
00750 vb->h = txHeight;
00751 if (!rtpVideo->queueVideo(vb))
00752 {
00753 cout << "Could not queue RTP Video frame for transmission\n";
00754 rtpVideo->freeVideoBuffer(vb);
00755 }
00756 }
00757 else
00758 {
00759 cout << "H263EncodeFrame returned -1\n";
00760 rtpVideo->freeVideoBuffer(vb);
00761 }
00762 }
00763 }
00764 else
00765 wcDroppedFrames++;
00766 }
00767 webcam->FreeVideoBuffer(txClient, yuvFrame);
00768 }
00769 }
00770
00771
00772 void PhoneUIBox::ProcessRxVideoFrame()
00773 {
00774 QImage ScaledImage;
00775 QImage *imageToDisplay;
00776 VIDEOBUFFER *v;
00777
00778 if (VideoOn && rtpVideo && (v = rtpVideo->getRxedVideo()))
00779 {
00780 if ((rxWidth != v->w) || (rxHeight != v->h))
00781 {
00782 cout << "SIP: Rx Image size changed from " << rxWidth << "x" << rxHeight << " to " << v->w << "x" << v->h << endl;
00783 rxWidth = v->w;
00784 rxHeight = v->h;
00785 ChangeVideoRxResolution();
00786 }
00787
00788 uchar *decRgbFrame = h263->H263DecodeFrame(v->video, v->len, rxRgbBuffer, sizeof(rxRgbBuffer));
00789 if (decRgbFrame)
00790 {
00791 QImage rxImage(rxRgbBuffer, v->w, v->h, 32, (QRgb *)0, 0, QImage::LittleEndian);
00792
00793 if ((v->w != rxVideoArea.width()) || (v->h != rxVideoArea.height()))
00794 {
00795 ScaledImage = rxImage.scale(rxVideoArea.width(), rxVideoArea.height(), QImage::ScaleMin);
00796 imageToDisplay = &ScaledImage;
00797 }
00798 else
00799 imageToDisplay = &rxImage;
00800
00801
00802 if ((fullScreen) && (!savedLocalWebcam.isNull()))
00803 {
00804 QPixmap fsPixmap(screenwidth, screenheight);
00805 fsPixmap.fill(Qt::black);
00806 QPainter p(&fsPixmap);
00807 p.drawImage((screenwidth-imageToDisplay->width())/2,
00808 (screenheight-imageToDisplay->height())/2,
00809 *imageToDisplay);
00810 p.drawImage(screenwidth-WC_INSET_WIDTH, screenheight-WC_INSET_HEIGHT,
00811 savedLocalWebcam);
00812 p.setPen(Qt::white);
00813 p.drawRect(screenwidth-WC_INSET_WIDTH, screenheight-WC_INSET_HEIGHT,
00814 WC_INSET_WIDTH, WC_INSET_HEIGHT);
00815 bitBlt(this, rxVideoArea.x(), rxVideoArea.y(), &fsPixmap);
00816 }
00817 else
00818 bitBlt(this, rxVideoArea.x(), rxVideoArea.y(), imageToDisplay);
00819 }
00820 rtpVideo->freeVideoBuffer(v);
00821 }
00822 }
00823
00824
00825 void PhoneUIBox::ProcessSipStateChange()
00826 {
00827 int OldState = State;
00828
00829
00830 State = sipStack->GetSipState();
00831
00832
00833 if (State != OldState)
00834 {
00835
00836 if (vmail)
00837 delete vmail;
00838 vmail = 0;
00839
00840 if (State == SIP_IDLE)
00841 {
00842
00843 if (currentCallEntry)
00844 {
00845 currentCallEntry->setDuration(ConnectTime.elapsed()/1000);
00846 DirContainer->AddToCallHistory(currentCallEntry, true);
00847 DirectoryList->refresh();
00848 }
00849 currentCallEntry = 0;
00850 ConnectTime.restart();
00851 }
00852
00853 switch(State)
00854 {
00855 case SIP_IDLE: phoneUIStatusBar->DisplayCallState(tr("No Active Calls")); break;
00856 case SIP_CONNECTED: break;
00857 case SIP_CONNECTED_VXML: phoneUIStatusBar->DisplayCallState(tr("Caller is Leaving Voicemail")); break;
00858 case SIP_OCONNECTING1: phoneUIStatusBar->DisplayCallState(tr("Trying to Contact Remote Party")); break;
00859 case SIP_ICONNECTING_WAITACK: phoneUIStatusBar->DisplayCallState(tr("Connecting")); break;
00860 case SIP_ICONNECTING: phoneUIStatusBar->DisplayCallState(tr("Incoming Call")); break;
00861 case SIP_DISCONNECTING: phoneUIStatusBar->DisplayCallState(tr("Hanging Up")); break;
00862 case SIP_OCONNECTING2:
00863 default:
00864 break;
00865 }
00866 }
00867 }
00868
00869
00870 void PhoneUIBox::ProcessSipNotification()
00871 {
00872
00873 QString NotifyType, NotifyUrl, NotifyParam1, NotifyParam2;
00874 while (sipStack->GetNotification(NotifyType, NotifyUrl, NotifyParam1, NotifyParam2))
00875 {
00876
00877 if (NotifyType == "CALLSTATUS")
00878 {
00879 phoneUIStatusBar->DisplayCallState(NotifyParam2);
00880 }
00881
00882
00883 else if (NotifyType == "PRESENCE")
00884 {
00885 int newStatus = ICON_PRES_UNKNOWN;
00886 if (NotifyParam1 == "offline")
00887 newStatus = ICON_PRES_OFFLINE;
00888 else if (NotifyParam1 == "open")
00889 newStatus = ICON_PRES_ONLINE;
00890 else if (NotifyParam1 == "inactive")
00891 newStatus = ICON_PRES_AWAY;
00892 DirContainer->ChangePresenceStatus(NotifyUrl, newStatus, NotifyParam2, true);
00893 DirectoryList->refresh();
00894 }
00895
00896
00897 else if (NotifyType == "IM")
00898 {
00899 doIMPopup(NotifyUrl, NotifyParam1, NotifyParam2);
00900 }
00901
00902 else
00903 cerr << "SIP: Unknown Notify type " << NotifyType << endl;
00904 }
00905 }
00906
00907
00908 void PhoneUIBox::OnScreenClockTick()
00909 {
00910 if (rtpAudio)
00911 phoneUIStatusBar->updateMidCallTime(ConnectTime.elapsed()/1000);
00912 }
00913
00914
00915 void PhoneUIBox::ProcessAudioRtpStatistics(RtpEvent *stats)
00916 {
00917 phoneUIStatusBar->updateMidCallAudioStats(stats->getPkIn(), stats->getPkMissed(),
00918 stats->getPkLate(), stats->getPkOut(),
00919 stats->getBytesIn(), stats->getBytesOut(),
00920 stats->getPeriod());
00921 updateAudioStatistics(stats->getPkIn(), stats->getPkMissed(), stats->getPkLate(),
00922 stats->getPkOut(), stats->getPkInDisc(), stats->getPkOutDrop(),
00923 stats->getBytesIn(), stats->getBytesOut(),
00924 stats->getMinPlayout(), stats->getAvgPlayout(), stats->getMaxPlayout());
00925 }
00926
00927
00928 void PhoneUIBox::ProcessVideoRtpStatistics(RtpEvent *stats)
00929 {
00930 phoneUIStatusBar->updateMidCallVideoStats(stats->getPkIn(), stats->getPkMissed(),
00931 stats->getPkLate(), stats->getPkOut(),
00932 stats->getBytesIn(), stats->getBytesOut(),
00933 stats->getPeriod());
00934 updateVideoStatistics(stats->getPkIn(), stats->getPkMissed(), stats->getPkLate(),
00935 stats->getPkOut(), stats->getPkInDisc(), stats->getPkOutDrop(),
00936 stats->getBytesIn(), stats->getBytesOut(),
00937 stats->getFramesIn(), stats->getFramesOut(),
00938 stats->getFramesInDiscarded(), stats->getFramesOutDiscarded());
00939 }
00940
00941
00942 void PhoneUIBox::ProcessAudioRtcpStatistics(RtpEvent *stats)
00943 {
00944 updateAudioRtcpStatistics(stats->getRtcpFractionLoss(), stats->getRtcpTotalLoss());
00945 }
00946
00947
00948 void PhoneUIBox::ProcessVideoRtcpStatistics(RtpEvent *stats)
00949 {
00950 updateVideoRtcpStatistics(stats->getRtcpFractionLoss(), stats->getRtcpTotalLoss());
00951 if (stats->getRtcpFractionLoss() > 0)
00952 h263->H263ForceIFrame();
00953 }
00954
00955
00956 void PhoneUIBox::startRTP(int audioPayload, int videoPayload, int dtmfPayload, int audioPort, int videoPort,
00957 QString remoteIp, QString audioCodec, QString videoCodec, QString videoRes)
00958 {
00959 if (rtpAudio == 0)
00960 {
00961 int laPort = atoi((const char *)gContext->GetSetting("AudioLocalPort"));
00962 QString spk = gContext->GetSetting("AudioOutputDevice");
00963 QString mic = gContext->GetSetting("MicrophoneDevice");
00964 int playout = (videoPayload != -1) ?
00965 atoi((const char *)gContext->GetSetting("PlayoutVideoCall")) :
00966 atoi((const char *)gContext->GetSetting("PlayoutAudioCall"));
00967 rtpAudio = new rtp (this, laPort, remoteIp, audioPort, audioPayload, playout, dtmfPayload, mic, spk);
00968 OnScreenClockTimer->start(1000);
00969 phoneUIStatusBar->DisplayInCallStats(true);
00970 phoneUIStatusBar->updateMidCallAudioCodec(audioCodec);
00971 audioCodecInUse = audioCodec;
00972 powerDispTimer->start(100);
00973 }
00974 if (rtpVideo == 0)
00975 {
00976 if (videoPayload != -1)
00977 {
00978 int lvPort = atoi((const char *)gContext->GetSetting("VideoLocalPort"));
00979 StartVideo(lvPort, remoteIp, videoPort, videoPayload, videoRes);
00980 videoCodecInUse = videoCodec;
00981 phoneUIStatusBar->updateMidCallVideoCodec(videoCodec);
00982 }
00983 else
00984 phoneUIStatusBar->updateMidCallVideoCodec("");
00985 }
00986 if (rtpVideo != 0)
00987 rtpVideo->setMaxBandwidth(atoi((const char *)gContext->GetSetting("TransmitBandwidth")) -
00988 rtpAudio->getCodecBandwidth());
00989 }
00990
00991 void PhoneUIBox::stopRTP(bool stopAudio, bool stopVideo)
00992 {
00993
00994 if ((rtpAudio != 0) && (stopAudio))
00995 {
00996 powerDispTimer->stop();
00997 micAmplitude->setRepeat(0);
00998 spkAmplitude->setRepeat(0);
00999 delete rtpAudio;
01000 rtpAudio = 0;
01001 audioCodecInUse = "";
01002 }
01003
01004 if ((rtpVideo != 0) && (stopVideo))
01005 StopVideo();
01006
01007 OnScreenClockTimer->stop();
01008 }
01009
01010 void PhoneUIBox::alertUser(QString callerUser, QString callerName, QString callerUrl, bool inAudioOnly)
01011 {
01012 QString callerDisplay;
01013
01014 DirEntry *entry = DirContainer->FindMatchingDirectoryEntry(callerUrl);
01015 if (entry)
01016 callerDisplay = entry->getNickName();
01017 else if (callerName.length()>0)
01018 callerDisplay = callerName;
01019 else if (callerUser.length()>0)
01020 callerDisplay = callerUser;
01021 else
01022 callerDisplay = "";
01023
01024
01025 phoneUIStatusBar->updateMidCallCaller(callerDisplay);
01026
01027
01028 QDateTime now = QDateTime::currentDateTime();
01029 QString ts = now.toString();
01030 if (currentCallEntry)
01031 delete currentCallEntry;
01032 currentCallEntry = new CallRecord(callerDisplay, callerUrl, true, ts);
01033
01034 bool AutoanswerEnabled = gContext->GetNumSetting("SipAutoanswer",1);
01035 if ((AutoanswerEnabled) && (entry))
01036 AnswerCall(txVideoMode, true);
01037 else
01038 {
01039
01040 closeCallPopup();
01041 if (entry)
01042 doCallPopup(entry, tr("Answer"), inAudioOnly);
01043 else
01044 {
01045 DirEntry dummyEntry(callerDisplay, callerUrl, "", "", "");
01046 doCallPopup(&dummyEntry, tr("Answer"), inAudioOnly);
01047 }
01048 }
01049 }
01050
01051 void PhoneUIBox::doMenuPopup()
01052 {
01053 if (menuPopup)
01054 return;
01055
01056 GenericTree *Current = DirectoryList->getCurrentNode();
01057 if (Current == 0)
01058 {
01059 cerr << "Mythphone: Can't get your context\n";
01060 return;
01061 }
01062
01063 int selType = Current->getAttribute(0);
01064
01065 menuPopup = new MythPopupBox(gContext->GetMainWindow(), "MENU_popup");
01066
01067 QButton *b1 = 0;
01068
01069 switch (selType)
01070 {
01071 case TA_DIR:
01072 case TA_VMAIL:
01073 menuPopup->addLabel(tr("Directory"), MythPopupBox::Large);
01074 b1 = menuPopup->addButton(tr("Add someone to your Directory "), this, SLOT(menuAddContact()));
01075 break;
01076 case TA_SPEEDDIALENTRY:
01077 menuPopup->addLabel(tr("Speed Dials"), MythPopupBox::Large);
01078 b1 = menuPopup->addButton(tr("Edit this Entry"), this, SLOT(menuEntryEdit()));
01079 menuPopup->addButton(tr("Remove from Speed Dials"), this, SLOT(menuSpeedDialRemove()));
01080 menuPopup->addButton(tr("Add someone to your Directory "), this, SLOT(menuAddContact()));
01081 break;
01082 case TA_CALLHISTENTRY:
01083 menuPopup->addLabel(tr("Call History"), MythPopupBox::Large);
01084 b1 = menuPopup->addButton(tr("Save this in the Directory"), this, SLOT(menuHistorySave()));
01085 menuPopup->addButton(tr("Clear the Call History"), this, SLOT(menuHistoryClear()));
01086 break;
01087 case TA_DIRENTRY:
01088 menuPopup->addLabel(tr("Directory"), MythPopupBox::Large);
01089 b1 = menuPopup->addButton(tr("Edit this Entry"), this, SLOT(menuEntryEdit()));
01090 menuPopup->addButton(tr("Make this a Speeddial"), this, SLOT(menuEntryMakeSpeedDial()));
01091 menuPopup->addButton(tr("Delete this Entry"), this, SLOT(menuEntryDelete()));
01092 menuPopup->addButton(tr("Add someone to your Directory "), this, SLOT(menuAddContact()));
01093 break;
01094 case TA_VMAIL_ENTRY:
01095 menuPopup->addLabel(tr("Voicemail"), MythPopupBox::Large);
01096 b1 = menuPopup->addButton(tr("Delete this Voicemail"), this, SLOT(vmailEntryDelete()));
01097 menuPopup->addButton(tr("Delete all Voicemails"), this, SLOT(vmailEntryDeleteAll()));
01098 break;
01099 default:
01100 menuPopup->deleteLater();
01101 menuPopup = NULL;
01102 return;
01103 break;
01104 }
01105
01106 menuPopup->ShowPopupAtXY(180, 40, this, SLOT(closeMenuPopup()));
01107 if (b1)
01108 b1->setFocus();
01109 }
01110
01111
01112 void PhoneUIBox::menuCallUrl()
01113 {
01114 doUrlPopup(0, true);
01115 }
01116
01117 void PhoneUIBox::menuAddContact()
01118 {
01119 doAddEntryPopup(0);
01120 }
01121
01122 void PhoneUIBox::menuSpeedDialRemove()
01123 {
01124 GenericTree *Current = DirectoryList->getCurrentNode();
01125 if (Current != 0)
01126 {
01127 DirEntry *Entry = DirContainer->fetchDirEntryById(Current->getAttribute(1));
01128 if (Entry != 0)
01129 {
01130 if (Entry->isSpeedDial())
01131 {
01132 DirectoryList->popUp();
01133 DirContainer->removeSpeedDial(Entry);
01134 DirectoryList->refresh();
01135 }
01136 }
01137 else
01138 cerr << "mythphone: Error finding your directory entry\n";
01139 }
01140 else
01141 cerr << "mythphone: Error getting info from the tree\n";
01142 closeMenuPopup();
01143 }
01144
01145 void PhoneUIBox::menuHistorySave()
01146 {
01147 GenericTree *Current = DirectoryList->getCurrentNode();
01148 if (Current != 0)
01149 {
01150 CallRecord *crEntry = DirContainer->fetchCallRecordById(Current->getAttribute(1));
01151 DirEntry *entry = DirContainer->FindMatchingDirectoryEntry(crEntry->getUri());
01152 if (crEntry != 0)
01153 {
01154 if (entry != 0)
01155 {
01156
01157 DialogBox *NoDeviceDialog = new DialogBox(gContext->GetMainWindow(),
01158 "\n\n" + QObject::tr("A directory entry already exists with this URL."));
01159 NoDeviceDialog->AddButton(QObject::tr("OK"));
01160 NoDeviceDialog->exec();
01161 NoDeviceDialog->deleteLater();
01162 closeMenuPopup();
01163 }
01164 else
01165 doAddEntryPopup(0, crEntry->getDisplayName(), crEntry->getUri());
01166 }
01167 else
01168 cerr << "mythphone: Error finding your call history entry\n";
01169 }
01170 else
01171 cerr << "mythphone: Error getting info from the tree\n";
01172 }
01173
01174
01175 void PhoneUIBox::menuHistoryClear()
01176 {
01177
01178
01179 GenericTree *Current = DirectoryList->getCurrentNode();
01180 int selType = Current->getAttribute(0);
01181 if (selType == TA_CALLHISTENTRY)
01182 DirectoryList->popUp();
01183
01184 DirContainer->clearCallHistory();
01185 DirectoryList->refresh();
01186 closeMenuPopup();
01187 }
01188
01189
01190 void PhoneUIBox::menuEntryEdit()
01191 {
01192 GenericTree *Current = DirectoryList->getCurrentNode();
01193 if (Current != 0)
01194 {
01195 DirEntry *Entry = DirContainer->fetchDirEntryById(Current->getAttribute(1));
01196 if (Entry != 0)
01197 {
01198 doAddEntryPopup(Entry);
01199 }
01200 else
01201 cerr << "mythphone: Error finding your directory entry\n";
01202 }
01203 else
01204 cerr << "mythphone: Error getting info from the tree\n";
01205 }
01206
01207 void PhoneUIBox::menuEntryMakeSpeedDial()
01208 {
01209 GenericTree *Current = DirectoryList->getCurrentNode();
01210 if (Current != 0)
01211 {
01212 DirEntry *Entry = DirContainer->fetchDirEntryById(Current->getAttribute(1));
01213 if (Entry != 0)
01214 {
01215 if (!Entry->isSpeedDial())
01216 {
01217 DirContainer->setSpeedDial(Entry);
01218 DirectoryList->refresh();
01219 }
01220 }
01221 else
01222 cerr << "mythphone: Error finding your directory entry\n";
01223 }
01224 else
01225 cerr << "mythphone: Error getting info from the tree\n";
01226 closeMenuPopup();
01227 }
01228
01229 void PhoneUIBox::menuEntryDelete()
01230 {
01231 GenericTree *Current = DirectoryList->getCurrentNode();
01232 if (Current != 0)
01233 {
01234 DirEntry *Entry = DirContainer->fetchDirEntryById(Current->getAttribute(1));
01235 if (Entry != 0)
01236 {
01237 DirectoryList->popUp();
01238 DirContainer->deleteFromTree(Current, Entry);
01239 DirectoryList->refresh();
01240 }
01241 else
01242 cerr << "mythphone: Error finding your directory entry\n";
01243 }
01244 else
01245 cerr << "mythphone: Error getting info from the tree\n";
01246 closeMenuPopup();
01247 }
01248
01249 void PhoneUIBox::vmailEntryDelete()
01250 {
01251
01252
01253 GenericTree *Current = DirectoryList->getCurrentNode();
01254 int selType = Current->getAttribute(0);
01255 QString vmailName = Current->getString();
01256 if (selType == TA_VMAIL_ENTRY)
01257 DirectoryList->popUp();
01258
01259 DirContainer->deleteVoicemail(vmailName);
01260 DirectoryList->refresh();
01261 closeMenuPopup();
01262 }
01263
01264 void PhoneUIBox::vmailEntryDeleteAll()
01265 {
01266
01267
01268 GenericTree *Current = DirectoryList->getCurrentNode();
01269 int selType = Current->getAttribute(0);
01270 if (selType == TA_VMAIL_ENTRY)
01271 DirectoryList->popUp();
01272
01273 DirContainer->clearAllVoicemail();
01274 DirectoryList->refresh();
01275 closeMenuPopup();
01276 }
01277
01278 void PhoneUIBox::closeMenuPopup()
01279 {
01280 if (!menuPopup)
01281 return;
01282
01283 menuPopup->deleteLater();
01284 menuPopup = NULL;
01285 }
01286
01287 void PhoneUIBox::doUrlPopup(char key, bool digitsOrUrl)
01288 {
01289 if (urlPopup)
01290 return;
01291
01292 QString text = "";
01293 if (key)
01294 text += key;
01295
01296 urlPopup = new MythPopupBox(gContext->GetMainWindow(), "URL_popup");
01297 if (digitsOrUrl)
01298 {
01299 urlField = new MythLineEdit(urlPopup);
01300 urlRemoteField = 0;
01301 urlPopup->addWidget(urlField);
01302 urlField->setText(text);
01303 urlField->setCursorPosition(text.length());
01304 urlField->setFocus();
01305 }
01306 else
01307 {
01308 urlRemoteField = new MythRemoteLineEdit(urlPopup);
01309 urlField = 0;
01310 urlPopup->addWidget(urlRemoteField);
01311 urlRemoteField->setFocus();
01312 }
01313 urlPopup->addButton(tr("Place Videocall Now"), this, SLOT(dialUrlVideo()));
01314 urlPopup->addButton(tr("Place Voice-Only Call Now"), this, SLOT(dialUrlVoice()));
01315 if (digitsOrUrl)
01316 urlPopup->addButton(tr("Switch from digits to URL input"), this, SLOT(dialUrlSwitchToUrl()));
01317 else
01318 urlPopup->addButton(tr("Switch from URL to Digits input"), this, SLOT(dialUrlSwitchToDigits()));
01319
01320 urlPopup->ShowPopupAtXY(200, 60, this, SLOT(closeUrlPopup()));
01321 }
01322
01323 void PhoneUIBox::closeUrlPopup()
01324 {
01325 if (!urlPopup)
01326 return;
01327
01328 urlPopup->deleteLater();
01329 urlPopup = NULL;
01330 }
01331
01332 void PhoneUIBox::dialUrlVideo()
01333 {
01334 PlaceCall(urlField==0 ? urlRemoteField->text() : urlField->text(), "", txVideoMode);
01335 closeUrlPopup();
01336
01337
01338
01339 if (menuPopup)
01340 closeMenuPopup();
01341 }
01342
01343
01344 void PhoneUIBox::dialUrlVoice()
01345 {
01346 PlaceCall(urlField==0 ? urlRemoteField->text() : urlField->text(), "", "AUDIOONLY");
01347 closeUrlPopup();
01348
01349
01350
01351 if (menuPopup)
01352 closeMenuPopup();
01353 }
01354
01355 void PhoneUIBox::dialUrlSwitchToDigits()
01356 {
01357 closeUrlPopup();
01358 doUrlPopup(0, true);
01359 }
01360
01361 void PhoneUIBox::dialUrlSwitchToUrl()
01362 {
01363 closeUrlPopup();
01364 doUrlPopup(0, false);
01365 }
01366
01367 void PhoneUIBox::doIMPopup(QString otherParty, QString callId, QString Msg)
01368 {
01369 if (imPopup)
01370 scrollIMText(Msg, true);
01371 else
01372 {
01373 imPopup = new MythPopupBox(gContext->GetMainWindow(), "IM_popup");
01374 QLabel *title = imPopup->addLabel("IM: "+otherParty, MythPopupBox::Medium);
01375 title->setAlignment(Qt::AlignHCenter);
01376 for (int i=0; i<MAX_DISPLAY_IM_MSGS; i++)
01377 imLine[i] = imPopup->addLabel("", MythPopupBox::Small, true);
01378 displayedIMMsgs = 0;
01379 if (callId.length() > 0)
01380 {
01381 imCallid = callId;
01382 scrollIMText(Msg, true);
01383 }
01384 else
01385 imCallid = "";
01386 imUrl = otherParty;
01387 imReplyField = new MythRemoteLineEdit(imPopup);
01388 imPopup->addWidget(imReplyField);
01389 imReplyField->setFocus();
01390 imPopup->addButton(tr("Send IM"), this, SLOT(imSendReply()));
01391
01392 imPopup->ShowPopupAtXY(200, 100, this, SLOT(closeIMPopup()));
01393 }
01394 }
01395
01396 void PhoneUIBox::scrollIMText(QString Msg, bool msgReceived)
01397 {
01398 if (imPopup)
01399 {
01400
01401 if (displayedIMMsgs >= MAX_DISPLAY_IM_MSGS)
01402 {
01403 for (int i=0;i<displayedIMMsgs-1;i++)
01404 {
01405 imLine[i]->setPaletteForegroundColor(imLine[i+1]->paletteForegroundColor());
01406 imLine[i]->setText(imLine[i+1]->text());
01407 }
01408 }
01409 else
01410 displayedIMMsgs++;
01411
01412
01413 if (msgReceived)
01414 imLine[displayedIMMsgs-1]->setPaletteForegroundColor(Qt::white);
01415 else
01416 imLine[displayedIMMsgs-1]->setPaletteForegroundColor(Qt::yellow);
01417 imLine[displayedIMMsgs-1]->setText(Msg);
01418 }
01419 }
01420
01421 void PhoneUIBox::closeIMPopup()
01422 {
01423 if (!imPopup)
01424 return;
01425
01426 imPopup->deleteLater();
01427 imPopup = NULL;
01428 }
01429
01430 void PhoneUIBox::imSendReply()
01431 {
01432 if (!imPopup)
01433 return;
01434 imCallid = sipStack->UiSendIMMessage(imUrl, imCallid, imReplyField->text());
01435 scrollIMText(imReplyField->text(), false);
01436 imReplyField->setText("");
01437 imReplyField->setFocus();
01438 }
01439
01440
01441 void PhoneUIBox::doAddEntryPopup(DirEntry *edit, QString nn, QString Url)
01442 {
01443 if (addEntryPopup)
01444 return;
01445
01446 addEntryPopup = new MythPopupBox(gContext->GetMainWindow(), "add_entry_popup");
01447
01448 if (edit == 0)
01449 {
01450 addEntryPopup->addLabel(tr("Nickname"), MythPopupBox::Small);
01451 entryNickname = new MythRemoteLineEdit(addEntryPopup);
01452 addEntryPopup->addWidget(entryNickname);
01453 }
01454 else
01455 {
01456 entryNickname = 0;
01457 addEntryPopup->addLabel(edit->getNickName(), MythPopupBox::Large);
01458 }
01459
01460 addEntryPopup->addLabel(tr("First Name (Optional)"), MythPopupBox::Small);
01461 entryFirstname = new MythRemoteLineEdit(addEntryPopup);
01462 addEntryPopup->addWidget(entryFirstname);
01463
01464 addEntryPopup->addLabel(tr("Surname (Optional)"), MythPopupBox::Small);
01465 entrySurname = new MythRemoteLineEdit(addEntryPopup);
01466 addEntryPopup->addWidget(entrySurname);
01467
01468 addEntryPopup->addLabel(tr("URL"), MythPopupBox::Small);
01469 entryUrl = new MythRemoteLineEdit(addEntryPopup);
01470 addEntryPopup->addWidget(entryUrl);
01471
01472 if (edit == 0)
01473 {
01474 entrySpeed = new MythCheckBox(addEntryPopup);
01475 entrySpeed->setText(tr("Speed Dial"));
01476 addEntryPopup->addWidget(entrySpeed);
01477 }
01478
01479 entryOnHomeLan = new MythCheckBox(addEntryPopup);
01480 entryOnHomeLan->setText(tr("Client is on My Home LAN"));
01481 addEntryPopup->addWidget(entryOnHomeLan);
01482
01483 #ifdef PHOTO
01484 entryPhoto = new MythComboBox(false, addEntryPopup);
01485 addEntryPopup->addLabel(tr("Default Photo"), MythPopupBox::Small);
01486 addEntryPopup->addWidget(entryPhoto);
01487 #endif
01488
01489 if (edit == 0)
01490 {
01491 addEntryPopup->addLabel(tr("To Directory"), MythPopupBox::Small);
01492 entryDir = new MythComboBox(false, addEntryPopup);
01493 addEntryPopup->addWidget(entryDir);
01494 }
01495
01496 if (edit != 0)
01497 addEntryPopup->addButton(tr("Save Changes"), this, SLOT(entryAddSelected()));
01498 else
01499 addEntryPopup->addButton(tr("ADD"), this, SLOT(entryAddSelected()));
01500
01501
01502
01503 addEntryPopup->addLabel("", MythPopupBox::Small);
01504
01505 addEntryPopup->ShowPopupAtXY(220, 20, this, SLOT(closeAddEntryPopup()));
01506
01507 #ifdef PHOTO
01508
01509 QDir photos(gContext->FindThemeDir("default"), "mp_photo-*", QDir::Name, QDir::Files);
01510 const QFileInfoList *il = photos.entryInfoList();
01511 int PhotoIndex = 0;
01512 if (il)
01513 {
01514 QFileInfoListIterator it(*il);
01515 QFileInfo *fi;
01516 for (int i=0; (fi = it.current()) != 0; ++it, i++)
01517 {
01518 QString PhotoFile = fi->baseName();
01519 PhotoFile = PhotoFile.mid(9);
01520 entryPhoto->insertItem(PhotoFile);
01521 if ((edit) && (PhotoFile == edit->getPhotoFile()))
01522 PhotoIndex = i;
01523 }
01524 }
01525 entryPhoto->setCurrentItem(PhotoIndex);
01526 #endif
01527
01528
01529 if (edit == 0)
01530 {
01531 QStrList DirList = DirContainer->getDirectoryList();
01532 DirList.append("new");
01533 entryDir->insertStrList(DirList);
01534 }
01535
01536 if (edit == 0)
01537 {
01538 entryNickname->setText(nn);
01539 entryFirstname->setText("");
01540 entrySurname->setText("");
01541 entryUrl->setText(Url);
01542 entryNickname->setFocus();
01543 }
01544 else
01545 {
01546 entryFirstname->setText(edit->getFirstName());
01547 entrySurname->setText(edit->getSurname());
01548 entryUrl->setText(edit->getUri());
01549 entryOnHomeLan->setChecked(edit->getOnHomeLan());
01550 entryFirstname->setFocus();
01551 }
01552
01553 EntrytoEdit = edit;
01554 }
01555
01556 void PhoneUIBox::closeAddEntryPopup()
01557 {
01558 if (!addEntryPopup)
01559 return;
01560
01561 addEntryPopup->deleteLater();
01562 addEntryPopup = NULL;
01563 }
01564
01565
01566
01567 void PhoneUIBox::entryAddSelected()
01568 {
01569 if (EntrytoEdit == 0)
01570 {
01571 QString Directory = entryDir->currentText();
01572 if (Directory == "new")
01573 {
01574 doAddDirectoryPopup();
01575 return;
01576 }
01577 else
01578 addNewDirectoryEntry(entryNickname->text(),
01579 entryUrl->text(),
01580 entryDir->currentText(),
01581 entryFirstname->text(),
01582 entrySurname->text(),
01583 "",
01584 entrySpeed->isChecked(),
01585 entryOnHomeLan->isChecked());
01586 }
01587 else
01588 addNewDirectoryEntry(0,
01589 entryUrl->text(),
01590 0,
01591 entryFirstname->text(),
01592 entrySurname->text(),
01593 "",
01594 false,
01595 entryOnHomeLan->isChecked());
01596
01597 closeAddEntryPopup();
01598
01599
01600 if (menuPopup)
01601 closeMenuPopup();
01602 }
01603
01604
01605
01606 void PhoneUIBox::addNewDirectoryEntry(QString Name, QString Url, QString Dir, QString fn, QString sn, QString ph, bool isSpeed, bool OnHomeLan)
01607 {
01608
01609 if (EntrytoEdit == 0)
01610 {
01611
01612 DirEntry *newEntry = new DirEntry(Name, Url, fn, sn, ph, OnHomeLan);
01613 newEntry->setSpeedDial(isSpeed);
01614 DirContainer->AddEntry(newEntry, Dir, true);
01615 DirectoryList->refresh();
01616
01617
01618 }
01619
01620
01621 else
01622 {
01623 DirContainer->ChangeEntry(EntrytoEdit, Name, Url, fn, sn, ph, OnHomeLan);
01624 DirectoryList->refresh();
01625 }
01626
01627 }
01628
01629
01630
01631
01632 void PhoneUIBox::doAddDirectoryPopup()
01633 {
01634 if (addDirectoryPopup)
01635 return;
01636
01637 addDirectoryPopup = new MythPopupBox(gContext->GetMainWindow(), "add_directory_popup");
01638
01639 newDirName = new MythRemoteLineEdit(addDirectoryPopup);
01640 addDirectoryPopup->addWidget(newDirName);
01641 addDirectoryPopup->addButton(tr("ADD DIRECTORY"), this, SLOT(directoryAddSelected()));
01642
01643 addDirectoryPopup->ShowPopupAtXY(240, 90, this, SLOT(closeAddDirectoryPopup()));
01644 newDirName->setFocus();
01645 }
01646
01647 void PhoneUIBox::closeAddDirectoryPopup()
01648 {
01649 if (!addDirectoryPopup)
01650 return;
01651
01652 addDirectoryPopup->deleteLater();
01653 addDirectoryPopup = NULL;
01654 }
01655
01656
01657
01658 void PhoneUIBox::directoryAddSelected()
01659 {
01660 if (!addDirectoryPopup)
01661 return;
01662
01663
01664
01665 if (addEntryPopup)
01666 {
01667 if (EntrytoEdit == 0)
01668 addNewDirectoryEntry(entryNickname->text(),
01669 entryUrl->text(),
01670 newDirName->text(),
01671 entryFirstname->text(),
01672 entrySurname->text(),
01673 "",
01674 entrySpeed->isChecked(),
01675 entryOnHomeLan->isChecked());
01676 else
01677 addNewDirectoryEntry(0,
01678 entryUrl->text(),
01679 0,
01680 entryFirstname->text(),
01681 entrySurname->text(),
01682 "",
01683 false,
01684 entryOnHomeLan->isChecked());
01685 closeAddDirectoryPopup();
01686 closeAddEntryPopup();
01687 closeMenuPopup();
01688 }
01689 else
01690 closeAddDirectoryPopup();
01691
01692
01693
01694 if (urlPopup)
01695 closeUrlPopup();
01696 }
01697
01698
01699 void PhoneUIBox::doCallPopup(DirEntry *entry, QString DialorAnswer, bool audioOnly)
01700 {
01701 if (!incallPopup)
01702 {
01703 incallPopup = new MythPopupBox(gContext->GetMainWindow(), tr("Business Card"));
01704
01705 callLabelName = incallPopup->addLabel(entry->getNickName(), MythPopupBox::Large);
01706 incallPopup->addLabel(entry->getFullName());
01707 callLabelUrl = incallPopup->addLabel(entry->getUri());
01708
01709 entryIsOnLocalLan = entry->getOnHomeLan();
01710
01711
01712 CallHistory RecentCalls;
01713 DirContainer->getRecentCalls(entry, RecentCalls);
01714 if (RecentCalls.count() > 0)
01715 {
01716 incallPopup->addLabel(tr("Latest Calls:"), MythPopupBox::Small);
01717 drawCallPopupCallHistory(incallPopup, RecentCalls.last());
01718 drawCallPopupCallHistory(incallPopup, RecentCalls.prev());
01719 drawCallPopupCallHistory(incallPopup, RecentCalls.prev());
01720 }
01721
01722 QButton *button2=0;
01723 if (DialorAnswer == tr("Dial"))
01724 {
01725 if (!audioOnly)
01726 {
01727 QButton *button1 = incallPopup->addButton(DialorAnswer + tr(" Videocall"), this, SLOT(outcallDialVideoSelected()));
01728 button1->setFocus();
01729 }
01730 button2 = incallPopup->addButton(DialorAnswer + tr(" Voice-Only"), this, SLOT(outcallDialVoiceSelected()));
01731 incallPopup->addButton(tr("Send an Instant Message"), this, SLOT(outcallSendIMSelected()));
01732 }
01733 else
01734 {
01735 if (!audioOnly)
01736 {
01737 QButton *button1 = incallPopup->addButton(DialorAnswer + tr(" Videocall"), this, SLOT(incallDialVideoSelected()));
01738 button1->setFocus();
01739 }
01740 button2 = incallPopup->addButton(DialorAnswer + tr(" Voice-Only"), this, SLOT(incallDialVoiceSelected()));
01741 }
01742
01743 if (audioOnly)
01744 button2->setFocus();
01745 incallPopup->ShowPopup(this, SLOT(closeCallPopup()));
01746 }
01747 }
01748
01749
01750 void PhoneUIBox::closeCallPopup()
01751 {
01752 if (!incallPopup)
01753 return;
01754
01755 incallPopup->deleteLater();
01756 incallPopup = NULL;
01757 }
01758
01759 void PhoneUIBox::incallDialVideoSelected()
01760 {
01761 AnswerCall(txVideoMode, entryIsOnLocalLan);
01762 closeCallPopup();
01763 }
01764
01765 void PhoneUIBox::incallDialVoiceSelected()
01766 {
01767 AnswerCall("AUDIOONLY", entryIsOnLocalLan);
01768 closeCallPopup();
01769 }
01770
01771 void PhoneUIBox::outcallDialVideoSelected()
01772 {
01773 PlaceCall(callLabelUrl->text(), callLabelName->text(), txVideoMode, entryIsOnLocalLan);
01774 closeCallPopup();
01775 }
01776
01777 void PhoneUIBox::outcallDialVoiceSelected()
01778 {
01779 PlaceCall(callLabelUrl->text(), callLabelName->text(), "AUDIOONLY", entryIsOnLocalLan);
01780 closeCallPopup();
01781 }
01782
01783 void PhoneUIBox::outcallSendIMSelected()
01784 {
01785 QString OtherParty = callLabelUrl->text();
01786 closeCallPopup();
01787 doIMPopup(OtherParty, "", "");
01788 }
01789
01790
01791 void PhoneUIBox::drawCallPopupCallHistory(MythPopupBox *popup, CallRecord *call)
01792 {
01793 if ((call) && (call->getTimestamp().length() > 0))
01794 {
01795 QString label;
01796
01797 if (!call->isIncoming())
01798 label = tr("You Called ");
01799 else if (call->getDuration() != 0)
01800 label = tr("They Called ");
01801 else
01802 label = tr("You missed their call ");
01803
01804 QDateTime dt = QDateTime::fromString(call->getTimestamp());
01805 if (dt.date() == QDateTime::currentDateTime().date())
01806 label += tr("Today ");
01807 else if (dt.date().addDays(1) == QDateTime::currentDateTime().date())
01808 label += tr("Yesterday ");
01809 else
01810 label += dt.toString("dd-MMM ");
01811 label += tr("at");
01812 label += dt.toString(" hh:mm");
01813 if (call->getDuration() > 0)
01814 {
01815 QString Duration;
01816 Duration.sprintf(tr(" for %d min"), call->getDuration()/60);
01817 label += Duration;
01818 }
01819 popup->addLabel(label);
01820 }
01821 }
01822
01823
01824 void PhoneUIBox::showStatistics(bool showVideo)
01825 {
01826 if (statsPopup)
01827 {
01828 closeStatisticsPopup();
01829 return;
01830 }
01831
01832 statsPopup = new MythPopupBox(gContext->GetMainWindow(), "statistics_popup");
01833
01834 statsPopup->addLabel(tr("Audio"), MythPopupBox::Medium);
01835 audioPkInOutLabel = statsPopup->addLabel(tr("Packets In/Out/Lost/Late: "), MythPopupBox::Small);
01836 audioPlayoutLabel = statsPopup->addLabel(tr("Playout Delay Min/Avg/Max: "), MythPopupBox::Small);
01837 audioPkRtcpLabel = statsPopup->addLabel(tr("Packets Lost by Peer: "), MythPopupBox::Small);
01838
01839 if (showVideo)
01840 {
01841 statsPopup->addLabel(tr("Video"), MythPopupBox::Medium);
01842 videoResLabel = statsPopup->addLabel(tr("Resolution In/Out: ") +
01843 QString::number(rxWidth) + "x" + QString::number(rxHeight) + " / " +
01844 QString::number(txWidth) + "x" + QString::number(txHeight),
01845 MythPopupBox::Small);
01846 videoPkInLabel = statsPopup->addLabel(tr("Packets In/Lost/Disc/Late: "), MythPopupBox::Small);
01847 videoPkOutLabel = statsPopup->addLabel(tr("Packets Out/Dropped: "), MythPopupBox::Small);
01848 videoPkRtcpLabel = statsPopup->addLabel(tr("Packets Lost by Peer: "), MythPopupBox::Small);
01849 videoFramesInOutDiscLabel = statsPopup->addLabel(tr("Video Frames In/Out/Disc: "), MythPopupBox::Small);
01850 videoAvgFpsLabel = statsPopup->addLabel(tr("Average FPS In/Out: "), MythPopupBox::Small);
01851 videoWebcamFpsLabel = statsPopup->addLabel(tr("Webcam Frames Delivered/Dropped: "), MythPopupBox::Small);
01852
01853 }
01854
01855
01856
01857 statsPopup->ShowPopup(this, SLOT(closeStatisticsPopup()));
01858 }
01859
01860 void PhoneUIBox::updateAudioStatistics(int pkIn, int pkLost, int pkLate, int pkOut, int pkInDisc, int pkOutDrop, int bIn, int bOut, int minPlayout, int avgPlayout, int maxPlayout)
01861 {
01862 (void)pkInDisc;
01863 (void)pkOutDrop;
01864 (void)bIn;
01865 (void)bOut;
01866 if (!statsPopup)
01867 return;
01868
01869 audioPkInOutLabel->setText(tr("Packets In/Out/Lost/Late: ") + QString::number(pkIn) + " / " +
01870 QString::number(pkOut) + " / " + QString::number(pkLost)
01871 + " / " + QString::number(pkLate));
01872 audioPlayoutLabel->setText(tr("Playout Delay Min/Avg/Max: ") + QString::number(minPlayout) + " / " +
01873 QString::number(avgPlayout) + " / " + QString::number(maxPlayout));
01874 }
01875
01876
01877 void PhoneUIBox::updateAudioRtcpStatistics(int fractionLoss, int totalLoss)
01878 {
01879 if (!statsPopup)
01880 return;
01881
01882 audioPkRtcpLabel->setText(tr("Packets Lost by Peer: ") + QString::number(fractionLoss) + " / " + QString::number(totalLoss));
01883 }
01884
01885
01886 void PhoneUIBox::updateVideoStatistics(int pkIn, int pkLost, int pkLate, int pkOut, int pkInDisc, int pkOutDrop, int bIn, int bOut, int fIn, int fOut, int fDiscIn, int fDiscOut)
01887 {
01888 (void)bIn;
01889 (void)bOut;
01890 if ((!statsPopup) || (videoPkInLabel == 0))
01891 return;
01892
01893 videoPkInLabel->setText(tr("Packets In/Lost/Disc/Late: ") + QString::number(pkIn) + " / " +
01894 QString::number(pkLost) + " / " + QString::number(pkInDisc)
01895 + " / " + QString::number(pkLate));
01896 videoPkOutLabel->setText(tr("Packets Out/Dropped: ") + QString::number(pkOut) + " / " +
01897 QString::number(pkOutDrop));
01898 videoFramesInOutDiscLabel->setText(tr("Video Frames In/Out/Disc: ") + QString::number(fIn) + " / " + QString::number(fOut) + " / " + QString::number(fDiscIn) + " / " + QString::number(fDiscOut));
01899 if (ConnectTime.elapsed()/1000 != 0)
01900 videoAvgFpsLabel->setText(tr("Average FPS In/Out: ") + QString::number(fIn*1000/ConnectTime.elapsed()) + " / " + QString::number(fOut*1000/ConnectTime.elapsed()));
01901 if ((ConnectTime.elapsed()/1000 != 0) && (txClient != 0))
01902 videoWebcamFpsLabel->setText(tr("Webcam Frames Delivered/Dropped: ") + QString::number(wcDeliveredFrames) + " / " + QString::number(wcDroppedFrames));
01903 }
01904
01905
01906 void PhoneUIBox::updateVideoRtcpStatistics(int fractionLoss, int totalLoss)
01907 {
01908 if ((!statsPopup) || (videoPkInLabel == 0))
01909 return;
01910
01911 videoPkRtcpLabel->setText(tr("Packets Lost by Peer: ") + QString::number(fractionLoss) + " / " + QString::number(totalLoss));
01912 }
01913
01914
01915 void PhoneUIBox::closeStatisticsPopup()
01916 {
01917 if (!statsPopup)
01918 return;
01919
01920 statsPopup->deleteLater();
01921 statsPopup = NULL;
01922 audioPkInOutLabel = audioPlayoutLabel = audioPkRtcpLabel = 0;
01923 videoResLabel = videoPkOutLabel = videoPkInLabel = videoPkRtcpLabel = videoFramesInOutDiscLabel = videoAvgFpsLabel = 0;
01924 }
01925
01926
01927 void PhoneUIBox::changeVolume(bool up_or_down)
01928 {
01929 switch (VolumeMode)
01930 {
01931 default:
01932 case VOL_VOLUME:
01933
01934
01935 break;
01936 case VOL_MICVOLUME:
01937 break;
01938 case VOL_BRIGHTNESS:
01939 camBrightness += (up_or_down ? 2048 : -2048);
01940 if (camBrightness > 65535)
01941 camBrightness = 65535;
01942 if (camBrightness < 0)
01943 camBrightness = 0;
01944 camBrightness = webcam->SetBrightness(camBrightness);
01945 break;
01946 case VOL_CONTRAST:
01947 camContrast += (up_or_down ? 2048 : -2048);
01948 if (camContrast > 65535)
01949 camContrast = 65535;
01950 if (camContrast < 0)
01951 camContrast = 0;
01952 camContrast = webcam->SetContrast(camContrast);
01953 break;
01954 case VOL_COLOUR:
01955 camColour += (up_or_down ? 2048 : -2048);
01956 if (camColour > 65535)
01957 camColour = 65535;
01958 if (camColour < 0)
01959 camColour = 0;
01960 camColour = webcam->SetColour(camColour);
01961 break;
01962 case VOL_TXSIZE:
01963 switch (txWidth)
01964 {
01965 case 704:
01966 txWidth = (up_or_down ? 704 : 352);
01967 txHeight = (up_or_down ? 576 : 288);
01968 break;
01969 default:
01970 case 352:
01971 txWidth = (up_or_down ? 704 : 176);
01972 txHeight = (up_or_down ? 576 : 144);
01973 break;
01974 case 176:
01975 txWidth = (up_or_down ? 352 : 128);
01976 txHeight = (up_or_down ? 288 : 96);
01977 break;
01978 case 128:
01979 txWidth = (up_or_down ? 176 : 128);
01980 txHeight = (up_or_down ? 144 : 96);
01981 break;
01982 }
01983 txVideoMode = videoResToCifMode(txWidth);
01984 ChangeVideoTxResolution();
01985 break;
01986 case VOL_TXRATE:
01987 txFps += (up_or_down ? 1 : -1);
01988 if (txFps > 30)
01989 txFps = 30;
01990 if (txFps < 1)
01991 txFps = 1;
01992 webcam->ChangeClientFps(txClient, txFps);
01993 break;
01994 case VOL_AUDCODEC:
01995 if ((up_or_down) && (audioCodecInUse == "GSM"))
01996 sipStack->ModifyCall("PCMU");
01997 else if ((!up_or_down) && (audioCodecInUse != "GSM"))
01998 sipStack->ModifyCall("GSM");
01999 break;
02000 }
02001 showVolume(true);
02002 }
02003
02004 void PhoneUIBox::changeVolumeControl(bool up_or_down)
02005 {
02006 if ((volume_status) && (volume_status->getOrder() != -1))
02007 {
02008
02009 switch (VolumeMode)
02010 {
02011 default:
02012 case VOL_VOLUME: VolumeMode = (up_or_down ? VOL_MICVOLUME : VOL_TXRATE); break;
02013 case VOL_MICVOLUME: VolumeMode = (up_or_down ? VOL_AUDCODEC : VOL_VOLUME); break;
02014 case VOL_AUDCODEC: VolumeMode = (up_or_down ? VOL_BRIGHTNESS : VOL_MICVOLUME); break;
02015 case VOL_BRIGHTNESS: VolumeMode = (up_or_down ? VOL_CONTRAST : VOL_AUDCODEC); break;
02016 case VOL_CONTRAST: VolumeMode = (up_or_down ? VOL_COLOUR : VOL_BRIGHTNESS); break;
02017 case VOL_COLOUR: VolumeMode = (up_or_down ? VOL_TXSIZE : VOL_CONTRAST); break;
02018 case VOL_TXSIZE: VolumeMode = (up_or_down ? VOL_TXRATE : VOL_COLOUR); break;
02019 case VOL_TXRATE: VolumeMode = (up_or_down ? VOL_VOLUME : VOL_TXSIZE); break;
02020 }
02021
02022 QString themepath = gContext->FindThemeDir("default") + "/";
02023 switch (VolumeMode)
02024 {
02025 default:
02026 case VOL_VOLUME: volume_icon->SetImage(themepath + "mp_volume_icon.png");
02027 volume_setting->SetText(tr("Volume"));
02028 volume_value->SetText("");
02029 break;
02030 case VOL_MICVOLUME: volume_icon->SetImage(themepath + "mp_microphone_icon.png");
02031 volume_setting->SetText(tr("Mic Volume (not impl.)"));
02032 volume_value->SetText("");
02033 break;
02034 case VOL_AUDCODEC: volume_icon->SetImage(themepath + "mp_microphone_icon.png");
02035 volume_setting->SetText(tr("Audio Codec"));
02036 volume_value->SetText(audioCodecInUse);
02037 break;
02038 case VOL_BRIGHTNESS: volume_icon->SetImage(themepath + "mp_brightness_icon.png");
02039 volume_setting->SetText(tr("Brightness"));
02040 volume_value->SetText("");
02041 break;
02042 case VOL_CONTRAST: volume_icon->SetImage(themepath + "mp_contrast_icon.png");
02043 volume_setting->SetText(tr("Contrast"));
02044 volume_value->SetText("");
02045 break;
02046 case VOL_COLOUR: volume_icon->SetImage(themepath + "mp_colour_icon.png");
02047 volume_setting->SetText(tr("Colour"));
02048 volume_value->SetText("");
02049 break;
02050 case VOL_TXSIZE: volume_icon->SetImage(themepath + "mp_framesize_icon.png");
02051 volume_setting->SetText(tr("Transmit Video Size"));
02052 volume_value->SetText(getVideoFrameSizeText());
02053 break;
02054 case VOL_TXRATE: volume_icon->SetImage(themepath + "mp_framerate_icon.png");
02055 volume_setting->SetText(tr("Transmit Video FPS"));
02056 volume_value->SetText(QString::number(txFps));
02057 break;
02058 }
02059
02060 volume_icon->LoadImage();
02061 showVolume(true);
02062 }
02063 }
02064
02065 void PhoneUIBox::toggleMute()
02066 {
02067 if (rtpAudio)
02068 rtpAudio->toggleMute();
02069 }
02070
02071 QString PhoneUIBox::getVideoFrameSizeText()
02072 {
02073 QString fsText = QString::number(txWidth) + "x" + QString::number(txHeight);
02074 return fsText;
02075 }
02076
02077 void PhoneUIBox::showVolume(bool on_or_off)
02078 {
02079 if (volume_status)
02080 {
02081 if (on_or_off)
02082 {
02083 switch (VolumeMode)
02084 {
02085 case VOL_VOLUME:
02086 default:
02087
02088 break;
02089 case VOL_MICVOLUME:
02090 volume_status->SetUsed(50);
02091 break;
02092 case VOL_AUDCODEC:
02093 if (audioCodecInUse == "GSM")
02094 volume_status->SetUsed(0);
02095 else
02096 volume_status->SetUsed(100);
02097 break;
02098 case VOL_BRIGHTNESS:
02099 volume_status->SetUsed((camBrightness * 100) / 65535);
02100 break;
02101 case VOL_CONTRAST:
02102 volume_status->SetUsed((camContrast * 100) / 65535);
02103 break;
02104 case VOL_COLOUR:
02105 volume_status->SetUsed((camColour * 100) / 65535);
02106 break;
02107 case VOL_TXSIZE:
02108 switch (txWidth)
02109 {
02110 default:
02111 case 704: volume_status->SetUsed(100); break;
02112 case 352: volume_status->SetUsed(66); break;
02113 case 176: volume_status->SetUsed(33); break;
02114 case 128: volume_status->SetUsed(0); break;
02115 }
02116 volume_value->SetText(getVideoFrameSizeText());
02117 break;
02118 case VOL_TXRATE:
02119 volume_status->SetUsed((txFps * 100) / 30);
02120 volume_value->SetText(QString::number(txFps));
02121 break;
02122 }
02123 volume_bkgnd->SetOrder(4);
02124 volume_bkgnd->refresh();
02125 volume_status->SetOrder(5);
02126 volume_status->refresh();
02127 volume_icon->SetOrder(5);
02128 volume_icon->refresh();
02129 volume_setting->SetOrder(6);
02130 volume_setting->refresh();
02131 volume_value->SetOrder(6);
02132 volume_value->refresh();
02133 volume_info->SetOrder(6);
02134 volume_info->refresh();
02135
02136 volume_display_timer->start(3000, true);
02137 }
02138 else
02139 {
02140 if (volume_status->getOrder() != -1)
02141 {
02142 volume_bkgnd->SetOrder(-1);
02143 volume_bkgnd->refresh();
02144 volume_status->SetOrder(-1);
02145 volume_status->refresh();
02146 volume_icon->SetOrder(-1);
02147 volume_icon->refresh();
02148 volume_icon->SetImage(gContext->FindThemeDir("default") + "/mp_volume_icon.png");
02149 volume_icon->LoadImage();
02150 volume_setting->SetOrder(-1);
02151 volume_setting->refresh();
02152 volume_setting->SetText(tr("Volume"));
02153 volume_value->SetOrder(-1);
02154 volume_value->refresh();
02155 volume_value->SetText("");
02156 volume_info->SetOrder(-1);
02157 volume_info->refresh();
02158 VolumeMode = VOL_VOLUME;
02159 }
02160 }
02161 }
02162 }
02163
02164 void PhoneUIBox::DisplayMicSpkPower()
02165 {
02166 if (rtpAudio != 0)
02167 {
02168 short micPower = 0;
02169 short spkPower = 0;
02170 rtpAudio->getPower(micPower, spkPower);
02171 micAmplitude->setRepeat(((int)micPower*19)/32768);
02172 spkAmplitude->setRepeat(((int)spkPower*19)/32768);
02173 }
02174 }
02175
02176 void PhoneUIBox::wireUpTheme()
02177 {
02178
02179 DirectoryList = getUIManagedTreeListType("directorytreelist");
02180 if (!DirectoryList)
02181 {
02182 cerr << "phoneui.o: Couldn't find a Directory box in your theme\n";
02183 exit(0);
02184 }
02185 connect(DirectoryList, SIGNAL(nodeSelected(int, IntVector*)),
02186 this, SLOT(handleTreeListSignals(int, IntVector*)));
02187
02188 volume_status = NULL;
02189
02190 micAmplitude = getUIRepeatedImageType("mic_amplitude");
02191 spkAmplitude = getUIRepeatedImageType("spk_amplitude");
02192 micAmplitude->setRepeat(15);
02193 spkAmplitude->setRepeat(15);
02194 micAmplitude->setRepeat(0);
02195 spkAmplitude->setRepeat(0);
02196
02197 volume_status = getUIStatusBarType("volume_status");
02198 if (volume_status)
02199 {
02200 volume_status->SetTotal(100);
02201 volume_status->SetOrder(-1);
02202 }
02203 volume_icon = getUIImageType("volumeicon");
02204 if (volume_icon)
02205 volume_icon->SetOrder(-1);
02206 volume_bkgnd = getUIImageType("volumebkgnd");
02207 if (volume_bkgnd)
02208 volume_bkgnd->SetOrder(-1);
02209 volume_setting = getUITextType("volume_setting_text");
02210 if (volume_setting)
02211 volume_setting->SetOrder(-1);
02212 volume_setting->SetText("Volume");
02213 volume_value = getUITextType("volume_value_text");
02214 if (volume_value)
02215 volume_value->SetOrder(-1);
02216 volume_value->SetText("");
02217 volume_info = getUITextType("volume_info_text");
02218 if (volume_info)
02219 volume_info->SetOrder(-1);
02220 volume_info->SetText(tr("Up/Down - Change Left/Right - Adjust"));
02221
02222 localWebcamArea = getUIBlackHoleType("local_webcam_blackhole");
02223 receivedWebcamArea = getUIBlackHoleType("mp_received_video_blackhole");
02224
02225 }
02226
02227
02228 void PhoneUIBox::handleTreeListSignals(int , IntVector *attributes)
02229 {
02230 if (!SelectHit)
02231 {
02232 SelectHit = false;
02233 return;
02234 }
02235
02236
02237 if ((attributes->at(0) == TA_DIRENTRY) ||
02238 (attributes->at(0) == TA_SPEEDDIALENTRY))
02239 {
02240 DirEntry *entry = DirContainer->fetchDirEntryById(attributes->at(1));
02241 if (entry)
02242 doCallPopup(entry, tr("Dial"), false);
02243 else
02244 cerr << "Cannot find entry to dial\n";
02245 }
02246
02247
02248 else if (attributes->at(0) == TA_CALLHISTENTRY)
02249 {
02250 CallRecord *rec = DirContainer->fetchCallRecordById(attributes->at(1));
02251 DirEntry *entry = DirContainer->FindMatchingDirectoryEntry(rec->getUri());
02252 if (entry)
02253 doCallPopup(entry, tr("Dial"), false);
02254 else
02255 {
02256 DirEntry dummyEntry(rec->getDisplayName(), rec->getUri(), "", "", "");
02257 doCallPopup(&dummyEntry, tr("Dial"), false);
02258 }
02259 }
02260
02261
02262 else if (attributes->at(0) == TA_VMAIL_ENTRY)
02263 {
02264 GenericTree *node = DirectoryList->getCurrentNode();
02265 QString fileName = MythContext::GetConfDir() + "/MythPhone/Voicemail/" + node->getString() + ".wav";
02266 wavfile *vmailWav = new wavfile();
02267 if (vmailWav->load(fileName))
02268 {
02269 if (vmail)
02270 delete vmail;
02271 vmail = new Tone(*vmailWav);
02272 QString spk = gContext->GetSetting("AudioOutputDevice");
02273 vmail->Play(spk, false);
02274 }
02275 delete vmailWav;
02276 }
02277 }
02278
02279
02280 PhoneUIBox::~PhoneUIBox(void)
02281 {
02282 sipStack->UiStopWatchAll();
02283 sipStack->UiClosed();
02284
02285
02286 if (rtpAudio != 0)
02287 delete rtpAudio;
02288 if (rtpVideo != 0)
02289 StopVideo();
02290 rtpAudio = 0;
02291 rtpVideo = 0;
02292
02293 if (localClient != 0)
02294 webcam->UnregisterClient(localClient);
02295 if (txClient != 0)
02296 webcam->UnregisterClient(txClient);
02297 webcam->camClose();
02298
02299
02300 QApplication::sendPostedEvents(this, 0);
02301
02302
02303
02304 delete DirContainer;
02305 if (vmail)
02306 delete vmail;
02307 delete h263;
02308 delete webcam;
02309
02310 delete phoneUIStatusBar;
02311 delete powerDispTimer;
02312 delete OnScreenClockTimer;
02313 delete volume_display_timer;
02314 }
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326 PhoneUIStatusBar::PhoneUIStatusBar(UITextType *a, UITextType *b, UITextType *c, UITextType *d, UITextType *e, UITextType *f,
02327 QObject *parent, const char *name) : QObject(parent, name)
02328 {
02329 callerText = a;
02330 audioStatsText = b;
02331 videoStatsText = c;
02332 bwStatsText = d;
02333 callTimeText = e;
02334 statusMsgText = f;
02335
02336 statsVideoCodec = "";
02337 statsAudioCodec = "";
02338 audLast_pIn = 0;
02339 audLast_pLoss = 0;
02340 audLast_pTotal = 0;
02341 vidLast_pIn = 0;
02342 vidLast_pLoss = 0;
02343 vidLast_pTotal = 0;
02344 audLast_bIn = 0;
02345 audLast_bOut = 0;
02346 vidLast_bIn = 0;
02347 vidLast_bOut = 0;
02348 modeInCallStats = false;
02349 modeNotification = false;
02350 callStateString = "";
02351 callerText->SetText("");
02352 callTimeText->SetText("");
02353 audioStatsText->SetText("");
02354 videoStatsText->SetText("");
02355
02356 statusMsgText->SetText("");
02357 lastPoll = QTime::currentTime();
02358 last_bOut = 0;
02359
02360 notificationTimer = new QTimer(this);
02361 connect(notificationTimer, SIGNAL(timeout()), this, SLOT(notificationTimeout()));
02362 }
02363
02364 PhoneUIStatusBar::~PhoneUIStatusBar()
02365 {
02366 delete notificationTimer;
02367 }
02368
02369 void PhoneUIStatusBar::DisplayInCallStats(bool initialise)
02370 {
02371 if (initialise)
02372 {
02373 audLast_bIn = 0;
02374 audLast_bOut = 0;
02375 vidLast_bIn = 0;
02376 vidLast_bOut = 0;
02377 audLast_pIn = 0;
02378 audLast_pLoss = 0;
02379 audLast_pTotal = 0;
02380 vidLast_pIn = 0;
02381 vidLast_pLoss = 0;
02382 vidLast_pTotal = 0;
02383 lastPoll = QTime::currentTime();
02384 last_bOut = 0;
02385 }
02386
02387 modeInCallStats = true;
02388 if (!modeNotification)
02389 {
02390 callerText->SetText(callerString);
02391 callTimeText->SetText(TimeString);
02392 audioStatsText->SetText(audioStatsString);
02393 videoStatsText->SetText(videoStatsString);
02394
02395 statusMsgText->SetText("");
02396 }
02397 }
02398
02399 void PhoneUIStatusBar::DisplayCallState(QString s)
02400 {
02401 modeInCallStats = false;
02402 callStateString = s;
02403 if (!modeNotification)
02404 {
02405 callerText->SetText("");
02406 callTimeText->SetText("");
02407 audioStatsText->SetText("");
02408 videoStatsText->SetText("");
02409
02410 statusMsgText->SetText(s);
02411 }
02412 }
02413
02414 void PhoneUIStatusBar::DisplayNotification(QString s, int Seconds)
02415 {
02416 modeNotification = true;
02417 callerText->SetText("");
02418 callTimeText->SetText("");
02419 audioStatsText->SetText("");
02420 videoStatsText->SetText("");
02421
02422 statusMsgText->SetText(s);
02423
02424 notificationTimer->start(Seconds*1000, true);
02425 }
02426
02427 void PhoneUIStatusBar::notificationTimeout()
02428 {
02429 modeNotification = false;
02430 if (modeInCallStats)
02431 DisplayInCallStats(false);
02432 else
02433 DisplayCallState(callStateString);
02434 }
02435
02436 void PhoneUIStatusBar::updateMidCallCaller(QString t)
02437 {
02438 callerString = t;
02439 if (modeInCallStats && !modeNotification)
02440 callerText->SetText(t);
02441 }
02442
02443 void PhoneUIStatusBar::updateMidCallTime(int Seconds)
02444 {
02445 int Hours = Seconds / 60 / 60;
02446 int Mins = (Seconds - (Hours*60*60)) / 60;
02447 int Secs = (Seconds - (Hours*60*60) - (Mins*60));
02448 TimeString.sprintf("%d:%02d:%02d", Hours, Mins, Secs);
02449
02450 if (modeInCallStats && !modeNotification)
02451 callTimeText->SetText(TimeString);
02452 }
02453
02454 void PhoneUIStatusBar::updateMidCallAudioStats(int pIn, int pMiss, int pLate, int pOut, int bIn, int bOut, int msPeriod)
02455 {
02456 audioStatsString = statsAudioCodec;
02457 (void)pIn;
02458 (void)pOut;
02459 (void)pMiss;
02460 (void)pLate;
02461
02462 QString StatsString;
02463
02464 StatsString.sprintf("; %dkbps / %dkbps", (bOut-audLast_bOut)*8*msPeriod/1000/1000,
02465 (bIn-audLast_bIn)*8*msPeriod/1000/1000);
02466 audLast_bIn = bIn;
02467 audLast_bOut = bOut;
02468 audioStatsString += StatsString;
02469 if (modeInCallStats && !modeNotification)
02470 audioStatsText->SetText(audioStatsString);
02471 }
02472
02473 void PhoneUIStatusBar::updateMidCallVideoStats(int pIn, int pMiss, int pLate, int pOut, int bIn, int bOut, int msPeriod)
02474 {
02475 videoStatsString = statsVideoCodec;
02476 (void)pIn;
02477 (void)pOut;
02478 (void)pMiss;
02479 (void)pLate;
02480
02481 QString StatsString;
02482 StatsString.sprintf("; %dkbps / %dkbps", (bOut-vidLast_bOut)*8*msPeriod/1000/1000,
02483 (bIn-vidLast_bIn)*8*msPeriod/1000/1000);
02484 vidLast_bIn = bIn;
02485 vidLast_bOut = bOut;
02486 videoStatsString += StatsString;
02487 if (modeInCallStats && !modeNotification)
02488 videoStatsText->SetText(videoStatsString);
02489 }
02490
02491 void PhoneUIStatusBar::updateMidCallVideoCodec(QString c)
02492 {
02493 statsVideoCodec = c;
02494 }
02495
02496 void PhoneUIStatusBar::updateMidCallAudioCodec(QString c)
02497 {
02498 statsAudioCodec = c;
02499 }
02500
02501
02502