blob: e98d0b32cbc2d09274e94296cc8a74ce8cc242c9 [file] [log] [blame]
Benny Prijono01f01542006-08-01 23:09:35 +00001// pjsua_wince.cpp : Defines the entry point for the application.
2//
3
4#include "stdafx.h"
5#include "pjsua_wince.h"
6#include <commctrl.h>
7#include <pjsua-lib/pjsua.h>
8
9#define MAX_LOADSTRING 100
10
11// Global Variables:
12static HINSTANCE hInst;
13static HWND hMainWnd;
14static HWND hwndCB;
Benny Prijonof20687a2006-08-04 18:27:19 +000015static HWND hwndGlobalStatus, hwndURI, hwndCallStatus;
16static HWND hwndActionButton, hwndExitButton;
Benny Prijono01f01542006-08-01 23:09:35 +000017
Benny Prijono8a744452007-05-10 20:40:57 +000018
19
20//
21// Basic config.
22//
23#define SIP_PORT 5060
24
25
26//
27// Destination URI (to make call, or to subscribe presence)
28//
29#define SIP_DST_URI "sip:192.168.0.7:5061"
30
31//
32// Account
33//
34#define HAS_SIP_ACCOUNT 0 // 0 to disable registration
35#define SIP_DOMAIN "server"
36#define SIP_REALM "server"
37#define SIP_USER "user"
38#define SIP_PASSWD "secret"
39
40//
41// Outbound proxy for all accounts
42//
43#define SIP_PROXY NULL
44//#define SIP_PROXY "sip:192.168.0.2;lr"
45
46
47//
48// Configure nameserver if DNS SRV is to be used with both SIP
49// or STUN (for STUN see other settings below)
50//
51#define NAMESERVER NULL
52//#define NAMESERVER "62.241.163.201"
53
54//
55// STUN server
Nanang Izzuddinae0e64b2009-04-21 14:08:49 +000056#if 0
Benny Prijono8a744452007-05-10 20:40:57 +000057 // Use this to have the STUN server resolved normally
58# define STUN_DOMAIN NULL
Benny Prijonof4e03a72007-10-12 23:29:27 +000059# define STUN_SERVER "stun.fwdnet.net"
Benny Prijono8a744452007-05-10 20:40:57 +000060#elif 0
61 // Use this to have the STUN server resolved with DNS SRV
62# define STUN_DOMAIN "iptel.org"
63# define STUN_SERVER NULL
64#else
65 // Use this to disable STUN
66# define STUN_DOMAIN NULL
67# define STUN_SERVER NULL
68#endif
69
70//
71// Use ICE?
72//
Nanang Izzuddinae0e64b2009-04-21 14:08:49 +000073#define USE_ICE 0
Benny Prijono8a744452007-05-10 20:40:57 +000074
75
76//
77// Globals
78//
Benny Prijono01f01542006-08-01 23:09:35 +000079static pj_pool_t *g_pool;
80static pj_str_t g_local_uri;
81static int g_current_acc;
82static int g_current_call = PJSUA_INVALID_ID;
Benny Prijonof20687a2006-08-04 18:27:19 +000083static int g_current_action;
Benny Prijono01f01542006-08-01 23:09:35 +000084
85enum
86{
87 ID_GLOBAL_STATUS = 21,
88 ID_URI,
89 ID_CALL_STATUS,
90 ID_POLL_TIMER,
91};
92
93enum
94{
95 ID_MENU_NONE = 64,
96 ID_MENU_CALL,
97 ID_MENU_ANSWER,
98 ID_MENU_DISCONNECT,
Benny Prijonof20687a2006-08-04 18:27:19 +000099 ID_BTN_ACTION,
Benny Prijono01f01542006-08-01 23:09:35 +0000100};
101
102
103// Forward declarations of functions included in this code module:
104static ATOM MyRegisterClass (HINSTANCE, LPTSTR);
105BOOL InitInstance (HINSTANCE, int);
106static void OnCreate (HWND hWnd);
107static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
108
109
110
111/////////////////////////////////////////////////////////////////////////////
112
113static void OnError(const wchar_t *title, pj_status_t status)
114{
115 char errmsg[PJ_ERR_MSG_SIZE];
116 PJ_DECL_UNICODE_TEMP_BUF(werrmsg, PJ_ERR_MSG_SIZE);
117
118 pj_strerror(status, errmsg, sizeof(errmsg));
119
120 MessageBox(NULL, PJ_STRING_TO_NATIVE(errmsg, werrmsg, PJ_ERR_MSG_SIZE),
121 title, MB_OK);
122}
123
124
125static void SetLocalURI(const char *uri, int len, bool enabled=true)
126{
127 wchar_t tmp[128];
Benny Prijonof20687a2006-08-04 18:27:19 +0000128 if (len==-1) len=pj_ansi_strlen(uri);
Benny Prijono01f01542006-08-01 23:09:35 +0000129 pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp));
130 SetDlgItemText(hMainWnd, ID_GLOBAL_STATUS, tmp);
131 EnableWindow(hwndGlobalStatus, enabled?TRUE:FALSE);
132}
133
134
135
136static void SetURI(const char *uri, int len, bool enabled=true)
137{
138 wchar_t tmp[128];
Benny Prijonof20687a2006-08-04 18:27:19 +0000139 if (len==-1) len=pj_ansi_strlen(uri);
Benny Prijono01f01542006-08-01 23:09:35 +0000140 pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp));
141 SetDlgItemText(hMainWnd, ID_URI, tmp);
142 EnableWindow(hwndURI, enabled?TRUE:FALSE);
143}
144
145
146static void SetCallStatus(const char *state, int len)
147{
148 wchar_t tmp[128];
Benny Prijonof20687a2006-08-04 18:27:19 +0000149 if (len==-1) len=pj_ansi_strlen(state);
Benny Prijono01f01542006-08-01 23:09:35 +0000150 pj_ansi_to_unicode(state, len, tmp, PJ_ARRAY_SIZE(tmp));
151 SetDlgItemText(hMainWnd, ID_CALL_STATUS, tmp);
152}
153
154static void SetAction(int action, bool enable=true)
155{
156 HMENU hMenu;
157
158 hMenu = CommandBar_GetMenu(hwndCB, 0);
159
160 RemoveMenu(hMenu, ID_MENU_NONE, MF_BYCOMMAND);
161 RemoveMenu(hMenu, ID_MENU_CALL, MF_BYCOMMAND);
162 RemoveMenu(hMenu, ID_MENU_ANSWER, MF_BYCOMMAND);
163 RemoveMenu(hMenu, ID_MENU_DISCONNECT, MF_BYCOMMAND);
164
165 switch (action) {
166 case ID_MENU_NONE:
167 InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("None"));
Benny Prijonof20687a2006-08-04 18:27:19 +0000168 SetWindowText(hwndActionButton, TEXT("-"));
Benny Prijono01f01542006-08-01 23:09:35 +0000169 break;
170 case ID_MENU_CALL:
171 InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Call"));
Benny Prijonof20687a2006-08-04 18:27:19 +0000172 SetWindowText(hwndActionButton, TEXT("&Call"));
Benny Prijono01f01542006-08-01 23:09:35 +0000173 break;
174 case ID_MENU_ANSWER:
175 InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Answer"));
Benny Prijonof20687a2006-08-04 18:27:19 +0000176 SetWindowText(hwndActionButton, TEXT("&Answer"));
Benny Prijono01f01542006-08-01 23:09:35 +0000177 break;
178 case ID_MENU_DISCONNECT:
179 InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Hangup"));
Benny Prijonof20687a2006-08-04 18:27:19 +0000180 SetWindowText(hwndActionButton, TEXT("&Hangup"));
Benny Prijono01f01542006-08-01 23:09:35 +0000181 break;
182 }
183
184 EnableMenuItem(hMenu, action, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED));
Benny Prijonof20687a2006-08-04 18:27:19 +0000185 DrawMenuBar(hMainWnd);
186
187 g_current_action = action;
Benny Prijono01f01542006-08-01 23:09:35 +0000188}
189
190
191/*
192 * Handler when invite state has changed.
193 */
194static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
195{
196 pjsua_call_info call_info;
197
198 PJ_UNUSED_ARG(e);
199
200 pjsua_call_get_info(call_id, &call_info);
201
202 if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) {
203
204 g_current_call = PJSUA_INVALID_ID;
Benny Prijono8a744452007-05-10 20:40:57 +0000205 SetURI(SIP_DST_URI, -1);
Benny Prijono01f01542006-08-01 23:09:35 +0000206 SetAction(ID_MENU_CALL);
Benny Prijonof20687a2006-08-04 18:27:19 +0000207 //SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen);
208 SetCallStatus(call_info.last_status_text.ptr, call_info.last_status_text.slen);
Benny Prijono01f01542006-08-01 23:09:35 +0000209
210 } else {
Benny Prijonoedba0792006-08-06 18:23:56 +0000211 //if (g_current_call == PJSUA_INVALID_ID)
212 // g_current_call = call_id;
Benny Prijono01f01542006-08-01 23:09:35 +0000213
214 if (call_info.remote_contact.slen)
215 SetURI(call_info.remote_contact.ptr, call_info.remote_contact.slen, false);
216 else
217 SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false);
Benny Prijonoedba0792006-08-06 18:23:56 +0000218
219 if (call_info.state == PJSIP_INV_STATE_CONFIRMED)
220 SetAction(ID_MENU_DISCONNECT);
221
Benny Prijono01f01542006-08-01 23:09:35 +0000222 SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen);
223 }
224}
225
226
227/*
228 * Callback on media state changed event.
229 * The action may connect the call to sound device, to file, or
230 * to loop the call.
231 */
232static void on_call_media_state(pjsua_call_id call_id)
233{
234 pjsua_call_info call_info;
235
236 pjsua_call_get_info(call_id, &call_info);
237
238 if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
239 pjsua_conf_connect(call_info.conf_slot, 0);
240 pjsua_conf_connect(0, call_info.conf_slot);
241 }
242}
243
244
245/**
246 * Handler when there is incoming call.
247 */
248static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
249 pjsip_rx_data *rdata)
250{
251 pjsua_call_info call_info;
252
253 PJ_UNUSED_ARG(acc_id);
254 PJ_UNUSED_ARG(rdata);
255
256 if (g_current_call != PJSUA_INVALID_ID) {
Benny Prijonoedba0792006-08-06 18:23:56 +0000257 pj_str_t reason;
258 reason = pj_str("Another call is in progress");
259 pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, &reason, NULL);
Benny Prijono01f01542006-08-01 23:09:35 +0000260 return;
261 }
262
263 g_current_call = call_id;
264
265 pjsua_call_get_info(call_id, &call_info);
266
267 SetAction(ID_MENU_ANSWER);
268 SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false);
Benny Prijonofd27c662006-08-09 11:59:26 +0000269 pjsua_call_answer(call_id, 200, NULL, NULL);
Benny Prijono01f01542006-08-01 23:09:35 +0000270}
271
272
273/*
274 * Handler registration status has changed.
275 */
276static void on_reg_state(pjsua_acc_id acc_id)
277{
278 PJ_UNUSED_ARG(acc_id);
279
280 // Log already written.
281}
282
283
284/*
285 * Handler on buddy state changed.
286 */
287static void on_buddy_state(pjsua_buddy_id buddy_id)
288{
289}
290
291
292/**
293 * Incoming IM message (i.e. MESSAGE request)!
294 */
295static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
296 const pj_str_t *to, const pj_str_t *contact,
297 const pj_str_t *mime_type, const pj_str_t *text)
298{
299}
300
301
302/**
303 * Received typing indication
304 */
305static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
306 const pj_str_t *to, const pj_str_t *contact,
307 pj_bool_t is_typing)
308{
309}
310
311
Benny Prijono01f01542006-08-01 23:09:35 +0000312static BOOL OnInitStack(void)
313{
314 pjsua_config cfg;
315 pjsua_logging_config log_cfg;
316 pjsua_media_config media_cfg;
317 pjsua_transport_config udp_cfg;
318 pjsua_transport_config rtp_cfg;
319 pjsua_transport_id transport_id;
320 pjsua_transport_info transport_info;
Benny Prijono7c3741f2006-08-05 21:07:15 +0000321 pj_str_t tmp;
Benny Prijono01f01542006-08-01 23:09:35 +0000322 pj_status_t status;
323
324 /* Create pjsua */
325 status = pjsua_create();
326 if (status != PJ_SUCCESS) {
327 OnError(TEXT("Error creating pjsua"), status);
328 return FALSE;
329 }
330
331 /* Create global pool for application */
332 g_pool = pjsua_pool_create("pjsua", 4000, 4000);
333
334 /* Init configs */
335 pjsua_config_default(&cfg);
Benny Prijono01f01542006-08-01 23:09:35 +0000336 pjsua_media_config_default(&media_cfg);
337 pjsua_transport_config_default(&udp_cfg);
Benny Prijono8a744452007-05-10 20:40:57 +0000338 udp_cfg.port = SIP_PORT;
339
Benny Prijono01f01542006-08-01 23:09:35 +0000340 pjsua_transport_config_default(&rtp_cfg);
Benny Prijonof20687a2006-08-04 18:27:19 +0000341 rtp_cfg.port = 40000;
Benny Prijono01f01542006-08-01 23:09:35 +0000342
Benny Prijono4e05b472006-10-16 15:52:31 +0000343 pjsua_logging_config_default(&log_cfg);
344 log_cfg.level = 5;
345 log_cfg.log_filename = pj_str("\\pjsua.txt");
346 log_cfg.msg_logging = 1;
347 log_cfg.decor = pj_log_get_decor() | PJ_LOG_HAS_CR;
348
Benny Prijono01f01542006-08-01 23:09:35 +0000349 /* Setup media */
350 media_cfg.clock_rate = 8000;
Benny Prijono5da50432006-08-07 10:24:52 +0000351 media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE;
Benny Prijonofd27c662006-08-09 11:59:26 +0000352 media_cfg.ec_tail_len = 256;
Benny Prijonoedba0792006-08-06 18:23:56 +0000353 media_cfg.quality = 1;
354 media_cfg.ptime = 20;
Benny Prijono8a744452007-05-10 20:40:57 +0000355 media_cfg.enable_ice = USE_ICE;
Benny Prijono01f01542006-08-01 23:09:35 +0000356
357 /* Initialize application callbacks */
358 cfg.cb.on_call_state = &on_call_state;
359 cfg.cb.on_call_media_state = &on_call_media_state;
360 cfg.cb.on_incoming_call = &on_incoming_call;
361 cfg.cb.on_reg_state = &on_reg_state;
362 cfg.cb.on_buddy_state = &on_buddy_state;
363 cfg.cb.on_pager = &on_pager;
364 cfg.cb.on_typing = &on_typing;
365
Benny Prijono8a744452007-05-10 20:40:57 +0000366 if (SIP_PROXY) {
367 cfg.outbound_proxy_cnt = 1;
368 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
369 }
370
371 if (NAMESERVER) {
372 cfg.nameserver_count = 1;
373 cfg.nameserver[0] = pj_str(NAMESERVER);
374 }
375
376 if (NAMESERVER && STUN_DOMAIN) {
377 cfg.stun_domain = pj_str(STUN_DOMAIN);
378 } else if (STUN_SERVER) {
379 cfg.stun_host = pj_str(STUN_SERVER);
380 }
381
382
Benny Prijono01f01542006-08-01 23:09:35 +0000383 /* Initialize pjsua */
384 status = pjsua_init(&cfg, &log_cfg, &media_cfg);
385 if (status != PJ_SUCCESS) {
386 OnError(TEXT("Initialization error"), status);
387 return FALSE;
388 }
389
390 /* Set codec priority */
Benny Prijonoedba0792006-08-06 18:23:56 +0000391 pjsua_codec_set_priority(pj_cstr(&tmp, "pcmu"), 240);
392 pjsua_codec_set_priority(pj_cstr(&tmp, "pcma"), 230);
393 pjsua_codec_set_priority(pj_cstr(&tmp, "speex/8000"), 190);
Benny Prijonofd27c662006-08-09 11:59:26 +0000394 pjsua_codec_set_priority(pj_cstr(&tmp, "ilbc"), 189);
Benny Prijonoedba0792006-08-06 18:23:56 +0000395 pjsua_codec_set_priority(pj_cstr(&tmp, "speex/16000"), 180);
Benny Prijono7c3741f2006-08-05 21:07:15 +0000396 pjsua_codec_set_priority(pj_cstr(&tmp, "speex/32000"), 0);
Benny Prijonofd27c662006-08-09 11:59:26 +0000397 pjsua_codec_set_priority(pj_cstr(&tmp, "gsm"), 100);
Benny Prijono7c3741f2006-08-05 21:07:15 +0000398
Benny Prijono01f01542006-08-01 23:09:35 +0000399
400 /* Add UDP transport and the corresponding PJSUA account */
401 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
402 &udp_cfg, &transport_id);
403 if (status != PJ_SUCCESS) {
404 OnError(TEXT("Error starting SIP transport"), status);
405 return FALSE;
406 }
407
408 pjsua_transport_get_info(transport_id, &transport_info);
409
410 g_local_uri.ptr = (char*)pj_pool_alloc(g_pool, 128);
411 g_local_uri.slen = pj_ansi_sprintf(g_local_uri.ptr,
412 "<sip:%.*s:%d>",
413 (int)transport_info.local_name.host.slen,
414 transport_info.local_name.host.ptr,
415 transport_info.local_name.port);
416
417
418 /* Add local account */
419 pjsua_acc_add_local(transport_id, PJ_TRUE, &g_current_acc);
420 pjsua_acc_set_online_status(g_current_acc, PJ_TRUE);
421
Benny Prijono8a744452007-05-10 20:40:57 +0000422 /* Add account */
423 if (HAS_SIP_ACCOUNT) {
424 pjsua_acc_config cfg;
425
426 pjsua_acc_config_default(&cfg);
427 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
428 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
429 cfg.cred_count = 1;
430 cfg.cred_info[0].realm = pj_str(SIP_REALM);
431 cfg.cred_info[0].scheme = pj_str("digest");
432 cfg.cred_info[0].username = pj_str(SIP_USER);
433 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
434 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
435
436 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_current_acc);
437 if (status != PJ_SUCCESS) {
438 pjsua_destroy();
439 return PJ_FALSE;
440 }
441 }
442
443 /* Add buddy */
444 if (SIP_DST_URI) {
445 pjsua_buddy_config bcfg;
446
447 pjsua_buddy_config_default(&bcfg);
448 bcfg.uri = pj_str(SIP_DST_URI);
449 bcfg.subscribe = PJ_FALSE;
450
451 pjsua_buddy_add(&bcfg, NULL);
452 }
453
Benny Prijono01f01542006-08-01 23:09:35 +0000454 /* Start pjsua */
455 status = pjsua_start();
456 if (status != PJ_SUCCESS) {
457 OnError(TEXT("Error starting pjsua"), status);
458 return FALSE;
459 }
460
461 return TRUE;
462}
463
464
465//////////////////////////////////////////////////////////////////////////////
466
467int WINAPI WinMain(HINSTANCE hInstance,
468 HINSTANCE hPrevInstance,
469 LPTSTR lpCmdLine,
470 int nCmdShow)
471{
472 MSG msg;
473 HACCEL hAccelTable;
474
475
476
477 // Perform application initialization:
478 if (!InitInstance (hInstance, nCmdShow))
479 {
480 return FALSE;
481 }
482
483 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PJSUA_WINCE);
484
485
486 // Main message loop:
487 while (GetMessage(&msg, NULL, 0, 0))
488 {
489 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
490 {
491 TranslateMessage(&msg);
492 DispatchMessage(&msg);
493 }
494 }
495
496 return msg.wParam;
497}
498
499static ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
500{
501 WNDCLASS wc;
502
503 wc.style = CS_HREDRAW | CS_VREDRAW;
504 wc.lpfnWndProc = (WNDPROC) WndProc;
505 wc.cbClsExtra = 0;
506 wc.cbWndExtra = 0;
507 wc.hInstance = hInstance;
508 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PJSUA_WINCE));
509 wc.hCursor = 0;
510 wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
511 wc.lpszMenuName = 0;
512 wc.lpszClassName = szWindowClass;
513
514 return RegisterClass(&wc);
515}
516
517
Benny Prijono4ab9fbb2007-10-12 12:14:27 +0000518/* Callback upon NAT detection completion */
Benny Prijono3808af12007-10-18 01:40:44 +0000519static void nat_detect_cb(const pj_stun_nat_detect_result *res)
Benny Prijono4ab9fbb2007-10-12 12:14:27 +0000520{
Benny Prijono4ab9fbb2007-10-12 12:14:27 +0000521 if (res->status != PJ_SUCCESS) {
522 char msg[250];
523 pj_ansi_snprintf(msg, sizeof(msg), "NAT detection failed: %s",
524 res->status_text);
525 SetCallStatus(msg, pj_ansi_strlen(msg));
526 } else {
527 char msg[250];
528 pj_ansi_snprintf(msg, sizeof(msg), "NAT type is %s",
529 res->nat_type_name);
530 SetCallStatus(msg, pj_ansi_strlen(msg));
531 }
532}
533
Benny Prijono01f01542006-08-01 23:09:35 +0000534
535BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
536{
537 HWND hWnd;
538 TCHAR szTitle[MAX_LOADSTRING];
539 TCHAR szWindowClass[MAX_LOADSTRING];
540
541 hInst = hInstance;
542
543 /* Init stack */
544 if (OnInitStack() == FALSE)
545 return FALSE;
546
547 LoadString(hInstance, IDC_PJSUA_WINCE, szWindowClass, MAX_LOADSTRING);
548 MyRegisterClass(hInstance, szWindowClass);
549
550 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
551 hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
Benny Prijonof20687a2006-08-04 18:27:19 +0000552 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 200,
Benny Prijono01f01542006-08-01 23:09:35 +0000553 NULL, NULL, hInstance, NULL);
554
555 if (!hWnd)
556 {
557 return FALSE;
558 }
559
560 hMainWnd = hWnd;
561 ShowWindow(hWnd, nCmdShow);
562 UpdateWindow(hWnd);
563 if (hwndCB)
564 CommandBar_Show(hwndCB, TRUE);
565
566 SetTimer(hMainWnd, ID_POLL_TIMER, 50, NULL);
Benny Prijono4ab9fbb2007-10-12 12:14:27 +0000567
Benny Prijono3808af12007-10-18 01:40:44 +0000568 pjsua_detect_nat_type();
Benny Prijono01f01542006-08-01 23:09:35 +0000569 return TRUE;
570}
571
572
573static void OnCreate(HWND hWnd)
574{
575 enum
576 {
577 X = 10,
Benny Prijonof20687a2006-08-04 18:27:19 +0000578 Y = 40,
Benny Prijono01f01542006-08-01 23:09:35 +0000579 W = 220,
580 H = 30,
581 };
582
583 DWORD dwStyle;
584
585 hMainWnd = hWnd;
586
587 hwndCB = CommandBar_Create(hInst, hWnd, 1);
588 CommandBar_InsertMenubar(hwndCB, hInst, IDM_MENU, 0);
589 CommandBar_AddAdornments(hwndCB, 0, 0);
590
591 // Create global status text
592 dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_LEFT;
593 hwndGlobalStatus = CreateWindow(
594 TEXT("EDIT"), // Class name
595 NULL, // Window text
596 dwStyle, // Window style
597 X, // x-coordinate of the upper-left corner
Benny Prijonof20687a2006-08-04 18:27:19 +0000598 Y+0, // y-coordinate of the upper-left corner
Benny Prijono01f01542006-08-01 23:09:35 +0000599 W, // Width of the window for the edit
600 // control
Benny Prijonof20687a2006-08-04 18:27:19 +0000601 H-5, // Height of the window for the edit
Benny Prijono01f01542006-08-01 23:09:35 +0000602 // control
603 hWnd, // Window handle to the parent window
604 (HMENU) ID_GLOBAL_STATUS, // Control identifier
605 hInst, // Instance handle
606 NULL); // Specify NULL for this parameter when
607 // you create a control
608 SetLocalURI(g_local_uri.ptr, g_local_uri.slen, false);
609
610
611 // Create URI edit
612 dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER;
613 hwndURI = CreateWindow (
614 TEXT("EDIT"), // Class name
615 NULL, // Window text
616 dwStyle, // Window style
617 X, // x-coordinate of the upper-left corner
Benny Prijonof20687a2006-08-04 18:27:19 +0000618 Y+H, // y-coordinate of the upper-left corner
Benny Prijono01f01542006-08-01 23:09:35 +0000619 W, // Width of the window for the edit
620 // control
Benny Prijonof20687a2006-08-04 18:27:19 +0000621 H-5, // Height of the window for the edit
Benny Prijono01f01542006-08-01 23:09:35 +0000622 // control
623 hWnd, // Window handle to the parent window
624 (HMENU) ID_URI, // Control identifier
625 hInst, // Instance handle
626 NULL); // Specify NULL for this parameter when
627 // you create a control
Benny Prijonof20687a2006-08-04 18:27:19 +0000628
629 // Create action Button
630 hwndActionButton = CreateWindow( L"button", L"Action",
631 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
632 X, Y+2*H,
633 60, H-5, hWnd,
634 (HMENU) ID_BTN_ACTION,
635 hInst, NULL );
636
637 // Create exit button
638 hwndExitButton = CreateWindow( L"button", L"E&xit",
639 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
640 X+70, Y+2*H,
641 60, H-5, hWnd,
642 (HMENU) ID_EXIT,
643 hInst, NULL );
644
Benny Prijono01f01542006-08-01 23:09:35 +0000645
646 // Create call status edit
647 dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED;
648 hwndCallStatus = CreateWindow (
649 TEXT("EDIT"), // Class name
650 NULL, // Window text
651 dwStyle, // Window style
652 X, // x-coordinate of the upper-left corner
Benny Prijonof20687a2006-08-04 18:27:19 +0000653 Y+3*H, // y-coordinate of the upper-left corner
Benny Prijono01f01542006-08-01 23:09:35 +0000654 W, // Width of the window for the edit
655 // control
Benny Prijonof20687a2006-08-04 18:27:19 +0000656 H-5, // Height of the window for the edit
Benny Prijono01f01542006-08-01 23:09:35 +0000657 // control
658 hWnd, // Window handle to the parent window
659 (HMENU) ID_CALL_STATUS, // Control identifier
660 hInst, // Instance handle
661 NULL); // Specify NULL for this parameter when
662 // you create a control
663 SetCallStatus("Ready", 5);
Benny Prijono01f01542006-08-01 23:09:35 +0000664 SetAction(ID_MENU_CALL);
Benny Prijono8a744452007-05-10 20:40:57 +0000665 SetURI(SIP_DST_URI, -1);
Benny Prijono39ea7f02006-09-14 13:52:29 +0000666 SetFocus(hWnd);
Benny Prijonof20687a2006-08-04 18:27:19 +0000667
Benny Prijono01f01542006-08-01 23:09:35 +0000668}
669
670
671static void OnDestroy(void)
672{
673 pjsua_destroy();
674}
675
676static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
677{
678 int wmId, wmEvent;
679
680 switch (message) {
Benny Prijono39ea7f02006-09-14 13:52:29 +0000681 case WM_KEYUP:
682 if (wParam==114) {
683 wParam = ID_MENU_CALL;
684 } else if (wParam==115) {
685 if (g_current_call == PJSUA_INVALID_ID)
686 wParam = ID_EXIT;
687 else
688 wParam = ID_MENU_DISCONNECT;
689 } else
690 break;
691
Benny Prijono01f01542006-08-01 23:09:35 +0000692 case WM_COMMAND:
693 wmId = LOWORD(wParam);
694 wmEvent = HIWORD(wParam);
Benny Prijonof20687a2006-08-04 18:27:19 +0000695 if (wmId == ID_BTN_ACTION)
696 wmId = g_current_action;
Benny Prijono01f01542006-08-01 23:09:35 +0000697 switch (wmId)
698 {
699 case ID_MENU_CALL:
700 if (g_current_call != PJSUA_INVALID_ID) {
701 MessageBox(NULL, TEXT("Can not make call"),
702 TEXT("You already have one call active"), MB_OK);
703 }
704 pj_str_t dst_uri;
705 wchar_t text[256];
706 char tmp[256];
707 pj_status_t status;
708
709 GetWindowText(hwndURI, text, PJ_ARRAY_SIZE(text));
710 pj_unicode_to_ansi(text, pj_unicode_strlen(text),
711 tmp, sizeof(tmp));
712 dst_uri.ptr = tmp;
713 dst_uri.slen = pj_ansi_strlen(tmp);
714 status = pjsua_call_make_call(g_current_acc,
715 &dst_uri, 0, NULL,
716 NULL, &g_current_call);
717 if (status != PJ_SUCCESS)
718 OnError(TEXT("Unable to make call"), status);
719 break;
720 case ID_MENU_ANSWER:
721 if (g_current_call == PJSUA_INVALID_ID)
722 MessageBox(NULL, TEXT("Can not answer"),
723 TEXT("There is no call!"), MB_OK);
Benny Prijonoedba0792006-08-06 18:23:56 +0000724 else
725 pjsua_call_answer(g_current_call, 200, NULL, NULL);
Benny Prijono01f01542006-08-01 23:09:35 +0000726 break;
727 case ID_MENU_DISCONNECT:
728 if (g_current_call == PJSUA_INVALID_ID)
729 MessageBox(NULL, TEXT("Can not disconnect"),
730 TEXT("There is no call!"), MB_OK);
731 else
732 pjsua_call_hangup(g_current_call, PJSIP_SC_DECLINE, NULL, NULL);
733 break;
734 case ID_EXIT:
735 DestroyWindow(hWnd);
736 break;
737 default:
738 return DefWindowProc(hWnd, message, wParam, lParam);
739 }
740 break;
741
742 case WM_CREATE:
743 OnCreate(hWnd);
744 break;
745
746 case WM_DESTROY:
747 OnDestroy();
748 CommandBar_Destroy(hwndCB);
749 PostQuitMessage(0);
750 break;
751
752 case WM_TIMER:
753 pjsua_handle_events(1);
754 break;
755
756 default:
757 return DefWindowProc(hWnd, message, wParam, lParam);
758 }
759 return 0;
760}
761