blob: a10c67f887e3396f998e694ce5b4f3322de127f2 [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{
Nanang Izzuddin2e4f03f2009-04-27 19:18:38 +0000289 /* Currently this is not processed */
290 PJ_UNUSED_ARG(buddy_id);
Benny Prijono01f01542006-08-01 23:09:35 +0000291}
292
293
294/**
295 * Incoming IM message (i.e. MESSAGE request)!
296 */
297static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
298 const pj_str_t *to, const pj_str_t *contact,
299 const pj_str_t *mime_type, const pj_str_t *text)
300{
Nanang Izzuddin2e4f03f2009-04-27 19:18:38 +0000301 /* Currently this is not processed */
302 PJ_UNUSED_ARG(call_id);
303 PJ_UNUSED_ARG(from);
304 PJ_UNUSED_ARG(to);
305 PJ_UNUSED_ARG(contact);
306 PJ_UNUSED_ARG(mime_type);
307 PJ_UNUSED_ARG(text);
Benny Prijono01f01542006-08-01 23:09:35 +0000308}
309
310
311/**
312 * Received typing indication
313 */
314static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
315 const pj_str_t *to, const pj_str_t *contact,
316 pj_bool_t is_typing)
317{
Nanang Izzuddin2e4f03f2009-04-27 19:18:38 +0000318 /* Currently this is not processed */
319 PJ_UNUSED_ARG(call_id);
320 PJ_UNUSED_ARG(from);
321 PJ_UNUSED_ARG(to);
322 PJ_UNUSED_ARG(contact);
323 PJ_UNUSED_ARG(is_typing);
324}
325
326/**
327 * Callback upon NAT detection completion
328 */
329static void nat_detect_cb(const pj_stun_nat_detect_result *res)
330{
331 if (res->status != PJ_SUCCESS) {
332 char msg[250];
333 pj_ansi_snprintf(msg, sizeof(msg), "NAT detection failed: %s",
334 res->status_text);
335 SetCallStatus(msg, pj_ansi_strlen(msg));
336 } else {
337 char msg[250];
338 pj_ansi_snprintf(msg, sizeof(msg), "NAT type is %s",
339 res->nat_type_name);
340 SetCallStatus(msg, pj_ansi_strlen(msg));
341 }
Benny Prijono01f01542006-08-01 23:09:35 +0000342}
343
344
Benny Prijono01f01542006-08-01 23:09:35 +0000345static BOOL OnInitStack(void)
346{
347 pjsua_config cfg;
348 pjsua_logging_config log_cfg;
349 pjsua_media_config media_cfg;
350 pjsua_transport_config udp_cfg;
351 pjsua_transport_config rtp_cfg;
352 pjsua_transport_id transport_id;
353 pjsua_transport_info transport_info;
Benny Prijono7c3741f2006-08-05 21:07:15 +0000354 pj_str_t tmp;
Benny Prijono01f01542006-08-01 23:09:35 +0000355 pj_status_t status;
356
357 /* Create pjsua */
358 status = pjsua_create();
359 if (status != PJ_SUCCESS) {
360 OnError(TEXT("Error creating pjsua"), status);
361 return FALSE;
362 }
363
364 /* Create global pool for application */
365 g_pool = pjsua_pool_create("pjsua", 4000, 4000);
366
367 /* Init configs */
368 pjsua_config_default(&cfg);
Benny Prijono01f01542006-08-01 23:09:35 +0000369 pjsua_media_config_default(&media_cfg);
370 pjsua_transport_config_default(&udp_cfg);
Benny Prijono8a744452007-05-10 20:40:57 +0000371 udp_cfg.port = SIP_PORT;
372
Benny Prijono01f01542006-08-01 23:09:35 +0000373 pjsua_transport_config_default(&rtp_cfg);
Benny Prijonof20687a2006-08-04 18:27:19 +0000374 rtp_cfg.port = 40000;
Benny Prijono01f01542006-08-01 23:09:35 +0000375
Benny Prijono4e05b472006-10-16 15:52:31 +0000376 pjsua_logging_config_default(&log_cfg);
377 log_cfg.level = 5;
378 log_cfg.log_filename = pj_str("\\pjsua.txt");
379 log_cfg.msg_logging = 1;
380 log_cfg.decor = pj_log_get_decor() | PJ_LOG_HAS_CR;
381
Benny Prijono01f01542006-08-01 23:09:35 +0000382 /* Setup media */
383 media_cfg.clock_rate = 8000;
Benny Prijono5da50432006-08-07 10:24:52 +0000384 media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE;
Benny Prijonofd27c662006-08-09 11:59:26 +0000385 media_cfg.ec_tail_len = 256;
Nanang Izzuddinc91cd642009-05-06 18:59:31 +0000386 // use default quality setting
387 //media_cfg.quality = 1;
Benny Prijonoedba0792006-08-06 18:23:56 +0000388 media_cfg.ptime = 20;
Benny Prijono8a744452007-05-10 20:40:57 +0000389 media_cfg.enable_ice = USE_ICE;
Benny Prijono01f01542006-08-01 23:09:35 +0000390
391 /* Initialize application callbacks */
392 cfg.cb.on_call_state = &on_call_state;
393 cfg.cb.on_call_media_state = &on_call_media_state;
394 cfg.cb.on_incoming_call = &on_incoming_call;
395 cfg.cb.on_reg_state = &on_reg_state;
396 cfg.cb.on_buddy_state = &on_buddy_state;
397 cfg.cb.on_pager = &on_pager;
398 cfg.cb.on_typing = &on_typing;
Nanang Izzuddin2e4f03f2009-04-27 19:18:38 +0000399 cfg.cb.on_nat_detect = &nat_detect_cb;
Benny Prijono01f01542006-08-01 23:09:35 +0000400
Benny Prijono8a744452007-05-10 20:40:57 +0000401 if (SIP_PROXY) {
402 cfg.outbound_proxy_cnt = 1;
403 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
404 }
405
406 if (NAMESERVER) {
407 cfg.nameserver_count = 1;
408 cfg.nameserver[0] = pj_str(NAMESERVER);
409 }
410
411 if (NAMESERVER && STUN_DOMAIN) {
412 cfg.stun_domain = pj_str(STUN_DOMAIN);
413 } else if (STUN_SERVER) {
414 cfg.stun_host = pj_str(STUN_SERVER);
415 }
416
417
Benny Prijono01f01542006-08-01 23:09:35 +0000418 /* Initialize pjsua */
419 status = pjsua_init(&cfg, &log_cfg, &media_cfg);
420 if (status != PJ_SUCCESS) {
421 OnError(TEXT("Initialization error"), status);
422 return FALSE;
423 }
424
425 /* Set codec priority */
Benny Prijonoedba0792006-08-06 18:23:56 +0000426 pjsua_codec_set_priority(pj_cstr(&tmp, "pcmu"), 240);
427 pjsua_codec_set_priority(pj_cstr(&tmp, "pcma"), 230);
428 pjsua_codec_set_priority(pj_cstr(&tmp, "speex/8000"), 190);
Benny Prijonofd27c662006-08-09 11:59:26 +0000429 pjsua_codec_set_priority(pj_cstr(&tmp, "ilbc"), 189);
Benny Prijonoedba0792006-08-06 18:23:56 +0000430 pjsua_codec_set_priority(pj_cstr(&tmp, "speex/16000"), 180);
Benny Prijono7c3741f2006-08-05 21:07:15 +0000431 pjsua_codec_set_priority(pj_cstr(&tmp, "speex/32000"), 0);
Benny Prijonofd27c662006-08-09 11:59:26 +0000432 pjsua_codec_set_priority(pj_cstr(&tmp, "gsm"), 100);
Benny Prijono7c3741f2006-08-05 21:07:15 +0000433
Benny Prijono01f01542006-08-01 23:09:35 +0000434
435 /* Add UDP transport and the corresponding PJSUA account */
436 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP,
437 &udp_cfg, &transport_id);
438 if (status != PJ_SUCCESS) {
439 OnError(TEXT("Error starting SIP transport"), status);
440 return FALSE;
441 }
442
443 pjsua_transport_get_info(transport_id, &transport_info);
444
445 g_local_uri.ptr = (char*)pj_pool_alloc(g_pool, 128);
446 g_local_uri.slen = pj_ansi_sprintf(g_local_uri.ptr,
447 "<sip:%.*s:%d>",
448 (int)transport_info.local_name.host.slen,
449 transport_info.local_name.host.ptr,
450 transport_info.local_name.port);
451
452
453 /* Add local account */
454 pjsua_acc_add_local(transport_id, PJ_TRUE, &g_current_acc);
455 pjsua_acc_set_online_status(g_current_acc, PJ_TRUE);
456
Benny Prijono8a744452007-05-10 20:40:57 +0000457 /* Add account */
458 if (HAS_SIP_ACCOUNT) {
459 pjsua_acc_config cfg;
460
461 pjsua_acc_config_default(&cfg);
462 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
463 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
464 cfg.cred_count = 1;
465 cfg.cred_info[0].realm = pj_str(SIP_REALM);
466 cfg.cred_info[0].scheme = pj_str("digest");
467 cfg.cred_info[0].username = pj_str(SIP_USER);
468 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
469 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
470
471 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_current_acc);
472 if (status != PJ_SUCCESS) {
473 pjsua_destroy();
474 return PJ_FALSE;
475 }
476 }
477
478 /* Add buddy */
479 if (SIP_DST_URI) {
480 pjsua_buddy_config bcfg;
481
482 pjsua_buddy_config_default(&bcfg);
483 bcfg.uri = pj_str(SIP_DST_URI);
484 bcfg.subscribe = PJ_FALSE;
485
486 pjsua_buddy_add(&bcfg, NULL);
487 }
488
Benny Prijono01f01542006-08-01 23:09:35 +0000489 /* Start pjsua */
490 status = pjsua_start();
491 if (status != PJ_SUCCESS) {
492 OnError(TEXT("Error starting pjsua"), status);
493 return FALSE;
494 }
495
496 return TRUE;
497}
498
499
500//////////////////////////////////////////////////////////////////////////////
501
502int WINAPI WinMain(HINSTANCE hInstance,
503 HINSTANCE hPrevInstance,
504 LPTSTR lpCmdLine,
505 int nCmdShow)
506{
507 MSG msg;
508 HACCEL hAccelTable;
Benny Prijono01f01542006-08-01 23:09:35 +0000509
Nanang Izzuddin2e4f03f2009-04-27 19:18:38 +0000510 PJ_UNUSED_ARG(lpCmdLine);
511 PJ_UNUSED_ARG(hPrevInstance);
Benny Prijono01f01542006-08-01 23:09:35 +0000512
513 // Perform application initialization:
514 if (!InitInstance (hInstance, nCmdShow))
515 {
516 return FALSE;
517 }
518
519 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PJSUA_WINCE);
520
521
522 // Main message loop:
523 while (GetMessage(&msg, NULL, 0, 0))
524 {
525 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
526 {
527 TranslateMessage(&msg);
528 DispatchMessage(&msg);
529 }
530 }
531
532 return msg.wParam;
533}
534
535static ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
536{
537 WNDCLASS wc;
538
539 wc.style = CS_HREDRAW | CS_VREDRAW;
540 wc.lpfnWndProc = (WNDPROC) WndProc;
541 wc.cbClsExtra = 0;
542 wc.cbWndExtra = 0;
543 wc.hInstance = hInstance;
544 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PJSUA_WINCE));
545 wc.hCursor = 0;
546 wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
547 wc.lpszMenuName = 0;
548 wc.lpszClassName = szWindowClass;
549
550 return RegisterClass(&wc);
551}
552
553
Benny Prijono01f01542006-08-01 23:09:35 +0000554BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
555{
556 HWND hWnd;
557 TCHAR szTitle[MAX_LOADSTRING];
558 TCHAR szWindowClass[MAX_LOADSTRING];
559
560 hInst = hInstance;
561
562 /* Init stack */
563 if (OnInitStack() == FALSE)
564 return FALSE;
565
566 LoadString(hInstance, IDC_PJSUA_WINCE, szWindowClass, MAX_LOADSTRING);
567 MyRegisterClass(hInstance, szWindowClass);
568
569 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
570 hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
Benny Prijonof20687a2006-08-04 18:27:19 +0000571 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 200,
Benny Prijono01f01542006-08-01 23:09:35 +0000572 NULL, NULL, hInstance, NULL);
573
574 if (!hWnd)
575 {
576 return FALSE;
577 }
578
579 hMainWnd = hWnd;
580 ShowWindow(hWnd, nCmdShow);
581 UpdateWindow(hWnd);
582 if (hwndCB)
583 CommandBar_Show(hwndCB, TRUE);
584
585 SetTimer(hMainWnd, ID_POLL_TIMER, 50, NULL);
Benny Prijono4ab9fbb2007-10-12 12:14:27 +0000586
Benny Prijono3808af12007-10-18 01:40:44 +0000587 pjsua_detect_nat_type();
Benny Prijono01f01542006-08-01 23:09:35 +0000588 return TRUE;
589}
590
591
592static void OnCreate(HWND hWnd)
593{
594 enum
595 {
596 X = 10,
Benny Prijonof20687a2006-08-04 18:27:19 +0000597 Y = 40,
Benny Prijono01f01542006-08-01 23:09:35 +0000598 W = 220,
599 H = 30,
600 };
601
602 DWORD dwStyle;
603
604 hMainWnd = hWnd;
605
606 hwndCB = CommandBar_Create(hInst, hWnd, 1);
607 CommandBar_InsertMenubar(hwndCB, hInst, IDM_MENU, 0);
608 CommandBar_AddAdornments(hwndCB, 0, 0);
609
610 // Create global status text
611 dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_LEFT;
612 hwndGlobalStatus = CreateWindow(
613 TEXT("EDIT"), // Class name
614 NULL, // Window text
615 dwStyle, // Window style
616 X, // x-coordinate of the upper-left corner
Benny Prijonof20687a2006-08-04 18:27:19 +0000617 Y+0, // y-coordinate of the upper-left corner
Benny Prijono01f01542006-08-01 23:09:35 +0000618 W, // Width of the window for the edit
619 // control
Benny Prijonof20687a2006-08-04 18:27:19 +0000620 H-5, // Height of the window for the edit
Benny Prijono01f01542006-08-01 23:09:35 +0000621 // control
622 hWnd, // Window handle to the parent window
623 (HMENU) ID_GLOBAL_STATUS, // Control identifier
624 hInst, // Instance handle
625 NULL); // Specify NULL for this parameter when
626 // you create a control
627 SetLocalURI(g_local_uri.ptr, g_local_uri.slen, false);
628
629
630 // Create URI edit
631 dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER;
632 hwndURI = CreateWindow (
633 TEXT("EDIT"), // Class name
634 NULL, // Window text
635 dwStyle, // Window style
636 X, // x-coordinate of the upper-left corner
Benny Prijonof20687a2006-08-04 18:27:19 +0000637 Y+H, // y-coordinate of the upper-left corner
Benny Prijono01f01542006-08-01 23:09:35 +0000638 W, // Width of the window for the edit
639 // control
Benny Prijonof20687a2006-08-04 18:27:19 +0000640 H-5, // Height of the window for the edit
Benny Prijono01f01542006-08-01 23:09:35 +0000641 // control
642 hWnd, // Window handle to the parent window
643 (HMENU) ID_URI, // Control identifier
644 hInst, // Instance handle
645 NULL); // Specify NULL for this parameter when
646 // you create a control
Benny Prijonof20687a2006-08-04 18:27:19 +0000647
648 // Create action Button
649 hwndActionButton = CreateWindow( L"button", L"Action",
650 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
651 X, Y+2*H,
652 60, H-5, hWnd,
653 (HMENU) ID_BTN_ACTION,
654 hInst, NULL );
655
656 // Create exit button
657 hwndExitButton = CreateWindow( L"button", L"E&xit",
658 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
659 X+70, Y+2*H,
660 60, H-5, hWnd,
661 (HMENU) ID_EXIT,
662 hInst, NULL );
663
Benny Prijono01f01542006-08-01 23:09:35 +0000664
665 // Create call status edit
666 dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED;
667 hwndCallStatus = CreateWindow (
668 TEXT("EDIT"), // Class name
669 NULL, // Window text
670 dwStyle, // Window style
671 X, // x-coordinate of the upper-left corner
Benny Prijonof20687a2006-08-04 18:27:19 +0000672 Y+3*H, // y-coordinate of the upper-left corner
Benny Prijono01f01542006-08-01 23:09:35 +0000673 W, // Width of the window for the edit
674 // control
Benny Prijonof20687a2006-08-04 18:27:19 +0000675 H-5, // Height of the window for the edit
Benny Prijono01f01542006-08-01 23:09:35 +0000676 // control
677 hWnd, // Window handle to the parent window
678 (HMENU) ID_CALL_STATUS, // Control identifier
679 hInst, // Instance handle
680 NULL); // Specify NULL for this parameter when
681 // you create a control
682 SetCallStatus("Ready", 5);
Benny Prijono01f01542006-08-01 23:09:35 +0000683 SetAction(ID_MENU_CALL);
Benny Prijono8a744452007-05-10 20:40:57 +0000684 SetURI(SIP_DST_URI, -1);
Benny Prijono39ea7f02006-09-14 13:52:29 +0000685 SetFocus(hWnd);
Benny Prijonof20687a2006-08-04 18:27:19 +0000686
Benny Prijono01f01542006-08-01 23:09:35 +0000687}
688
689
690static void OnDestroy(void)
691{
692 pjsua_destroy();
693}
694
695static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
696{
697 int wmId, wmEvent;
698
699 switch (message) {
Benny Prijono39ea7f02006-09-14 13:52:29 +0000700 case WM_KEYUP:
701 if (wParam==114) {
702 wParam = ID_MENU_CALL;
703 } else if (wParam==115) {
704 if (g_current_call == PJSUA_INVALID_ID)
705 wParam = ID_EXIT;
706 else
707 wParam = ID_MENU_DISCONNECT;
708 } else
709 break;
710
Benny Prijono01f01542006-08-01 23:09:35 +0000711 case WM_COMMAND:
712 wmId = LOWORD(wParam);
713 wmEvent = HIWORD(wParam);
Benny Prijonof20687a2006-08-04 18:27:19 +0000714 if (wmId == ID_BTN_ACTION)
715 wmId = g_current_action;
Benny Prijono01f01542006-08-01 23:09:35 +0000716 switch (wmId)
717 {
718 case ID_MENU_CALL:
719 if (g_current_call != PJSUA_INVALID_ID) {
720 MessageBox(NULL, TEXT("Can not make call"),
721 TEXT("You already have one call active"), MB_OK);
722 }
723 pj_str_t dst_uri;
724 wchar_t text[256];
725 char tmp[256];
726 pj_status_t status;
727
728 GetWindowText(hwndURI, text, PJ_ARRAY_SIZE(text));
729 pj_unicode_to_ansi(text, pj_unicode_strlen(text),
730 tmp, sizeof(tmp));
731 dst_uri.ptr = tmp;
732 dst_uri.slen = pj_ansi_strlen(tmp);
733 status = pjsua_call_make_call(g_current_acc,
734 &dst_uri, 0, NULL,
735 NULL, &g_current_call);
736 if (status != PJ_SUCCESS)
737 OnError(TEXT("Unable to make call"), status);
738 break;
739 case ID_MENU_ANSWER:
740 if (g_current_call == PJSUA_INVALID_ID)
741 MessageBox(NULL, TEXT("Can not answer"),
742 TEXT("There is no call!"), MB_OK);
Benny Prijonoedba0792006-08-06 18:23:56 +0000743 else
744 pjsua_call_answer(g_current_call, 200, NULL, NULL);
Benny Prijono01f01542006-08-01 23:09:35 +0000745 break;
746 case ID_MENU_DISCONNECT:
747 if (g_current_call == PJSUA_INVALID_ID)
748 MessageBox(NULL, TEXT("Can not disconnect"),
749 TEXT("There is no call!"), MB_OK);
750 else
751 pjsua_call_hangup(g_current_call, PJSIP_SC_DECLINE, NULL, NULL);
752 break;
753 case ID_EXIT:
754 DestroyWindow(hWnd);
755 break;
756 default:
757 return DefWindowProc(hWnd, message, wParam, lParam);
758 }
759 break;
760
761 case WM_CREATE:
762 OnCreate(hWnd);
763 break;
764
765 case WM_DESTROY:
766 OnDestroy();
767 CommandBar_Destroy(hwndCB);
768 PostQuitMessage(0);
769 break;
770
771 case WM_TIMER:
772 pjsua_handle_events(1);
773 break;
774
775 default:
776 return DefWindowProc(hWnd, message, wParam, lParam);
777 }
778 return 0;
779}
780