blob: 1dd8a20d10328e30073abf9367d1167cf02c76d5 [file] [log] [blame]
Benny Prijonoba5926a2007-05-02 11:29:37 +00001/* $Id$ */
2/*
3 * Copyright (C) 2003-2007 Benny Prijono <benny@prijono.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
Benny Prijonoba5926a2007-05-02 11:29:37 +000019#include <pjsua-lib/pjsua.h>
Benny Prijono72a81aa2007-05-02 23:06:11 +000020#include <pjsua-lib/pjsua_internal.h>
Benny Prijonoba5926a2007-05-02 11:29:37 +000021#include "ua.h"
22
23#define THIS_FILE "symbian_ua.cpp"
24
Benny Prijono72a81aa2007-05-02 23:06:11 +000025//
Benny Prijonoc71ad432007-05-04 07:25:19 +000026// Basic config.
27//
28#define SIP_PORT 5060
29
30
31//
Benny Prijonob2c96822007-05-03 13:31:21 +000032// Destination URI (to make call, or to subscribe presence)
33//
Benny Prijono5df8bb62007-12-28 18:55:02 +000034#define SIP_DST_URI "sip:192.168.0.11:5060"
Benny Prijonob2c96822007-05-03 13:31:21 +000035
36//
Benny Prijono72a81aa2007-05-02 23:06:11 +000037// Account
38//
39#define HAS_SIP_ACCOUNT 0 // 0 to disable registration
Benny Prijono897f9f82007-05-03 19:56:21 +000040#define SIP_DOMAIN "server"
41#define SIP_USER "user"
42#define SIP_PASSWD "password"
Benny Prijonoba5926a2007-05-02 11:29:37 +000043
Benny Prijono72a81aa2007-05-02 23:06:11 +000044//
45// Outbound proxy for all accounts
46//
47#define SIP_PROXY NULL
Benny Prijono897f9f82007-05-03 19:56:21 +000048//#define SIP_PROXY "sip:192.168.0.8"
49
50
51//
52// Configure nameserver if DNS SRV is to be used with both SIP
53// or STUN (for STUN see other settings below)
54//
55#define NAMESERVER NULL
56//#define NAMESERVER "62.241.163.201"
57
58//
59// STUN server
Benny Prijono5df8bb62007-12-28 18:55:02 +000060#if 0
Benny Prijono897f9f82007-05-03 19:56:21 +000061 // Use this to have the STUN server resolved normally
62# define STUN_DOMAIN NULL
63# define STUN_SERVER "stun.fwdnet.net"
64#elif 0
65 // Use this to have the STUN server resolved with DNS SRV
66# define STUN_DOMAIN "iptel.org"
67# define STUN_SERVER NULL
68#else
69 // Use this to disable STUN
70# define STUN_DOMAIN NULL
71# define STUN_SERVER NULL
72#endif
73
74//
75// Use ICE?
76//
Benny Prijono5df8bb62007-12-28 18:55:02 +000077#define USE_ICE 0
Benny Prijono72a81aa2007-05-02 23:06:11 +000078
79
Benny Prijonob2c96822007-05-03 13:31:21 +000080//
81// Globals
82//
83static pjsua_acc_id g_acc_id = PJSUA_INVALID_ID;
84static pjsua_call_id g_call_id = PJSUA_INVALID_ID;
85static pjsua_buddy_id g_buddy_id = PJSUA_INVALID_ID;
Benny Prijono72a81aa2007-05-02 23:06:11 +000086
Benny Prijonoba5926a2007-05-02 11:29:37 +000087
88/* Callback called by the library upon receiving incoming call */
89static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
90 pjsip_rx_data *rdata)
91{
92 pjsua_call_info ci;
93
94 PJ_UNUSED_ARG(acc_id);
95 PJ_UNUSED_ARG(rdata);
96
Benny Prijonob2c96822007-05-03 13:31:21 +000097 if (g_call_id != PJSUA_INVALID_ID) {
98 pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL);
99 return;
100 }
101
Benny Prijonoba5926a2007-05-02 11:29:37 +0000102 pjsua_call_get_info(call_id, &ci);
103
104 PJ_LOG(3,(THIS_FILE, "Incoming call from %.*s!!",
105 (int)ci.remote_info.slen,
106 ci.remote_info.ptr));
107
Benny Prijonob2c96822007-05-03 13:31:21 +0000108 g_call_id = call_id;
109
Benny Prijono897f9f82007-05-03 19:56:21 +0000110 /* Automatically answer incoming calls with 180/Ringing */
111 pjsua_call_answer(call_id, 180, NULL, NULL);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000112}
113
114/* Callback called by the library when call's state has changed */
115static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
116{
117 pjsua_call_info ci;
118
119 PJ_UNUSED_ARG(e);
120
121 pjsua_call_get_info(call_id, &ci);
Benny Prijonob2c96822007-05-03 13:31:21 +0000122
123 if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
124 if (call_id == g_call_id)
125 g_call_id = PJSUA_INVALID_ID;
Benny Prijono897f9f82007-05-03 19:56:21 +0000126 } else if (ci.state != PJSIP_INV_STATE_INCOMING) {
Benny Prijonob2c96822007-05-03 13:31:21 +0000127 if (g_call_id == PJSUA_INVALID_ID)
128 g_call_id = call_id;
129 }
130
Benny Prijonoba5926a2007-05-02 11:29:37 +0000131 PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s", call_id,
132 (int)ci.state_text.slen,
133 ci.state_text.ptr));
134}
135
136/* Callback called by the library when call's media state has changed */
137static void on_call_media_state(pjsua_call_id call_id)
138{
139 pjsua_call_info ci;
140
141 pjsua_call_get_info(call_id, &ci);
142
143 if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
144 // When media is active, connect call to sound device.
145 pjsua_conf_connect(ci.conf_slot, 0);
146 pjsua_conf_connect(0, ci.conf_slot);
147 }
148}
149
150
Benny Prijonob2c96822007-05-03 13:31:21 +0000151/* Handler on buddy state changed. */
152static void on_buddy_state(pjsua_buddy_id buddy_id)
153{
154 pjsua_buddy_info info;
155 pjsua_buddy_get_info(buddy_id, &info);
156
157 PJ_LOG(3,(THIS_FILE, "%.*s status is %.*s",
158 (int)info.uri.slen,
159 info.uri.ptr,
160 (int)info.status_text.slen,
161 info.status_text.ptr));
162}
163
164
165/* Incoming IM message (i.e. MESSAGE request)! */
166static void on_pager(pjsua_call_id call_id, const pj_str_t *from,
167 const pj_str_t *to, const pj_str_t *contact,
168 const pj_str_t *mime_type, const pj_str_t *text)
169{
170 /* Note: call index may be -1 */
171 PJ_UNUSED_ARG(call_id);
172 PJ_UNUSED_ARG(to);
173 PJ_UNUSED_ARG(contact);
174 PJ_UNUSED_ARG(mime_type);
175
176 PJ_LOG(3,(THIS_FILE,"MESSAGE from %.*s: %.*s",
177 (int)from->slen, from->ptr,
178 (int)text->slen, text->ptr));
179}
180
181
182/* Received typing indication */
183static void on_typing(pjsua_call_id call_id, const pj_str_t *from,
184 const pj_str_t *to, const pj_str_t *contact,
185 pj_bool_t is_typing)
186{
187 PJ_UNUSED_ARG(call_id);
188 PJ_UNUSED_ARG(to);
189 PJ_UNUSED_ARG(contact);
190
191 PJ_LOG(3,(THIS_FILE, "IM indication: %.*s %s",
192 (int)from->slen, from->ptr,
193 (is_typing?"is typing..":"has stopped typing")));
194}
195
196
197/* Call transfer request status. */
198static void on_call_transfer_status(pjsua_call_id call_id,
199 int status_code,
200 const pj_str_t *status_text,
201 pj_bool_t final,
202 pj_bool_t *p_cont)
203{
204 PJ_LOG(3,(THIS_FILE, "Call %d: transfer status=%d (%.*s) %s",
205 call_id, status_code,
206 (int)status_text->slen, status_text->ptr,
207 (final ? "[final]" : "")));
208
209 if (status_code/100 == 2) {
210 PJ_LOG(3,(THIS_FILE,
211 "Call %d: call transfered successfully, disconnecting call",
212 call_id));
213 pjsua_call_hangup(call_id, PJSIP_SC_GONE, NULL, NULL);
214 *p_cont = PJ_FALSE;
215 }
216}
217
218
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000219/* NAT detection result */
220static void on_nat_detect(const pj_stun_nat_detect_result *res)
221{
222 if (res->status != PJ_SUCCESS) {
223 pjsua_perror(THIS_FILE, "NAT detection failed", res->status);
224 } else {
225 PJ_LOG(3, (THIS_FILE, "NAT detected as %s", res->nat_type_name));
226 }
227}
228
Benny Prijonob2c96822007-05-03 13:31:21 +0000229/* Notification that call is being replaced. */
230static void on_call_replaced(pjsua_call_id old_call_id,
231 pjsua_call_id new_call_id)
232{
233 pjsua_call_info old_ci, new_ci;
234
235 pjsua_call_get_info(old_call_id, &old_ci);
236 pjsua_call_get_info(new_call_id, &new_ci);
237
238 PJ_LOG(3,(THIS_FILE, "Call %d with %.*s is being replaced by "
239 "call %d with %.*s",
240 old_call_id,
241 (int)old_ci.remote_info.slen, old_ci.remote_info.ptr,
242 new_call_id,
243 (int)new_ci.remote_info.slen, new_ci.remote_info.ptr));
244}
245
246
Benny Prijonoba5926a2007-05-02 11:29:37 +0000247/* Logging callback */
Benny Prijono797e3382007-12-01 09:10:07 +0000248static void log_writer(int level, const char *buf, int len)
Benny Prijonoba5926a2007-05-02 11:29:37 +0000249{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000250 static wchar_t buf16[PJ_LOG_MAX_SIZE];
Benny Prijonoba5926a2007-05-02 11:29:37 +0000251
252 PJ_UNUSED_ARG(level);
253
254 pj_ansi_to_unicode(buf, len, buf16, PJ_ARRAY_SIZE(buf16));
255
256 TPtrC16 aBuf((const TUint16*)buf16, (TInt)len);
257 console->Write(aBuf);
Benny Prijono797e3382007-12-01 09:10:07 +0000258
Benny Prijonoba5926a2007-05-02 11:29:37 +0000259}
260
261/*
262 * app_startup()
263 *
264 * url may contain URL to call.
265 */
Benny Prijonob2c96822007-05-03 13:31:21 +0000266static pj_status_t app_startup()
Benny Prijonoba5926a2007-05-02 11:29:37 +0000267{
Benny Prijonoba5926a2007-05-02 11:29:37 +0000268 pj_status_t status;
269
270 /* Redirect log before pjsua_init() */
271 pj_log_set_log_func((void (*)(int,const char*,int)) &log_writer);
272
273 /* Create pjsua first! */
274 status = pjsua_create();
275 if (status != PJ_SUCCESS) {
276 pjsua_perror(THIS_FILE, "pjsua_create() error", status);
277 return status;
278 }
279
Benny Prijonoba5926a2007-05-02 11:29:37 +0000280 /* Init pjsua */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000281 pjsua_config cfg;
282 pjsua_logging_config log_cfg;
283 pjsua_media_config med_cfg;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000284
Benny Prijonoc71ad432007-05-04 07:25:19 +0000285 pjsua_config_default(&cfg);
286 cfg.max_calls = 2;
287 cfg.thread_cnt = 0; // Disable threading on Symbian
288 cfg.cb.on_incoming_call = &on_incoming_call;
289 cfg.cb.on_call_media_state = &on_call_media_state;
290 cfg.cb.on_call_state = &on_call_state;
291 cfg.cb.on_buddy_state = &on_buddy_state;
292 cfg.cb.on_pager = &on_pager;
293 cfg.cb.on_typing = &on_typing;
294 cfg.cb.on_call_transfer_status = &on_call_transfer_status;
295 cfg.cb.on_call_replaced = &on_call_replaced;
Benny Prijonoaecabfc2007-10-26 05:35:42 +0000296 cfg.cb.on_nat_detect = &on_nat_detect;
297
Benny Prijonoc71ad432007-05-04 07:25:19 +0000298 if (SIP_PROXY) {
299 cfg.outbound_proxy_cnt = 1;
300 cfg.outbound_proxy[0] = pj_str(SIP_PROXY);
301 }
302
303 if (NAMESERVER) {
304 cfg.nameserver_count = 1;
305 cfg.nameserver[0] = pj_str(NAMESERVER);
306 }
307
308 if (NAMESERVER && STUN_DOMAIN) {
309 cfg.stun_domain = pj_str(STUN_DOMAIN);
310 } else if (STUN_SERVER) {
311 cfg.stun_host = pj_str(STUN_SERVER);
312 }
313
314
315 pjsua_logging_config_default(&log_cfg);
316 log_cfg.console_level = 4;
317 log_cfg.cb = &log_writer;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000318
Benny Prijonoc71ad432007-05-04 07:25:19 +0000319 pjsua_media_config_default(&med_cfg);
320 med_cfg.thread_cnt = 0; // Disable threading on Symbian
321 med_cfg.has_ioqueue = PJ_FALSE;
322 med_cfg.clock_rate = 8000;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000323 med_cfg.audio_frame_ptime = 40;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000324 med_cfg.ec_tail_len = 0;
325 med_cfg.enable_ice = USE_ICE;
326
327 status = pjsua_init(&cfg, &log_cfg, &med_cfg);
328 if (status != PJ_SUCCESS) {
329 pjsua_perror(THIS_FILE, "pjsua_init() error", status);
330 pjsua_destroy();
331 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000332 }
333
334 /* Add UDP transport. */
Benny Prijonoc71ad432007-05-04 07:25:19 +0000335 pjsua_transport_config tcfg;
336 pjsua_transport_id tid;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000337
Benny Prijonoc71ad432007-05-04 07:25:19 +0000338 pjsua_transport_config_default(&tcfg);
339 tcfg.port = SIP_PORT;
340 status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &tcfg, &tid);
341 if (status != PJ_SUCCESS) {
342 pjsua_perror(THIS_FILE, "Error creating transport", status);
343 pjsua_destroy();
344 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000345 }
346
Benny Prijonoc71ad432007-05-04 07:25:19 +0000347 /* Add account for the transport */
348 pjsua_acc_add_local(tid, PJ_TRUE, &g_acc_id);
349
350
Benny Prijonoba5926a2007-05-02 11:29:37 +0000351 /* Initialization is done, now start pjsua */
352 status = pjsua_start();
353 if (status != PJ_SUCCESS) {
354 pjsua_perror(THIS_FILE, "Error starting pjsua", status);
355 pjsua_destroy();
356 return status;
357 }
358
359 /* Register to SIP server by creating SIP account. */
Benny Prijono72a81aa2007-05-02 23:06:11 +0000360 if (HAS_SIP_ACCOUNT) {
Benny Prijonoba5926a2007-05-02 11:29:37 +0000361 pjsua_acc_config cfg;
362
363 pjsua_acc_config_default(&cfg);
364 cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
365 cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
366 cfg.cred_count = 1;
367 cfg.cred_info[0].realm = pj_str(SIP_DOMAIN);
368 cfg.cred_info[0].scheme = pj_str("digest");
369 cfg.cred_info[0].username = pj_str(SIP_USER);
370 cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
371 cfg.cred_info[0].data = pj_str(SIP_PASSWD);
372
Benny Prijonob2c96822007-05-03 13:31:21 +0000373 status = pjsua_acc_add(&cfg, PJ_TRUE, &g_acc_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000374 if (status != PJ_SUCCESS) {
375 pjsua_perror(THIS_FILE, "Error adding account", status);
376 pjsua_destroy();
377 return status;
378 }
379 }
380
Benny Prijonob2c96822007-05-03 13:31:21 +0000381 if (SIP_DST_URI) {
382 pjsua_buddy_config bcfg;
383
384 pjsua_buddy_config_default(&bcfg);
385 bcfg.uri = pj_str(SIP_DST_URI);
386 bcfg.subscribe = PJ_FALSE;
387
388 pjsua_buddy_add(&bcfg, &g_buddy_id);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000389 }
Benny Prijonoba5926a2007-05-02 11:29:37 +0000390 return PJ_SUCCESS;
391}
392
393
394////////////////////////////////////////////////////////////////////////////
Benny Prijonoc71ad432007-05-04 07:25:19 +0000395/*
396 * The interractive console UI
397 */
Benny Prijonoba5926a2007-05-02 11:29:37 +0000398#include <e32base.h>
399
400class ConsoleUI : public CActive
401{
402public:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000403 ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000404
Benny Prijonoc71ad432007-05-04 07:25:19 +0000405 // Run console UI
406 void Run();
407
408 // Stop
409 void Stop();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000410
411protected:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000412 // Cancel asynchronous read.
413 void DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000414
Benny Prijonoc71ad432007-05-04 07:25:19 +0000415 // Implementation: called when read has completed.
416 void RunL();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000417
418private:
Benny Prijonoc71ad432007-05-04 07:25:19 +0000419 CActiveSchedulerWait *asw_;
420 CConsoleBase *con_;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000421};
422
423
424ConsoleUI::ConsoleUI(CActiveSchedulerWait *asw, CConsoleBase *con)
425: CActive(EPriorityStandard), asw_(asw), con_(con)
426{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000427 CActiveScheduler::Add(this);
Benny Prijonoba5926a2007-05-02 11:29:37 +0000428}
429
430// Run console UI
431void ConsoleUI::Run()
432{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000433 con_->Read(iStatus);
434 SetActive();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000435}
436
437// Stop console UI
438void ConsoleUI::Stop()
439{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000440 DoCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000441}
442
443// Cancel asynchronous read.
444void ConsoleUI::DoCancel()
445{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000446 con_->ReadCancel();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000447}
448
Benny Prijono72a81aa2007-05-02 23:06:11 +0000449static void PrintMenu()
450{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000451 PJ_LOG(3, (THIS_FILE, "\n\n"
452 "Menu:\n"
453 " d Dump states\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000454 " D Dump states detail\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000455 " P Dump pool factory\n"
Benny Prijono5df8bb62007-12-28 18:55:02 +0000456 " l Start loopback audio device\n"
457 " L Stop loopback audio device\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000458 " m Call " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000459 " a Answer call\n"
460 " h Hangup all calls\n"
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000461 " s Subscribe " SIP_DST_URI "\n"
Benny Prijonoc71ad432007-05-04 07:25:19 +0000462 " S Unsubscribe presence\n"
463 " o Set account online\n"
464 " O Set account offline\n"
465 " q Quit\n"));
Benny Prijono72a81aa2007-05-02 23:06:11 +0000466}
467
Benny Prijonoba5926a2007-05-02 11:29:37 +0000468// Implementation: called when read has completed.
469void ConsoleUI::RunL()
470{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000471 TKeyCode kc = con_->KeyCode();
472 pj_bool_t reschedule = PJ_TRUE;
473
474 switch (kc) {
475 case 'q':
476 asw_->AsyncStop();
477 reschedule = PJ_FALSE;
478 break;
479 case 'D':
480 case 'd':
481 pjsua_dump(kc == 'D');
482 break;
483 case 'p':
484 case 'P':
Benny Prijono1f61a8f2007-08-16 10:11:44 +0000485 pj_pool_factory_dump(pjsua_get_pool_factory(), PJ_TRUE);
Benny Prijonoc71ad432007-05-04 07:25:19 +0000486 break;
Benny Prijono5df8bb62007-12-28 18:55:02 +0000487 case 'l':
488 pjsua_conf_connect(0, 0);
489 break;
490 case 'L':
491 pjsua_conf_disconnect(0, 0);
492 break;
Benny Prijonoc71ad432007-05-04 07:25:19 +0000493 case 'm':
494 if (g_call_id != PJSUA_INVALID_ID) {
495 PJ_LOG(3,(THIS_FILE, "Another call is active"));
496 break;
497 }
498
499 if (pjsua_verify_sip_url(SIP_DST_URI) == PJ_SUCCESS) {
500 pj_str_t dst = pj_str(SIP_DST_URI);
501 pjsua_call_make_call(g_acc_id, &dst, 0, NULL,
502 NULL, &g_call_id);
503 } else {
504 PJ_LOG(3,(THIS_FILE, "Invalid SIP URI"));
505 }
506 break;
507 case 'a':
508 if (g_call_id != PJSUA_INVALID_ID)
509 pjsua_call_answer(g_call_id, 200, NULL, NULL);
510 break;
511 case 'h':
512 pjsua_call_hangup_all();
513 break;
514 case 's':
515 case 'S':
516 if (g_buddy_id != PJSUA_INVALID_ID)
517 pjsua_buddy_subscribe_pres(g_buddy_id, kc=='s');
518 break;
519 case 'o':
520 case 'O':
521 pjsua_acc_set_online_status(g_acc_id, kc=='o');
522 break;
523 default:
524 PJ_LOG(3,(THIS_FILE, "Keycode '%c' (%d) is pressed",
525 kc, kc));
526 break;
527 }
Benny Prijono72a81aa2007-05-02 23:06:11 +0000528
Benny Prijonoc71ad432007-05-04 07:25:19 +0000529 PrintMenu();
530
531 if (reschedule)
532 Run();
Benny Prijonoba5926a2007-05-02 11:29:37 +0000533}
534
Benny Prijono897f9f82007-05-03 19:56:21 +0000535
Benny Prijonoba5926a2007-05-02 11:29:37 +0000536////////////////////////////////////////////////////////////////////////////
537int ua_main()
538{
Benny Prijonoc71ad432007-05-04 07:25:19 +0000539 pj_status_t status;
540
541 // Initialize pjsua
542 status = app_startup();
543 if (status != PJ_SUCCESS)
544 return status;
Benny Prijono897f9f82007-05-03 19:56:21 +0000545
Benny Prijonoc71ad432007-05-04 07:25:19 +0000546 // Run the UI
547 CActiveSchedulerWait *asw = new CActiveSchedulerWait;
548 ConsoleUI *con = new ConsoleUI(asw, console);
549
550 con->Run();
551
552 PrintMenu();
553 asw->Start();
554
555 delete con;
556 delete asw;
557
558 // Shutdown pjsua
559 pjsua_destroy();
560
Benny Prijono797e3382007-12-01 09:10:07 +0000561on_return:
562 return status;
Benny Prijonoba5926a2007-05-02 11:29:37 +0000563}
564