summaryrefslogtreecommitdiff
path: root/pjsip-apps/src/ipjsua/Classes/ipjsuaAppDelegate.m
blob: c60084db22c38be50d63094d1079ff8299a66a95 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/* $Id: ipjsuaAppDelegate.m 3550 2011-05-05 05:33:27Z nanang $ */
/* 
 * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#import <pjlib.h>
#import <pjsua.h>
#import "ipjsuaAppDelegate.h"

extern pj_log_func *log_cb;

@implementation ipjsuaAppDelegate
@synthesize window;
@synthesize tabBarController;
@synthesize mainView;
@synthesize cfgView;

/* Sleep interval duration */
#define SLEEP_INTERVAL	    0.5
/* Determine whether we should print the messages in the debugger
 * console as well
 */
#define DEBUGGER_PRINT	    1
/* Whether we should show pj log messages in the text area */
#define SHOW_LOG	    1
#define PATH_LENGTH	    PJ_MAXPATH
#define KEEP_ALIVE_INTERVAL 600

extern pj_bool_t app_restart;

char argv_buf[PATH_LENGTH];
char *argv[] = {"", "--config-file", argv_buf};

ipjsuaAppDelegate	*app;

bool			 app_running;
bool			 thread_quit;
NSMutableString		*mstr;
pj_thread_desc		 a_thread_desc;
pj_thread_t		*a_thread;
pjsua_call_id		 ccall_id;

pj_status_t app_init(int argc, char *argv[]);
pj_status_t app_main(void);
pj_status_t app_destroy(void);
void keepAliveFunction(int timeout);

void showMsg(const char *format, ...)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    va_list arg;
    
    va_start(arg, format);
    NSString *str = [[NSString alloc] initWithFormat:[NSString stringWithFormat:@"%s", format] arguments: arg];
#if DEBUGGER_PRINT
    NSLog(@"%@", str);
#endif
    va_end(arg);
    
    [mstr appendString:str];
    [pool release];
}

char * getInput(char *s, int n, FILE *stream)
{
    if (stream != stdin) {
	return fgets(s, n, stream);
    }
    
    app.mainView.hasInput = false;
    [app.mainView.textField setEnabled: true];
    [app performSelectorOnMainThread:@selector(displayMsg:) withObject:mstr waitUntilDone:YES];
    [mstr setString:@""];
    
    while (!thread_quit && !app.mainView.hasInput) {
	int ctr = 0;
	[NSThread sleepForTimeInterval:SLEEP_INTERVAL];
	if (ctr == 4) {
	    [app performSelectorOnMainThread:@selector(displayMsg:) withObject:mstr waitUntilDone:YES];
	    [mstr setString:@""];
	    ctr = 0;
	}
	ctr++;
    }
    
    [app.mainView.text getCString:s maxLength:n encoding:NSASCIIStringEncoding];
    [app.mainView.textField setEnabled: false];    
    [app performSelectorOnMainThread:@selector(displayMsg:) withObject:app.mainView.text waitUntilDone:NO];
    
    return s;
}

void showLog(int level, const char *data, int len)
{
    showMsg("%s", data);
}

pj_bool_t showNotification(pjsua_call_id call_id)
{
#ifdef __IPHONE_4_0
    ccall_id = call_id;

    // Create a new notification
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    UILocalNotification* alert = [[[UILocalNotification alloc] init] autorelease];
    if (alert)
    {
	alert.repeatInterval = 0;
	alert.alertBody = @"Incoming call received...";
	alert.alertAction = @"Answer";
	
	[[UIApplication sharedApplication] presentLocalNotificationNow:alert];
    }
    
    [pool release];
    
    return PJ_FALSE;
#else
    return PJ_TRUE;
#endif
}

- (void)answer_call {
    if (!pj_thread_is_registered())
    {
	pj_thread_register("ipjsua", a_thread_desc, &a_thread);
    }
    pjsua_call_answer(ccall_id, 200, NULL, NULL);
}

#ifdef __IPHONE_4_0
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
    [app performSelectorOnMainThread:@selector(answer_call) withObject:nil waitUntilDone:YES];
}

- (void)keepAlive {
    if (!pj_thread_is_registered())
    {
	pj_thread_register("ipjsua", a_thread_desc, &a_thread);
    }    
    keepAliveFunction(KEEP_ALIVE_INTERVAL);
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [app performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
    [application setKeepAliveTimeout:KEEP_ALIVE_INTERVAL handler: ^{
	[app performSelectorOnMainThread:@selector(keepAlive) withObject:nil waitUntilDone:YES];
    }];
}

#endif

- (void)start_app {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    /* Wait until the view is ready */
    while (self.mainView == nil) {
	[NSThread sleepForTimeInterval:SLEEP_INTERVAL];
    }    

    [NSThread setThreadPriority:1.0];
    mstr = [NSMutableString stringWithCapacity:4196];
#if SHOW_LOG
    pj_log_set_log_func(&showLog);
    log_cb = &showLog;
#endif
    
    do {
	app_restart = PJ_FALSE;
	if (app_init(3, argv) != PJ_SUCCESS) {
	    NSString *str = @"Failed to initialize pjsua\n";
	    [app performSelectorOnMainThread:@selector(displayMsg:) withObject:str waitUntilDone:YES];
	} else {
	    app_running = true;
	    app_main();
	    
	    app_destroy();
	    /* This is on purpose */
	    app_destroy();
	}

	[app performSelectorOnMainThread:@selector(displayMsg:) withObject:mstr waitUntilDone:YES];
	[mstr setString:@""];
    } while (app_restart);
    
    [pool release];
}

- (void)displayMsg:(NSString *)str {
    self.mainView.textView.text = [self.mainView.textView.text stringByAppendingString:str];
    [self.mainView.textView scrollRangeToVisible:NSMakeRange([self.mainView.textView.text length] - 1, 1)];
}

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    /* If there is no config file in the document dir, copy the default config file into the directory */ 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *cfgPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"/config.cfg"];
    if (![[NSFileManager defaultManager] fileExistsAtPath:cfgPath]) {
	NSString *resPath = [[NSBundle mainBundle] pathForResource:@"config" ofType:@"cfg"];
	NSString *cfg = [NSString stringWithContentsOfFile:resPath encoding:NSASCIIStringEncoding error:NULL];
	[cfg writeToFile:cfgPath atomically:NO encoding:NSASCIIStringEncoding error:NULL];
    }
    [cfgPath getCString:argv[2] maxLength:PATH_LENGTH encoding:NSASCIIStringEncoding];    
    
    // Add the tab bar controller's current view as a subview of the window
    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];

    app = self;
    app_running = false;
    thread_quit = false;
    /* Start pjsua thread */
    [NSThread detachNewThreadSelector:@selector(start_app) toTarget:self withObject:nil];
}

/*
// Optional UITabBarControllerDelegate method
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
}
*/

/*
// Optional UITabBarControllerDelegate method
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
}
*/


- (void)dealloc {
    thread_quit = true;
    [NSThread sleepForTimeInterval:SLEEP_INTERVAL];
    
    [tabBarController release];
    [window release];
    [super dealloc];
}

@end