linphonecore.c 133 KB
Newer Older
aymeric's avatar
aymeric committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
linphone
Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)

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.
*/

#include "linphonecore.h"
smorlat's avatar
smorlat committed
21
#include "sipsetup.h"
aymeric's avatar
aymeric committed
22
23
#include "lpconfig.h"
#include "private.h"
24
25

#include <ortp/telephonyevents.h>
26
#include <ortp/zrtp.h>
aymeric's avatar
aymeric committed
27
#include "mediastreamer2/mediastream.h"
28
#include "mediastreamer2/mseventqueue.h"
smorlat's avatar
smorlat committed
29
#include "mediastreamer2/msvolume.h"
30
#include "mediastreamer2/msequalizer.h"
31
#include "mediastreamer2/dtmfgen.h"
aymeric's avatar
aymeric committed
32

33
#ifdef INET6
aymeric's avatar
aymeric committed
34
#ifndef WIN32
35
#include <netdb.h>
aymeric's avatar
aymeric committed
36
37
38
#endif
#endif

39
40
41
42
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

smorlat's avatar
smorlat committed
43
/*#define UNSTANDART_GSM_11K 1*/
aymeric's avatar
aymeric committed
44

45
46
#define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"

aymeric's avatar
aymeric committed
47
static const char *liblinphone_version=LIBLINPHONE_VERSION;
48
static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
Simon Morlat's avatar
Simon Morlat committed
49
50
static void linphone_core_run_hooks(LinphoneCore *lc);
static void linphone_core_free_hooks(LinphoneCore *lc);
aymeric's avatar
aymeric committed
51
52

#include "enum.h"
53
const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
aymeric's avatar
aymeric committed
54
55
56
57
58
59
void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result);
static void toggle_video_preview(LinphoneCore *lc, bool_t val);

/* relative path where is stored local ring*/
#define LOCAL_RING "rings/oldphone.wav"
/* same for remote ring (ringback)*/
60
#define REMOTE_RING "ringback.wav"
61
62
#define HOLD_MUSIC "rings/toy-mono.wav"

aymeric's avatar
aymeric committed
63

Simon Morlat's avatar
Simon Morlat committed
64
extern SalCallbacks linphone_sal_callbacks;
aymeric's avatar
aymeric committed
65
66
67
68
69
70
71
72
73
74
75
76

void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud)
{
  obj->_func=func;
  obj->_user_data=ud;
}

int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
	if (obj->_func!=NULL) obj->_func(lc,obj->_user_data);
	return 0;
}

77

aymeric's avatar
aymeric committed
78
79
/*prevent a gcc bug with %c*/
static size_t my_strftime(char *s, size_t max, const char  *fmt,  const struct tm *tm){
Jehan Monnier's avatar
Jehan Monnier committed
80
#if !defined(_WIN32_WCE)
aymeric's avatar
aymeric committed
81
	return strftime(s, max, fmt, tm);
Jehan Monnier's avatar
Jehan Monnier committed
82
83
84
85
#else
	return 0;
	/*FIXME*/
#endif /*_WIN32_WCE*/
aymeric's avatar
aymeric committed
86
87
}

88
89
90
91
static void set_call_log_date(LinphoneCallLog *cl, const struct tm *loctime){
	my_strftime(cl->start_date,sizeof(cl->start_date),"%c",loctime);
}

92
LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
aymeric's avatar
aymeric committed
93
94
95
96
	LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
	struct tm loctime;
	cl->dir=call->dir;
#ifdef WIN32
Jehan Monnier's avatar
Jehan Monnier committed
97
#if !defined(_WIN32_WCE)
aymeric's avatar
aymeric committed
98
	loctime=*localtime(&call->start_time);
Jehan Monnier's avatar
Jehan Monnier committed
99
100
	/*FIXME*/
#endif /*_WIN32_WCE*/
aymeric's avatar
aymeric committed
101
102
103
#else
	localtime_r(&call->start_time,&loctime);
#endif
104
	set_call_log_date(cl,&loctime);
aymeric's avatar
aymeric committed
105
106
	cl->from=from;
	cl->to=to;
107
    cl->status=LinphoneCallAborted; /*default status*/
aymeric's avatar
aymeric committed
108
109
	return cl;
}
110

111
void call_logs_write_to_config_file(LinphoneCore *lc){
112
113
114
115
116
117
	MSList *elem;
	char logsection[32];
	int i;
	char *tmp;
	LpConfig *cfg=lc->config;

118
	if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return;
119

120
121
122
123
124
125
126
127
128
129
130
131
132
133
	for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
		LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
		snprintf(logsection,sizeof(logsection),"call_log_%i",i);
		lp_config_set_int(cfg,logsection,"dir",cl->dir);
		lp_config_set_int(cfg,logsection,"status",cl->status);
		tmp=linphone_address_as_string(cl->from);
		lp_config_set_string(cfg,logsection,"from",tmp);
		ms_free(tmp);
		tmp=linphone_address_as_string(cl->to);
		lp_config_set_string(cfg,logsection,"to",tmp);
		ms_free(tmp);
		lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
		lp_config_set_int(cfg,logsection,"duration",cl->duration);
		if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
134
		lp_config_set_float(cfg,logsection,"quality",cl->quality);
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
	}
	for(;i<lc->max_call_logs;++i){
		snprintf(logsection,sizeof(logsection),"call_log_%i",i);
		lp_config_clean_section(cfg,logsection);
	}
}

static void call_logs_read_from_config_file(LinphoneCore *lc){
	char logsection[32];
	int i;
	const char *tmp;
	LpConfig *cfg=lc->config;
	for(i=0;;++i){
		snprintf(logsection,sizeof(logsection),"call_log_%i",i);
		if (lp_config_has_section(cfg,logsection)){
			LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
			cl->dir=lp_config_get_int(cfg,logsection,"dir",0);
			cl->status=lp_config_get_int(cfg,logsection,"status",0);
			tmp=lp_config_get_string(cfg,logsection,"from",NULL);
			if (tmp) cl->from=linphone_address_new(tmp);
			tmp=lp_config_get_string(cfg,logsection,"to",NULL);
			if (tmp) cl->to=linphone_address_new(tmp);
			tmp=lp_config_get_string(cfg,logsection,"start_date",NULL);
			if (tmp) strncpy(cl->start_date,tmp,sizeof(cl->start_date));
			cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
			tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
			if (tmp) cl->refkey=ms_strdup(tmp);
162
			cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
163
			lc->call_logs=ms_list_append(lc->call_logs,cl);
164
		}else break;
165
166
167
168
	}
}


aymeric's avatar
aymeric committed
169

smorlat's avatar
smorlat committed
170
171
172
173
174
175
176
/**
 * @addtogroup call_logs
 * @{
**/

/**
 * Returns a human readable string describing the call.
177
 *
smorlat's avatar
smorlat committed
178
179
 * @note: the returned char* must be freed by the application (use ms_free()).
**/
aymeric's avatar
aymeric committed
180
181
char * linphone_call_log_to_str(LinphoneCallLog *cl){
	char *status;
182
	char *tmp;
183
184
	char *from=linphone_address_as_string (cl->from);
	char *to=linphone_address_as_string (cl->to);
aymeric's avatar
aymeric committed
185
186
187
188
189
190
191
192
193
194
195
196
197
	switch(cl->status){
		case LinphoneCallAborted:
			status=_("aborted");
			break;
		case LinphoneCallSuccess:
			status=_("completed");
			break;
		case LinphoneCallMissed:
			status=_("missed");
			break;
		default:
			status="unknown";
	}
198
	tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"),
aymeric's avatar
aymeric committed
199
200
			(cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"),
			cl->start_date,
201
202
			from,
			to,
aymeric's avatar
aymeric committed
203
204
205
			status,
			cl->duration/60,
			cl->duration%60);
206
207
208
	ms_free(from);
	ms_free(to);
	return tmp;
aymeric's avatar
aymeric committed
209
210
}

211
212
/**
 * Returns RTP statistics computed locally regarding the call.
213
 *
214
215
216
217
218
219
220
221
222
223
224
225
226
227
**/
const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
	return &cl->local_stats;
}

/**
 * Returns RTP statistics computed by remote end and sent back via RTCP.
 *
 * @note Not implemented yet.
**/
const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){
	return &cl->remote_stats;
}

smorlat's avatar
smorlat committed
228
229
230
231
232
233
234
235
void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){
	cl->user_pointer=up;
}

void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){
	return cl->user_pointer;
}

smorlat's avatar
smorlat committed
236
237


238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/**
 * Associate a persistent reference key to the call log.
 *
 * The reference key can be for example an id to an external database.
 * It is stored in the config file, thus can survive to process exits/restarts.
 *
**/
void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
	if (cl->refkey!=NULL){
		ms_free(cl->refkey);
		cl->refkey=NULL;
	}
	if (refkey) cl->refkey=ms_strdup(refkey);
}

/**
 * Get the persistent reference key associated to the call log.
 *
 * The reference key can be for example an id to an external database.
 * It is stored in the config file, thus can survive to process exits/restarts.
 *
**/
const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
	return cl->refkey;
}

smorlat's avatar
smorlat committed
264
265
/** @} */

aymeric's avatar
aymeric committed
266
void linphone_call_log_destroy(LinphoneCallLog *cl){
267
268
269
	if (cl->from!=NULL) linphone_address_destroy(cl->from);
	if (cl->to!=NULL) linphone_address_destroy(cl->to);
	if (cl->refkey!=NULL) ms_free(cl->refkey);
aymeric's avatar
aymeric committed
270
271
272
	ms_free(cl);
}

273
274
275
276
277
278
279
280
281
282
283
284
/**
 * Returns TRUE if the LinphoneCall asked to autoanswer
 *
**/
bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){
	//return TRUE if the unique(for the moment) incoming call asked to be autoanswered
	if(call)
		return sal_call_autoanswer_asked(call->op);
	else
		return FALSE;
}

285
286
int linphone_core_get_current_call_duration(const LinphoneCore *lc){
	LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc);
287
288
	if (call)  return linphone_call_get_duration(call);
	return -1;
289
290
291
292
}

const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){
	LinphoneCall *call=linphone_core_get_current_call(lc);
Simon Morlat's avatar
Simon Morlat committed
293
	if (call==NULL) return NULL;
294
	return linphone_call_get_remote_address(call);
smorlat's avatar
smorlat committed
295
296
}

297
298
299
300
301
302
/**
 * Enable logs in supplied FILE*.
 *
 * @ingroup misc
 *
 * @param file a C FILE* where to fprintf logs. If null stdout is used.
303
 *
304
**/
aymeric's avatar
aymeric committed
305
306
307
308
309
310
void linphone_core_enable_logs(FILE *file){
	if (file==NULL) file=stdout;
	ortp_set_log_file(file);
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
}

311
312
313
314
315
316
317
/**
 * Enable logs through the user's supplied log callback.
 *
 * @ingroup misc
 *
 * @param logfunc The address of a OrtpLogFunc callback whose protoype is
 *            	  typedef void (*OrtpLogFunc)(OrtpLogLevel lev, const char *fmt, va_list args);
318
 *
319
**/
aymeric's avatar
aymeric committed
320
321
322
323
324
void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
	ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
	ortp_set_log_handler(logfunc);
}

325
326
327
328
329
/**
 * Entirely disable logging.
 *
 * @ingroup misc
**/
aymeric's avatar
aymeric committed
330
331
332
333
334
void linphone_core_disable_logs(){
	ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
}


335
static void net_config_read (LinphoneCore *lc)
aymeric's avatar
aymeric committed
336
337
338
339
340
{
	int tmp;
	const char *tmpstr;
	LpConfig *config=lc->config;

341
	lc->net_conf.nat_address_ip = NULL;
aymeric's avatar
aymeric committed
342
343
344
345
346
347
348
349
350
351
352
353
354
355
	tmp=lp_config_get_int(config,"net","download_bw",0);
	linphone_core_set_download_bandwidth(lc,tmp);
	tmp=lp_config_get_int(config,"net","upload_bw",0);
	linphone_core_set_upload_bandwidth(lc,tmp);
	linphone_core_set_stun_server(lc,lp_config_get_string(config,"net","stun_server",NULL));
	tmpstr=lp_config_get_string(lc->config,"net","nat_address",NULL);
	if (tmpstr!=NULL && (strlen(tmpstr)<1)) tmpstr=NULL;
	linphone_core_set_nat_address(lc,tmpstr);
	tmp=lp_config_get_int(lc->config,"net","firewall_policy",0);
	linphone_core_set_firewall_policy(lc,tmp);
	tmp=lp_config_get_int(lc->config,"net","nat_sdp_only",0);
	lc->net_conf.nat_sdp_only=tmp;
	tmp=lp_config_get_int(lc->config,"net","mtu",0);
	linphone_core_set_mtu(lc,tmp);
jehan's avatar
jehan committed
356
357
358
	tmp=lp_config_get_int(lc->config,"net","download_ptime",0);
	linphone_core_set_download_ptime(lc,tmp);

aymeric's avatar
aymeric committed
359
360
}

361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
static void build_sound_devices_table(LinphoneCore *lc){
	const char **devices;
	const char **old;
	int ndev;
	int i;
	const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
	ndev=ms_list_size(elem);
	devices=ms_malloc((ndev+1)*sizeof(const char *));
	for (i=0;elem!=NULL;elem=elem->next,i++){
		devices[i]=ms_snd_card_get_string_id((MSSndCard *)elem->data);
	}
	devices[ndev]=NULL;
	old=lc->sound_conf.cards;
	lc->sound_conf.cards=devices;
	if (old!=NULL) ms_free(old);
}
aymeric's avatar
aymeric committed
377

378
static void sound_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
379
{
380
	int tmp;
aymeric's avatar
aymeric committed
381
382
	const char *tmpbuf;
	const char *devid;
383
	float gain=0;
384
#ifdef __linux
aymeric's avatar
aymeric committed
385
386
387
388
389
390
	/*alsadev let the user use custom alsa device within linphone*/
	devid=lp_config_get_string(lc->config,"sound","alsadev",NULL);
	if (devid){
		MSSndCard *card=ms_alsa_card_new_custom(devid,devid);
		ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card);
	}
Simon Morlat's avatar
Simon Morlat committed
391
	tmp=lp_config_get_int(lc->config,"sound","alsa_forced_rate",-1);
392
	if (tmp>0) ms_alsa_card_set_forced_sample_rate(tmp);
aymeric's avatar
aymeric committed
393
394
#endif
	/* retrieve all sound devices */
395
396
	build_sound_devices_table(lc);

aymeric's avatar
aymeric committed
397
398
	devid=lp_config_get_string(lc->config,"sound","playback_dev_id",NULL);
	linphone_core_set_playback_device(lc,devid);
399

aymeric's avatar
aymeric committed
400
401
	devid=lp_config_get_string(lc->config,"sound","ringer_dev_id",NULL);
	linphone_core_set_ringer_device(lc,devid);
402

aymeric's avatar
aymeric committed
403
404
	devid=lp_config_get_string(lc->config,"sound","capture_dev_id",NULL);
	linphone_core_set_capture_device(lc,devid);
405

aymeric's avatar
aymeric committed
406
407
408
409
410
411
412
413
414
415
/*
	tmp=lp_config_get_int(lc->config,"sound","play_lev",80);
	linphone_core_set_play_level(lc,tmp);
	tmp=lp_config_get_int(lc->config,"sound","ring_lev",80);
	linphone_core_set_ring_level(lc,tmp);
	tmp=lp_config_get_int(lc->config,"sound","rec_lev",80);
	linphone_core_set_rec_level(lc,tmp);
	tmpbuf=lp_config_get_string(lc->config,"sound","source","m");
	linphone_core_set_sound_source(lc,tmpbuf[0]);
*/
416

aymeric's avatar
aymeric committed
417
418
	tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	tmpbuf=lp_config_get_string(lc->config,"sound","local_ring",tmpbuf);
Jehan Monnier's avatar
Jehan Monnier committed
419
	if (ortp_file_exist(tmpbuf)==-1) {
420
		ms_warning("%s does not exist",tmpbuf);
aymeric's avatar
aymeric committed
421
422
423
424
425
426
427
		tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	}
	if (strstr(tmpbuf,".wav")==NULL){
		/* it currently uses old sound files, so replace them */
		tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
	}
	linphone_core_set_ring(lc,tmpbuf);
428

429
	tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
430
	tmpbuf=lp_config_get_string(lc->config,"sound","remote_ring",tmpbuf);
Jehan Monnier's avatar
Jehan Monnier committed
431
	if (ortp_file_exist(tmpbuf)==-1){
432
		tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
433
434
435
	}
	if (strstr(tmpbuf,".wav")==NULL){
		/* it currently uses old sound files, so replace them */
436
		tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
aymeric's avatar
aymeric committed
437
	}
438
	linphone_core_set_ringback(lc,tmpbuf);
439
440

	linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC));
aymeric's avatar
aymeric committed
441
442
	check_sound_device(lc);
	lc->sound_conf.latency=0;
Simon Morlat's avatar
Simon Morlat committed
443
#ifndef __ios 
444
    tmp=TRUE;
445
#else
Simon Morlat's avatar
Simon Morlat committed
446
    tmp=FALSE; /* on iOS we have builtin echo cancellation.*/
447
448
449
#endif
    tmp=lp_config_get_int(lc->config,"sound","echocancellation",tmp);
	linphone_core_enable_echo_cancellation(lc,tmp);
smorlat's avatar
smorlat committed
450
451
	linphone_core_enable_echo_limiter(lc,
		lp_config_get_int(lc->config,"sound","echolimiter",0));
452
453
	linphone_core_enable_agc(lc,
		lp_config_get_int(lc->config,"sound","agc",0));
454

455
456
	gain=lp_config_get_float(lc->config,"sound","playback_gain_db",0);
	linphone_core_set_playback_gain_db (lc,gain);
457
458

	linphone_core_set_remote_ringback_tone (lc,lp_config_get_string(lc->config,"sound","ringback_tone",NULL));
aymeric's avatar
aymeric committed
459
460
}

461
static void sip_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
462
463
464
{
	char *contact;
	const char *tmpstr;
465
	LCSipTransports tr;
aymeric's avatar
aymeric committed
466
467
	int i,tmp;
	int ipv6;
468

469
470
	tmp=lp_config_get_int(lc->config,"sip","use_info",0);
	linphone_core_set_use_info_for_dtmf(lc,tmp);
aymeric's avatar
aymeric committed
471

472
473
474
	if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
		sal_use_session_timers(lc->sal,200);
	}
aymeric's avatar
aymeric committed
475

476
	sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1));
477
	sal_use_101(lc->sal,lp_config_get_int(lc->config,"sip","use_101",1));
478
	sal_reuse_authorization(lc->sal, lp_config_get_int(lc->config,"sip","reuse_authorization",0));
479

480
481
	tmp=lp_config_get_int(lc->config,"sip","use_rfc2833",0);
	linphone_core_set_use_rfc2833_for_dtmf(lc,tmp);
482

aymeric's avatar
aymeric committed
483
484
485
486
487
	ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1);
	if (ipv6==-1){
		ipv6=0;
	}
	linphone_core_enable_ipv6(lc,ipv6);
488
	memset(&tr,0,sizeof(tr));
jehan's avatar
jehan committed
489
490
491
492
493
494
495
496
497
498
	if (lp_config_get_int(lc->config,"sip","sip_random_port",0)) {
		tr.udp_port=(0xDFF&+random())+1024;
	} else {
		tr.udp_port=lp_config_get_int(lc->config,"sip","sip_port",5060);
	}
	if (lp_config_get_int(lc->config,"sip","sip_tcp_random_port",0)) {
		tr.tcp_port=(0xDFF&+random())+1024;
	} else {
		tr.tcp_port=lp_config_get_int(lc->config,"sip","sip_tcp_port",0);
	}
Pierre-Eric's avatar
Pierre-Eric committed
499
500
501
502
503
	if (lp_config_get_int(lc->config,"sip","sip_tls_random_port",0)) {
		tr.tls_port=(0xDFF&+random())+1024;
	} else {
		tr.tls_port=lp_config_get_int(lc->config,"sip","sip_tls_port",0);
	}
504
505
	/*start listening on ports*/
 	linphone_core_set_sip_transports(lc,&tr);
506

aymeric's avatar
aymeric committed
507
508
	tmpstr=lp_config_get_string(lc->config,"sip","contact",NULL);
	if (tmpstr==NULL || linphone_core_set_primary_contact(lc,tmpstr)==-1) {
smorlat's avatar
smorlat committed
509
510
		const char *hostname=NULL;
		const char *username=NULL;
511
#ifdef HAVE_GETENV
smorlat's avatar
smorlat committed
512
513
		hostname=getenv("HOST");
		username=getenv("USER");
aymeric's avatar
aymeric committed
514
		if (hostname==NULL) hostname=getenv("HOSTNAME");
515
#endif /*HAVE_GETENV*/
aymeric's avatar
aymeric committed
516
517
518
519
520
521
522
523
524
525
		if (hostname==NULL)
			hostname="unknown-host";
		if (username==NULL){
			username="toto";
		}
		contact=ortp_strdup_printf("sip:%s@%s",username,hostname);
		linphone_core_set_primary_contact(lc,contact);
		ms_free(contact);
	}

526
#ifdef __linux
527
	sal_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", "/etc/ssl/certs"));
528
529
#else
	sal_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE));
530
#endif
531
	
aymeric's avatar
aymeric committed
532
533
	tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1);
	linphone_core_set_guess_hostname(lc,tmp);
534
535


aymeric's avatar
aymeric committed
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
	tmp=lp_config_get_int(lc->config,"sip","inc_timeout",15);
	linphone_core_set_inc_timeout(lc,tmp);

	/* get proxies config */
	for(i=0;; i++){
		LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc->config,i);
		if (cfg!=NULL){
			linphone_core_add_proxy_config(lc,cfg);
		}else{
			break;
		}
	}
	/* get the default proxy */
	tmp=lp_config_get_int(lc->config,"sip","default_proxy",-1);
	linphone_core_set_default_proxy_index(lc,tmp);
551

aymeric's avatar
aymeric committed
552
553
554
555
556
	/* read authentication information */
	for(i=0;; i++){
		LinphoneAuthInfo *ai=linphone_auth_info_new_from_config_file(lc->config,i);
		if (ai!=NULL){
			linphone_core_add_auth_info(lc,ai);
Simon Morlat's avatar
Simon Morlat committed
557
			linphone_auth_info_destroy(ai);
aymeric's avatar
aymeric committed
558
559
560
561
		}else{
			break;
		}
	}
562

563
	/*for tuning or test*/
aymeric's avatar
aymeric committed
564
	lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
565
	lc->sip_conf.register_only_when_network_is_up=
566
		lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1);
567
	lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",1);
jehan's avatar
jehan committed
568
	lc->sip_conf.auto_net_state_mon=lp_config_get_int(lc->config,"sip","auto_net_state_mon",1);
569
570
	lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
	sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
Simon Morlat's avatar
Simon Morlat committed
571
	sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
572
	sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
aymeric's avatar
aymeric committed
573
574
}

575
static void rtp_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
576
577
578
579
{
	int port;
	int jitt_comp;
	int nortp_timeout;
Simon Morlat's avatar
Simon Morlat committed
580
581
	bool_t rtp_no_xmit_on_audio_mute;

aymeric's avatar
aymeric committed
582
583
	port=lp_config_get_int(lc->config,"rtp","audio_rtp_port",7078);
	linphone_core_set_audio_port(lc,port);
584

aymeric's avatar
aymeric committed
585
586
587
	port=lp_config_get_int(lc->config,"rtp","video_rtp_port",9078);
	if (port==0) port=9078;
	linphone_core_set_video_port(lc,port);
588

aymeric's avatar
aymeric committed
589
	jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
590
	linphone_core_set_audio_jittcomp(lc,jitt_comp);
aymeric's avatar
aymeric committed
591
	jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
592
593
	if (jitt_comp==0) jitt_comp=60;
	lc->rtp_conf.video_jitt_comp=jitt_comp;
aymeric's avatar
aymeric committed
594
	nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
595
	linphone_core_set_nortp_timeout(lc,nortp_timeout);
Simon Morlat's avatar
Simon Morlat committed
596
	rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE);
597
	linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_no_xmit_on_audio_mute);
aymeric's avatar
aymeric committed
598
599
}

600
601
602
603
604
605
606
607
static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, const char *recv_fmtp){
	PayloadType *candidate=NULL;
	int i;
	PayloadType *it;
	for(i=0;i<127;++i){
		it=rtp_profile_get_payload(prof,i);
		if (it!=NULL && strcasecmp(mime_type,it->mime_type)==0
			&& (clock_rate==it->clock_rate || clock_rate<=0) ){
608
			if ( (recv_fmtp && it->recv_fmtp && strstr(recv_fmtp,it->recv_fmtp)!=NULL) ||
609
610
				(recv_fmtp==NULL && it->recv_fmtp==NULL) ){
				/*exact match*/
611
				if (recv_fmtp) payload_type_set_recv_fmtp(it,recv_fmtp);
612
				return it;
613
614
615
616
617
			}else {
				if (candidate){
					if (it->recv_fmtp==NULL) candidate=it;
				}else candidate=it;
			}
618
619
		}
	}
620
621
622
	if (candidate && recv_fmtp){
		payload_type_set_recv_fmtp(candidate,recv_fmtp);
	}
623
624
	return candidate;
}
aymeric's avatar
aymeric committed
625

626
static bool_t get_codec(LpConfig *config, const char* type, int index, PayloadType **ret){
aymeric's avatar
aymeric committed
627
628
629
630
	char codeckey[50];
	const char *mime,*fmtp;
	int rate,enabled;
	PayloadType *pt;
631

632
	*ret=NULL;
aymeric's avatar
aymeric committed
633
634
	snprintf(codeckey,50,"%s_%i",type,index);
	mime=lp_config_get_string(config,codeckey,"mime",NULL);
635
	if (mime==NULL || strlen(mime)==0 ) return FALSE;
636

aymeric's avatar
aymeric committed
637
638
639
	rate=lp_config_get_int(config,codeckey,"rate",8000);
	fmtp=lp_config_get_string(config,codeckey,"recv_fmtp",NULL);
	enabled=lp_config_get_int(config,codeckey,"enabled",1);
640
641
	pt=find_payload(&av_profile,mime,rate,fmtp);
	if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
aymeric's avatar
aymeric committed
642
	//ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate);
643
644
645
646
647
648
	if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported",
	    		mime,rate,fmtp ? fmtp : "");
	*ret=pt;
	return TRUE;
}

649
#define RANK_END 10000
650
651
static const char *codec_pref_order[]={
	"speex",
652
653
	"iLBC",
	"amr",
654
655
656
	"gsm",
	"pcmu",
	"pcma",
Simon Morlat's avatar
Simon Morlat committed
657
	"VP8-DRAFT-0-3-2",
658
659
660
661
662
663
664
665
666
667
	"H264",
	"MP4V-ES",
	"H263-1998",
	NULL,
};

static int find_codec_rank(const char *mime){
	int i;
	for(i=0;codec_pref_order[i]!=NULL;++i){
		if (strcasecmp(codec_pref_order[i],mime)==0)
668
			return i;
669
	}
670
	return RANK_END;
671
672
673
674
675
676
677
678
}

static int codec_compare(const PayloadType *a, const PayloadType *b){
	int ra,rb;
	ra=find_codec_rank(a->mime_type);
	rb=find_codec_rank(b->mime_type);
	if (ra>rb) return 1;
	if (ra<rb) return -1;
679
	return 0;
680
681
}

682
683
684
685
686
687
688
static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
	int i;
	for(i=0;i<127;++i){
		PayloadType *pt=rtp_profile_get_payload(&av_profile,i);
		if (pt){
			if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
				pt=NULL;
689
			else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED
690
691
692
693
694
			    && pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
				pt=NULL;
			}
			if (pt && ms_filter_codec_supported(pt->mime_type)){
				if (ms_list_find(l,pt)==NULL){
695
696
					/*unranked codecs are disabled by default*/
					if (find_codec_rank(pt->mime_type)!=RANK_END){
697
698
						payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
					}
699
700
					ms_message("Adding new codec %s/%i with fmtp %s",
					    pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
701
					l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare);
702
703
704
705
706
				}
			}
		}
	}
	return l;
aymeric's avatar
aymeric committed
707
708
}

709
710
static MSList *codec_append_if_new(MSList *l, PayloadType *pt){
	MSList *elem;
711
	for (elem=l;elem!=NULL;elem=elem->next){
712
713
714
715
716
717
718
719
		PayloadType *ept=(PayloadType*)elem->data;
		if (pt==ept)
			return l;
	}
	l=ms_list_append(l,pt);
	return l;
}

720
static void codecs_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
721
722
723
724
725
{
	int i;
	PayloadType *pt;
	MSList *audio_codecs=NULL;
	MSList *video_codecs=NULL;
726
727
728
729
	for (i=0;get_codec(lc->config,"audio_codec",i,&pt);i++){
		if (pt){
			if (!ms_filter_codec_supported(pt->mime_type)){
				ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
730
			}else audio_codecs=codec_append_if_new(audio_codecs,pt);
731
		}
aymeric's avatar
aymeric committed
732
	}
733
734
735
736
737
	audio_codecs=add_missing_codecs(SalAudio,audio_codecs);
	for (i=0;get_codec(lc->config,"video_codec",i,&pt);i++){
		if (pt){
			if (!ms_filter_codec_supported(pt->mime_type)){
				ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
738
			}else video_codecs=codec_append_if_new(video_codecs,(void *)pt);
739
		}
aymeric's avatar
aymeric committed
740
	}
741
	video_codecs=add_missing_codecs(SalVideo,video_codecs);
aymeric's avatar
aymeric committed
742
743
	linphone_core_set_audio_codecs(lc,audio_codecs);
	linphone_core_set_video_codecs(lc,video_codecs);
744
	linphone_core_update_allocated_audio_bandwidth(lc);
aymeric's avatar
aymeric committed
745
746
}

747
static void video_config_read(LinphoneCore *lc){
Simon Morlat's avatar
Simon Morlat committed
748
	int capture, display, self_view;
aymeric's avatar
aymeric committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
	const char *str;
	int ndev;
	const char **devices;
	const MSList *elem;
	int i;

	/* retrieve all video devices */
	elem=ms_web_cam_manager_get_list(ms_web_cam_manager_get());
	ndev=ms_list_size(elem);
	devices=ms_malloc((ndev+1)*sizeof(const char *));
	for (i=0;elem!=NULL;elem=elem->next,i++){
		devices[i]=ms_web_cam_get_string_id((MSWebCam *)elem->data);
	}
	devices[ndev]=NULL;
	lc->video_conf.cams=devices;

	str=lp_config_get_string(lc->config,"video","device",NULL);
	if (str && str[0]==0) str=NULL;
	linphone_core_set_video_device(lc,str);
768

smorlat's avatar
smorlat committed
769
770
771
	linphone_core_set_preferred_video_size_by_name(lc,
		lp_config_get_string(lc->config,"video","size","cif"));

772
773
774
	capture=lp_config_get_int(lc->config,"video","capture",1);
	display=lp_config_get_int(lc->config,"video","display",1);
	self_view=lp_config_get_int(lc->config,"video","self_view",1);
775
776
777
	lc->video_conf.displaytype=lp_config_get_string(lc->config,"video","displaytype",NULL);
	if(lc->video_conf.displaytype)
		ms_message("we are using a specific display:%s\n",lc->video_conf.displaytype);
aymeric's avatar
aymeric committed
778
779
#ifdef VIDEO_ENABLED
	linphone_core_enable_video(lc,capture,display);
Simon Morlat's avatar
Simon Morlat committed
780
	linphone_core_enable_self_view(lc,self_view);
aymeric's avatar
aymeric committed
781
782
783
#endif
}

784
static void ui_config_read(LinphoneCore *lc)
aymeric's avatar
aymeric committed
785
786
787
788
789
790
{
	LinphoneFriend *lf;
	int i;
	for (i=0;(lf=linphone_friend_new_from_config_file(lc,i))!=NULL;i++){
		linphone_core_add_friend(lc,lf);
	}
791
	call_logs_read_from_config_file(lc);
aymeric's avatar
aymeric committed
792
793
}

794
795
/*
static void autoreplier_config_init(LinphoneCore *lc)
aymeric's avatar
aymeric committed
796
797
798
799
800
801
802
803
804
{
	autoreplier_config_t *config=&lc->autoreplier_conf;
	config->enabled=lp_config_get_int(lc->config,"autoreplier","enabled",0);
	config->after_seconds=lp_config_get_int(lc->config,"autoreplier","after_seconds",6);
	config->max_users=lp_config_get_int(lc->config,"autoreplier","max_users",1);
	config->max_rec_time=lp_config_get_int(lc->config,"autoreplier","max_rec_time",60);
	config->max_rec_msg=lp_config_get_int(lc->config,"autoreplier","max_rec_msg",10);
	config->message=lp_config_get_string(lc->config,"autoreplier","message",NULL);
}
805
*/
aymeric's avatar
aymeric committed
806

807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
/**
 * Enable adaptive rate control (experimental feature, audio-only).
 *
 * Adaptive rate control consists in using RTCP feedback provided information to dynamically
 * control the output bitrate of the encoders, so that we can adapt to the network conditions and
 * available bandwidth.
**/
void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled){
	lp_config_set_int(lc->config,"net","adaptive_rate_control",(int)enabled);
}

/**
 * Returns whether adaptive rate control is enabled.
 *
 * See linphone_core_enable_adaptive_rate_control().
**/
bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){
824
	return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE);
825
826
}

827
828
829
830
bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){
	return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE);
}

831
832
833
834
835
836
837
838
839
840
841
842
843
844
/**
 * Sets maximum available download bandwidth
 *
 * @ingroup media_parameters
 *
 * This is IP bandwidth, in kbit/s.
 * This information is used signaled to other parties during
 * calls (within SDP messages) so that the remote end can have
 * sufficient knowledge to properly configure its audio & video
 * codec output bitrate to not overflow available bandwidth.
 *
 * @param lc the LinphoneCore object
 * @param bw the bandwidth in kbits/s, 0 for infinite
 */
aymeric's avatar
aymeric committed
845
846
void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
	lc->net_conf.download_bw=bw;
847
	if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","download_bw",bw);
aymeric's avatar
aymeric committed
848
849
}

850
851
852
853
854
855
856
857
858
859
860
861
862
/**
 * Sets maximum available upload bandwidth
 *
 * @ingroup media_parameters
 *
 * This is IP bandwidth, in kbit/s.
 * This information is used by liblinphone together with remote
 * side available bandwidth signaled in SDP messages to properly
 * configure audio & video codec's output bitrate.
 *
 * @param lc the LinphoneCore object
 * @param bw the bandwidth in kbits/s, 0 for infinite
 */
aymeric's avatar
aymeric committed
863
864
void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw){
	lc->net_conf.upload_bw=bw;
865
	if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","upload_bw",bw);
aymeric's avatar
aymeric committed
866
867
}

868
869
870
871
872
873
874
875
/**
 * Retrieve the maximum available download bandwidth.
 *
 * @ingroup media_parameters
 *
 * This value was set by linphone_core_set_download_bandwidth().
 *
**/
aymeric's avatar
aymeric committed
876
877
878
879
int linphone_core_get_download_bandwidth(const LinphoneCore *lc){
	return lc->net_conf.download_bw;
}

880
881
882
883
884
885
886
887
/**
 * Retrieve the maximum available upload bandwidth.
 *
 * @ingroup media_parameters
 *
 * This value was set by linphone_core_set_upload_bandwidth().
 *
**/
aymeric's avatar
aymeric committed
888
889
890
int linphone_core_get_upload_bandwidth(const LinphoneCore *lc){
	return lc->net_conf.upload_bw;
}
jehan's avatar
jehan committed
891
/**
892
 * Set audio packetization time linphone expects to receive from peer
jehan's avatar
jehan committed
893
894
 */
void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime) {
895
	lc->net_conf.down_ptime=ptime;
jehan's avatar
jehan committed
896
}
897

898
899
900
901
/**
 * Get audio packetization time linphone expects to receive from peer
 */
int linphone_core_get_download_ptime(LinphoneCore *lc) {
902
	return lc->net_conf.down_ptime;
jehan's avatar
jehan committed
903
904
}

905
906
907
908
909
910
/**
 * Set audio packetization time linphone will send (in absence of requirement from peer)
 * A value of 0 stands for the current codec default packetization time.
 *
**/
void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){
911
	lp_config_set_int(lc->config,"rtp","upload_ptime",ptime);
912
913
914
915
916
917
918
919
}

/**
 * Set audio packetization time linphone will send (in absence of requirement from peer)
 * A value of 0 stands for the current codec default packetization time.
 *
**/
int linphone_core_get_upload_ptime(LinphoneCore *lc){
920
	return lp_config_get_int(lc->config,"rtp","upload_ptime",0);
921
922
923
}


aymeric's avatar
aymeric committed
924

925
926
927
928
929
930
/**
 * Returns liblinphone's version as a string.
 *
 * @ingroup misc
 *
**/
aymeric's avatar
aymeric committed
931
932
933
934
const char * linphone_core_get_version(void){
	return liblinphone_version;
}

935
static void linphone_core_assign_payload_type(LinphoneCore *lc, PayloadType *const_pt, int number, const char *recv_fmtp){
936
937
	PayloadType *pt;
	pt=payload_type_clone(const_pt);
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
	if (number==-1){
		/*look for a free number */
		MSList *elem;
		int i;
		for(i=lc->dyn_pt;i<=127;++i){
			bool_t already_assigned=FALSE;
			for(elem=lc->payload_types;elem!=NULL;elem=elem->next){
				PayloadType *it=(PayloadType*)elem->data;
				if (payload_type_get_number(it)==i){
					already_assigned=TRUE;
					break;
				}
			}
			if (!already_assigned){
				number=i;
				lc->dyn_pt=i+1;
				break;
			}
		}
		if (number==-1){
			ms_fatal("FIXME: too many codecs, no more free numbers.");
		}
	}
	ms_message("assigning %s/%i payload type number %i",pt->mime_type,pt->clock_rate,number);
962
	payload_type_set_number(pt,number);
963
964
	if (recv_fmtp!=NULL) payload_type_set_recv_fmtp(pt,recv_fmtp);
	rtp_profile_set_payload(&av_profile,number,pt);
965
	lc->payload_types=ms_list_append(lc->payload_types,pt);
966
967
}

968
969
970
971
static void linphone_core_free_payload_types(LinphoneCore *lc){
	ms_list_for_each(lc->payload_types,(void (*)(void*))payload_type_destroy);
	ms_list_free(lc->payload_types);
	lc->payload_types=NULL;
972
}
973

974
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){
Simon Morlat's avatar
Simon Morlat committed
975
	lc->state=gstate;
976
977
978
979
	if (lc->vtable.global_state_changed){
		lc->vtable.global_state_changed(lc,gstate,message);
	}
}
980
981
982
static void misc_config_read (LinphoneCore *lc) {
	LpConfig *config=lc->config;
    lc->max_call_logs=lp_config_get_int(config,"misc","history_max_size",15);
983
    lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS);
984
}
985

986
static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path,
987
    const char *factory_config_path, void * userdata)
aymeric's avatar
aymeric committed
988
989
990
{
	memset (lc, 0, sizeof (LinphoneCore));
	lc->data=userdata;
991
	lc->ringstream_autorelease=TRUE;
992

aymeric's avatar
aymeric committed
993
994
	memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));

995
	linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
aymeric's avatar
aymeric committed
996
	ortp_init();
997
998
999
1000
1001
1002
1003
1004
	lc->dyn_pt=96;
	linphone_core_assign_payload_type(lc,&payload_type_pcmu8000,0,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_gsm,3,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_pcma8000,8,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_speex_nb,110,"vbr=on");
	linphone_core_assign_payload_type(lc,&payload_type_speex_wb,111,"vbr=on");
	linphone_core_assign_payload_type(lc,&payload_type_speex_uwb,112,"vbr=on");
	linphone_core_assign_payload_type(lc,&payload_type_telephone_event,101,"0-11");
Sylvain Berfini's avatar
Sylvain Berfini committed
1005
	linphone_core_assign_payload_type(lc,&payload_type_g722,9,NULL);
1006

1007
1008
1009
1010
1011
1012
1013
1014
#if defined(ANDROID) || defined (__IPHONE_OS_VERSION_MIN_REQUIRED)
	/*shorten the DNS lookup time and send more retransmissions on mobiles:
	 - to workaround potential packet losses
	 - to avoid hanging for 30 seconds when the network doesn't work despite the phone thinks it does.
	 */
	_linphone_core_configure_resolver();
#endif

1015
1016
1017
1018
1019
#ifdef ENABLE_NONSTANDARD_GSM
	{
		PayloadType *pt;
		pt=payload_type_clone(&payload_type_gsm);
		pt->clock_rate=11025;
1020
		linphone_core_assign_payload_type(lc,pt,-1,NULL);
1021
		pt->clock_rate=22050;
1022
1023
		linphone_core_assign_payload_type(lc,pt,-1,NULL);
		payload_type_destroy(pt);
1024
	}
aymeric's avatar
aymeric committed
1025
1026
#endif

1027
#ifdef VIDEO_ENABLED
1028
1029
1030
1031
1032
1033
1034
	linphone_core_assign_payload_type(lc,&payload_type_h263,34,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_h263_1998,98,"CIF=1;QCIF=1");
	linphone_core_assign_payload_type(lc,&payload_type_mp4v,99,"profile-level-id=3");
	linphone_core_assign_payload_type(lc,&payload_type_h264,102,"profile-level-id=428014");
	linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL);
1035
	/* due to limited space in SDP, we have to disable this h264 line which is normally no more necessary */
1036
	/* linphone_core_assign_payload_type(&payload_type_h264,-1,"packetization-mode=1;profile-level-id=428014");*/
1037
1038
#endif

1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
	/*add all payload type for which we don't care about the number */
	linphone_core_assign_payload_type(lc,&payload_type_ilbc,-1,"mode=30");
	linphone_core_assign_payload_type(lc,&payload_type_amr,-1,"octet-align=1");
	linphone_core_assign_payload_type(lc,&payload_type_lpc1015,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_g726_16,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_g726_24,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_g726_32,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_g726_40,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_16,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_24,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_32,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_40,-1,NULL);
jehan's avatar
jehan committed
1051
1052
1053
1054
1055
	linphone_core_assign_payload_type(lc,&payload_type_silk_nb,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_silk_mb,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_silk_wb,-1,NULL);
	linphone_core_assign_payload_type(lc,&payload_type_silk_swb,-1,NULL);
	
aymeric's avatar
aymeric committed
1056
	ms_init();
1057
1058
1059
1060
	/* create a mediastreamer2 event queue and set it as global */
	/* This allows to run event's callback in linphone_core_iterate() */
	lc->msevq=ms_event_queue_new();
	ms_set_global_event_queue(lc->msevq);
1061

aymeric's avatar
aymeric committed
1062
	lc->config=lp_config_new(config_path);
1063
1064
	if (factory_config_path)
		lp_config_read_file(lc->config,factory_config_path);
1065

1066
	lc->sal=sal_init();
Simon Morlat's avatar
Simon Morlat committed
1067
	sal_set_user_pointer(lc->sal,lc);
Simon Morlat's avatar
Simon Morlat committed
1068
	sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
1069

smorlat's avatar
smorlat committed
1070
	sip_setup_register_all();
aymeric's avatar
aymeric committed
1071
1072
1073
1074
1075
1076
1077
	sound_config_read(lc);
	net_config_read(lc);
	rtp_config_read(lc);
	codecs_config_read(lc);
	sip_config_read(lc); /* this will start eXosip*/
	video_config_read(lc);
	//autoreplier_config_init(&lc->autoreplier_conf);
1078
	lc->presence_mode=LinphoneStatusOnline;
1079
	misc_config_read(lc);
aymeric's avatar
aymeric committed
1080
	ui_config_read(lc);
1081
1082
	if (lc->vtable.display_status)
		lc->vtable.display_status(lc,_("Ready"));
jehan's avatar
jehan committed
1083
	lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
1084
	linphone_core_set_state(lc,LinphoneGlobalOn,"Ready");
aymeric's avatar
aymeric committed
1085
1086
}

1087
1088
1089
/**
 * Instanciates a LinphoneCore object.
 * @ingroup initializing
1090
 *
1091
1092
1093
1094
 * The LinphoneCore object is the primary handle for doing all phone actions.
 * It should be unique within your application.
 * @param vtable a LinphoneCoreVTable structure holding your application callbacks
 * @param config_path a path to a config file. If it does not exists it will be created.
Simon Morlat's avatar
Simon Morlat committed
1095
1096
1097
 *        The config file is used to store all settings, call logs, friends, proxies... so that all these settings
 *	       become persistent over the life of the LinphoneCore object.
 *	       It is allowed to set a NULL config file. In that case LinphoneCore will not store any settings.
1098
 * @param factory_config_path a path to a read-only config file that can be used to
1099
1100
1101
1102
1103
 *        to store hard-coded preference such as proxy settings or internal preferences.
 *        The settings in this factory file always override the one in the normal config file.
 *        It is OPTIONAL, use NULL if unneeded.
 * @param userdata an opaque user pointer that can be retrieved at any time (for example in
 *        callbacks) using linphone_core_get_user_data().
1104
 *
1105
**/
aymeric's avatar
aymeric committed
1106
LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
1107
						const char *config_path, const char *factory_config_path, void * userdata)
aymeric's avatar
aymeric committed
1108
1109
{
	LinphoneCore *core=ms_new(LinphoneCore,1);
1110
	linphone_core_init(core,vtable,config_path, factory_config_path, userdata);
aymeric's avatar
aymeric committed
1111
1112
1113
	return core;
}

1114
1115
1116