blob: 6178f6c67177c9fba037d23533b92ea9d4b64b60 [file] [log] [blame]
Benny Prijono5d9c16f2008-02-22 23:38:47 +00001// PocketPJDlg.cpp : implementation file
2//
3
4#include "stdafx.h"
5#include "PocketPJ.h"
6#include "PocketPJDlg.h"
7#include <iphlpapi.h>
8
9#ifdef _DEBUG
10#define new DEBUG_NEW
11#undef THIS_FILE
12static char THIS_FILE[] = __FILE__;
13#endif
14
15#define TIMER_ID 101
16static CPocketPJDlg *theDlg;
17
18/////////////////////////////////////////////////////////////////////////////
19// CPocketPJDlg dialog
20
21CPocketPJDlg::CPocketPJDlg(CWnd* pParent /*=NULL*/)
22 : CDialog(CPocketPJDlg::IDD, pParent), m_PopUp(NULL)
23{
24 //{{AFX_DATA_INIT(CPocketPJDlg)
25 // NOTE: the ClassWizard will add member initialization here
26 //}}AFX_DATA_INIT
27 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
28 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
29
30 theDlg = this;
31
32 m_PopUp = new CPopUpWnd(this);
33 m_PopUp->Hide();
34
35 unsigned i;
36 m_PopUpCount = 0;
37 for (i=0; i<POPUP_MAX_TYPE; ++i) {
38 m_PopUpState[i] = FALSE;
39 }
40}
41
42void CPocketPJDlg::DoDataExchange(CDataExchange* pDX)
43{
44 CDialog::DoDataExchange(pDX);
45 //{{AFX_DATA_MAP(CPocketPJDlg)
46 DDX_Control(pDX, IDC_URL, m_Url);
47 DDX_Control(pDX, IDC_BUDDY_LIST, m_BuddyList);
48 DDX_Control(pDX, IDC_BTN_ACTION, m_BtnUrlAction);
49 DDX_Control(pDX, IDC_BTN_ACC, m_BtnAcc);
50 DDX_Control(pDX, IDC_ACC_ID, m_AccId);
51 //}}AFX_DATA_MAP
52}
53
54BEGIN_MESSAGE_MAP(CPocketPJDlg, CDialog)
55 //{{AFX_MSG_MAP(CPocketPJDlg)
56 ON_BN_CLICKED(IDC_BTN_ACC, OnBtnAcc)
57 ON_BN_CLICKED(IDC_BTN_ACTION, OnBtnAction)
58 ON_COMMAND(IDC_ACC_SETTINGS, OnSettings)
59 ON_COMMAND(IDC_URI_CALL, OnUriCall)
60 ON_WM_TIMER()
61 ON_COMMAND(IDC_URI_ADD_BUDDY, OnUriAddBuddy)
62 ON_COMMAND(IDC_URI_DEL_BUDDY, OnUriDelBuddy)
63 ON_COMMAND(IDC_ACC_ONLINE, OnAccOnline)
64 ON_COMMAND(IDC_ACC_INVISIBLE, OnAccInvisible)
65 ON_NOTIFY(NM_CLICK, IDC_BUDDY_LIST, OnClickBuddyList)
66 //}}AFX_MSG_MAP
67END_MESSAGE_MAP()
68
69
70void CPocketPJDlg::Error(const CString &title, pj_status_t rc)
71{
72 char errmsg[PJ_ERR_MSG_SIZE];
73 wchar_t werrmsg[PJ_ERR_MSG_SIZE];
74
75 pj_strerror(rc, errmsg, sizeof(errmsg));
76 pj_ansi_to_unicode(errmsg, strlen(errmsg), werrmsg, PJ_ARRAY_SIZE(werrmsg));
77
78 AfxMessageBox(title + _T(": ") + werrmsg);
79}
80
81BOOL CPocketPJDlg::Restart()
82{
Benny Prijono36e76ef2008-08-13 13:56:24 +000083 unsigned i;
Benny Prijono5d9c16f2008-02-22 23:38:47 +000084 pj_status_t status;
85
86 char ver[80];
87 sprintf(ver, "PocketPJ/%s", pj_get_version());
88
89 ShowWindow(SW_SHOW);
90 PopUp_Show(POPUP_REGISTRATION, ver,
91 "Starting up....", "", "", "", 0);
92
93 KillTimer(TIMER_ID);
94
95 // Destroy first.
96 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Cleaning up..");
97 pjsua_destroy();
98
99 m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_OFFLINE)) );
100 UpdateWindow();
101
102
103 // Create
104 PopUp_Show(POPUP_REGISTRATION, ver,
105 "Starting up....", "Creating stack..", "", "", 0);
106
107 status = pjsua_create();
108 if (status != PJ_SUCCESS) {
109 Error(_T("Error in creating library"), status);
110 PopUp_Hide(POPUP_REGISTRATION);
111 return FALSE;
112 }
113
114 pjsua_config cfg;
115 pjsua_logging_config log_cfg;
116 pjsua_media_config media_cfg;
117
118 pjsua_config_default(&cfg);
119 cfg.max_calls = 1;
120 cfg.thread_cnt = 0;
121 cfg.user_agent = pj_str(ver);
122
123 cfg.cb.on_call_state = &on_call_state;
124 cfg.cb.on_call_media_state = &on_call_media_state;
125 cfg.cb.on_incoming_call = &on_incoming_call;
126 cfg.cb.on_reg_state = &on_reg_state;
127 cfg.cb.on_buddy_state = &on_buddy_state;
128 cfg.cb.on_pager = &on_pager;
129
130 /* Configure nameserver */
131 char nameserver[60];
132 {
133 FIXED_INFO fi;
134 ULONG len = sizeof(fi);
135 CString err;
136
137 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Retrieving network parameters..");
138 if (GetNetworkParams(&fi, &len) != ERROR_SUCCESS) {
139 err = _T("Info: Error querying network parameters. You must configure DNS server.");
140 } else if (fi.CurrentDnsServer == NULL) {
141 err = _T("Info: DNS server not configured. You must configure DNS server.");
142 }
143
144 if (err.GetLength()) {
145 if (m_Cfg.m_DNS.GetLength()) {
146 pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_DNS, m_Cfg.m_DNS.GetLength(),
147 nameserver, sizeof(nameserver));
148 cfg.nameserver_count = 1;
149 cfg.nameserver[0] = pj_str(nameserver);
150 } else {
151 AfxMessageBox(err);
152 pjsua_destroy();
153 PopUp_Hide(POPUP_REGISTRATION);
154 return FALSE;
155 }
156 } else {
157 strcpy(nameserver, fi.CurrentDnsServer->IpAddress.String);
158 cfg.nameserver_count = 1;
159 cfg.nameserver[0] = pj_str(nameserver);
160 }
161 }
162
163 char tmp_stun[80];
164 if (m_Cfg.m_UseStun) {
165 pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_StunSrv, m_Cfg.m_StunSrv.GetLength(),
166 tmp_stun, sizeof(tmp_stun));
167 cfg.stun_host = pj_str(tmp_stun);
168 }
169
170 pjsua_logging_config_default(&log_cfg);
171 log_cfg.log_filename = pj_str("\\PocketPJ.TXT");
172
173 pjsua_media_config_default(&media_cfg);
174 media_cfg.clock_rate = 8000;
175 media_cfg.audio_frame_ptime = 40;
176 media_cfg.ec_tail_len = 0;
177 media_cfg.ilbc_mode = 30;
178 media_cfg.max_media_ports = 8;
Benny Prijonodfd30522008-05-23 12:31:55 +0000179 media_cfg.quality = 5;
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000180 media_cfg.thread_cnt = 1;
181 media_cfg.enable_ice = m_Cfg.m_UseIce;
Benny Prijono36e76ef2008-08-13 13:56:24 +0000182 media_cfg.no_vad = !m_Cfg.m_VAD;
Benny Prijono4d3eed12008-03-11 13:18:48 +0000183
184 if (m_Cfg.m_EchoSuppress) {
185 media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE;
186 media_cfg.ec_tail_len = m_Cfg.m_EcTail;
187 }
188
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000189 // Init
190 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Initializing..");
191 status = pjsua_init(&cfg, &log_cfg, &media_cfg);
192 if (status != PJ_SUCCESS) {
193 Error(_T("Error initializing library"), status);
194 pjsua_destroy();
195 PopUp_Hide(POPUP_REGISTRATION);
196 return FALSE;
197 }
198
199 // Create one UDP transport
Benny Prijono36e76ef2008-08-13 13:56:24 +0000200 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Adding UDP transport..");
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000201 pjsua_transport_id transport_id;
202 pjsua_transport_config udp_cfg;
203
204 pjsua_transport_config_default(&udp_cfg);
205 udp_cfg.port = 0;
206 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
207 &udp_cfg, &transport_id);
208 if (status != PJ_SUCCESS) {
209 Error(_T("Error creating UDP transport"), status);
210 pjsua_destroy();
211 PopUp_Hide(POPUP_REGISTRATION);
212 return FALSE;
213 }
214
Benny Prijono36e76ef2008-08-13 13:56:24 +0000215 if (m_Cfg.m_TCP) {
216 // Create one TCP transport
217 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Adding TCP transport..");
218 pjsua_transport_id transport_id;
219 pjsua_transport_config tcp_cfg;
220
221 pjsua_transport_config_default(&tcp_cfg);
222 tcp_cfg.port = 0;
223 status = pjsua_transport_create(PJSIP_TRANSPORT_TCP,
224 &tcp_cfg, &transport_id);
225 if (status != PJ_SUCCESS) {
226 Error(_T("Error creating TCP transport"), status);
227 pjsua_destroy();
228 PopUp_Hide(POPUP_REGISTRATION);
229 return FALSE;
230 }
231 }
232
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000233 // Adjust codecs priority
234 pj_str_t tmp;
Benny Prijono36e76ef2008-08-13 13:56:24 +0000235 pjsua_codec_set_priority(pj_cstr(&tmp, "*"), 0);
236 for (i=0; i<(unsigned)m_Cfg.m_Codecs.GetSize(); ++i) {
237 CString codec = m_Cfg.m_Codecs.GetAt(i);
238 char tmp_nam[80];
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000239
Benny Prijono36e76ef2008-08-13 13:56:24 +0000240 pj_unicode_to_ansi((LPCTSTR)codec, codec.GetLength(),
241 tmp_nam, sizeof(tmp_nam));
242 pjsua_codec_set_priority(pj_cstr(&tmp, tmp_nam), 200-i);
243 }
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000244
245 // Start!
246 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Starting..");
247 status = pjsua_start();
248 if (status != PJ_SUCCESS) {
249 Error(_T("Error starting library"), status);
250 pjsua_destroy();
251 PopUp_Hide(POPUP_REGISTRATION);
252 return FALSE;
253 }
254
255 // Add account
256 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "Adding account..");
257 char domain[80], username[80], passwd[80];
258 char id[80], reg_uri[80];
259 pjsua_acc_config acc_cfg;
260
261 pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_Domain, m_Cfg.m_Domain.GetLength(),
262 domain, sizeof(domain));
263 pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_User, m_Cfg.m_User.GetLength(),
264 username, sizeof(username));
265 pj_unicode_to_ansi((LPCTSTR)m_Cfg.m_Password, m_Cfg.m_Password.GetLength(),
266 passwd, sizeof(passwd));
267
268 snprintf(id, sizeof(id), "<sip:%s@%s>", username, domain);
269 snprintf(reg_uri, sizeof(reg_uri), "sip:%s", domain);
270
271 pjsua_acc_config_default(&acc_cfg);
272 acc_cfg.id = pj_str(id);
273 acc_cfg.reg_uri = pj_str(reg_uri);
274 acc_cfg.cred_count = 1;
275 acc_cfg.cred_info[0].scheme = pj_str("Digest");
276 acc_cfg.cred_info[0].realm = pj_str("*");
277 acc_cfg.cred_info[0].username = pj_str(username);
278 acc_cfg.cred_info[0].data_type = 0;
279 acc_cfg.cred_info[0].data = pj_str(passwd);
280
Nanang Izzuddin51b1e552008-09-16 15:15:45 +0000281#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
Benny Prijono9b862572008-05-22 10:49:42 +0000282 acc_cfg.use_srtp = (m_Cfg.m_UseSrtp ? PJMEDIA_SRTP_OPTIONAL : PJMEDIA_SRTP_DISABLED);
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000283 acc_cfg.srtp_secure_signaling = 0;
Nanang Izzuddin51b1e552008-09-16 15:15:45 +0000284#endif
285
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000286 acc_cfg.publish_enabled = m_Cfg.m_UsePublish;
287
Benny Prijono36e76ef2008-08-13 13:56:24 +0000288 char route[80];
289 if (m_Cfg.m_TCP) {
290 snprintf(route, sizeof(route), "<sip:%s;lr;transport=tcp>", domain);
291 acc_cfg.proxy[acc_cfg.proxy_cnt++] = pj_str(route);
292 } else {
293 snprintf(route, sizeof(route), "<sip:%s;lr>", domain);
294 acc_cfg.proxy[acc_cfg.proxy_cnt++] = pj_str(route);
295 }
296
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000297 status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &m_PjsuaAccId);
298 if (status != PJ_SUCCESS) {
299 Error(_T("Invalid account settings"), status);
300 pjsua_destroy();
301 PopUp_Hide(POPUP_REGISTRATION);
302 return FALSE;
303 }
304
305 CString acc_text = m_Cfg.m_User + _T("@") + m_Cfg.m_Domain;
306 m_AccId.SetWindowText(acc_text);
307
308 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE1, acc_text);
309 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE2, "Registering..");
310 PopUp_Modify(POPUP_REGISTRATION, POPUP_EL_TITLE3, "");
311
312 SetTimer(TIMER_ID, 100, NULL);
313 return TRUE;
314}
315
316
317void CPocketPJDlg::PopUp_Show( PopUpType type,
318 const CString& title1,
319 const CString& title2,
320 const CString& title3,
321 const CString& btn1,
322 const CString& btn2,
323 unsigned userData)
324{
325 if (!m_PopUpState[type])
326 ++m_PopUpCount;
327
328 m_PopUpState[type] = TRUE;
329
330 m_PopUpContent[type].m_Title1 = title1;
331 m_PopUpContent[type].m_Title2 = title2;
332 m_PopUpContent[type].m_Title3 = title3;
333 m_PopUpContent[type].m_Btn1 = btn1;
334 m_PopUpContent[type].m_Btn2 = btn2;
335
336 m_PopUp->SetContent(m_PopUpContent[type]);
337 m_PopUp->Show();
338}
339
340void CPocketPJDlg::PopUp_Modify(PopUpType type,
341 PopUpElement el,
342 const CString& text)
343{
344 switch (el) {
345 case POPUP_EL_TITLE1:
346 m_PopUpContent[type].m_Title1 = text;
347 break;
348 case POPUP_EL_TITLE2:
349 m_PopUpContent[type].m_Title2 = text;
350 break;
351 case POPUP_EL_TITLE3:
352 m_PopUpContent[type].m_Title3 = text;
353 break;
354 case POPUP_EL_BUTTON1:
355 m_PopUpContent[type].m_Btn1 = text;
356 break;
357 case POPUP_EL_BUTTON2:
358 m_PopUpContent[type].m_Btn1 = text;
359 break;
360 }
361
362 m_PopUp->SetContent(m_PopUpContent[type]);
363}
364
365void CPocketPJDlg::PopUp_Hide(PopUpType type)
366{
367 if (m_PopUpState[type])
368 --m_PopUpCount;
369
370 m_PopUpState[type] = FALSE;
371
372 if (m_PopUpCount == 0) {
373 m_PopUp->Hide();
374 UpdateWindow();
375 } else {
376 for (int i=POPUP_MAX_TYPE-1; i>=0; --i) {
377 if (m_PopUpState[i]) {
378 m_PopUp->SetContent(m_PopUpContent[i]);
379 break;
380 }
381 }
382 }
383}
384
385void CPocketPJDlg::OnCallState()
386{
387 pjsua_call_info ci;
388
389 pjsua_call_get_info(0, &ci);
390
391 switch (ci.state) {
392 case PJSIP_INV_STATE_NULL: /**< Before INVITE is sent or received */
393 break;
394 case PJSIP_INV_STATE_CALLING: /**< After INVITE is sent */
395 PopUp_Show(POPUP_CALL, "Calling..", ci.remote_info.ptr, "",
396 "", "Hangup", 0);
397 break;
398 case PJSIP_INV_STATE_INCOMING: /**< After INVITE is received. */
399 PopUp_Show(POPUP_CALL, "Incoming call..", ci.remote_info.ptr, "",
400 "Answer", "Hangup", 0);
401 pjsua_call_answer(0, 180, NULL, NULL);
Benny Prijono36e76ef2008-08-13 13:56:24 +0000402 if (m_Cfg.m_AutoAnswer)
403 OnPopUpButton(1);
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000404 break;
405 case PJSIP_INV_STATE_EARLY: /**< After response with To tag. */
406 case PJSIP_INV_STATE_CONNECTING:/**< After 2xx is sent/received. */
407 case PJSIP_INV_STATE_CONFIRMED: /**< After ACK is sent/received. */
408 {
409 CString stateText = ci.state_text.ptr;
410 PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE3, stateText);
411 }
412 break;
413 case PJSIP_INV_STATE_DISCONNECTED:/**< Session is terminated. */
414 PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE3, "Disconnected");
415 PopUp_Hide(POPUP_CALL);
416 break;
417 }
418}
419
420void CPocketPJDlg::on_call_state(pjsua_call_id call_id, pjsip_event *e)
421{
422 theDlg->OnCallState();
423}
424
425void CPocketPJDlg::on_call_media_state(pjsua_call_id call_id)
426{
427 pjsua_call_info call_info;
428
429 pjsua_call_get_info(call_id, &call_info);
430 if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
431 pjsua_conf_connect(call_info.conf_slot, 0);
432 pjsua_conf_connect(0, call_info.conf_slot);
433 }
434}
435
436void CPocketPJDlg::on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
437 pjsip_rx_data *rdata)
438{
439}
440
441void CPocketPJDlg::OnRegState()
442{
443 pjsua_acc_info ai;
444 pjsua_acc_get_info(m_PjsuaAccId, &ai);
445
446 CString acc_text = m_Cfg.m_User + _T("@") + m_Cfg.m_Domain;
447
448 if (ai.expires>0 && ai.status/100==2) {
449 /* Registration success */
450 HBITMAP old = m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ONLINE)) );
451 acc_text += " (OK)";
452 m_AccId.SetWindowText(acc_text);
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000453 } else if (ai.status/100 != 2) {
454 acc_text += " (err)";
455 Error(_T("SIP registration error"), PJSIP_ERRNO_FROM_SIP_STATUS(ai.status));
456 m_AccId.SetWindowText(acc_text);
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000457 }
Benny Prijono5796dca2008-02-23 00:24:44 +0000458 PopUp_Hide(POPUP_REGISTRATION);
Benny Prijono5d9c16f2008-02-22 23:38:47 +0000459}
460
461void CPocketPJDlg::on_reg_state(pjsua_acc_id acc_id)
462{
463 theDlg->OnRegState();
464}
465
466void CPocketPJDlg::on_buddy_state(pjsua_buddy_id buddy_id)
467{
468 theDlg->RedrawBuddyList();
469}
470
471void CPocketPJDlg::on_pager(pjsua_call_id call_id, const pj_str_t *from,
472 const pj_str_t *to, const pj_str_t *contact,
473 const pj_str_t *mime_type, const pj_str_t *text)
474{
475}
476
477/////////////////////////////////////////////////////////////////////////////
478// CPocketPJDlg message handlers
479
480BOOL CPocketPJDlg::OnInitDialog()
481{
482 CDialog::OnInitDialog();
483
484 // Set the icon for this dialog. The framework does this automatically
485 // when the application's main window is not a dialog
486 SetIcon(m_hIcon, TRUE); // Set big icon
487 SetIcon(m_hIcon, FALSE); // Set small icon
488
489 CenterWindow(GetDesktopWindow()); // center to the hpc screen
490
491 // TODO: Add extra initialization here
492
493 m_Cfg.LoadRegistry();
494 //ShowWindow(SW_SHOW);
495 m_AccId.SetWindowText(m_Cfg.m_User);
496
497 CImageList *il = new CImageList;
498 VERIFY(il->Create(16, 16, ILC_COLOR|ILC_MASK, 2, 4));
499
500 CBitmap *bmp = new CBitmap;
501 bmp->LoadBitmap(MAKEINTRESOURCE(IDB_BLANK));
502 il->Add(bmp, RGB(255,255,255));
503 bmp = new CBitmap;
504 bmp->LoadBitmap(MAKEINTRESOURCE(IDB_ONLINE));
505 il->Add(bmp, RGB(255,255,255));
506
507 m_BuddyList.SetImageList(il, LVSIL_SMALL);
508
509 if (m_Cfg.m_Domain.GetLength()==0 || Restart() == FALSE) {
510 for (;;) {
511 CSettingsDlg dlg(m_Cfg);
512 if (dlg.DoModal() != IDOK) {
513 EndDialog(IDOK);
514 return TRUE;
515 }
516
517 m_Cfg.SaveRegistry();
518
519 if (Restart())
520 break;
521 }
522 }
523
524 RedrawBuddyList();
525 return TRUE; // return TRUE unless you set the focus to a control
526}
527
528
529
530void CPocketPJDlg::OnBtnAcc()
531{
532 CMenu menu;
533 VERIFY(menu.LoadMenu(IDR_ACC_MENU));
534 CMenu* pPopup = menu.GetSubMenu(0);
535 ASSERT(pPopup != NULL);
536
537 RECT r;
538 m_BtnAcc.GetWindowRect(&r);
539 pPopup->TrackPopupMenu(TPM_LEFTALIGN, r.left+4, r.top+4, this);
540}
541
542void CPocketPJDlg::OnBtnAction()
543{
544 CMenu menu;
545 VERIFY(menu.LoadMenu(IDR_URI_MENU));
546 CMenu* pPopup = menu.GetSubMenu(0);
547 ASSERT(pPopup != NULL);
548
549 RECT r;
550 this->m_BtnUrlAction.GetWindowRect(&r);
551 pPopup->TrackPopupMenu(TPM_LEFTALIGN, r.left+4, r.top+4, this);
552}
553
554void CPocketPJDlg::OnSettings()
555{
556 for (;;) {
557 CSettingsDlg dlg(m_Cfg);
558 if (dlg.DoModal() != IDOK) {
559 return;
560 }
561
562 m_Cfg.SaveRegistry();
563
564 if (Restart())
565 break;
566 }
567}
568
569void CPocketPJDlg::OnOK()
570{
571 if (AfxMessageBox(_T("Quit PocketPJ?"), MB_YESNO)==IDYES) {
572 KillTimer(TIMER_ID);
573 PopUp_Show(POPUP_REGISTRATION, "", "Shutting down..", "", "", "", 0);
574 pjsua_destroy();
575 CDialog::OnOK();
576 PopUp_Hide(POPUP_REGISTRATION);
577 m_Cfg.SaveRegistry();
578 return;
579 }
580}
581
582void CPocketPJDlg::OnTimer(UINT nIDEvent)
583{
584 pjsua_handle_events(10);
585 CDialog::OnTimer(nIDEvent);
586}
587
588int CPocketPJDlg::FindBuddyInPjsua(const CString &Uri)
589{
590 char uri[80];
591 pjsua_buddy_id id[128];
592 unsigned i, count = PJ_ARRAY_SIZE(id);
593
594 if (pjsua_enum_buddies(id, &count) != PJ_SUCCESS)
595 return PJSUA_INVALID_ID;
596 if (count==0)
597 return PJSUA_INVALID_ID;
598
599 pj_unicode_to_ansi((LPCTSTR)Uri, Uri.GetLength(), uri, sizeof(uri));
600
601 for (i=0; i<count; ++i) {
602 pjsua_buddy_info bi;
603 pjsua_buddy_get_info(id[i], &bi);
604 if (pj_strcmp2(&bi.uri, uri)==0)
605 return i;
606 }
607
608 return PJSUA_INVALID_ID;
609}
610
611int CPocketPJDlg::FindBuddyInCfg(const CString &uri)
612{
613 int i;
614 for (i=0; i<m_Cfg.m_BuddyList.GetSize(); ++i) {
615 if (m_Cfg.m_BuddyList.GetAt(0) == uri) {
616 return i;
617 }
618 }
619 return -1;
620}
621
622void CPocketPJDlg::RedrawBuddyList()
623{
624 int i;
625
626 m_BuddyList.DeleteAllItems();
627
628 for (i=0; i<m_Cfg.m_BuddyList.GetSize(); ++i) {
629 int isOnline;
630 int id;
631
632 id = FindBuddyInPjsua(m_Cfg.m_BuddyList.GetAt(i));
633 if (id != PJSUA_INVALID_ID) {
634 pjsua_buddy_info bi;
635 pjsua_buddy_get_info(id, &bi);
636 isOnline = (bi.status == PJSUA_BUDDY_STATUS_ONLINE);
637 } else {
638 isOnline = 0;
639 }
640
641 LVITEM lvi;
642 memset(&lvi, 0, sizeof(lvi));
643 lvi.mask = LVIF_TEXT | LVIF_IMAGE;
644 lvi.iItem = i;
645 lvi.iImage = isOnline;
646 lvi.pszText = (LPTSTR)(LPCTSTR)m_Cfg.m_BuddyList.GetAt(i);
647
648 m_BuddyList.InsertItem(&lvi);
649 }
650}
651
652void CPocketPJDlg::OnUriCall()
653{
654 char tmp[120];
655 CString uri;
656 pj_status_t status;
657
658 m_Url.GetWindowText(uri);
659 pj_unicode_to_ansi((LPCTSTR)uri, uri.GetLength(), tmp, sizeof(tmp));
660 if ((status=pjsua_verify_sip_url(tmp)) != PJ_SUCCESS) {
661 Error("The URL is not valid SIP URL", status);
662 return;
663 }
664
665 pj_str_t dest_uri = pj_str(tmp);
666 pjsua_call_id call_id;
667
668 status = pjsua_call_make_call(m_PjsuaAccId, &dest_uri, 0, NULL, NULL, &call_id);
669
670 if (status != PJ_SUCCESS)
671 Error("Unable to make call", status);
672}
673
674void CPocketPJDlg::OnUriAddBuddy()
675{
676 int i;
677 char tmp[120];
678 CString uri;
679 pj_status_t status;
680
681 m_Url.GetWindowText(uri);
682 pj_unicode_to_ansi((LPCTSTR)uri, uri.GetLength(), tmp, sizeof(tmp));
683 if ((status=pjsua_verify_sip_url(tmp)) != PJ_SUCCESS) {
684 Error("The URL is not valid SIP URL", status);
685 return;
686 }
687
688 for (i=0; i<m_Cfg.m_BuddyList.GetSize(); ++i) {
689 if (m_Cfg.m_BuddyList.GetAt(0) == uri) {
690 AfxMessageBox(_T("The URI is already in the buddy list"));
691 return;
692 }
693 }
694
695 m_Cfg.m_BuddyList.Add(uri);
696 RedrawBuddyList();
697}
698
699void CPocketPJDlg::OnUriDelBuddy()
700{
701 CString uri;
702
703 m_Url.GetWindowText(uri);
704 int i = FindBuddyInCfg(uri);
705 if (i<0) {
706 /* Buddy not found */
707 return;
708 }
709
710 m_Cfg.m_BuddyList.RemoveAt(i);
711 RedrawBuddyList();
712 AfxMessageBox(_T("Buddy " + uri + " deleted"));
713}
714
715void CPocketPJDlg::OnAccOnline()
716{
717 pjsua_acc_set_online_status(m_PjsuaAccId, PJ_TRUE);
718 m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_ONLINE)) );
719}
720
721void CPocketPJDlg::OnAccInvisible()
722{
723 pjsua_acc_set_online_status(m_PjsuaAccId, PJ_FALSE);
724 m_BtnAcc.SetBitmap(::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_INVISIBLE)) );
725}
726
727void CPocketPJDlg::OnPopUpButton(int btnNo)
728{
729 if (btnNo == 1) {
730 pjsua_call_answer(0, 200, NULL, 0);
731 PopUp_Modify(POPUP_CALL, POPUP_EL_BUTTON1, "");
732 } else if (btnNo == 2) {
733 // Hangup button
734 PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE2, "Hang up..");
735 PopUp_Modify(POPUP_CALL, POPUP_EL_TITLE3, "");
736 pjsua_call_hangup(0, PJSIP_SC_DECLINE, 0, 0);
737 }
738}
739
740void CPocketPJDlg::OnClickBuddyList(NMHDR* pNMHDR, LRESULT* pResult)
741{
742 POSITION pos = m_BuddyList.GetFirstSelectedItemPosition();
743 if (pos != NULL) {
744 int iItem = m_BuddyList.GetNextSelectedItem(pos);
745 CString uri = m_BuddyList.GetItemText(iItem, 0);
746 m_Url.SetWindowText(uri);
747 }
748 *pResult = 0;
749}