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