Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 1 | // 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: |
| 12 | static HINSTANCE hInst; |
| 13 | static HWND hMainWnd; |
| 14 | static HWND hwndCB; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 15 | static HWND hwndGlobalStatus, hwndURI, hwndCallStatus; |
| 16 | static HWND hwndActionButton, hwndExitButton; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 17 | |
| 18 | static pj_pool_t *g_pool; |
| 19 | static pj_str_t g_local_uri; |
| 20 | static int g_current_acc; |
| 21 | static int g_current_call = PJSUA_INVALID_ID; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 22 | static int g_current_action; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 23 | |
| 24 | enum |
| 25 | { |
| 26 | ID_GLOBAL_STATUS = 21, |
| 27 | ID_URI, |
| 28 | ID_CALL_STATUS, |
| 29 | ID_POLL_TIMER, |
| 30 | }; |
| 31 | |
| 32 | enum |
| 33 | { |
| 34 | ID_MENU_NONE = 64, |
| 35 | ID_MENU_CALL, |
| 36 | ID_MENU_ANSWER, |
| 37 | ID_MENU_DISCONNECT, |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 38 | ID_BTN_ACTION, |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 39 | }; |
| 40 | |
Benny Prijono | 5da5043 | 2006-08-07 10:24:52 +0000 | [diff] [blame^] | 41 | #define DEFAULT_URI "sip:192.168.0.7" |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 42 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 43 | |
| 44 | // Forward declarations of functions included in this code module: |
| 45 | static ATOM MyRegisterClass (HINSTANCE, LPTSTR); |
| 46 | BOOL InitInstance (HINSTANCE, int); |
| 47 | static void OnCreate (HWND hWnd); |
| 48 | static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); |
| 49 | |
| 50 | |
| 51 | |
| 52 | ///////////////////////////////////////////////////////////////////////////// |
| 53 | |
| 54 | static void OnError(const wchar_t *title, pj_status_t status) |
| 55 | { |
| 56 | char errmsg[PJ_ERR_MSG_SIZE]; |
| 57 | PJ_DECL_UNICODE_TEMP_BUF(werrmsg, PJ_ERR_MSG_SIZE); |
| 58 | |
| 59 | pj_strerror(status, errmsg, sizeof(errmsg)); |
| 60 | |
| 61 | MessageBox(NULL, PJ_STRING_TO_NATIVE(errmsg, werrmsg, PJ_ERR_MSG_SIZE), |
| 62 | title, MB_OK); |
| 63 | } |
| 64 | |
| 65 | |
| 66 | static void SetLocalURI(const char *uri, int len, bool enabled=true) |
| 67 | { |
| 68 | wchar_t tmp[128]; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 69 | if (len==-1) len=pj_ansi_strlen(uri); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 70 | pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp)); |
| 71 | SetDlgItemText(hMainWnd, ID_GLOBAL_STATUS, tmp); |
| 72 | EnableWindow(hwndGlobalStatus, enabled?TRUE:FALSE); |
| 73 | } |
| 74 | |
| 75 | |
| 76 | |
| 77 | static void SetURI(const char *uri, int len, bool enabled=true) |
| 78 | { |
| 79 | wchar_t tmp[128]; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 80 | if (len==-1) len=pj_ansi_strlen(uri); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 81 | pj_ansi_to_unicode(uri, len, tmp, PJ_ARRAY_SIZE(tmp)); |
| 82 | SetDlgItemText(hMainWnd, ID_URI, tmp); |
| 83 | EnableWindow(hwndURI, enabled?TRUE:FALSE); |
| 84 | } |
| 85 | |
| 86 | |
| 87 | static void SetCallStatus(const char *state, int len) |
| 88 | { |
| 89 | wchar_t tmp[128]; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 90 | if (len==-1) len=pj_ansi_strlen(state); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 91 | pj_ansi_to_unicode(state, len, tmp, PJ_ARRAY_SIZE(tmp)); |
| 92 | SetDlgItemText(hMainWnd, ID_CALL_STATUS, tmp); |
| 93 | } |
| 94 | |
| 95 | static void SetAction(int action, bool enable=true) |
| 96 | { |
| 97 | HMENU hMenu; |
| 98 | |
| 99 | hMenu = CommandBar_GetMenu(hwndCB, 0); |
| 100 | |
| 101 | RemoveMenu(hMenu, ID_MENU_NONE, MF_BYCOMMAND); |
| 102 | RemoveMenu(hMenu, ID_MENU_CALL, MF_BYCOMMAND); |
| 103 | RemoveMenu(hMenu, ID_MENU_ANSWER, MF_BYCOMMAND); |
| 104 | RemoveMenu(hMenu, ID_MENU_DISCONNECT, MF_BYCOMMAND); |
| 105 | |
| 106 | switch (action) { |
| 107 | case ID_MENU_NONE: |
| 108 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("None")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 109 | SetWindowText(hwndActionButton, TEXT("-")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 110 | break; |
| 111 | case ID_MENU_CALL: |
| 112 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Call")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 113 | SetWindowText(hwndActionButton, TEXT("&Call")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 114 | break; |
| 115 | case ID_MENU_ANSWER: |
| 116 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Answer")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 117 | SetWindowText(hwndActionButton, TEXT("&Answer")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 118 | break; |
| 119 | case ID_MENU_DISCONNECT: |
| 120 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Hangup")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 121 | SetWindowText(hwndActionButton, TEXT("&Hangup")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 122 | break; |
| 123 | } |
| 124 | |
| 125 | EnableMenuItem(hMenu, action, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED)); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 126 | DrawMenuBar(hMainWnd); |
| 127 | |
| 128 | g_current_action = action; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | |
| 132 | /* |
| 133 | * Handler when invite state has changed. |
| 134 | */ |
| 135 | static void on_call_state(pjsua_call_id call_id, pjsip_event *e) |
| 136 | { |
| 137 | pjsua_call_info call_info; |
| 138 | |
| 139 | PJ_UNUSED_ARG(e); |
| 140 | |
| 141 | pjsua_call_get_info(call_id, &call_info); |
| 142 | |
| 143 | if (call_info.state == PJSIP_INV_STATE_DISCONNECTED) { |
| 144 | |
| 145 | g_current_call = PJSUA_INVALID_ID; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 146 | SetURI(DEFAULT_URI, -1); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 147 | SetAction(ID_MENU_CALL); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 148 | //SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen); |
| 149 | SetCallStatus(call_info.last_status_text.ptr, call_info.last_status_text.slen); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 150 | |
| 151 | } else { |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 152 | //if (g_current_call == PJSUA_INVALID_ID) |
| 153 | // g_current_call = call_id; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 154 | |
| 155 | if (call_info.remote_contact.slen) |
| 156 | SetURI(call_info.remote_contact.ptr, call_info.remote_contact.slen, false); |
| 157 | else |
| 158 | SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false); |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 159 | |
| 160 | if (call_info.state == PJSIP_INV_STATE_CONFIRMED) |
| 161 | SetAction(ID_MENU_DISCONNECT); |
| 162 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 163 | SetCallStatus(call_info.state_text.ptr, call_info.state_text.slen); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | |
| 168 | /* |
| 169 | * Callback on media state changed event. |
| 170 | * The action may connect the call to sound device, to file, or |
| 171 | * to loop the call. |
| 172 | */ |
| 173 | static void on_call_media_state(pjsua_call_id call_id) |
| 174 | { |
| 175 | pjsua_call_info call_info; |
| 176 | |
| 177 | pjsua_call_get_info(call_id, &call_info); |
| 178 | |
| 179 | if (call_info.media_status == PJSUA_CALL_MEDIA_ACTIVE) { |
| 180 | pjsua_conf_connect(call_info.conf_slot, 0); |
| 181 | pjsua_conf_connect(0, call_info.conf_slot); |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | |
| 186 | /** |
| 187 | * Handler when there is incoming call. |
| 188 | */ |
| 189 | static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, |
| 190 | pjsip_rx_data *rdata) |
| 191 | { |
| 192 | pjsua_call_info call_info; |
| 193 | |
| 194 | PJ_UNUSED_ARG(acc_id); |
| 195 | PJ_UNUSED_ARG(rdata); |
| 196 | |
| 197 | if (g_current_call != PJSUA_INVALID_ID) { |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 198 | pj_str_t reason; |
| 199 | reason = pj_str("Another call is in progress"); |
| 200 | pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, &reason, NULL); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 201 | return; |
| 202 | } |
| 203 | |
| 204 | g_current_call = call_id; |
| 205 | |
| 206 | pjsua_call_get_info(call_id, &call_info); |
| 207 | |
| 208 | SetAction(ID_MENU_ANSWER); |
| 209 | SetURI(call_info.remote_info.ptr, call_info.remote_info.slen, false); |
| 210 | pjsua_call_answer(call_id, 180, NULL, NULL); |
| 211 | } |
| 212 | |
| 213 | |
| 214 | /* |
| 215 | * Handler registration status has changed. |
| 216 | */ |
| 217 | static void on_reg_state(pjsua_acc_id acc_id) |
| 218 | { |
| 219 | PJ_UNUSED_ARG(acc_id); |
| 220 | |
| 221 | // Log already written. |
| 222 | } |
| 223 | |
| 224 | |
| 225 | /* |
| 226 | * Handler on buddy state changed. |
| 227 | */ |
| 228 | static void on_buddy_state(pjsua_buddy_id buddy_id) |
| 229 | { |
| 230 | } |
| 231 | |
| 232 | |
| 233 | /** |
| 234 | * Incoming IM message (i.e. MESSAGE request)! |
| 235 | */ |
| 236 | static void on_pager(pjsua_call_id call_id, const pj_str_t *from, |
| 237 | const pj_str_t *to, const pj_str_t *contact, |
| 238 | const pj_str_t *mime_type, const pj_str_t *text) |
| 239 | { |
| 240 | } |
| 241 | |
| 242 | |
| 243 | /** |
| 244 | * Received typing indication |
| 245 | */ |
| 246 | static void on_typing(pjsua_call_id call_id, const pj_str_t *from, |
| 247 | const pj_str_t *to, const pj_str_t *contact, |
| 248 | pj_bool_t is_typing) |
| 249 | { |
| 250 | } |
| 251 | |
| 252 | |
| 253 | |
| 254 | static BOOL OnInitStack(void) |
| 255 | { |
| 256 | pjsua_config cfg; |
| 257 | pjsua_logging_config log_cfg; |
| 258 | pjsua_media_config media_cfg; |
| 259 | pjsua_transport_config udp_cfg; |
| 260 | pjsua_transport_config rtp_cfg; |
| 261 | pjsua_transport_id transport_id; |
| 262 | pjsua_transport_info transport_info; |
Benny Prijono | 7c3741f | 2006-08-05 21:07:15 +0000 | [diff] [blame] | 263 | pj_str_t tmp; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 264 | pj_status_t status; |
| 265 | |
| 266 | /* Create pjsua */ |
| 267 | status = pjsua_create(); |
| 268 | if (status != PJ_SUCCESS) { |
| 269 | OnError(TEXT("Error creating pjsua"), status); |
| 270 | return FALSE; |
| 271 | } |
| 272 | |
| 273 | /* Create global pool for application */ |
| 274 | g_pool = pjsua_pool_create("pjsua", 4000, 4000); |
| 275 | |
| 276 | /* Init configs */ |
| 277 | pjsua_config_default(&cfg); |
| 278 | pjsua_logging_config_default(&log_cfg); |
| 279 | pjsua_media_config_default(&media_cfg); |
| 280 | pjsua_transport_config_default(&udp_cfg); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 281 | udp_cfg.port = 50060; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 282 | pjsua_transport_config_default(&rtp_cfg); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 283 | rtp_cfg.port = 40000; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 284 | |
| 285 | /* Setup media */ |
| 286 | media_cfg.clock_rate = 8000; |
Benny Prijono | 5da5043 | 2006-08-07 10:24:52 +0000 | [diff] [blame^] | 287 | media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE; |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 288 | media_cfg.quality = 1; |
| 289 | media_cfg.ptime = 20; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 290 | |
| 291 | /* Initialize application callbacks */ |
| 292 | cfg.cb.on_call_state = &on_call_state; |
| 293 | cfg.cb.on_call_media_state = &on_call_media_state; |
| 294 | cfg.cb.on_incoming_call = &on_incoming_call; |
| 295 | cfg.cb.on_reg_state = &on_reg_state; |
| 296 | cfg.cb.on_buddy_state = &on_buddy_state; |
| 297 | cfg.cb.on_pager = &on_pager; |
| 298 | cfg.cb.on_typing = &on_typing; |
| 299 | |
| 300 | /* Initialize pjsua */ |
| 301 | status = pjsua_init(&cfg, &log_cfg, &media_cfg); |
| 302 | if (status != PJ_SUCCESS) { |
| 303 | OnError(TEXT("Initialization error"), status); |
| 304 | return FALSE; |
| 305 | } |
| 306 | |
| 307 | /* Set codec priority */ |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 308 | pjsua_codec_set_priority(pj_cstr(&tmp, "gsm"), 10); |
| 309 | pjsua_codec_set_priority(pj_cstr(&tmp, "pcmu"), 240); |
| 310 | pjsua_codec_set_priority(pj_cstr(&tmp, "pcma"), 230); |
| 311 | pjsua_codec_set_priority(pj_cstr(&tmp, "speex/8000"), 190); |
| 312 | pjsua_codec_set_priority(pj_cstr(&tmp, "speex/16000"), 180); |
Benny Prijono | 7c3741f | 2006-08-05 21:07:15 +0000 | [diff] [blame] | 313 | pjsua_codec_set_priority(pj_cstr(&tmp, "speex/32000"), 0); |
| 314 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 315 | |
| 316 | /* Add UDP transport and the corresponding PJSUA account */ |
| 317 | status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, |
| 318 | &udp_cfg, &transport_id); |
| 319 | if (status != PJ_SUCCESS) { |
| 320 | OnError(TEXT("Error starting SIP transport"), status); |
| 321 | return FALSE; |
| 322 | } |
| 323 | |
| 324 | pjsua_transport_get_info(transport_id, &transport_info); |
| 325 | |
| 326 | g_local_uri.ptr = (char*)pj_pool_alloc(g_pool, 128); |
| 327 | g_local_uri.slen = pj_ansi_sprintf(g_local_uri.ptr, |
| 328 | "<sip:%.*s:%d>", |
| 329 | (int)transport_info.local_name.host.slen, |
| 330 | transport_info.local_name.host.ptr, |
| 331 | transport_info.local_name.port); |
| 332 | |
| 333 | |
| 334 | /* Add local account */ |
| 335 | pjsua_acc_add_local(transport_id, PJ_TRUE, &g_current_acc); |
| 336 | pjsua_acc_set_online_status(g_current_acc, PJ_TRUE); |
| 337 | |
| 338 | /* Start pjsua */ |
| 339 | status = pjsua_start(); |
| 340 | if (status != PJ_SUCCESS) { |
| 341 | OnError(TEXT("Error starting pjsua"), status); |
| 342 | return FALSE; |
| 343 | } |
| 344 | |
| 345 | return TRUE; |
| 346 | } |
| 347 | |
| 348 | |
| 349 | ////////////////////////////////////////////////////////////////////////////// |
| 350 | |
| 351 | int WINAPI WinMain(HINSTANCE hInstance, |
| 352 | HINSTANCE hPrevInstance, |
| 353 | LPTSTR lpCmdLine, |
| 354 | int nCmdShow) |
| 355 | { |
| 356 | MSG msg; |
| 357 | HACCEL hAccelTable; |
| 358 | |
| 359 | |
| 360 | |
| 361 | // Perform application initialization: |
| 362 | if (!InitInstance (hInstance, nCmdShow)) |
| 363 | { |
| 364 | return FALSE; |
| 365 | } |
| 366 | |
| 367 | hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_PJSUA_WINCE); |
| 368 | |
| 369 | |
| 370 | // Main message loop: |
| 371 | while (GetMessage(&msg, NULL, 0, 0)) |
| 372 | { |
| 373 | if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) |
| 374 | { |
| 375 | TranslateMessage(&msg); |
| 376 | DispatchMessage(&msg); |
| 377 | } |
| 378 | } |
| 379 | |
| 380 | return msg.wParam; |
| 381 | } |
| 382 | |
| 383 | static ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) |
| 384 | { |
| 385 | WNDCLASS wc; |
| 386 | |
| 387 | wc.style = CS_HREDRAW | CS_VREDRAW; |
| 388 | wc.lpfnWndProc = (WNDPROC) WndProc; |
| 389 | wc.cbClsExtra = 0; |
| 390 | wc.cbWndExtra = 0; |
| 391 | wc.hInstance = hInstance; |
| 392 | wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PJSUA_WINCE)); |
| 393 | wc.hCursor = 0; |
| 394 | wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); |
| 395 | wc.lpszMenuName = 0; |
| 396 | wc.lpszClassName = szWindowClass; |
| 397 | |
| 398 | return RegisterClass(&wc); |
| 399 | } |
| 400 | |
| 401 | |
| 402 | |
| 403 | BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) |
| 404 | { |
| 405 | HWND hWnd; |
| 406 | TCHAR szTitle[MAX_LOADSTRING]; |
| 407 | TCHAR szWindowClass[MAX_LOADSTRING]; |
| 408 | |
| 409 | hInst = hInstance; |
| 410 | |
| 411 | /* Init stack */ |
| 412 | if (OnInitStack() == FALSE) |
| 413 | return FALSE; |
| 414 | |
| 415 | LoadString(hInstance, IDC_PJSUA_WINCE, szWindowClass, MAX_LOADSTRING); |
| 416 | MyRegisterClass(hInstance, szWindowClass); |
| 417 | |
| 418 | LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); |
| 419 | hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE, |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 420 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 200, |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 421 | NULL, NULL, hInstance, NULL); |
| 422 | |
| 423 | if (!hWnd) |
| 424 | { |
| 425 | return FALSE; |
| 426 | } |
| 427 | |
| 428 | hMainWnd = hWnd; |
| 429 | ShowWindow(hWnd, nCmdShow); |
| 430 | UpdateWindow(hWnd); |
| 431 | if (hwndCB) |
| 432 | CommandBar_Show(hwndCB, TRUE); |
| 433 | |
| 434 | SetTimer(hMainWnd, ID_POLL_TIMER, 50, NULL); |
| 435 | return TRUE; |
| 436 | } |
| 437 | |
| 438 | |
| 439 | static void OnCreate(HWND hWnd) |
| 440 | { |
| 441 | enum |
| 442 | { |
| 443 | X = 10, |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 444 | Y = 40, |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 445 | W = 220, |
| 446 | H = 30, |
| 447 | }; |
| 448 | |
| 449 | DWORD dwStyle; |
| 450 | |
| 451 | hMainWnd = hWnd; |
| 452 | |
| 453 | hwndCB = CommandBar_Create(hInst, hWnd, 1); |
| 454 | CommandBar_InsertMenubar(hwndCB, hInst, IDM_MENU, 0); |
| 455 | CommandBar_AddAdornments(hwndCB, 0, 0); |
| 456 | |
| 457 | // Create global status text |
| 458 | dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED | ES_LEFT; |
| 459 | hwndGlobalStatus = CreateWindow( |
| 460 | TEXT("EDIT"), // Class name |
| 461 | NULL, // Window text |
| 462 | dwStyle, // Window style |
| 463 | X, // x-coordinate of the upper-left corner |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 464 | Y+0, // y-coordinate of the upper-left corner |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 465 | W, // Width of the window for the edit |
| 466 | // control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 467 | H-5, // Height of the window for the edit |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 468 | // control |
| 469 | hWnd, // Window handle to the parent window |
| 470 | (HMENU) ID_GLOBAL_STATUS, // Control identifier |
| 471 | hInst, // Instance handle |
| 472 | NULL); // Specify NULL for this parameter when |
| 473 | // you create a control |
| 474 | SetLocalURI(g_local_uri.ptr, g_local_uri.slen, false); |
| 475 | |
| 476 | |
| 477 | // Create URI edit |
| 478 | dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_BORDER; |
| 479 | hwndURI = CreateWindow ( |
| 480 | TEXT("EDIT"), // Class name |
| 481 | NULL, // Window text |
| 482 | dwStyle, // Window style |
| 483 | X, // x-coordinate of the upper-left corner |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 484 | Y+H, // y-coordinate of the upper-left corner |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 485 | W, // Width of the window for the edit |
| 486 | // control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 487 | H-5, // Height of the window for the edit |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 488 | // control |
| 489 | hWnd, // Window handle to the parent window |
| 490 | (HMENU) ID_URI, // Control identifier |
| 491 | hInst, // Instance handle |
| 492 | NULL); // Specify NULL for this parameter when |
| 493 | // you create a control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 494 | |
| 495 | // Create action Button |
| 496 | hwndActionButton = CreateWindow( L"button", L"Action", |
| 497 | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, |
| 498 | X, Y+2*H, |
| 499 | 60, H-5, hWnd, |
| 500 | (HMENU) ID_BTN_ACTION, |
| 501 | hInst, NULL ); |
| 502 | |
| 503 | // Create exit button |
| 504 | hwndExitButton = CreateWindow( L"button", L"E&xit", |
| 505 | WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, |
| 506 | X+70, Y+2*H, |
| 507 | 60, H-5, hWnd, |
| 508 | (HMENU) ID_EXIT, |
| 509 | hInst, NULL ); |
| 510 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 511 | |
| 512 | // Create call status edit |
| 513 | dwStyle = WS_CHILD | WS_VISIBLE | WS_DISABLED; |
| 514 | hwndCallStatus = CreateWindow ( |
| 515 | TEXT("EDIT"), // Class name |
| 516 | NULL, // Window text |
| 517 | dwStyle, // Window style |
| 518 | X, // x-coordinate of the upper-left corner |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 519 | Y+3*H, // y-coordinate of the upper-left corner |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 520 | W, // Width of the window for the edit |
| 521 | // control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 522 | H-5, // Height of the window for the edit |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 523 | // control |
| 524 | hWnd, // Window handle to the parent window |
| 525 | (HMENU) ID_CALL_STATUS, // Control identifier |
| 526 | hInst, // Instance handle |
| 527 | NULL); // Specify NULL for this parameter when |
| 528 | // you create a control |
| 529 | SetCallStatus("Ready", 5); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 530 | SetAction(ID_MENU_CALL); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 531 | SetURI(DEFAULT_URI, -1); |
| 532 | SetFocus(hwndURI); |
| 533 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 534 | } |
| 535 | |
| 536 | |
| 537 | static void OnDestroy(void) |
| 538 | { |
| 539 | pjsua_destroy(); |
| 540 | } |
| 541 | |
| 542 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) |
| 543 | { |
| 544 | int wmId, wmEvent; |
| 545 | |
| 546 | switch (message) { |
| 547 | case WM_COMMAND: |
| 548 | wmId = LOWORD(wParam); |
| 549 | wmEvent = HIWORD(wParam); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 550 | if (wmId == ID_BTN_ACTION) |
| 551 | wmId = g_current_action; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 552 | switch (wmId) |
| 553 | { |
| 554 | case ID_MENU_CALL: |
| 555 | if (g_current_call != PJSUA_INVALID_ID) { |
| 556 | MessageBox(NULL, TEXT("Can not make call"), |
| 557 | TEXT("You already have one call active"), MB_OK); |
| 558 | } |
| 559 | pj_str_t dst_uri; |
| 560 | wchar_t text[256]; |
| 561 | char tmp[256]; |
| 562 | pj_status_t status; |
| 563 | |
| 564 | GetWindowText(hwndURI, text, PJ_ARRAY_SIZE(text)); |
| 565 | pj_unicode_to_ansi(text, pj_unicode_strlen(text), |
| 566 | tmp, sizeof(tmp)); |
| 567 | dst_uri.ptr = tmp; |
| 568 | dst_uri.slen = pj_ansi_strlen(tmp); |
| 569 | status = pjsua_call_make_call(g_current_acc, |
| 570 | &dst_uri, 0, NULL, |
| 571 | NULL, &g_current_call); |
| 572 | if (status != PJ_SUCCESS) |
| 573 | OnError(TEXT("Unable to make call"), status); |
| 574 | break; |
| 575 | case ID_MENU_ANSWER: |
| 576 | if (g_current_call == PJSUA_INVALID_ID) |
| 577 | MessageBox(NULL, TEXT("Can not answer"), |
| 578 | TEXT("There is no call!"), MB_OK); |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 579 | else |
| 580 | pjsua_call_answer(g_current_call, 200, NULL, NULL); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 581 | break; |
| 582 | case ID_MENU_DISCONNECT: |
| 583 | if (g_current_call == PJSUA_INVALID_ID) |
| 584 | MessageBox(NULL, TEXT("Can not disconnect"), |
| 585 | TEXT("There is no call!"), MB_OK); |
| 586 | else |
| 587 | pjsua_call_hangup(g_current_call, PJSIP_SC_DECLINE, NULL, NULL); |
| 588 | break; |
| 589 | case ID_EXIT: |
| 590 | DestroyWindow(hWnd); |
| 591 | break; |
| 592 | default: |
| 593 | return DefWindowProc(hWnd, message, wParam, lParam); |
| 594 | } |
| 595 | break; |
| 596 | |
| 597 | case WM_CREATE: |
| 598 | OnCreate(hWnd); |
| 599 | break; |
| 600 | |
| 601 | case WM_DESTROY: |
| 602 | OnDestroy(); |
| 603 | CommandBar_Destroy(hwndCB); |
| 604 | PostQuitMessage(0); |
| 605 | break; |
| 606 | |
| 607 | case WM_TIMER: |
| 608 | pjsua_handle_events(1); |
| 609 | break; |
| 610 | |
| 611 | default: |
| 612 | return DefWindowProc(hWnd, message, wParam, lParam); |
| 613 | } |
| 614 | return 0; |
| 615 | } |
| 616 | |