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 | |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 18 | |
| 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 Izzuddin | ae0e64b | 2009-04-21 14:08:49 +0000 | [diff] [blame] | 56 | #if 0 |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 57 | // Use this to have the STUN server resolved normally |
| 58 | # define STUN_DOMAIN NULL |
Benny Prijono | f4e03a7 | 2007-10-12 23:29:27 +0000 | [diff] [blame] | 59 | # define STUN_SERVER "stun.fwdnet.net" |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 60 | #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 Izzuddin | ae0e64b | 2009-04-21 14:08:49 +0000 | [diff] [blame] | 73 | #define USE_ICE 0 |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 74 | |
| 75 | |
| 76 | // |
| 77 | // Globals |
| 78 | // |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 79 | static pj_pool_t *g_pool; |
| 80 | static pj_str_t g_local_uri; |
| 81 | static int g_current_acc; |
| 82 | static int g_current_call = PJSUA_INVALID_ID; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 83 | static int g_current_action; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 84 | |
| 85 | enum |
| 86 | { |
| 87 | ID_GLOBAL_STATUS = 21, |
| 88 | ID_URI, |
| 89 | ID_CALL_STATUS, |
| 90 | ID_POLL_TIMER, |
| 91 | }; |
| 92 | |
| 93 | enum |
| 94 | { |
| 95 | ID_MENU_NONE = 64, |
| 96 | ID_MENU_CALL, |
| 97 | ID_MENU_ANSWER, |
| 98 | ID_MENU_DISCONNECT, |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 99 | ID_BTN_ACTION, |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 100 | }; |
| 101 | |
| 102 | |
| 103 | // Forward declarations of functions included in this code module: |
| 104 | static ATOM MyRegisterClass (HINSTANCE, LPTSTR); |
| 105 | BOOL InitInstance (HINSTANCE, int); |
| 106 | static void OnCreate (HWND hWnd); |
| 107 | static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); |
| 108 | |
| 109 | |
| 110 | |
| 111 | ///////////////////////////////////////////////////////////////////////////// |
| 112 | |
| 113 | static 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 | |
| 125 | static void SetLocalURI(const char *uri, int len, bool enabled=true) |
| 126 | { |
| 127 | wchar_t tmp[128]; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 128 | if (len==-1) len=pj_ansi_strlen(uri); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 129 | 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 | |
| 136 | static void SetURI(const char *uri, int len, bool enabled=true) |
| 137 | { |
| 138 | wchar_t tmp[128]; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 139 | if (len==-1) len=pj_ansi_strlen(uri); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 140 | 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 | |
| 146 | static void SetCallStatus(const char *state, int len) |
| 147 | { |
| 148 | wchar_t tmp[128]; |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 149 | if (len==-1) len=pj_ansi_strlen(state); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 150 | pj_ansi_to_unicode(state, len, tmp, PJ_ARRAY_SIZE(tmp)); |
| 151 | SetDlgItemText(hMainWnd, ID_CALL_STATUS, tmp); |
| 152 | } |
| 153 | |
| 154 | static 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 Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 168 | SetWindowText(hwndActionButton, TEXT("-")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 169 | break; |
| 170 | case ID_MENU_CALL: |
| 171 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Call")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 172 | SetWindowText(hwndActionButton, TEXT("&Call")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 173 | break; |
| 174 | case ID_MENU_ANSWER: |
| 175 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Answer")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 176 | SetWindowText(hwndActionButton, TEXT("&Answer")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 177 | break; |
| 178 | case ID_MENU_DISCONNECT: |
| 179 | InsertMenu(hMenu, ID_EXIT, MF_BYCOMMAND, action, TEXT("Hangup")); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 180 | SetWindowText(hwndActionButton, TEXT("&Hangup")); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 181 | break; |
| 182 | } |
| 183 | |
| 184 | EnableMenuItem(hMenu, action, MF_BYCOMMAND | (enable?MF_ENABLED:MF_GRAYED)); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 185 | DrawMenuBar(hMainWnd); |
| 186 | |
| 187 | g_current_action = action; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | |
| 191 | /* |
| 192 | * Handler when invite state has changed. |
| 193 | */ |
| 194 | static 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 Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 205 | SetURI(SIP_DST_URI, -1); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 206 | SetAction(ID_MENU_CALL); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 207 | //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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 209 | |
| 210 | } else { |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 211 | //if (g_current_call == PJSUA_INVALID_ID) |
| 212 | // g_current_call = call_id; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 213 | |
| 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 Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 218 | |
| 219 | if (call_info.state == PJSIP_INV_STATE_CONFIRMED) |
| 220 | SetAction(ID_MENU_DISCONNECT); |
| 221 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 222 | 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 | */ |
| 232 | static 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 | */ |
| 248 | static 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 Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 257 | 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 260 | 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 Prijono | fd27c66 | 2006-08-09 11:59:26 +0000 | [diff] [blame] | 269 | pjsua_call_answer(call_id, 200, NULL, NULL); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 270 | } |
| 271 | |
| 272 | |
| 273 | /* |
| 274 | * Handler registration status has changed. |
| 275 | */ |
| 276 | static 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 | */ |
| 287 | static void on_buddy_state(pjsua_buddy_id buddy_id) |
| 288 | { |
Nanang Izzuddin | 2e4f03f | 2009-04-27 19:18:38 +0000 | [diff] [blame] | 289 | /* Currently this is not processed */ |
| 290 | PJ_UNUSED_ARG(buddy_id); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 291 | } |
| 292 | |
| 293 | |
| 294 | /** |
| 295 | * Incoming IM message (i.e. MESSAGE request)! |
| 296 | */ |
| 297 | static 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 Izzuddin | 2e4f03f | 2009-04-27 19:18:38 +0000 | [diff] [blame] | 301 | /* 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 308 | } |
| 309 | |
| 310 | |
| 311 | /** |
| 312 | * Received typing indication |
| 313 | */ |
| 314 | static 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 Izzuddin | 2e4f03f | 2009-04-27 19:18:38 +0000 | [diff] [blame] | 318 | /* 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 | */ |
| 329 | static 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 342 | } |
| 343 | |
| 344 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 345 | static 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 Prijono | 7c3741f | 2006-08-05 21:07:15 +0000 | [diff] [blame] | 354 | pj_str_t tmp; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 355 | 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 369 | pjsua_media_config_default(&media_cfg); |
| 370 | pjsua_transport_config_default(&udp_cfg); |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 371 | udp_cfg.port = SIP_PORT; |
| 372 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 373 | pjsua_transport_config_default(&rtp_cfg); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 374 | rtp_cfg.port = 40000; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 375 | |
Benny Prijono | 4e05b47 | 2006-10-16 15:52:31 +0000 | [diff] [blame] | 376 | 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 382 | /* Setup media */ |
| 383 | media_cfg.clock_rate = 8000; |
Benny Prijono | 5da5043 | 2006-08-07 10:24:52 +0000 | [diff] [blame] | 384 | media_cfg.ec_options = PJMEDIA_ECHO_SIMPLE; |
Benny Prijono | fd27c66 | 2006-08-09 11:59:26 +0000 | [diff] [blame] | 385 | media_cfg.ec_tail_len = 256; |
Nanang Izzuddin | c91cd64 | 2009-05-06 18:59:31 +0000 | [diff] [blame] | 386 | // use default quality setting |
| 387 | //media_cfg.quality = 1; |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 388 | media_cfg.ptime = 20; |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 389 | media_cfg.enable_ice = USE_ICE; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 390 | |
| 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 Izzuddin | 2e4f03f | 2009-04-27 19:18:38 +0000 | [diff] [blame] | 399 | cfg.cb.on_nat_detect = &nat_detect_cb; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 400 | |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 401 | 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 418 | /* 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 Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 426 | 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 Prijono | fd27c66 | 2006-08-09 11:59:26 +0000 | [diff] [blame] | 429 | pjsua_codec_set_priority(pj_cstr(&tmp, "ilbc"), 189); |
Benny Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 430 | pjsua_codec_set_priority(pj_cstr(&tmp, "speex/16000"), 180); |
Benny Prijono | 7c3741f | 2006-08-05 21:07:15 +0000 | [diff] [blame] | 431 | pjsua_codec_set_priority(pj_cstr(&tmp, "speex/32000"), 0); |
Benny Prijono | fd27c66 | 2006-08-09 11:59:26 +0000 | [diff] [blame] | 432 | pjsua_codec_set_priority(pj_cstr(&tmp, "gsm"), 100); |
Benny Prijono | 7c3741f | 2006-08-05 21:07:15 +0000 | [diff] [blame] | 433 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 434 | |
| 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 Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 457 | /* 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 489 | /* 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 | |
| 502 | int WINAPI WinMain(HINSTANCE hInstance, |
| 503 | HINSTANCE hPrevInstance, |
| 504 | LPTSTR lpCmdLine, |
| 505 | int nCmdShow) |
| 506 | { |
| 507 | MSG msg; |
| 508 | HACCEL hAccelTable; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 509 | |
Nanang Izzuddin | 2e4f03f | 2009-04-27 19:18:38 +0000 | [diff] [blame] | 510 | PJ_UNUSED_ARG(lpCmdLine); |
| 511 | PJ_UNUSED_ARG(hPrevInstance); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 512 | |
| 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 | |
| 535 | static 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 554 | BOOL 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 Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 571 | CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 200, |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 572 | 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 Prijono | 4ab9fbb | 2007-10-12 12:14:27 +0000 | [diff] [blame] | 586 | |
Benny Prijono | 3808af1 | 2007-10-18 01:40:44 +0000 | [diff] [blame] | 587 | pjsua_detect_nat_type(); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 588 | return TRUE; |
| 589 | } |
| 590 | |
| 591 | |
| 592 | static void OnCreate(HWND hWnd) |
| 593 | { |
| 594 | enum |
| 595 | { |
| 596 | X = 10, |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 597 | Y = 40, |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 598 | 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 Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 617 | Y+0, // y-coordinate of the upper-left corner |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 618 | W, // Width of the window for the edit |
| 619 | // control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 620 | H-5, // Height of the window for the edit |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 621 | // 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 Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 637 | Y+H, // y-coordinate of the upper-left corner |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 638 | W, // Width of the window for the edit |
| 639 | // control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 640 | H-5, // Height of the window for the edit |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 641 | // 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 Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 647 | |
| 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 664 | |
| 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 Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 672 | Y+3*H, // y-coordinate of the upper-left corner |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 673 | W, // Width of the window for the edit |
| 674 | // control |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 675 | H-5, // Height of the window for the edit |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 676 | // 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 683 | SetAction(ID_MENU_CALL); |
Benny Prijono | 8a74445 | 2007-05-10 20:40:57 +0000 | [diff] [blame] | 684 | SetURI(SIP_DST_URI, -1); |
Benny Prijono | 39ea7f0 | 2006-09-14 13:52:29 +0000 | [diff] [blame] | 685 | SetFocus(hWnd); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 686 | |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 687 | } |
| 688 | |
| 689 | |
| 690 | static void OnDestroy(void) |
| 691 | { |
| 692 | pjsua_destroy(); |
| 693 | } |
| 694 | |
| 695 | static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) |
| 696 | { |
| 697 | int wmId, wmEvent; |
| 698 | |
| 699 | switch (message) { |
Benny Prijono | 39ea7f0 | 2006-09-14 13:52:29 +0000 | [diff] [blame] | 700 | 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 Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 711 | case WM_COMMAND: |
| 712 | wmId = LOWORD(wParam); |
| 713 | wmEvent = HIWORD(wParam); |
Benny Prijono | f20687a | 2006-08-04 18:27:19 +0000 | [diff] [blame] | 714 | if (wmId == ID_BTN_ACTION) |
| 715 | wmId = g_current_action; |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 716 | 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 Prijono | edba079 | 2006-08-06 18:23:56 +0000 | [diff] [blame] | 743 | else |
| 744 | pjsua_call_answer(g_current_call, 200, NULL, NULL); |
Benny Prijono | 01f0154 | 2006-08-01 23:09:35 +0000 | [diff] [blame] | 745 | 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 | |