]> sjero.net Git - linphone/blob - coreapi/linphonecore.c
7f706cc815789f4a2cabc603c173e4e6f93737e3
[linphone] / coreapi / linphonecore.c
1 /*
2 linphone
3 Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (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 */
19
20 #include "linphonecore.h"
21 #include "sipsetup.h"
22 #include "lpconfig.h"
23 #include "private.h"
24
25 #include <ortp/telephonyevents.h>
26 #include "mediastreamer2/mediastream.h"
27 #include "mediastreamer2/mseventqueue.h"
28 #include "mediastreamer2/msvolume.h"
29 #include "mediastreamer2/msequalizer.h"
30 #include "mediastreamer2/dtmfgen.h"
31
32 #ifdef INET6
33 #ifndef WIN32
34 #include <netdb.h>
35 #endif
36 #endif
37
38 /*#define UNSTANDART_GSM_11K 1*/
39
40 #define ROOT_CA_FILE PACKAGE_DATA_DIR "/linphone/rootca.pem"
41
42 static const char *liblinphone_version=LIBLINPHONE_VERSION;
43 static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime);
44 static void linphone_core_run_hooks(LinphoneCore *lc);
45 static void linphone_core_free_hooks(LinphoneCore *lc);
46
47 #include "enum.h"
48 const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc);
49 void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result);
50 static void toggle_video_preview(LinphoneCore *lc, bool_t val);
51
52 /* relative path where is stored local ring*/
53 #define LOCAL_RING "rings/oldphone.wav"
54 /* same for remote ring (ringback)*/
55 #define REMOTE_RING "ringback.wav"
56 #define HOLD_MUSIC "rings/toy-mono.wav"
57
58
59 extern SalCallbacks linphone_sal_callbacks;
60
61 void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud)
62 {
63   obj->_func=func;
64   obj->_user_data=ud;
65 }
66
67 int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){
68         if (obj->_func!=NULL) obj->_func(lc,obj->_user_data);
69         return 0;
70 }
71
72
73 /*prevent a gcc bug with %c*/
74 static size_t my_strftime(char *s, size_t max, const char  *fmt,  const struct tm *tm){
75 #if !defined(_WIN32_WCE)
76         return strftime(s, max, fmt, tm);
77 #else
78         return 0;
79         /*FIXME*/
80 #endif /*_WIN32_WCE*/
81 }
82
83 static void set_call_log_date(LinphoneCallLog *cl, const struct tm *loctime){
84         my_strftime(cl->start_date,sizeof(cl->start_date),"%c",loctime);
85 }
86
87 LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
88         LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
89         struct tm loctime;
90         cl->dir=call->dir;
91 #ifdef WIN32
92 #if !defined(_WIN32_WCE)
93         loctime=*localtime(&call->start_time);
94         /*FIXME*/
95 #endif /*_WIN32_WCE*/
96 #else
97         localtime_r(&call->start_time,&loctime);
98 #endif
99         set_call_log_date(cl,&loctime);
100         cl->from=from;
101         cl->to=to;
102     cl->status=LinphoneCallAborted; /*default status*/
103         return cl;
104 }
105
106 void call_logs_write_to_config_file(LinphoneCore *lc){
107         MSList *elem;
108         char logsection[32];
109         int i;
110         char *tmp;
111         LpConfig *cfg=lc->config;
112
113         if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return;
114
115         for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
116                 LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
117                 snprintf(logsection,sizeof(logsection),"call_log_%i",i);
118                 lp_config_set_int(cfg,logsection,"dir",cl->dir);
119                 lp_config_set_int(cfg,logsection,"status",cl->status);
120                 tmp=linphone_address_as_string(cl->from);
121                 lp_config_set_string(cfg,logsection,"from",tmp);
122                 ms_free(tmp);
123                 tmp=linphone_address_as_string(cl->to);
124                 lp_config_set_string(cfg,logsection,"to",tmp);
125                 ms_free(tmp);
126                 lp_config_set_string(cfg,logsection,"start_date",cl->start_date);
127                 lp_config_set_int(cfg,logsection,"duration",cl->duration);
128                 if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey);
129                 lp_config_set_float(cfg,logsection,"quality",cl->quality);
130         }
131         for(;i<lc->max_call_logs;++i){
132                 snprintf(logsection,sizeof(logsection),"call_log_%i",i);
133                 lp_config_clean_section(cfg,logsection);
134         }
135 }
136
137 static void call_logs_read_from_config_file(LinphoneCore *lc){
138         char logsection[32];
139         int i;
140         const char *tmp;
141         LpConfig *cfg=lc->config;
142         for(i=0;;++i){
143                 snprintf(logsection,sizeof(logsection),"call_log_%i",i);
144                 if (lp_config_has_section(cfg,logsection)){
145                         LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1);
146                         cl->dir=lp_config_get_int(cfg,logsection,"dir",0);
147                         cl->status=lp_config_get_int(cfg,logsection,"status",0);
148                         tmp=lp_config_get_string(cfg,logsection,"from",NULL);
149                         if (tmp) cl->from=linphone_address_new(tmp);
150                         tmp=lp_config_get_string(cfg,logsection,"to",NULL);
151                         if (tmp) cl->to=linphone_address_new(tmp);
152                         tmp=lp_config_get_string(cfg,logsection,"start_date",NULL);
153                         if (tmp) strncpy(cl->start_date,tmp,sizeof(cl->start_date));
154                         cl->duration=lp_config_get_int(cfg,logsection,"duration",0);
155                         tmp=lp_config_get_string(cfg,logsection,"refkey",NULL);
156                         if (tmp) cl->refkey=ms_strdup(tmp);
157                         cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
158                         lc->call_logs=ms_list_append(lc->call_logs,cl);
159                 }else break;
160         }
161 }
162
163
164
165 /**
166  * @addtogroup call_logs
167  * @{
168 **/
169
170 /**
171  * Returns a human readable string describing the call.
172  *
173  * @note: the returned char* must be freed by the application (use ms_free()).
174 **/
175 char * linphone_call_log_to_str(LinphoneCallLog *cl){
176         char *status;
177         char *tmp;
178         char *from=linphone_address_as_string (cl->from);
179         char *to=linphone_address_as_string (cl->to);
180         switch(cl->status){
181                 case LinphoneCallAborted:
182                         status=_("aborted");
183                         break;
184                 case LinphoneCallSuccess:
185                         status=_("completed");
186                         break;
187                 case LinphoneCallMissed:
188                         status=_("missed");
189                         break;
190                 default:
191                         status="unknown";
192         }
193         tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"),
194                         (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"),
195                         cl->start_date,
196                         from,
197                         to,
198                         status,
199                         cl->duration/60,
200                         cl->duration%60);
201         ms_free(from);
202         ms_free(to);
203         return tmp;
204 }
205
206 /**
207  * Returns RTP statistics computed locally regarding the call.
208  *
209 **/
210 const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
211         return &cl->local_stats;
212 }
213
214 /**
215  * Returns RTP statistics computed by remote end and sent back via RTCP.
216  *
217  * @note Not implemented yet.
218 **/
219 const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){
220         return &cl->remote_stats;
221 }
222
223 void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){
224         cl->user_pointer=up;
225 }
226
227 void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){
228         return cl->user_pointer;
229 }
230
231
232
233 /**
234  * Associate a persistent reference key to the call log.
235  *
236  * The reference key can be for example an id to an external database.
237  * It is stored in the config file, thus can survive to process exits/restarts.
238  *
239 **/
240 void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){
241         if (cl->refkey!=NULL){
242                 ms_free(cl->refkey);
243                 cl->refkey=NULL;
244         }
245         if (refkey) cl->refkey=ms_strdup(refkey);
246 }
247
248 /**
249  * Get the persistent reference key associated to the call log.
250  *
251  * The reference key can be for example an id to an external database.
252  * It is stored in the config file, thus can survive to process exits/restarts.
253  *
254 **/
255 const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){
256         return cl->refkey;
257 }
258
259 /** @} */
260
261 void linphone_call_log_destroy(LinphoneCallLog *cl){
262         if (cl->from!=NULL) linphone_address_destroy(cl->from);
263         if (cl->to!=NULL) linphone_address_destroy(cl->to);
264         if (cl->refkey!=NULL) ms_free(cl->refkey);
265         ms_free(cl);
266 }
267
268 /**
269  * Returns TRUE if the LinphoneCall asked to autoanswer
270  *
271 **/
272 bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){
273         //return TRUE if the unique(for the moment) incoming call asked to be autoanswered
274         if(call)
275                 return sal_call_autoanswer_asked(call->op);
276         else
277                 return FALSE;
278 }
279
280 int linphone_core_get_current_call_duration(const LinphoneCore *lc){
281         LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc);
282         if (call)  return linphone_call_get_duration(call);
283         return -1;
284 }
285
286 const LinphoneAddress *linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc){
287         LinphoneCall *call=linphone_core_get_current_call(lc);
288         if (call==NULL) return NULL;
289         return linphone_call_get_remote_address(call);
290 }
291
292 /**
293  * Enable logs in supplied FILE*.
294  *
295  * @ingroup misc
296  *
297  * @param file a C FILE* where to fprintf logs. If null stdout is used.
298  *
299 **/
300 void linphone_core_enable_logs(FILE *file){
301         if (file==NULL) file=stdout;
302         ortp_set_log_file(file);
303         ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
304 }
305
306 /**
307  * Enable logs through the user's supplied log callback.
308  *
309  * @ingroup misc
310  *
311  * @param logfunc The address of a OrtpLogFunc callback whose protoype is
312  *                typedef void (*OrtpLogFunc)(OrtpLogLevel lev, const char *fmt, va_list args);
313  *
314 **/
315 void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
316         ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
317         ortp_set_log_handler(logfunc);
318 }
319
320 /**
321  * Entirely disable logging.
322  *
323  * @ingroup misc
324 **/
325 void linphone_core_disable_logs(){
326         ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL);
327 }
328
329
330 static void net_config_read (LinphoneCore *lc)
331 {
332         int tmp;
333         const char *tmpstr;
334         LpConfig *config=lc->config;
335
336         lc->net_conf.nat_address_ip = NULL;
337         tmp=lp_config_get_int(config,"net","download_bw",0);
338         linphone_core_set_download_bandwidth(lc,tmp);
339         tmp=lp_config_get_int(config,"net","upload_bw",0);
340         linphone_core_set_upload_bandwidth(lc,tmp);
341         linphone_core_set_stun_server(lc,lp_config_get_string(config,"net","stun_server",NULL));
342         tmpstr=lp_config_get_string(lc->config,"net","nat_address",NULL);
343         if (tmpstr!=NULL && (strlen(tmpstr)<1)) tmpstr=NULL;
344         linphone_core_set_nat_address(lc,tmpstr);
345         tmp=lp_config_get_int(lc->config,"net","firewall_policy",0);
346         linphone_core_set_firewall_policy(lc,tmp);
347         tmp=lp_config_get_int(lc->config,"net","nat_sdp_only",0);
348         lc->net_conf.nat_sdp_only=tmp;
349         tmp=lp_config_get_int(lc->config,"net","mtu",0);
350         linphone_core_set_mtu(lc,tmp);
351         tmp=lp_config_get_int(lc->config,"net","download_ptime",0);
352         linphone_core_set_download_ptime(lc,tmp);
353
354 }
355
356 static void build_sound_devices_table(LinphoneCore *lc){
357         const char **devices;
358         const char **old;
359         int ndev;
360         int i;
361         const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
362         ndev=ms_list_size(elem);
363         devices=ms_malloc((ndev+1)*sizeof(const char *));
364         for (i=0;elem!=NULL;elem=elem->next,i++){
365                 devices[i]=ms_snd_card_get_string_id((MSSndCard *)elem->data);
366         }
367         devices[ndev]=NULL;
368         old=lc->sound_conf.cards;
369         lc->sound_conf.cards=devices;
370         if (old!=NULL) ms_free(old);
371 }
372
373 static void sound_config_read(LinphoneCore *lc)
374 {
375         int tmp;
376         const char *tmpbuf;
377         const char *devid;
378         float gain=0;
379 #ifdef __linux
380         /*alsadev let the user use custom alsa device within linphone*/
381         devid=lp_config_get_string(lc->config,"sound","alsadev",NULL);
382         if (devid){
383                 MSSndCard *card=ms_alsa_card_new_custom(devid,devid);
384                 ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card);
385         }
386         tmp=lp_config_get_int(lc->config,"sound","alsa_forced_rate",-1);
387         if (tmp>0) ms_alsa_card_set_forced_sample_rate(tmp);
388 #endif
389         /* retrieve all sound devices */
390         build_sound_devices_table(lc);
391
392         devid=lp_config_get_string(lc->config,"sound","playback_dev_id",NULL);
393         linphone_core_set_playback_device(lc,devid);
394
395         devid=lp_config_get_string(lc->config,"sound","ringer_dev_id",NULL);
396         linphone_core_set_ringer_device(lc,devid);
397
398         devid=lp_config_get_string(lc->config,"sound","capture_dev_id",NULL);
399         linphone_core_set_capture_device(lc,devid);
400
401 /*
402         tmp=lp_config_get_int(lc->config,"sound","play_lev",80);
403         linphone_core_set_play_level(lc,tmp);
404         tmp=lp_config_get_int(lc->config,"sound","ring_lev",80);
405         linphone_core_set_ring_level(lc,tmp);
406         tmp=lp_config_get_int(lc->config,"sound","rec_lev",80);
407         linphone_core_set_rec_level(lc,tmp);
408         tmpbuf=lp_config_get_string(lc->config,"sound","source","m");
409         linphone_core_set_sound_source(lc,tmpbuf[0]);
410 */
411
412         tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
413         tmpbuf=lp_config_get_string(lc->config,"sound","local_ring",tmpbuf);
414         if (ortp_file_exist(tmpbuf)==-1) {
415                 ms_warning("%s does not exist",tmpbuf);
416                 tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
417         }
418         if (strstr(tmpbuf,".wav")==NULL){
419                 /* it currently uses old sound files, so replace them */
420                 tmpbuf=PACKAGE_SOUND_DIR "/" LOCAL_RING;
421         }
422         linphone_core_set_ring(lc,tmpbuf);
423
424         tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
425         tmpbuf=lp_config_get_string(lc->config,"sound","remote_ring",tmpbuf);
426         if (ortp_file_exist(tmpbuf)==-1){
427                 tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
428         }
429         if (strstr(tmpbuf,".wav")==NULL){
430                 /* it currently uses old sound files, so replace them */
431                 tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
432         }
433         linphone_core_set_ringback(lc,tmpbuf);
434
435         linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC));
436         check_sound_device(lc);
437         lc->sound_conf.latency=0;
438 #ifndef __ios 
439     tmp=TRUE;
440 #else
441     tmp=FALSE; /* on iOS we have builtin echo cancellation.*/
442 #endif
443     tmp=lp_config_get_int(lc->config,"sound","echocancellation",tmp);
444         linphone_core_enable_echo_cancellation(lc,tmp);
445         linphone_core_enable_echo_limiter(lc,
446                 lp_config_get_int(lc->config,"sound","echolimiter",0));
447         linphone_core_enable_agc(lc,
448                 lp_config_get_int(lc->config,"sound","agc",0));
449
450         gain=lp_config_get_float(lc->config,"sound","playback_gain_db",0);
451         linphone_core_set_playback_gain_db (lc,gain);
452
453         linphone_core_set_remote_ringback_tone (lc,lp_config_get_string(lc->config,"sound","ringback_tone",NULL));
454 }
455
456 static void sip_config_read(LinphoneCore *lc)
457 {
458         char *contact;
459         const char *tmpstr;
460         LCSipTransports tr;
461         int i,tmp;
462         int ipv6;
463
464         tmp=lp_config_get_int(lc->config,"sip","use_info",0);
465         linphone_core_set_use_info_for_dtmf(lc,tmp);
466
467         if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){
468                 sal_use_session_timers(lc->sal,200);
469         }
470
471         sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1));
472         sal_use_101(lc->sal,lp_config_get_int(lc->config,"sip","use_101",1));
473         sal_reuse_authorization(lc->sal, lp_config_get_int(lc->config,"sip","reuse_authorization",0));
474
475         tmp=lp_config_get_int(lc->config,"sip","use_rfc2833",0);
476         linphone_core_set_use_rfc2833_for_dtmf(lc,tmp);
477
478         ipv6=lp_config_get_int(lc->config,"sip","use_ipv6",-1);
479         if (ipv6==-1){
480                 ipv6=0;
481         }
482         linphone_core_enable_ipv6(lc,ipv6);
483         memset(&tr,0,sizeof(tr));
484         if (lp_config_get_int(lc->config,"sip","sip_random_port",0)) {
485                 tr.udp_port=(0xDFF&+random())+1024;
486         } else {
487                 tr.udp_port=lp_config_get_int(lc->config,"sip","sip_port",5060);
488         }
489         if (lp_config_get_int(lc->config,"sip","sip_tcp_random_port",0)) {
490                 tr.tcp_port=(0xDFF&+random())+1024;
491         } else {
492                 tr.tcp_port=lp_config_get_int(lc->config,"sip","sip_tcp_port",0);
493         }
494         if (lp_config_get_int(lc->config,"sip","sip_tls_random_port",0)) {
495                 tr.tls_port=(0xDFF&+random())+1024;
496         } else {
497                 tr.tls_port=lp_config_get_int(lc->config,"sip","sip_tls_port",0);
498         }
499         /*start listening on ports*/
500         linphone_core_set_sip_transports(lc,&tr);
501
502         tmpstr=lp_config_get_string(lc->config,"sip","contact",NULL);
503         if (tmpstr==NULL || linphone_core_set_primary_contact(lc,tmpstr)==-1) {
504                 const char *hostname=NULL;
505                 const char *username=NULL;
506 #ifdef HAVE_GETENV
507                 hostname=getenv("HOST");
508                 username=getenv("USER");
509                 if (hostname==NULL) hostname=getenv("HOSTNAME");
510 #endif /*HAVE_GETENV*/
511                 if (hostname==NULL)
512                         hostname="unknown-host";
513                 if (username==NULL){
514                         username="toto";
515                 }
516                 contact=ortp_strdup_printf("sip:%s@%s",username,hostname);
517                 linphone_core_set_primary_contact(lc,contact);
518                 ms_free(contact);
519         }
520
521 #ifdef __linux
522         sal_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", "/etc/ssl/certs"));
523 #else
524         sal_root_ca(lc->sal, lp_config_get_string(lc->config,"sip","root_ca", ROOT_CA_FILE));
525 #endif
526
527         tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1);
528         linphone_core_set_guess_hostname(lc,tmp);
529
530
531         tmp=lp_config_get_int(lc->config,"sip","inc_timeout",15);
532         linphone_core_set_inc_timeout(lc,tmp);
533
534         /* get proxies config */
535         for(i=0;; i++){
536                 LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc->config,i);
537                 if (cfg!=NULL){
538                         linphone_core_add_proxy_config(lc,cfg);
539                 }else{
540                         break;
541                 }
542         }
543         /* get the default proxy */
544         tmp=lp_config_get_int(lc->config,"sip","default_proxy",-1);
545         linphone_core_set_default_proxy_index(lc,tmp);
546
547         /* read authentication information */
548         for(i=0;; i++){
549                 LinphoneAuthInfo *ai=linphone_auth_info_new_from_config_file(lc->config,i);
550                 if (ai!=NULL){
551                         linphone_core_add_auth_info(lc,ai);
552                         linphone_auth_info_destroy(ai);
553                 }else{
554                         break;
555                 }
556         }
557
558         /*for tuning or test*/
559         lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
560         lc->sip_conf.register_only_when_network_is_up=
561                 lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1);
562         lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",1);
563         lc->sip_conf.auto_net_state_mon=lp_config_get_int(lc->config,"sip","auto_net_state_mon",1);
564         lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
565         sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
566         sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
567         sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
568 }
569
570 static void rtp_config_read(LinphoneCore *lc)
571 {
572         int port;
573         int jitt_comp;
574         int nortp_timeout;
575         bool_t rtp_no_xmit_on_audio_mute;
576
577         port=lp_config_get_int(lc->config,"rtp","audio_rtp_port",7078);
578         linphone_core_set_audio_port(lc,port);
579
580         port=lp_config_get_int(lc->config,"rtp","video_rtp_port",9078);
581         if (port==0) port=9078;
582         linphone_core_set_video_port(lc,port);
583
584         jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
585         linphone_core_set_audio_jittcomp(lc,jitt_comp);
586         jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
587         if (jitt_comp==0) jitt_comp=60;
588         lc->rtp_conf.video_jitt_comp=jitt_comp;
589         nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
590         linphone_core_set_nortp_timeout(lc,nortp_timeout);
591         rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE);
592         linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_no_xmit_on_audio_mute);
593 }
594
595 static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, const char *recv_fmtp){
596         PayloadType *candidate=NULL;
597         int i;
598         PayloadType *it;
599         for(i=0;i<127;++i){
600                 it=rtp_profile_get_payload(prof,i);
601                 if (it!=NULL && strcasecmp(mime_type,it->mime_type)==0
602                         && (clock_rate==it->clock_rate || clock_rate<=0) ){
603                         if ( (recv_fmtp && it->recv_fmtp && strstr(recv_fmtp,it->recv_fmtp)!=NULL) ||
604                                 (recv_fmtp==NULL && it->recv_fmtp==NULL) ){
605                                 /*exact match*/
606                                 if (recv_fmtp) payload_type_set_recv_fmtp(it,recv_fmtp);
607                                 return it;
608                         }else {
609                                 if (candidate){
610                                         if (it->recv_fmtp==NULL) candidate=it;
611                                 }else candidate=it;
612                         }
613                 }
614         }
615         if (candidate && recv_fmtp){
616                 payload_type_set_recv_fmtp(candidate,recv_fmtp);
617         }
618         return candidate;
619 }
620
621 static bool_t get_codec(LpConfig *config, const char* type, int index, PayloadType **ret){
622         char codeckey[50];
623         const char *mime,*fmtp;
624         int rate,enabled;
625         PayloadType *pt;
626
627         *ret=NULL;
628         snprintf(codeckey,50,"%s_%i",type,index);
629         mime=lp_config_get_string(config,codeckey,"mime",NULL);
630         if (mime==NULL || strlen(mime)==0 ) return FALSE;
631
632         rate=lp_config_get_int(config,codeckey,"rate",8000);
633         fmtp=lp_config_get_string(config,codeckey,"recv_fmtp",NULL);
634         enabled=lp_config_get_int(config,codeckey,"enabled",1);
635         pt=find_payload(&av_profile,mime,rate,fmtp);
636         if (pt && enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED;
637         //ms_message("Found codec %s/%i",pt->mime_type,pt->clock_rate);
638         if (pt==NULL) ms_warning("Ignoring codec config %s/%i with fmtp=%s because unsupported",
639                         mime,rate,fmtp ? fmtp : "");
640         *ret=pt;
641         return TRUE;
642 }
643
644 #define RANK_END 10000
645 static const char *codec_pref_order[]={
646         "speex",
647         "iLBC",
648         "amr",
649         "gsm",
650         "pcmu",
651         "pcma",
652         "VP8-DRAFT-0-3-2",
653         "H264",
654         "MP4V-ES",
655         "H263-1998",
656         NULL,
657 };
658
659 static int find_codec_rank(const char *mime){
660         int i;
661         for(i=0;codec_pref_order[i]!=NULL;++i){
662                 if (strcasecmp(codec_pref_order[i],mime)==0)
663                         return i;
664         }
665         return RANK_END;
666 }
667
668 static int codec_compare(const PayloadType *a, const PayloadType *b){
669         int ra,rb;
670         ra=find_codec_rank(a->mime_type);
671         rb=find_codec_rank(b->mime_type);
672         if (ra>rb) return 1;
673         if (ra<rb) return -1;
674         return 0;
675 }
676
677 static MSList *add_missing_codecs(SalStreamType mtype, MSList *l){
678         int i;
679         for(i=0;i<127;++i){
680                 PayloadType *pt=rtp_profile_get_payload(&av_profile,i);
681                 if (pt){
682                         if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
683                                 pt=NULL;
684                         else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED
685                             && pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
686                                 pt=NULL;
687                         }
688                         if (pt && ms_filter_codec_supported(pt->mime_type)){
689                                 if (ms_list_find(l,pt)==NULL){
690                                         /*unranked codecs are disabled by default*/
691                                         if (find_codec_rank(pt->mime_type)!=RANK_END){
692                                                 payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED);
693                                         }
694                                         ms_message("Adding new codec %s/%i with fmtp %s",
695                                             pt->mime_type,pt->clock_rate,pt->recv_fmtp ? pt->recv_fmtp : "");
696                                         l=ms_list_insert_sorted(l,pt,(int (*)(const void *, const void *))codec_compare);
697                                 }
698                         }
699                 }
700         }
701         return l;
702 }
703
704 static MSList *codec_append_if_new(MSList *l, PayloadType *pt){
705         MSList *elem;
706         for (elem=l;elem!=NULL;elem=elem->next){
707                 PayloadType *ept=(PayloadType*)elem->data;
708                 if (pt==ept)
709                         return l;
710         }
711         l=ms_list_append(l,pt);
712         return l;
713 }
714
715 static void codecs_config_read(LinphoneCore *lc)
716 {
717         int i;
718         PayloadType *pt;
719         MSList *audio_codecs=NULL;
720         MSList *video_codecs=NULL;
721         for (i=0;get_codec(lc->config,"audio_codec",i,&pt);i++){
722                 if (pt){
723                         if (!ms_filter_codec_supported(pt->mime_type)){
724                                 ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
725                         }else audio_codecs=codec_append_if_new(audio_codecs,pt);
726                 }
727         }
728         audio_codecs=add_missing_codecs(SalAudio,audio_codecs);
729         for (i=0;get_codec(lc->config,"video_codec",i,&pt);i++){
730                 if (pt){
731                         if (!ms_filter_codec_supported(pt->mime_type)){
732                                 ms_warning("Codec %s is not supported by mediastreamer2, removed.",pt->mime_type);
733                         }else video_codecs=codec_append_if_new(video_codecs,(void *)pt);
734                 }
735         }
736         video_codecs=add_missing_codecs(SalVideo,video_codecs);
737         linphone_core_set_audio_codecs(lc,audio_codecs);
738         linphone_core_set_video_codecs(lc,video_codecs);
739         linphone_core_update_allocated_audio_bandwidth(lc);
740 }
741
742 static void video_config_read(LinphoneCore *lc){
743         int capture, display, self_view;
744         const char *str;
745         int ndev;
746         const char **devices;
747         const MSList *elem;
748         int i;
749
750         /* retrieve all video devices */
751         elem=ms_web_cam_manager_get_list(ms_web_cam_manager_get());
752         ndev=ms_list_size(elem);
753         devices=ms_malloc((ndev+1)*sizeof(const char *));
754         for (i=0;elem!=NULL;elem=elem->next,i++){
755                 devices[i]=ms_web_cam_get_string_id((MSWebCam *)elem->data);
756         }
757         devices[ndev]=NULL;
758         lc->video_conf.cams=devices;
759
760         str=lp_config_get_string(lc->config,"video","device",NULL);
761         if (str && str[0]==0) str=NULL;
762         linphone_core_set_video_device(lc,str);
763
764         linphone_core_set_preferred_video_size_by_name(lc,
765                 lp_config_get_string(lc->config,"video","size","cif"));
766
767         capture=lp_config_get_int(lc->config,"video","capture",1);
768         display=lp_config_get_int(lc->config,"video","display",1);
769         self_view=lp_config_get_int(lc->config,"video","self_view",1);
770         lc->video_conf.displaytype=lp_config_get_string(lc->config,"video","displaytype",NULL);
771         if(lc->video_conf.displaytype)
772                 ms_message("we are using a specific display:%s\n",lc->video_conf.displaytype);
773 #ifdef VIDEO_ENABLED
774         linphone_core_enable_video(lc,capture,display);
775         linphone_core_enable_self_view(lc,self_view);
776 #endif
777 }
778
779 static void ui_config_read(LinphoneCore *lc)
780 {
781         LinphoneFriend *lf;
782         int i;
783         for (i=0;(lf=linphone_friend_new_from_config_file(lc,i))!=NULL;i++){
784                 linphone_core_add_friend(lc,lf);
785         }
786         call_logs_read_from_config_file(lc);
787 }
788
789 /*
790 static void autoreplier_config_init(LinphoneCore *lc)
791 {
792         autoreplier_config_t *config=&lc->autoreplier_conf;
793         config->enabled=lp_config_get_int(lc->config,"autoreplier","enabled",0);
794         config->after_seconds=lp_config_get_int(lc->config,"autoreplier","after_seconds",6);
795         config->max_users=lp_config_get_int(lc->config,"autoreplier","max_users",1);
796         config->max_rec_time=lp_config_get_int(lc->config,"autoreplier","max_rec_time",60);
797         config->max_rec_msg=lp_config_get_int(lc->config,"autoreplier","max_rec_msg",10);
798         config->message=lp_config_get_string(lc->config,"autoreplier","message",NULL);
799 }
800 */
801
802 /**
803  * Enable adaptive rate control (experimental feature, audio-only).
804  *
805  * Adaptive rate control consists in using RTCP feedback provided information to dynamically
806  * control the output bitrate of the encoders, so that we can adapt to the network conditions and
807  * available bandwidth.
808 **/
809 void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled){
810         lp_config_set_int(lc->config,"net","adaptive_rate_control",(int)enabled);
811 }
812
813 /**
814  * Returns whether adaptive rate control is enabled.
815  *
816  * See linphone_core_enable_adaptive_rate_control().
817 **/
818 bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){
819         return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE);
820 }
821
822 bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){
823         return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE);
824 }
825
826 /**
827  * Sets maximum available download bandwidth
828  *
829  * @ingroup media_parameters
830  *
831  * This is IP bandwidth, in kbit/s.
832  * This information is used signaled to other parties during
833  * calls (within SDP messages) so that the remote end can have
834  * sufficient knowledge to properly configure its audio & video
835  * codec output bitrate to not overflow available bandwidth.
836  *
837  * @param lc the LinphoneCore object
838  * @param bw the bandwidth in kbits/s, 0 for infinite
839  */
840 void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
841         lc->net_conf.download_bw=bw;
842         if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","download_bw",bw);
843 }
844
845 /**
846  * Sets maximum available upload bandwidth
847  *
848  * @ingroup media_parameters
849  *
850  * This is IP bandwidth, in kbit/s.
851  * This information is used by liblinphone together with remote
852  * side available bandwidth signaled in SDP messages to properly
853  * configure audio & video codec's output bitrate.
854  *
855  * @param lc the LinphoneCore object
856  * @param bw the bandwidth in kbits/s, 0 for infinite
857  */
858 void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw){
859         lc->net_conf.upload_bw=bw;
860         if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"net","upload_bw",bw);
861 }
862
863 /**
864  * Retrieve the maximum available download bandwidth.
865  *
866  * @ingroup media_parameters
867  *
868  * This value was set by linphone_core_set_download_bandwidth().
869  *
870 **/
871 int linphone_core_get_download_bandwidth(const LinphoneCore *lc){
872         return lc->net_conf.download_bw;
873 }
874
875 /**
876  * Retrieve the maximum available upload bandwidth.
877  *
878  * @ingroup media_parameters
879  *
880  * This value was set by linphone_core_set_upload_bandwidth().
881  *
882 **/
883 int linphone_core_get_upload_bandwidth(const LinphoneCore *lc){
884         return lc->net_conf.upload_bw;
885 }
886 /**
887  * Set audio packetization time linphone expects to receive from peer
888  */
889 void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime) {
890         lc->net_conf.down_ptime=ptime;
891 }
892
893 /**
894  * Get audio packetization time linphone expects to receive from peer
895  */
896 int linphone_core_get_download_ptime(LinphoneCore *lc) {
897         return lc->net_conf.down_ptime;
898 }
899
900 /**
901  * Set audio packetization time linphone will send (in absence of requirement from peer)
902  * A value of 0 stands for the current codec default packetization time.
903  *
904 **/
905 void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime){
906         lp_config_set_int(lc->config,"rtp","upload_ptime",ptime);
907 }
908
909 /**
910  * Set audio packetization time linphone will send (in absence of requirement from peer)
911  * A value of 0 stands for the current codec default packetization time.
912  *
913 **/
914 int linphone_core_get_upload_ptime(LinphoneCore *lc){
915         return lp_config_get_int(lc->config,"rtp","upload_ptime",0);
916 }
917
918
919
920 /**
921  * Returns liblinphone's version as a string.
922  *
923  * @ingroup misc
924  *
925 **/
926 const char * linphone_core_get_version(void){
927         return liblinphone_version;
928 }
929
930 static void linphone_core_assign_payload_type(LinphoneCore *lc, PayloadType *const_pt, int number, const char *recv_fmtp){
931         PayloadType *pt;
932         pt=payload_type_clone(const_pt);
933         if (number==-1){
934                 /*look for a free number */
935                 MSList *elem;
936                 int i;
937                 for(i=lc->dyn_pt;i<=127;++i){
938                         bool_t already_assigned=FALSE;
939                         for(elem=lc->payload_types;elem!=NULL;elem=elem->next){
940                                 PayloadType *it=(PayloadType*)elem->data;
941                                 if (payload_type_get_number(it)==i){
942                                         already_assigned=TRUE;
943                                         break;
944                                 }
945                         }
946                         if (!already_assigned){
947                                 number=i;
948                                 lc->dyn_pt=i+1;
949                                 break;
950                         }
951                 }
952                 if (number==-1){
953                         ms_fatal("FIXME: too many codecs, no more free numbers.");
954                 }
955         }
956         ms_message("assigning %s/%i payload type number %i",pt->mime_type,pt->clock_rate,number);
957         payload_type_set_number(pt,number);
958         if (recv_fmtp!=NULL) payload_type_set_recv_fmtp(pt,recv_fmtp);
959         rtp_profile_set_payload(&av_profile,number,pt);
960         lc->payload_types=ms_list_append(lc->payload_types,pt);
961 }
962
963 static void linphone_core_free_payload_types(LinphoneCore *lc){
964         ms_list_for_each(lc->payload_types,(void (*)(void*))payload_type_destroy);
965         ms_list_free(lc->payload_types);
966         lc->payload_types=NULL;
967 }
968
969 void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){
970         lc->state=gstate;
971         if (lc->vtable.global_state_changed){
972                 lc->vtable.global_state_changed(lc,gstate,message);
973         }
974 }
975 static void misc_config_read (LinphoneCore *lc) {
976         LpConfig *config=lc->config;
977     lc->max_call_logs=lp_config_get_int(config,"misc","history_max_size",15);
978     lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS);
979 }
980
981 static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path,
982     const char *factory_config_path, void * userdata)
983 {
984         memset (lc, 0, sizeof (LinphoneCore));
985         lc->data=userdata;
986         lc->ringstream_autorelease=TRUE;
987
988         memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
989
990         linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
991         ortp_init();
992         lc->dyn_pt=96;
993         linphone_core_assign_payload_type(lc,&payload_type_pcmu8000,0,NULL);
994         linphone_core_assign_payload_type(lc,&payload_type_gsm,3,NULL);
995         linphone_core_assign_payload_type(lc,&payload_type_pcma8000,8,NULL);
996         linphone_core_assign_payload_type(lc,&payload_type_speex_nb,110,"vbr=on");
997         linphone_core_assign_payload_type(lc,&payload_type_speex_wb,111,"vbr=on");
998         linphone_core_assign_payload_type(lc,&payload_type_speex_uwb,112,"vbr=on");
999         linphone_core_assign_payload_type(lc,&payload_type_telephone_event,101,"0-11");
1000         linphone_core_assign_payload_type(lc,&payload_type_g722,9,NULL);
1001
1002 #if defined(ANDROID) || defined (__IPHONE_OS_VERSION_MIN_REQUIRED)
1003         /*shorten the DNS lookup time and send more retransmissions on mobiles:
1004          - to workaround potential packet losses
1005          - to avoid hanging for 30 seconds when the network doesn't work despite the phone thinks it does.
1006          */
1007         _linphone_core_configure_resolver();
1008 #endif
1009
1010 #ifdef ENABLE_NONSTANDARD_GSM
1011         {
1012                 PayloadType *pt;
1013                 pt=payload_type_clone(&payload_type_gsm);
1014                 pt->clock_rate=11025;
1015                 linphone_core_assign_payload_type(lc,pt,-1,NULL);
1016                 pt->clock_rate=22050;
1017                 linphone_core_assign_payload_type(lc,pt,-1,NULL);
1018                 payload_type_destroy(pt);
1019         }
1020 #endif
1021
1022 #ifdef VIDEO_ENABLED
1023         linphone_core_assign_payload_type(lc,&payload_type_h263,34,NULL);
1024         linphone_core_assign_payload_type(lc,&payload_type_theora,97,NULL);
1025         linphone_core_assign_payload_type(lc,&payload_type_h263_1998,98,"CIF=1;QCIF=1");
1026         linphone_core_assign_payload_type(lc,&payload_type_mp4v,99,"profile-level-id=3");
1027         linphone_core_assign_payload_type(lc,&payload_type_h264,102,"profile-level-id=428014");
1028         linphone_core_assign_payload_type(lc,&payload_type_vp8,103,NULL);
1029         linphone_core_assign_payload_type(lc,&payload_type_x_snow,-1,NULL);
1030         /* due to limited space in SDP, we have to disable this h264 line which is normally no more necessary */
1031         /* linphone_core_assign_payload_type(&payload_type_h264,-1,"packetization-mode=1;profile-level-id=428014");*/
1032 #endif
1033
1034         /*add all payload type for which we don't care about the number */
1035         linphone_core_assign_payload_type(lc,&payload_type_ilbc,-1,"mode=30");
1036         linphone_core_assign_payload_type(lc,&payload_type_amr,-1,"octet-align=1");
1037         linphone_core_assign_payload_type(lc,&payload_type_lpc1015,-1,NULL);
1038         linphone_core_assign_payload_type(lc,&payload_type_g726_16,-1,NULL);
1039         linphone_core_assign_payload_type(lc,&payload_type_g726_24,-1,NULL);
1040         linphone_core_assign_payload_type(lc,&payload_type_g726_32,-1,NULL);
1041         linphone_core_assign_payload_type(lc,&payload_type_g726_40,-1,NULL);
1042         linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_16,-1,NULL);
1043         linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_24,-1,NULL);
1044         linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_32,-1,NULL);
1045         linphone_core_assign_payload_type(lc,&payload_type_aal2_g726_40,-1,NULL);
1046
1047         ms_init();
1048         /* create a mediastreamer2 event queue and set it as global */
1049         /* This allows to run event's callback in linphone_core_iterate() */
1050         lc->msevq=ms_event_queue_new();
1051         ms_set_global_event_queue(lc->msevq);
1052
1053         lc->config=lp_config_new(config_path);
1054         if (factory_config_path)
1055                 lp_config_read_file(lc->config,factory_config_path);
1056
1057         lc->sal=sal_init();
1058         sal_set_user_pointer(lc->sal,lc);
1059         sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
1060
1061         sip_setup_register_all();
1062         sound_config_read(lc);
1063         net_config_read(lc);
1064         rtp_config_read(lc);
1065         codecs_config_read(lc);
1066         sip_config_read(lc); /* this will start eXosip*/
1067         video_config_read(lc);
1068         //autoreplier_config_init(&lc->autoreplier_conf);
1069         lc->presence_mode=LinphoneStatusOnline;
1070         misc_config_read(lc);
1071         ui_config_read(lc);
1072         if (lc->vtable.display_status)
1073                 lc->vtable.display_status(lc,_("Ready"));
1074         lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
1075         linphone_core_set_state(lc,LinphoneGlobalOn,"Ready");
1076 }
1077
1078 /**
1079  * Instanciates a LinphoneCore object.
1080  * @ingroup initializing
1081  *
1082  * The LinphoneCore object is the primary handle for doing all phone actions.
1083  * It should be unique within your application.
1084  * @param vtable a LinphoneCoreVTable structure holding your application callbacks
1085  * @param config_path a path to a config file. If it does not exists it will be created.
1086  *        The config file is used to store all settings, call logs, friends, proxies... so that all these settings
1087  *             become persistent over the life of the LinphoneCore object.
1088  *             It is allowed to set a NULL config file. In that case LinphoneCore will not store any settings.
1089  * @param factory_config_path a path to a read-only config file that can be used to
1090  *        to store hard-coded preference such as proxy settings or internal preferences.
1091  *        The settings in this factory file always override the one in the normal config file.
1092  *        It is OPTIONAL, use NULL if unneeded.
1093  * @param userdata an opaque user pointer that can be retrieved at any time (for example in
1094  *        callbacks) using linphone_core_get_user_data().
1095  *
1096 **/
1097 LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
1098                                                 const char *config_path, const char *factory_config_path, void * userdata)
1099 {
1100         LinphoneCore *core=ms_new(LinphoneCore,1);
1101         linphone_core_init(core,vtable,config_path, factory_config_path, userdata);
1102         return core;
1103 }
1104
1105 /**
1106  * Returns the list of available audio codecs.
1107  *
1108  * This list is unmodifiable. The ->data field of the MSList points a PayloadType
1109  * structure holding the codec information.
1110  * It is possible to make copy of the list with ms_list_copy() in order to modify it
1111  * (such as the order of codecs).
1112 **/
1113 const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc)
1114 {
1115         return lc->codecs_conf.audio_codecs;
1116 }
1117
1118 /**
1119  * Returns the list of available video codecs.
1120  *
1121  * This list is unmodifiable. The ->data field of the MSList points a PayloadType
1122  * structure holding the codec information.
1123  * It is possible to make copy of the list with ms_list_copy() in order to modify it
1124  * (such as the order of codecs).
1125 **/
1126 const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc)
1127 {
1128         return lc->codecs_conf.video_codecs;
1129 }
1130
1131 /**
1132  * Sets the local "from" identity.
1133  *
1134  * @ingroup proxies
1135  * This data is used in absence of any proxy configuration or when no
1136  * default proxy configuration is set. See LinphoneProxyConfig
1137 **/
1138 int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact)
1139 {
1140         LinphoneAddress *ctt;
1141
1142         if ((ctt=linphone_address_new(contact))==0) {
1143                 ms_error("Bad contact url: %s",contact);
1144                 return -1;
1145         }
1146         if (lc->sip_conf.contact!=NULL) ms_free(lc->sip_conf.contact);
1147         lc->sip_conf.contact=ms_strdup(contact);
1148         if (lc->sip_conf.guessed_contact!=NULL){
1149                 ms_free(lc->sip_conf.guessed_contact);
1150                 lc->sip_conf.guessed_contact=NULL;
1151         }
1152         linphone_address_destroy(ctt);
1153         return 0;
1154 }
1155
1156
1157 /*result must be an array of chars at least LINPHONE_IPADDR_SIZE */
1158 void linphone_core_get_local_ip(LinphoneCore *lc, const char *dest, char *result){
1159         const char *ip;
1160         if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress
1161             && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){
1162                 strncpy(result,ip,LINPHONE_IPADDR_SIZE);
1163                 return;
1164         }
1165         if (linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,dest,result)==0)
1166                 return;
1167         /*else fallback to SAL routine that will attempt to find the most realistic interface */
1168         sal_get_default_local_ip(lc->sal,lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,result,LINPHONE_IPADDR_SIZE);
1169 }
1170
1171 static void update_primary_contact(LinphoneCore *lc){
1172         char *guessed=NULL;
1173         char tmp[LINPHONE_IPADDR_SIZE];
1174
1175         LinphoneAddress *url;
1176         if (lc->sip_conf.guessed_contact!=NULL){
1177                 ms_free(lc->sip_conf.guessed_contact);
1178                 lc->sip_conf.guessed_contact=NULL;
1179         }
1180         url=linphone_address_new(lc->sip_conf.contact);
1181         if (!url){
1182                 ms_error("Could not parse identity contact !");
1183                 url=linphone_address_new("sip:unknown@unkwownhost");
1184         }
1185         linphone_core_get_local_ip(lc, NULL, tmp);
1186         if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){
1187                 ms_warning("Local loopback network only !");
1188                 lc->sip_conf.loopback_only=TRUE;
1189         }else lc->sip_conf.loopback_only=FALSE;
1190         linphone_address_set_domain(url,tmp);
1191         linphone_address_set_port_int(url,linphone_core_get_sip_port (lc));
1192         guessed=linphone_address_as_string(url);
1193         lc->sip_conf.guessed_contact=guessed;
1194         linphone_address_destroy(url);
1195 }
1196
1197 /**
1198  * Returns the default identity when no proxy configuration is used.
1199  *
1200  * @ingroup proxies
1201 **/
1202 const char *linphone_core_get_primary_contact(LinphoneCore *lc){
1203         char *identity;
1204
1205         if (lc->sip_conf.guess_hostname){
1206                 if (lc->sip_conf.guessed_contact==NULL || lc->sip_conf.loopback_only){
1207                         update_primary_contact(lc);
1208                 }
1209                 identity=lc->sip_conf.guessed_contact;
1210         }else{
1211                 identity=lc->sip_conf.contact;
1212         }
1213         return identity;
1214 }
1215
1216 /**
1217  * Tells LinphoneCore to guess local hostname automatically in primary contact.
1218  *
1219  * @ingroup proxies
1220 **/
1221 void linphone_core_set_guess_hostname(LinphoneCore *lc, bool_t val){
1222         lc->sip_conf.guess_hostname=val;
1223 }
1224
1225 /**
1226  * Returns TRUE if hostname part of primary contact is guessed automatically.
1227  *
1228  * @ingroup proxies
1229 **/
1230 bool_t linphone_core_get_guess_hostname(LinphoneCore *lc){
1231         return lc->sip_conf.guess_hostname;
1232 }
1233
1234 /**
1235  * Same as linphone_core_get_primary_contact() but the result is a LinphoneAddress object
1236  * instead of const char*
1237  *
1238  * @ingroup proxies
1239 **/
1240 LinphoneAddress *linphone_core_get_primary_contact_parsed(LinphoneCore *lc){
1241         return linphone_address_new(linphone_core_get_primary_contact(lc));
1242 }
1243
1244 /**
1245  * Sets the list of audio codecs.
1246  *
1247  * @ingroup media_parameters
1248  * The list is taken by the LinphoneCore thus the application should not free it.
1249  * This list is made of struct PayloadType describing the codec parameters.
1250 **/
1251 int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs)
1252 {
1253         if (lc->codecs_conf.audio_codecs!=NULL) ms_list_free(lc->codecs_conf.audio_codecs);
1254         lc->codecs_conf.audio_codecs=codecs;
1255         return 0;
1256 }
1257
1258 /**
1259  * Sets the list of video codecs.
1260  *
1261  * @ingroup media_parameters
1262  * The list is taken by the LinphoneCore thus the application should not free it.
1263  * This list is made of struct PayloadType describing the codec parameters.
1264 **/
1265 int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs)
1266 {
1267         if (lc->codecs_conf.video_codecs!=NULL) ms_list_free(lc->codecs_conf.video_codecs);
1268         lc->codecs_conf.video_codecs=codecs;
1269         return 0;
1270 }
1271
1272 const MSList * linphone_core_get_friend_list(const LinphoneCore *lc)
1273 {
1274         return lc->friends;
1275 }
1276
1277 /**
1278  * Returns the nominal jitter buffer size in milliseconds.
1279  *
1280  * @ingroup media_parameters
1281 **/
1282 int linphone_core_get_audio_jittcomp(LinphoneCore *lc)
1283 {
1284         return lc->rtp_conf.audio_jitt_comp;
1285 }
1286
1287 /**
1288  * Returns the UDP port used for audio streaming.
1289  *
1290  * @ingroup network_parameters
1291 **/
1292 int linphone_core_get_audio_port(const LinphoneCore *lc)
1293 {
1294         return lc->rtp_conf.audio_rtp_port;
1295 }
1296
1297 /**
1298  * Returns the UDP port used for video streaming.
1299  *
1300  * @ingroup network_parameters
1301 **/
1302 int linphone_core_get_video_port(const LinphoneCore *lc){
1303         return lc->rtp_conf.video_rtp_port;
1304 }
1305
1306
1307 /**
1308  * Returns the value in seconds of the no-rtp timeout.
1309  *
1310  * @ingroup media_parameters
1311  * When no RTP or RTCP packets have been received for a while
1312  * LinphoneCore will consider the call is broken (remote end crashed or
1313  * disconnected from the network), and thus will terminate the call.
1314  * The no-rtp timeout is the duration above which the call is considered broken.
1315 **/
1316 int linphone_core_get_nortp_timeout(const LinphoneCore *lc){
1317         return lc->rtp_conf.nortp_timeout;
1318 }
1319
1320 bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc){
1321         return lc->rtp_conf.rtp_no_xmit_on_audio_mute;
1322 }
1323
1324 /**
1325  * Sets the nominal audio jitter buffer size in milliseconds.
1326  *
1327  * @ingroup media_parameters
1328 **/
1329 void linphone_core_set_audio_jittcomp(LinphoneCore *lc, int value)
1330 {
1331         lc->rtp_conf.audio_jitt_comp=value;
1332 }
1333
1334 void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_xmit_on_audio_mute){
1335         lc->rtp_conf.rtp_no_xmit_on_audio_mute=rtp_no_xmit_on_audio_mute;
1336 }
1337
1338 /**
1339  * Sets the UDP port used for audio streaming.
1340  *
1341  * @ingroup network_parameters
1342 **/
1343 void linphone_core_set_audio_port(LinphoneCore *lc, int port)
1344 {
1345         lc->rtp_conf.audio_rtp_port=port;
1346 }
1347
1348 /**
1349  * Sets the UDP port used for video streaming.
1350  *
1351  * @ingroup network_parameters
1352 **/
1353 void linphone_core_set_video_port(LinphoneCore *lc, int port){
1354         lc->rtp_conf.video_rtp_port=port;
1355 }
1356
1357 /**
1358  * Sets the no-rtp timeout value in seconds.
1359  *
1360  * @ingroup media_parameters
1361  * See linphone_core_get_nortp_timeout() for details.
1362 **/
1363 void linphone_core_set_nortp_timeout(LinphoneCore *lc, int nortp_timeout){
1364         lc->rtp_conf.nortp_timeout=nortp_timeout;
1365 }
1366
1367 /**
1368  * Indicates whether SIP INFO is used for sending digits.
1369  *
1370  * @ingroup media_parameters
1371 **/
1372 bool_t linphone_core_get_use_info_for_dtmf(LinphoneCore *lc)
1373 {
1374         return lc->sip_conf.use_info;
1375 }
1376
1377 /**
1378  * Sets whether SIP INFO is to be used for sending digits.
1379  *
1380  * @ingroup media_parameters
1381 **/
1382 void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc,bool_t use_info)
1383 {
1384         lc->sip_conf.use_info=use_info;
1385 }
1386
1387 /**
1388  * Indicates whether RFC2833 is used for sending digits.
1389  *
1390  * @ingroup media_parameters
1391 **/
1392 bool_t linphone_core_get_use_rfc2833_for_dtmf(LinphoneCore *lc)
1393 {
1394         return lc->sip_conf.use_rfc2833;
1395 }
1396
1397 /**
1398  * Sets whether RFC2833 is to be used for sending digits.
1399  *
1400  * @ingroup media_parameters
1401 **/
1402 void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,bool_t use_rfc2833)
1403 {
1404         lc->sip_conf.use_rfc2833=use_rfc2833;
1405 }
1406
1407 /**
1408  * Returns the UDP port used by SIP.
1409  *
1410  * Deprecated: use linphone_core_get_sip_transports() instead.
1411  * @ingroup network_parameters
1412 **/
1413 int linphone_core_get_sip_port(LinphoneCore *lc)
1414 {
1415         LCSipTransports *tr=&lc->sip_conf.transports;
1416         return tr->udp_port>0 ? tr->udp_port : (tr->tcp_port > 0 ? tr->tcp_port : tr->tls_port);
1417 }
1418
1419 static char _ua_name[64]="Linphone";
1420 static char _ua_version[64]=LINPHONE_VERSION;
1421
1422 #ifdef HAVE_EXOSIP_GET_VERSION
1423 extern const char *eXosip_get_version();
1424 #endif
1425
1426 static void apply_user_agent(LinphoneCore *lc){
1427         char ua_string[256];
1428         snprintf(ua_string,sizeof(ua_string)-1,"%s/%s (eXosip2/%s)",_ua_name,_ua_version,
1429 #ifdef HAVE_EXOSIP_GET_VERSION
1430                  eXosip_get_version()
1431 #else
1432                  "unknown"
1433 #endif
1434         );
1435         if (lc->sal) sal_set_user_agent(lc->sal,ua_string);
1436 }
1437
1438 /**
1439  * Sets the user agent string used in SIP messages.
1440  *
1441  * @ingroup misc
1442 **/
1443 void linphone_core_set_user_agent(const char *name, const char *ver){
1444         strncpy(_ua_name,name,sizeof(_ua_name)-1);
1445         strncpy(_ua_version,ver,sizeof(_ua_version));
1446 }
1447
1448 static void transport_error(LinphoneCore *lc, const char* transport, int port){
1449         char *msg=ortp_strdup_printf("Could not start %s transport on port %i, maybe this port is already used.",transport,port);
1450         ms_warning("%s",msg);
1451         if (lc->vtable.display_warning)
1452                 lc->vtable.display_warning(lc,msg);
1453         ms_free(msg);
1454 }
1455
1456 static bool_t transports_unchanged(const LCSipTransports * tr1, const LCSipTransports * tr2){
1457         return
1458                 tr2->udp_port==tr1->udp_port &&
1459                 tr2->tcp_port==tr1->tcp_port &&
1460                 tr2->dtls_port==tr1->dtls_port &&
1461                 tr2->tls_port==tr1->tls_port;
1462 }
1463
1464 static int apply_transports(LinphoneCore *lc){
1465         Sal *sal=lc->sal;
1466         const char *anyaddr;
1467         LCSipTransports *tr=&lc->sip_conf.transports;
1468
1469         if (lc->sip_conf.ipv6_enabled)
1470                 anyaddr="::0";
1471         else
1472                 anyaddr="0.0.0.0";
1473
1474         sal_unlisten_ports (sal);
1475         if (tr->udp_port>0){
1476                 if (sal_listen_port (sal,anyaddr,tr->udp_port,SalTransportUDP,FALSE)!=0){
1477                         transport_error(lc,"udp",tr->udp_port);
1478                         return -1;
1479                 }
1480         }
1481         if (tr->tcp_port>0){
1482                 if (sal_listen_port (sal,anyaddr,tr->tcp_port,SalTransportTCP,FALSE)!=0){
1483                         transport_error(lc,"tcp",tr->tcp_port);
1484                 }
1485         }
1486         if (tr->tls_port>0){
1487                 if (sal_listen_port (sal,anyaddr,tr->tls_port,SalTransportTLS,TRUE)!=0){
1488                         transport_error(lc,"tls",tr->tls_port);
1489                 }
1490         }
1491         apply_user_agent(lc);
1492         return 0;
1493 }
1494
1495 /**
1496  * Sets the ports to be used for each of transport (UDP or TCP)
1497  *
1498  * A zero value port for a given transport means the transport
1499  * is not used.
1500  *
1501  * @ingroup network_parameters
1502 **/
1503 int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * tr){
1504
1505         if (transports_unchanged(tr,&lc->sip_conf.transports))
1506                 return 0;
1507         memcpy(&lc->sip_conf.transports,tr,sizeof(*tr));
1508
1509         if (linphone_core_ready(lc)){
1510                 lp_config_set_int(lc->config,"sip","sip_port",tr->udp_port);
1511                 lp_config_set_int(lc->config,"sip","sip_tcp_port",tr->tcp_port);
1512                 lp_config_set_int(lc->config,"sip","sip_tls_port",tr->tls_port);
1513         }
1514
1515         if (lc->sal==NULL) return 0;
1516         return apply_transports(lc);
1517 }
1518
1519 /**
1520  * Retrieves the ports used for each transport (udp, tcp).
1521  * A zero value port for a given transport means the transport
1522  * is not used.
1523  * @ingroup network_parameters
1524 **/
1525 int linphone_core_get_sip_transports(LinphoneCore *lc, LCSipTransports *tr){
1526         memcpy(tr,&lc->sip_conf.transports,sizeof(*tr));
1527         return 0;
1528 }
1529
1530 /**
1531  * Sets the UDP port to be used by SIP.
1532  *
1533  * Deprecated: use linphone_core_set_sip_transports() instead.
1534  * @ingroup network_parameters
1535 **/
1536 void linphone_core_set_sip_port(LinphoneCore *lc,int port)
1537 {
1538         LCSipTransports tr;
1539         memset(&tr,0,sizeof(tr));
1540         tr.udp_port=port;
1541         linphone_core_set_sip_transports (lc,&tr);
1542 }
1543
1544 /**
1545  * Returns TRUE if IPv6 is enabled.
1546  *
1547  * @ingroup network_parameters
1548  * See linphone_core_enable_ipv6() for more details on how IPv6 is supported in liblinphone.
1549 **/
1550 bool_t linphone_core_ipv6_enabled(LinphoneCore *lc){
1551         return lc->sip_conf.ipv6_enabled;
1552 }
1553
1554 /**
1555  * Turns IPv6 support on or off.
1556  *
1557  * @ingroup network_parameters
1558  *
1559  * @note IPv6 support is exclusive with IPv4 in liblinphone:
1560  * when IPv6 is turned on, IPv4 calls won't be possible anymore.
1561  * By default IPv6 support is off.
1562 **/
1563 void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){
1564         if (lc->sip_conf.ipv6_enabled!=val){
1565                 lc->sip_conf.ipv6_enabled=val;
1566                 if (lc->sal){
1567                         /* we need to restart eXosip */
1568                         apply_transports(lc);
1569                 }
1570         }
1571 }
1572
1573
1574 static void monitor_network_state(LinphoneCore *lc, time_t curtime){
1575         static time_t last_check=0;
1576         static bool_t last_status=FALSE;
1577         char result[LINPHONE_IPADDR_SIZE];
1578         bool_t new_status=last_status;
1579
1580         /* only do the network up checking every five seconds */
1581         if (last_check==0 || (curtime-last_check)>=5){
1582                 linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,NULL,result);
1583                 if (strcmp(result,"::1")!=0 && strcmp(result,"127.0.0.1")!=0){
1584                         new_status=TRUE;
1585                 }else new_status=FALSE;
1586                 last_check=curtime;
1587                 if (new_status!=last_status) {
1588                         if (new_status){
1589                                 ms_message("New local ip address is %s",result);
1590                         }
1591                         set_network_reachable(lc,new_status, curtime);
1592                         last_status=new_status;
1593                 }
1594         }
1595 }
1596
1597 static void proxy_update(LinphoneCore *lc){
1598         ms_list_for_each(lc->sip_conf.proxies,(void (*)(void*))&linphone_proxy_config_update);
1599         MSList* list=ms_list_copy(lc->sip_conf.deleted_proxies);
1600         for(;list!=NULL;list=list->next){
1601                 LinphoneProxyConfig* cfg = (LinphoneProxyConfig*) list->data;
1602                 if (ms_time(NULL) - cfg->deletion_date > 5) {
1603                         lc->sip_conf.deleted_proxies =ms_list_remove(lc->sip_conf.deleted_proxies,(void *)cfg);
1604                         ms_message("clearing proxy config for [%s]",linphone_proxy_config_get_addr(cfg));
1605                         linphone_proxy_config_destroy(cfg);
1606                 }
1607         }
1608         ms_list_free(list);
1609 }
1610
1611 static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){
1612         LinphoneFriend *lf=linphone_core_get_friend_by_address(lc,info->sip_uri);
1613         if (lf!=NULL){
1614                 lf->info=info;
1615                 ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data);
1616                 if (lc->vtable.buddy_info_updated)
1617                         lc->vtable.buddy_info_updated(lc,lf);
1618         }else{
1619                 ms_warning("Could not any friend with uri %s",info->sip_uri);
1620         }
1621 }
1622
1623 static void analyze_buddy_lookup_results(LinphoneCore *lc, LinphoneProxyConfig *cfg){
1624         MSList *elem;
1625         SipSetupContext *ctx=linphone_proxy_config_get_sip_setup_context(cfg);
1626         for (elem=lc->bl_reqs;elem!=NULL;elem=ms_list_next(elem)){
1627                 BuddyLookupRequest *req=(BuddyLookupRequest *)elem->data;
1628                 if (req->status==BuddyLookupDone || req->status==BuddyLookupFailure){
1629                         if (req->results!=NULL){
1630                                 BuddyInfo *i=(BuddyInfo*)req->results->data;
1631                                 ms_list_free(req->results);
1632                                 req->results=NULL;
1633                                 assign_buddy_info(lc,i);
1634                         }
1635                         sip_setup_context_buddy_lookup_free(ctx,req);
1636                         elem->data=NULL;
1637                 }
1638         }
1639         /*purge completed requests */
1640         while((elem=ms_list_find(lc->bl_reqs,NULL))!=NULL){
1641                 lc->bl_reqs=ms_list_remove_link(lc->bl_reqs,elem);
1642         }
1643 }
1644
1645 static void linphone_core_grab_buddy_infos(LinphoneCore *lc, LinphoneProxyConfig *cfg){
1646         const MSList *elem;
1647         SipSetupContext *ctx=linphone_proxy_config_get_sip_setup_context(cfg);
1648         for(elem=linphone_core_get_friend_list(lc);elem!=NULL;elem=elem->next){
1649                 LinphoneFriend *lf=(LinphoneFriend*)elem->data;
1650                 if (lf->info==NULL){
1651                         if (linphone_core_lookup_known_proxy(lc,lf->uri)==cfg){
1652                                 if (linphone_address_get_username(lf->uri)!=NULL){
1653                                         BuddyLookupRequest *req;
1654                                         char *tmp=linphone_address_as_string_uri_only(lf->uri);
1655                                         req=sip_setup_context_create_buddy_lookup_request(ctx);
1656                                         buddy_lookup_request_set_key(req,tmp);
1657                                         buddy_lookup_request_set_max_results(req,1);
1658                                         sip_setup_context_buddy_lookup_submit(ctx,req);
1659                                         lc->bl_reqs=ms_list_append(lc->bl_reqs,req);
1660                                         ms_free(tmp);
1661                                 }
1662                         }
1663                 }
1664         }
1665 }
1666
1667 static void linphone_core_do_plugin_tasks(LinphoneCore *lc){
1668         LinphoneProxyConfig *cfg=NULL;
1669         linphone_core_get_default_proxy(lc,&cfg);
1670         if (cfg){
1671                 if (lc->bl_refresh){
1672                         SipSetupContext *ctx=linphone_proxy_config_get_sip_setup_context(cfg);
1673                         if (ctx && (sip_setup_context_get_capabilities(ctx) & SIP_SETUP_CAP_BUDDY_LOOKUP)){
1674                                 linphone_core_grab_buddy_infos(lc,cfg);
1675                                 lc->bl_refresh=FALSE;
1676                         }
1677                 }
1678                 if (lc->bl_reqs) analyze_buddy_lookup_results(lc,cfg);
1679         }
1680 }
1681
1682 /**
1683  * Main loop function. It is crucial that your application call it periodically.
1684  *
1685  * @ingroup initializing
1686  * linphone_core_iterate() performs various backgrounds tasks:
1687  * - receiving of SIP messages
1688  * - handles timers and timeout
1689  * - performs registration to proxies
1690  * - authentication retries
1691  * The application MUST call this function periodically, in its main loop.
1692  * Be careful that this function must be called from the same thread as
1693  * other liblinphone methods. If it is not the case make sure all liblinphone calls are
1694  * serialized with a mutex.
1695 **/
1696 void linphone_core_iterate(LinphoneCore *lc){
1697         MSList *calls;
1698         LinphoneCall *call;
1699         time_t curtime=time(NULL);
1700         int elapsed;
1701         bool_t one_second_elapsed=FALSE;
1702
1703         if (curtime-lc->prevtime>=1){
1704                 lc->prevtime=curtime;
1705                 one_second_elapsed=TRUE;
1706         }
1707
1708         if (lc->ecc!=NULL){
1709                 LinphoneEcCalibratorStatus ecs=ec_calibrator_get_status(lc->ecc);
1710                 if (ecs!=LinphoneEcCalibratorInProgress){
1711                         if (lc->ecc->cb)
1712                                 lc->ecc->cb(lc,ecs,lc->ecc->delay,lc->ecc->cb_data);
1713                         if (ecs==LinphoneEcCalibratorDone){
1714                                 int len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
1715                                 lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-(len/2),0));
1716                         }
1717                         ec_calibrator_destroy(lc->ecc);
1718                         lc->ecc=NULL;
1719                 }
1720         }
1721
1722         if (lc->preview_finished){
1723                 lc->preview_finished=0;
1724                 ring_stop(lc->ringstream);
1725                 lc->ringstream=NULL;
1726                 lc_callback_obj_invoke(&lc->preview_finished_cb,lc);
1727         }
1728
1729         if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0
1730             && (curtime-lc->dmfs_playing_start_time)>5){
1731                 ring_stop(lc->ringstream);
1732                 lc->ringstream=NULL;
1733                 lc->dmfs_playing_start_time=0;
1734         }
1735
1736         sal_iterate(lc->sal);
1737         if (lc->msevq) ms_event_queue_pump(lc->msevq);
1738         if (lc->auto_net_state_mon) monitor_network_state(lc,curtime);
1739
1740         proxy_update(lc);
1741
1742         //we have to iterate for each call
1743         calls= lc->calls;
1744         while(calls!= NULL){
1745                 call = (LinphoneCall *)calls->data;
1746                  /* get immediately a reference to next one in case the one
1747                  we are going to examine is destroy and removed during
1748                  linphone_core_start_invite() */
1749                 calls=calls->next;
1750                 linphone_call_background_tasks(call,one_second_elapsed);
1751                 if (call->state==LinphoneCallOutgoingInit && (curtime-call->start_time>=2)){
1752                         /*start the call even if the OPTIONS reply did not arrive*/
1753                         linphone_core_start_invite(lc,call,NULL);
1754                 }
1755                 if (call->dir==LinphoneCallIncoming && call->state==LinphoneCallOutgoingRinging){
1756                         elapsed=curtime-call->start_time;
1757                         ms_message("incoming call ringing for %i seconds",elapsed);
1758                         if (elapsed>lc->sip_conf.inc_timeout){
1759                                 call->log->status=LinphoneCallMissed;
1760                                 linphone_core_terminate_call(lc,call);
1761                         }
1762                 }
1763         }
1764                 
1765         if (linphone_core_video_preview_enabled(lc)){
1766                 if (lc->previewstream==NULL && lc->calls==NULL)
1767                         toggle_video_preview(lc,TRUE);
1768 #ifdef VIDEO_ENABLED
1769                 if (lc->previewstream) video_stream_iterate(lc->previewstream);
1770 #endif
1771         }else{
1772                 if (lc->previewstream!=NULL)
1773                         toggle_video_preview(lc,FALSE);
1774         }
1775
1776         linphone_core_run_hooks(lc);
1777         linphone_core_do_plugin_tasks(lc);
1778
1779         if (lc->initial_subscribes_sent==FALSE && lc->netup_time!=0 &&
1780             (curtime-lc->netup_time)>3){
1781                 linphone_core_send_initial_subscribes(lc);
1782                 lc->initial_subscribes_sent=TRUE;
1783         }
1784
1785         if (one_second_elapsed && lp_config_needs_commit(lc->config)){
1786                 lp_config_sync(lc->config);
1787         }
1788 }
1789
1790 /**
1791  * Interpret a call destination as supplied by the user, and returns a fully qualified
1792  * LinphoneAddress.
1793  *
1794  * A sip address should look like DisplayName <sip:username@domain:port> .
1795  * Basically this function performs the following tasks
1796  * - if a phone number is entered, prepend country prefix of the default proxy
1797  *   configuration, eventually escape the '+' by 00.
1798  * - if no domain part is supplied, append the domain name of the default proxy
1799  * - if no sip: is present, prepend it
1800  *
1801  * The result is a syntaxically correct SIP address.
1802 **/
1803
1804 LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url){
1805         enum_lookup_res_t *enumres=NULL;
1806         char *enum_domain=NULL;
1807         LinphoneProxyConfig *proxy=lc->default_proxy;;
1808         char *tmpurl;
1809         LinphoneAddress *uri;
1810
1811         if (is_enum(url,&enum_domain)){
1812                 if (lc->vtable.display_status!=NULL)
1813                         lc->vtable.display_status(lc,_("Looking for telephone number destination..."));
1814                 if (enum_lookup(enum_domain,&enumres)<0){
1815                         if (lc->vtable.display_status!=NULL)
1816                                 lc->vtable.display_status(lc,_("Could not resolve this number."));
1817                         ms_free(enum_domain);
1818                         return NULL;
1819                 }
1820                 ms_free(enum_domain);
1821                 tmpurl=enumres->sip_address[0];
1822                 uri=linphone_address_new(tmpurl);
1823                 enum_lookup_res_free(enumres);
1824                 return uri;
1825         }
1826         /* check if we have a "sip:" */
1827         if (strstr(url,"sip:")==NULL){
1828                 /* this doesn't look like a true sip uri */
1829                 if (strchr(url,'@')!=NULL){
1830                         /* seems like sip: is missing !*/
1831                         tmpurl=ms_strdup_printf("sip:%s",url);
1832                         uri=linphone_address_new(tmpurl);
1833                         ms_free(tmpurl);
1834                         if (uri){
1835                                 return uri;
1836                         }
1837                 }
1838
1839                 if (proxy!=NULL){
1840                         /* append the proxy domain suffix */
1841                         const char *identity=linphone_proxy_config_get_identity(proxy);
1842                         char normalized_username[128];
1843                         uri=linphone_address_new(identity);
1844                         if (uri==NULL){
1845                                 return NULL;
1846                         }
1847                         linphone_address_set_display_name(uri,NULL);
1848                         linphone_proxy_config_normalize_number(proxy,url,normalized_username,
1849                                                                 sizeof(normalized_username));
1850                         linphone_address_set_username(uri,normalized_username);
1851                         return uri;
1852                 }else return NULL;
1853         }
1854         uri=linphone_address_new(url);
1855         if (uri!=NULL){
1856                 return uri;
1857         }
1858         /* else we could not do anything with url given by user, so display an error */
1859         if (lc->vtable.display_warning!=NULL){
1860                 lc->vtable.display_warning(lc,_("Could not parse given sip address. A sip url usually looks like sip:user@domain"));
1861         }
1862         return NULL;
1863 }
1864
1865 /**
1866  * Returns the default identity SIP address.
1867  *
1868  * @ingroup proxies
1869  * This is an helper function:
1870  *
1871  * If no default proxy is set, this will return the primary contact (
1872  * see linphone_core_get_primary_contact() ). If a default proxy is set
1873  * it returns the registered identity on the proxy.
1874 **/
1875 const char * linphone_core_get_identity(LinphoneCore *lc){
1876         LinphoneProxyConfig *proxy=NULL;
1877         const char *from;
1878         linphone_core_get_default_proxy(lc,&proxy);
1879         if (proxy!=NULL) {
1880                 from=linphone_proxy_config_get_identity(proxy);
1881         }else from=linphone_core_get_primary_contact(lc);
1882         return from;
1883 }
1884
1885 const char * linphone_core_get_route(LinphoneCore *lc){
1886         LinphoneProxyConfig *proxy=NULL;
1887         const char *route=NULL;
1888         linphone_core_get_default_proxy(lc,&proxy);
1889         if (proxy!=NULL) {
1890                 route=linphone_proxy_config_get_route(proxy);
1891         }
1892         return route;
1893 }
1894
1895 void linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call){
1896         if (call->refer_pending){
1897                 LinphoneCallParams *cp=linphone_core_create_default_call_parameters(lc);
1898                 cp->referer=call;
1899                 ms_message("Starting new call to refered address %s",call->refer_to);
1900                 call->refer_pending=FALSE;
1901                 linphone_core_invite_with_params(lc,call->refer_to,cp);
1902                 linphone_call_params_destroy(cp);
1903         }
1904 }
1905
1906 LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri){
1907         const MSList *elem;
1908         LinphoneProxyConfig *found_cfg=NULL;
1909         for (elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=elem->next){
1910                 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
1911                 const char *domain=linphone_proxy_config_get_domain(cfg);
1912                 if (domain!=NULL && strcmp(domain,linphone_address_get_domain(uri))==0){
1913                         found_cfg=cfg;
1914                         break;
1915                 }
1916         }
1917         return found_cfg;
1918 }
1919
1920 const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to, const char **route){
1921         LinphoneProxyConfig *cfg=linphone_core_lookup_known_proxy(lc,to);
1922         if (cfg==NULL)
1923                 linphone_core_get_default_proxy (lc,&cfg);
1924         if (cfg!=NULL){
1925                 if (route) *route=linphone_proxy_config_get_route(cfg);
1926                 return linphone_proxy_config_get_identity (cfg);
1927         }
1928         return linphone_core_get_primary_contact (lc);
1929 }
1930
1931 static char *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){
1932         LinphoneAddress *ctt;
1933         const char *localip=call->localip;
1934
1935         /* first use user's supplied ip address if asked*/
1936         if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){
1937                 ctt=linphone_core_get_primary_contact_parsed(lc);
1938                 return ms_strdup_printf("sip:%s@%s",linphone_address_get_username(ctt),
1939                         linphone_core_get_nat_address_resolved(lc));
1940         }
1941
1942         /* if already choosed, don't change it */
1943         if (call->op && sal_op_get_contact(call->op)!=NULL){
1944                 return NULL;
1945         }
1946         /* if the ping OPTIONS request succeeded use the contact guessed from the
1947          received, rport*/
1948         if (call->ping_op){
1949                 const char *guessed=sal_op_get_contact(call->ping_op);
1950                 if (guessed){
1951                         ms_message("Contact has been fixed using OPTIONS to %s",guessed);
1952                         return ms_strdup(guessed);
1953                 }
1954         }
1955
1956         /*if using a proxy, use the contact address as guessed with the REGISTERs*/
1957         if (dest_proxy && dest_proxy->op){
1958                 const char *fixed_contact=sal_op_get_contact(dest_proxy->op);
1959                 if (fixed_contact) {
1960                         ms_message("Contact has been fixed using proxy to %s",fixed_contact);
1961                         return ms_strdup(fixed_contact);
1962                 }
1963         }
1964
1965         ctt=linphone_core_get_primary_contact_parsed(lc);
1966
1967         if (ctt!=NULL){
1968                 char *ret;
1969                 /*otherwise use supllied localip*/
1970                 linphone_address_set_domain(ctt,localip);
1971                 linphone_address_set_port_int(ctt,linphone_core_get_sip_port(lc));
1972                 ret=linphone_address_as_string_uri_only(ctt);
1973                 linphone_address_destroy(ctt);
1974                 ms_message("Contact has been fixed using local ip to %s",ret);
1975                 return ret;
1976         }
1977         return NULL;
1978 }
1979
1980 int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy){
1981         int err;
1982         char *contact;
1983         char *real_url,*barmsg;
1984         char *from;
1985
1986         /*try to be best-effort in giving real local or routable contact address */
1987         contact=get_fixed_contact(lc,call,dest_proxy);
1988         if (contact){
1989                 sal_op_set_contact(call->op, contact);
1990                 ms_free(contact);
1991         }
1992
1993         //TODO : should probably not be done here
1994         linphone_call_init_media_streams(call);
1995         if (!lc->sip_conf.sdp_200_ack){
1996                 call->media_pending=TRUE;
1997                 sal_call_set_local_media_description(call->op,call->localdesc);
1998         }
1999         real_url=linphone_address_as_string(call->log->to);
2000         from=linphone_address_as_string(call->log->from);
2001         err=sal_call(call->op,from,real_url);
2002
2003         if (lc->sip_conf.sdp_200_ack){
2004                 call->media_pending=TRUE;
2005                 sal_call_set_local_media_description(call->op,call->localdesc);
2006         }
2007         barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url);
2008         if (lc->vtable.display_status!=NULL)
2009                 lc->vtable.display_status(lc,barmsg);
2010         ms_free(barmsg);
2011
2012         if (err<0){
2013                 if (lc->vtable.display_status!=NULL)
2014                         lc->vtable.display_status(lc,_("Could not call"));
2015                 linphone_call_stop_media_streams(call);
2016                 linphone_call_set_state(call,LinphoneCallError,"Call failed");
2017         }else {
2018                 linphone_call_set_state(call,LinphoneCallOutgoingProgress,"Outgoing call in progress");
2019         }
2020         ms_free(real_url);
2021         ms_free(from);
2022         return err;
2023 }
2024
2025 /**
2026  * Initiates an outgoing call
2027  *
2028  * @ingroup call_control
2029  * @param lc the LinphoneCore object
2030  * @param url the destination of the call (sip address, or phone number).
2031  *
2032  * The application doesn't own a reference to the returned LinphoneCall object.
2033  * Use linphone_call_ref() to safely keep the LinphoneCall pointer valid within your application.
2034  *
2035  * @return a LinphoneCall object or NULL in case of failure
2036 **/
2037 LinphoneCall * linphone_core_invite(LinphoneCore *lc, const char *url){
2038         LinphoneCall *call;
2039         LinphoneCallParams *p=linphone_core_create_default_call_parameters (lc);
2040         call=linphone_core_invite_with_params(lc,url,p);
2041         linphone_call_params_destroy(p);
2042         return call;
2043 }
2044
2045
2046 /**
2047  * Initiates an outgoing call according to supplied call parameters
2048  *
2049  * @ingroup call_control
2050  * @param lc the LinphoneCore object
2051  * @param url the destination of the call (sip address, or phone number).
2052  * @param p call parameters
2053  *
2054  * The application doesn't own a reference to the returned LinphoneCall object.
2055  * Use linphone_call_ref() to safely keep the LinphoneCall pointer valid within your application.
2056  *
2057  * @return a LinphoneCall object or NULL in case of failure
2058 **/
2059 LinphoneCall * linphone_core_invite_with_params(LinphoneCore *lc, const char *url, const LinphoneCallParams *p){
2060         LinphoneAddress *addr=linphone_core_interpret_url(lc,url);
2061         if (addr){
2062                 LinphoneCall *call;
2063                 call=linphone_core_invite_address_with_params(lc,addr,p);
2064                 linphone_address_destroy(addr);
2065                 return call;
2066         }
2067         return NULL;
2068 }
2069
2070 /**
2071  * Initiates an outgoing call given a destination LinphoneAddress
2072  *
2073  * @ingroup call_control
2074  * @param lc the LinphoneCore object
2075  * @param addr the destination of the call (sip address).
2076  *
2077  * The LinphoneAddress can be constructed directly using linphone_address_new(), or
2078  * created by linphone_core_interpret_url().
2079  * The application doesn't own a reference to the returned LinphoneCall object.
2080  * Use linphone_call_ref() to safely keep the LinphoneCall pointer valid within your application.
2081  *
2082  * @return a LinphoneCall object or NULL in case of failure
2083 **/
2084 LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr){
2085         LinphoneCall *call;
2086         LinphoneCallParams *p=linphone_core_create_default_call_parameters (lc);
2087         call=linphone_core_invite_address_with_params (lc,addr,p);
2088         linphone_call_params_destroy(p);
2089         return call;
2090 }
2091
2092
2093 /**
2094  * Initiates an outgoing call given a destination LinphoneAddress
2095  *
2096  * @ingroup call_control
2097  * @param lc the LinphoneCore object
2098  * @param addr the destination of the call (sip address).
2099         @param params call parameters
2100  *
2101  * The LinphoneAddress can be constructed directly using linphone_address_new(), or
2102  * created by linphone_core_interpret_url().
2103  * The application doesn't own a reference to the returned LinphoneCall object.
2104  * Use linphone_call_ref() to safely keep the LinphoneCall pointer valid within your application.
2105  *
2106  * @return a LinphoneCall object or NULL in case of failure
2107 **/
2108 LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const LinphoneAddress *addr, const LinphoneCallParams *params)
2109 {
2110         const char *route=NULL;
2111         const char *from=NULL;
2112         LinphoneProxyConfig *proxy=NULL;
2113         LinphoneAddress *parsed_url2=NULL;
2114         char *real_url=NULL;
2115         LinphoneProxyConfig *dest_proxy=NULL;
2116         LinphoneCall *call;
2117
2118         linphone_core_preempt_sound_resources(lc);
2119         
2120         if(!linphone_core_can_we_add_call(lc)){
2121                 if (lc->vtable.display_warning)
2122                         lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls"));
2123                 return NULL;
2124         }
2125         linphone_core_get_default_proxy(lc,&proxy);
2126         route=linphone_core_get_route(lc);
2127
2128         real_url=linphone_address_as_string(addr);
2129         dest_proxy=linphone_core_lookup_known_proxy(lc,addr);
2130
2131         if (proxy!=dest_proxy && dest_proxy!=NULL) {
2132                 ms_message("Overriding default proxy setting for this call:");
2133                 ms_message("The used identity will be %s",linphone_proxy_config_get_identity(dest_proxy));
2134         }
2135
2136         if (dest_proxy!=NULL)
2137                 from=linphone_proxy_config_get_identity(dest_proxy);
2138         else if (proxy!=NULL)
2139                 from=linphone_proxy_config_get_identity(proxy);
2140
2141         /* if no proxy or no identity defined for this proxy, default to primary contact*/
2142         if (from==NULL) from=linphone_core_get_primary_contact(lc);
2143
2144         parsed_url2=linphone_address_new(from);
2145
2146         call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),params);
2147         sal_op_set_route(call->op,route);
2148
2149         if(linphone_core_add_call(lc,call)!= 0)
2150         {
2151                 ms_warning("we had a problem in adding the call into the invite ... weird");
2152                 linphone_call_unref(call);
2153                 return NULL;
2154         }
2155         /* this call becomes now the current one*/
2156         lc->current_call=call;
2157         linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call");
2158         if (dest_proxy!=NULL || lc->sip_conf.ping_with_options==FALSE){
2159                 linphone_core_start_invite(lc,call,dest_proxy);
2160         }else{
2161                 /*defer the start of the call after the OPTIONS ping*/
2162                 call->ping_op=sal_op_new(lc->sal);
2163                 sal_ping(call->ping_op,from,real_url);
2164                 sal_op_set_user_pointer(call->ping_op,call);
2165                 call->start_time=time(NULL);
2166         }
2167
2168         if (real_url!=NULL) ms_free(real_url);
2169         return call;
2170 }
2171
2172 /**
2173  * Performs a simple call transfer to the specified destination.
2174  *
2175  * The remote endpoint is expected to issue a new call to the specified destination.
2176  * The current call remains active and thus can be later paused or terminated.
2177 **/
2178 int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *url)
2179 {
2180         char *real_url=NULL;
2181         LinphoneAddress *real_parsed_url=linphone_core_interpret_url(lc,url);
2182
2183         if (!real_parsed_url){
2184                 /* bad url */
2185                 return -1;
2186         }
2187         if (call==NULL){
2188                 ms_warning("No established call to refer.");
2189                 return -1;
2190         }
2191         //lc->call=NULL; //Do not do that you will lose the call afterward . . .
2192         real_url=linphone_address_as_string (real_parsed_url);
2193         sal_call_refer(call->op,real_url);
2194         ms_free(real_url);
2195         linphone_address_destroy(real_parsed_url);
2196         return 0;
2197 }
2198
2199 /**
2200  * Transfer a call to destination of another running call. This is used for "attended transfer" scenarios.
2201  * @param lc linphone core object
2202  * @param call a running call you want to transfer
2203  * @param dest a running call whose remote person will receive the transfer
2204  *
2205  * The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately.
2206  * The destination call is a call previously established to introduce the transfered person.
2207  * This method will send a transfer request to the transfered person. The phone of the transfered is then
2208  * expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically
2209  * close the call with us (the 'dest' call).
2210 **/
2211 int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, LinphoneCall *dest){
2212         return sal_call_refer_with_replaces (call->op,dest->op);
2213 }
2214
2215 bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
2216         LinphoneCall *call = linphone_core_get_current_call(lc);
2217         if(call != NULL)
2218         {
2219                 if(call->dir==LinphoneCallIncoming
2220                         && (call->state == LinphoneCallIncomingReceived || call->state ==  LinphoneCallIncomingEarlyMedia))
2221                         return TRUE;
2222         }
2223         return FALSE;
2224 }
2225
2226 /**
2227  * Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
2228  *
2229  * In this version this is limited to the following use cases:
2230  * - setting up/down the video stream according to the video parameter of the LinphoneCallParams (see linphone_call_params_enable_video() ).
2231  * - changing the size of the transmitted video after calling linphone_core_set_preferred_video_size()
2232  *
2233  * In case no changes are requested through the LinphoneCallParams argument, then this argument can be ommitted and set to NULL.
2234  *
2235  * @return 0 if successful, -1 otherwise.
2236 **/
2237 int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
2238         int err=0;
2239         if (params!=NULL){
2240                 const char *subject;
2241                 call->params=*params;
2242                 update_local_media_description(lc,call,&call->localdesc);
2243                 call->camera_active=params->has_video;
2244
2245                 if (params->in_conference){
2246                         subject="Conference";
2247                 }else{
2248                         subject="Media change";
2249                 }
2250                 if (lc->vtable.display_status)
2251                         lc->vtable.display_status(lc,_("Modifying call parameters..."));
2252                 sal_call_set_local_media_description (call->op,call->localdesc);
2253                 err=sal_call_update(call->op,subject);
2254         }else{
2255 #ifdef VIDEO_ENABLED
2256                 if (call->videostream!=NULL){
2257                         video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
2258                         if (call->camera_active && call->videostream->cam!=lc->video_conf.device){
2259                                 video_stream_change_camera(call->videostream,lc->video_conf.device);
2260                         }else video_stream_update_video_params(call->videostream);
2261                 }
2262 #endif
2263         }
2264
2265         return err;
2266 }
2267
2268
2269 /**
2270  * Accept an incoming call.
2271  *
2272  * @ingroup call_control
2273  * Basically the application is notified of incoming calls within the
2274  * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive
2275  * a LinphoneCallIncoming event with the associated LinphoneCall object.
2276  * The application can later accept the call using
2277  * this method.
2278  * @param lc the LinphoneCore object
2279  * @param call the LinphoneCall object representing the call to be answered.
2280  *
2281 **/
2282 int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
2283 {
2284         LinphoneProxyConfig *cfg=NULL,*dest_proxy=NULL;
2285         const char *contact=NULL;
2286         SalOp *replaced;
2287         SalMediaDescription *new_md;
2288
2289         if (call==NULL){
2290                 //if just one call is present answer the only one ...
2291                 if(linphone_core_get_calls_nb (lc) != 1)
2292                         return -1;
2293                 else
2294                         call = (LinphoneCall*)linphone_core_get_calls(lc)->data;
2295         }
2296
2297         if (call->state==LinphoneCallConnected){
2298                 /*call already accepted*/
2299                 return -1;
2300         }
2301
2302         /* check if this call is supposed to replace an already running one*/
2303         replaced=sal_call_get_replaces(call->op);
2304         if (replaced){
2305                 LinphoneCall *rc=(LinphoneCall*)sal_op_get_user_pointer (replaced);
2306                 if (rc){
2307                         ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.",
2308                                    call,rc);
2309                         linphone_core_terminate_call(lc,rc);
2310                 }
2311         }
2312
2313         if (lc->current_call!=call){
2314                 linphone_core_preempt_sound_resources(lc);
2315         }
2316
2317         /*stop ringing */
2318         if (lc->ringstream!=NULL) {
2319                 ms_message("stop ringing");
2320                 ring_stop(lc->ringstream);
2321                 ms_message("ring stopped");
2322                 lc->ringstream=NULL;
2323         }
2324         if (call->ringing_beep){
2325                 linphone_core_stop_dtmf(lc);
2326                 call->ringing_beep=FALSE;
2327         }
2328
2329         linphone_core_get_default_proxy(lc,&cfg);
2330         dest_proxy=cfg;
2331         dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
2332
2333         if (cfg!=dest_proxy && dest_proxy!=NULL) {
2334                 ms_message("Overriding default proxy setting for this call:");
2335                 ms_message("The used identity will be %s",linphone_proxy_config_get_identity(dest_proxy));
2336         }
2337         /*try to be best-effort in giving real local or routable contact address*/
2338         contact=get_fixed_contact(lc,call,dest_proxy);
2339         if (contact)
2340                 sal_op_set_contact(call->op,contact);
2341
2342         if (call->audiostream==NULL)
2343                 linphone_call_init_media_streams(call);
2344
2345         sal_call_accept(call->op);
2346         if (lc->vtable.display_status!=NULL)
2347                 lc->vtable.display_status(lc,_("Connected."));
2348         lc->current_call=call;
2349         linphone_call_set_state(call,LinphoneCallConnected,"Connected");
2350         new_md=sal_call_get_final_media_description(call->op);
2351         linphone_core_update_streams(lc, call, new_md);
2352         if (new_md){
2353                 linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
2354         }else call->media_pending=TRUE;
2355
2356         ms_message("call answered.");
2357         return 0;
2358 }
2359
2360 int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error){
2361         sal_call_terminate(call->op);
2362
2363         /*stop ringing*/
2364         if (lc->ringstream!=NULL) {
2365                 ring_stop(lc->ringstream);
2366                 lc->ringstream=NULL;
2367         }
2368         linphone_call_stop_media_streams(call);
2369         if (lc->vtable.display_status!=NULL)
2370                 lc->vtable.display_status(lc,_("Call aborted") );
2371         linphone_call_set_state(call,LinphoneCallError,error);
2372         return 0;
2373 }
2374
2375 static void terminate_call(LinphoneCore *lc, LinphoneCall *call){
2376         if (call->state==LinphoneCallIncomingReceived){
2377                 call->reason=LinphoneReasonDeclined;
2378         }
2379         /*stop ringing*/
2380         if (lc->ringstream!=NULL) {
2381                 ring_stop(lc->ringstream);
2382                 lc->ringstream=NULL;
2383         }
2384
2385         linphone_call_stop_media_streams(call);
2386         if (lc->vtable.display_status!=NULL)
2387                 lc->vtable.display_status(lc,_("Call ended") );
2388 }
2389
2390 int linphone_core_redirect_call(LinphoneCore *lc, LinphoneCall *call, const char *redirect_uri){
2391         if (call->state==LinphoneCallIncomingReceived){
2392                 sal_call_decline(call->op,SalReasonRedirect,redirect_uri);
2393                 call->reason=LinphoneReasonDeclined;
2394                 terminate_call(lc,call);
2395                 linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
2396         }else{
2397                 ms_error("Bad state for call redirection.");
2398                 return -1;
2399     }
2400         return 0;
2401 }
2402
2403
2404 /**
2405  * Terminates a call.
2406  *
2407  * @ingroup call_control
2408  * @param lc the LinphoneCore
2409  * @param the_call the LinphoneCall object representing the call to be terminated.
2410 **/
2411 int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *the_call)
2412 {
2413         LinphoneCall *call;
2414         if (the_call == NULL){
2415                 call = linphone_core_get_current_call(lc);
2416                 if (ms_list_size(lc->calls)==1){
2417                         call=(LinphoneCall*)lc->calls->data;
2418                 }else{
2419                         ms_warning("No unique call to terminate !");
2420                         return -1;
2421                 }
2422         }
2423         else
2424         {
2425                 call = the_call;
2426         }
2427         sal_call_terminate(call->op);
2428         terminate_call(lc,call);
2429
2430         linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
2431         return 0;
2432 }
2433
2434 /**
2435  * Terminates all the calls.
2436  *
2437  * @ingroup call_control
2438  * @param lc The LinphoneCore
2439 **/
2440 int linphone_core_terminate_all_calls(LinphoneCore *lc){
2441         MSList *calls=lc->calls;
2442         while(calls) {
2443                 LinphoneCall *c=(LinphoneCall*)calls->data;
2444                 calls=calls->next;
2445                 linphone_core_terminate_call(lc,c);
2446         }
2447         return 0;
2448 }
2449
2450 /**
2451  * Returns the current list of calls.
2452  *
2453  * Note that this list is read-only and might be changed by the core after a function call to linphone_core_iterate().
2454  * Similarly the LinphoneCall objects inside it might be destroyed without prior notice.
2455  * To hold references to LinphoneCall object into your program, you must use linphone_call_ref().
2456  *
2457  * @ingroup call_control
2458 **/
2459 const MSList *linphone_core_get_calls(LinphoneCore *lc)
2460 {
2461         return lc->calls;
2462 }
2463
2464 /**
2465  * Returns TRUE if there is a call running.
2466  *
2467  * @ingroup call_control
2468 **/
2469 bool_t linphone_core_in_call(const LinphoneCore *lc){
2470         return linphone_core_get_current_call((LinphoneCore *)lc)!=NULL || linphone_core_is_in_conference(lc);
2471 }
2472
2473 /**
2474  * Returns The _LinphoneCall struct of the current call if one is in call
2475  *
2476  * @ingroup call_control
2477 **/
2478 LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc)
2479 {
2480         return lc->current_call;
2481 }
2482
2483 /**
2484  * Pauses the call. If a music file has been setup using linphone_core_set_play_file(),
2485  * this file will be played to the remote user.
2486  *
2487  * @ingroup call_control
2488 **/
2489 int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
2490 {
2491         LinphoneCall *call = the_call;
2492         const char *subject=NULL;
2493
2494         if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
2495                 ms_warning("Cannot pause this call, it is not active.");
2496                 return -1;
2497         }
2498         if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
2499                 sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
2500                 subject="Call on hold";
2501         }else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
2502                 sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
2503                 subject="Call on hold for me too";
2504         }else{
2505                 ms_error("No reason to pause this call, it is already paused or inactive.");
2506                 return -1;
2507         }
2508         if (sal_call_update(call->op,subject) != 0){
2509                 if (lc->vtable.display_warning)
2510                         lc->vtable.display_warning(lc,_("Could not pause the call"));
2511         }
2512         linphone_call_set_state(call,LinphoneCallPausing,"Pausing call");
2513         if (lc->vtable.display_status)
2514                 lc->vtable.display_status(lc,_("Pausing the current call..."));
2515         lc->current_call=NULL;
2516         if (call->audiostream || call->videostream)
2517                 linphone_call_stop_media_streams (call);
2518         return 0;
2519 }
2520
2521 /**
2522  * Pause all currently running calls.
2523 **/
2524 int linphone_core_pause_all_calls(LinphoneCore *lc){
2525         const MSList *elem;
2526         for(elem=lc->calls;elem!=NULL;elem=elem->next){
2527                 LinphoneCall *call=(LinphoneCall *)elem->data;
2528                 LinphoneCallState cs=linphone_call_get_state(call);
2529                 if (cs==LinphoneCallStreamsRunning || cs==LinphoneCallPausedByRemote){
2530                         linphone_core_pause_call(lc,call);
2531                 }
2532         }
2533         return 0;
2534 }
2535
2536 void linphone_core_preempt_sound_resources(LinphoneCore *lc){
2537         LinphoneCall *current_call;
2538         if (linphone_core_is_in_conference(lc)){
2539                 linphone_core_leave_conference(lc);
2540                 return;
2541         }
2542         current_call=linphone_core_get_current_call(lc);
2543         if(current_call != NULL){
2544                 ms_message("Pausing automatically the current call.");
2545                 linphone_core_pause_call(lc,current_call);
2546         }
2547 }
2548
2549 /**
2550  * Resumes the call.
2551  *
2552  * @ingroup call_control
2553 **/
2554 int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
2555 {
2556         char temp[255]={0};
2557         LinphoneCall *call = the_call;
2558         const char *subject="Call resuming";
2559         
2560         if(call->state!=LinphoneCallPaused ){
2561                 ms_warning("we cannot resume a call that has not been established and paused before");
2562                 return -1;
2563         }
2564         if (call->params.in_conference==FALSE){
2565                 linphone_core_preempt_sound_resources(lc);
2566                 ms_message("Resuming call %p",call);
2567         }
2568         update_local_media_description(lc,the_call,&call->localdesc);
2569         sal_call_set_local_media_description(call->op,call->localdesc);
2570         sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
2571         if (call->params.in_conference && !call->current_params.in_conference) subject="Conference";
2572         if(sal_call_update(call->op,subject) != 0){
2573                 return -1;
2574         }
2575         linphone_call_set_state (call,LinphoneCallResuming,"Resuming");
2576         snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call));
2577         if (lc->vtable.display_status)
2578                 lc->vtable.display_status(lc,temp);
2579         return 0;
2580 }
2581
2582 static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *raddr){
2583         const LinphoneAddress *addr=linphone_call_get_remote_address (call);
2584         return !linphone_address_weak_equal (addr,raddr);
2585 }
2586
2587 /**
2588  * Get the call with the remote_address specified
2589  * @param lc
2590  * @param remote_address
2591  * @return the LinphoneCall of the call if found
2592  */
2593 LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){
2594         LinphoneAddress *raddr=linphone_address_new(remote_address);
2595         MSList *elem=ms_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr);
2596         if (elem) return (LinphoneCall*) elem->data;
2597         return NULL;
2598 }
2599
2600 int linphone_core_send_publish(LinphoneCore *lc,
2601                                LinphoneOnlineStatus presence_mode)
2602 {
2603         const MSList *elem;
2604         for (elem=linphone_core_get_proxy_config_list(lc);elem!=NULL;elem=ms_list_next(elem)){
2605                 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
2606                 if (cfg->publish) linphone_proxy_config_send_publish(cfg,presence_mode);
2607         }
2608         return 0;
2609 }
2610
2611 /**
2612  * Set the incoming call timeout in seconds.
2613  *
2614  * @ingroup call_control
2615  * If an incoming call isn't answered for this timeout period, it is
2616  * automatically declined.
2617 **/
2618 void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds){
2619         lc->sip_conf.inc_timeout=seconds;
2620 }
2621
2622 /**
2623  * Returns the incoming call timeout
2624  *
2625  * @ingroup call_control
2626  * See linphone_core_set_inc_timeout() for details.
2627 **/
2628 int linphone_core_get_inc_timeout(LinphoneCore *lc){
2629         return lc->sip_conf.inc_timeout;
2630 }
2631
2632 void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
2633                                                                                                         const char *contact,
2634                                                                                                         LinphoneOnlineStatus presence_mode)
2635 {
2636         if (minutes_away>0) lc->minutes_away=minutes_away;
2637
2638         if (lc->alt_contact!=NULL) {
2639                 ms_free(lc->alt_contact);
2640                 lc->alt_contact=NULL;
2641         }
2642         if (contact) lc->alt_contact=ms_strdup(contact);
2643         if (lc->presence_mode!=presence_mode){
2644                 linphone_core_notify_all_friends(lc,presence_mode);
2645                 /*
2646                    Improve the use of all LINPHONE_STATUS available.
2647                    !TODO Do not mix "presence status" with "answer status code"..
2648                    Use correct parameter to follow sip_if_match/sip_etag.
2649                  */
2650                 linphone_core_send_publish(lc,presence_mode);
2651         }
2652         lc->presence_mode=presence_mode;
2653 }
2654
2655 LinphoneOnlineStatus linphone_core_get_presence_info(const LinphoneCore *lc){
2656         return lc->presence_mode;
2657 }
2658
2659 /**
2660  * Get playback sound level in 0-100 scale.
2661  *
2662  * @ingroup media_parameters
2663 **/
2664 int linphone_core_get_play_level(LinphoneCore *lc)
2665 {
2666         return lc->sound_conf.play_lev;
2667 }
2668
2669 /**
2670  * Get ring sound level in 0-100 scale
2671  *
2672  * @ingroup media_parameters
2673 **/
2674 int linphone_core_get_ring_level(LinphoneCore *lc)
2675 {
2676         return lc->sound_conf.ring_lev;
2677 }
2678
2679 /**
2680  * Get sound capture level in 0-100 scale
2681  *
2682  * @ingroup media_parameters
2683 **/
2684 int linphone_core_get_rec_level(LinphoneCore *lc){
2685         return lc->sound_conf.rec_lev;
2686 }
2687
2688 /**
2689  * Set sound ring level in 0-100 scale
2690  *
2691  * @ingroup media_parameters
2692 **/
2693 void linphone_core_set_ring_level(LinphoneCore *lc, int level){
2694         MSSndCard *sndcard;
2695         lc->sound_conf.ring_lev=level;
2696         sndcard=lc->sound_conf.ring_sndcard;
2697         if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_PLAYBACK,level);
2698 }
2699
2700 /**
2701  * Allow to control play level before entering sound card:  gain in db
2702  *
2703  * @ingroup media_parameters
2704 **/
2705 void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){
2706         float gain=gaindb;
2707         LinphoneCall *call=linphone_core_get_current_call (lc);
2708         AudioStream *st;
2709
2710         lc->sound_conf.soft_play_lev=gaindb;
2711
2712         if (call==NULL || (st=call->audiostream)==NULL){
2713                 ms_message("linphone_core_set_playback_gain_db(): no active call.");
2714                 return;
2715         }
2716         if (st->volrecv){
2717                 ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain);
2718         }else ms_warning("Could not apply gain: gain control wasn't activated.");
2719 }
2720
2721 /**
2722  * Get playback gain in db before entering  sound card.
2723  *
2724  * @ingroup media_parameters
2725 **/
2726 float linphone_core_get_playback_gain_db(LinphoneCore *lc) {
2727         return lc->sound_conf.soft_play_lev;
2728 }
2729
2730 /**
2731  * Set sound playback level in 0-100 scale
2732  *
2733  * @ingroup media_parameters
2734 **/
2735 void linphone_core_set_play_level(LinphoneCore *lc, int level){
2736         MSSndCard *sndcard;
2737         lc->sound_conf.play_lev=level;
2738         sndcard=lc->sound_conf.play_sndcard;
2739         if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_PLAYBACK,level);
2740 }
2741
2742 /**
2743  * Set sound capture level in 0-100 scale
2744  *
2745  * @ingroup media_parameters
2746 **/
2747 void linphone_core_set_rec_level(LinphoneCore *lc, int level)
2748 {
2749         MSSndCard *sndcard;
2750         lc->sound_conf.rec_lev=level;
2751         sndcard=lc->sound_conf.capt_sndcard;
2752         if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_CAPTURE,level);
2753 }
2754
2755 static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){
2756         MSSndCard *sndcard=NULL;
2757         if (devid!=NULL){
2758                 sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid);
2759                 if (sndcard!=NULL &&
2760                         (ms_snd_card_get_capabilities(sndcard) & cap)==0 ){
2761                         ms_warning("%s card does not have the %s capability, ignoring.",
2762                                 devid,
2763                                 cap==MS_SND_CARD_CAP_CAPTURE ? "capture" : "playback");
2764                         sndcard=NULL;
2765                 }
2766         }
2767         if (sndcard==NULL) {
2768                 /* get a card that has read+write capabilities */
2769                 sndcard=ms_snd_card_manager_get_default_card(ms_snd_card_manager_get());
2770                 /* otherwise refine to the first card having the right capability*/
2771                 if (sndcard==NULL){
2772                         const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
2773                         for(;elem!=NULL;elem=elem->next){
2774                                 sndcard=(MSSndCard*)elem->data;
2775                                 if (ms_snd_card_get_capabilities(sndcard) & cap) break;
2776                         }
2777                 }
2778                 if (sndcard==NULL){/*looks like a bug! take the first one !*/
2779                         const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get());
2780                         if (elem) sndcard=(MSSndCard*)elem->data;
2781         }
2782         }
2783         if (sndcard==NULL) ms_error("Could not find a suitable soundcard !");
2784         return sndcard;
2785 }
2786
2787 /**
2788  * Returns true if the specified sound device can capture sound.
2789  *
2790  * @ingroup media_parameters
2791  * @param lc The LinphoneCore object
2792  * @param devid the device name as returned by linphone_core_get_sound_devices()
2793 **/
2794 bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *devid){
2795         MSSndCard *sndcard;
2796         sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid);
2797         if (sndcard!=NULL && (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_CAPTURE)) return TRUE;
2798         return FALSE;
2799 }
2800
2801 /**
2802  * Returns true if the specified sound device can play sound.
2803  *
2804  * @ingroup media_parameters
2805  * @param lc The LinphoneCore object
2806  * @param devid the device name as returned by linphone_core_get_sound_devices()
2807 **/
2808 bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *devid){
2809         MSSndCard *sndcard;
2810         sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid);
2811         if (sndcard!=NULL && (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_PLAYBACK)) return TRUE;
2812         return FALSE;
2813 }
2814
2815 /**
2816  * Sets the sound device used for ringing.
2817  *
2818  * @ingroup media_parameters
2819  * @param lc The LinphoneCore object
2820  * @param devid the device name as returned by linphone_core_get_sound_devices()
2821 **/
2822 int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){
2823         MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK);
2824         lc->sound_conf.ring_sndcard=card;
2825         if (card && linphone_core_ready(lc))
2826                 lp_config_set_string(lc->config,"sound","ringer_dev_id",ms_snd_card_get_string_id(card));
2827         return 0;
2828 }
2829
2830 /**
2831  * Sets the sound device used for playback.
2832  *
2833  * @ingroup media_parameters
2834  * @param lc The LinphoneCore object
2835  * @param devid the device name as returned by linphone_core_get_sound_devices()
2836 **/
2837 int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){
2838         MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK);
2839         lc->sound_conf.play_sndcard=card;
2840         if (card &&  linphone_core_ready(lc))
2841                 lp_config_set_string(lc->config,"sound","playback_dev_id",ms_snd_card_get_string_id(card));
2842         return 0;
2843 }
2844
2845 /**
2846  * Sets the sound device used for capture.
2847  *
2848  * @ingroup media_parameters
2849  * @param lc The LinphoneCore object
2850  * @param devid the device name as returned by linphone_core_get_sound_devices()
2851 **/
2852 int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid){
2853         MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_CAPTURE);
2854         lc->sound_conf.capt_sndcard=card;
2855         if (card &&  linphone_core_ready(lc))
2856                 lp_config_set_string(lc->config,"sound","capture_dev_id",ms_snd_card_get_string_id(card));
2857         return 0;
2858 }
2859
2860 /**
2861  * Returns the name of the currently assigned sound device for ringing.
2862  *
2863  * @ingroup media_parameters
2864  * @param lc The LinphoneCore object
2865 **/
2866 const char * linphone_core_get_ringer_device(LinphoneCore *lc)
2867 {
2868         if (lc->sound_conf.ring_sndcard) return ms_snd_card_get_string_id(lc->sound_conf.ring_sndcard);
2869         return NULL;
2870 }
2871
2872 /**
2873  * Returns the name of the currently assigned sound device for playback.
2874  *
2875  * @ingroup media_parameters
2876  * @param lc The LinphoneCore object
2877 **/
2878 const char * linphone_core_get_playback_device(LinphoneCore *lc)
2879 {
2880         return lc->sound_conf.play_sndcard ? ms_snd_card_get_string_id(lc->sound_conf.play_sndcard) : NULL;
2881 }
2882
2883 /**
2884  * Returns the name of the currently assigned sound device for capture.
2885  *
2886  * @ingroup media_parameters
2887  * @param lc The LinphoneCore object
2888 **/
2889 const char * linphone_core_get_capture_device(LinphoneCore *lc)
2890 {
2891         return lc->sound_conf.capt_sndcard ? ms_snd_card_get_string_id(lc->sound_conf.capt_sndcard) : NULL;
2892 }
2893
2894 /**
2895  * Returns an unmodifiable array of available sound devices.
2896  *
2897  * The array is NULL terminated.
2898  *
2899  * @ingroup media_parameters
2900  * @param lc The LinphoneCore object
2901 **/
2902 const char**  linphone_core_get_sound_devices(LinphoneCore *lc){
2903         build_sound_devices_table(lc);
2904         return lc->sound_conf.cards;
2905 }
2906
2907 /**
2908  * Returns an unmodifiable array of available video capture devices.
2909  *
2910  * @ingroup media_parameters
2911  * The array is NULL terminated.
2912 **/
2913 const char**  linphone_core_get_video_devices(const LinphoneCore *lc){
2914         return lc->video_conf.cams;
2915 }
2916
2917 char linphone_core_get_sound_source(LinphoneCore *lc)
2918 {
2919         return lc->sound_conf.source;
2920 }
2921
2922 void linphone_core_set_sound_source(LinphoneCore *lc, char source)
2923 {
2924         MSSndCard *sndcard=lc->sound_conf.capt_sndcard;
2925         lc->sound_conf.source=source;
2926         if (!sndcard) return;
2927         switch(source){
2928                 case 'm':
2929                         ms_snd_card_set_capture(sndcard,MS_SND_CARD_MIC);
2930                         break;
2931                 case 'l':
2932                         ms_snd_card_set_capture(sndcard,MS_SND_CARD_LINE);
2933                         break;
2934         }
2935
2936 }
2937
2938
2939 /**
2940  * Sets the path to a wav file used for ringing.
2941  *
2942  * @param path The file must be a wav 16bit linear. Local ring is disabled if null
2943  * @param lc The LinphoneCore object
2944  *
2945  * @ingroup media_parameters
2946 **/
2947 void linphone_core_set_ring(LinphoneCore *lc,const char *path){
2948         if (lc->sound_conf.local_ring!=0){
2949                 ms_free(lc->sound_conf.local_ring);
2950                 lc->sound_conf.local_ring=NULL;
2951         }
2952         if (path)
2953                 lc->sound_conf.local_ring=ms_strdup(path);
2954         if ( linphone_core_ready(lc) && lc->sound_conf.local_ring)
2955                 lp_config_set_string(lc->config,"sound","local_ring",lc->sound_conf.local_ring);
2956 }
2957
2958 /**
2959  * Returns the path to the wav file used for ringing.
2960  *
2961  * @param lc The LinphoneCore object
2962  * @ingroup media_parameters
2963 **/
2964 const char *linphone_core_get_ring(const LinphoneCore *lc){
2965         return lc->sound_conf.local_ring;
2966 }
2967
2968 /**
2969  * Sets the path to a file or folder containing trusted root CAs (PEM format)
2970  *
2971  * @param path
2972  * @param lc The LinphoneCore object
2973  *
2974  * @ingroup media_parameters
2975 **/
2976 void linphone_core_set_root_ca(LinphoneCore *lc,const char *path){
2977         sal_root_ca(lc->sal, path);
2978 }
2979
2980 static void notify_end_of_ring(void *ud, MSFilter *f, unsigned int event, void *arg){
2981         LinphoneCore *lc=(LinphoneCore*)ud;
2982         lc->preview_finished=1;
2983 }
2984
2985 int linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCbFunc func,void * userdata)
2986 {
2987         if (lc->ringstream!=0){
2988                 ms_warning("Cannot start ring now,there's already a ring being played");
2989                 return -1;
2990         }
2991         lc_callback_obj_init(&lc->preview_finished_cb,func,userdata);
2992         lc->preview_finished=0;
2993         if (lc->sound_conf.ring_sndcard!=NULL){
2994                 MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
2995                 lc->ringstream=ring_start_with_cb(ring,2000,ringcard,notify_end_of_ring,(void *)lc);
2996         }
2997         return 0;
2998 }
2999
3000 /**
3001  * Sets the path to a wav file used for ringing back.
3002  *
3003  * Ringback means the ring that is heard when it's ringing at the remote party.
3004  * The file must be a wav 16bit linear.
3005  *
3006  * @ingroup media_parameters
3007 **/
3008 void linphone_core_set_ringback(LinphoneCore *lc, const char *path){
3009         if (lc->sound_conf.remote_ring!=0){
3010                 ms_free(lc->sound_conf.remote_ring);
3011         }
3012         lc->sound_conf.remote_ring=ms_strdup(path);
3013 }
3014
3015 /**
3016  * Returns the path to the wav file used for ringing back.
3017  *
3018  * @ingroup media_parameters
3019 **/
3020 const char * linphone_core_get_ringback(const LinphoneCore *lc){
3021         return lc->sound_conf.remote_ring;
3022 }
3023
3024 /**
3025  * Enables or disable echo cancellation. Value is saved an used for subsequent calls
3026  *
3027  * @ingroup media_parameters
3028 **/
3029 void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bool_t val){
3030         lc->sound_conf.ec=val;
3031         if ( linphone_core_ready(lc))
3032                 lp_config_set_int(lc->config,"sound","echocancellation",val);
3033 }
3034
3035
3036 /**
3037  * Returns TRUE if echo cancellation is enabled.
3038  *
3039  * @ingroup media_parameters
3040 **/
3041 bool_t linphone_core_echo_cancellation_enabled(LinphoneCore *lc){
3042         return lc->sound_conf.ec;
3043 }
3044
3045 void linphone_core_enable_echo_limiter(LinphoneCore *lc, bool_t val){
3046         lc->sound_conf.ea=val;
3047 }
3048
3049 bool_t linphone_core_echo_limiter_enabled(const LinphoneCore *lc){
3050         return lc->sound_conf.ea;
3051 }
3052
3053 /**
3054  * Mutes or unmutes the local microphone.
3055  *
3056  * @ingroup media_parameters
3057 **/
3058 void linphone_core_mute_mic(LinphoneCore *lc, bool_t val){
3059         LinphoneCall *call=linphone_core_get_current_call(lc);
3060         AudioStream *st=NULL;
3061         if (linphone_core_is_in_conference(lc)){
3062                 lc->conf_ctx.local_muted=val;
3063                 st=lc->conf_ctx.local_participant;
3064         }else if (call==NULL){
3065                 ms_warning("linphone_core_mute_mic(): No current call !");
3066                 return;
3067         }else{
3068                 st=call->audiostream;
3069                 call->audio_muted=val;
3070         }
3071         if (st!=NULL){
3072                 audio_stream_set_mic_gain(st,
3073                         (val==TRUE) ? 0 : lp_config_get_float(lc->config,"sound","mic_gain",1));
3074                 if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){
3075                         audio_stream_mute_rtp(st,val);
3076                 }
3077                 
3078         }
3079 }
3080 /**
3081  * Returns whether microphone is muted.
3082 **/
3083 bool_t linphone_core_is_mic_muted(LinphoneCore *lc) {
3084         LinphoneCall *call=linphone_core_get_current_call(lc);
3085         if (linphone_core_is_in_conference(lc)){
3086                 return lc->conf_ctx.local_muted;
3087         }else if (call==NULL){
3088                 ms_warning("linphone_core_is_mic_muted(): No current call !");
3089                 return FALSE;
3090         }
3091         return call->audio_muted;
3092 }
3093
3094 // returns rtp transmission status for an active stream
3095 // if audio is muted and config parameter rtp_no_xmit_on_audio_mute
3096 // was set on then rtp transmission is also muted
3097 bool_t linphone_core_is_rtp_muted(LinphoneCore *lc){
3098         LinphoneCall *call=linphone_core_get_current_call(lc);
3099         if (call==NULL){
3100                 ms_warning("linphone_core_is_mic_muted(): No current call !");
3101                 return FALSE;
3102         }
3103         if( linphone_core_get_rtp_no_xmit_on_audio_mute(lc)){
3104                 return call->audio_muted;
3105         }
3106         return FALSE;
3107 }
3108
3109 void linphone_core_enable_agc(LinphoneCore *lc, bool_t val){
3110         lc->sound_conf.agc=val;
3111 }
3112
3113 bool_t linphone_core_agc_enabled(const LinphoneCore *lc){
3114         return lc->sound_conf.agc;
3115 }
3116
3117 /**
3118  * Send the specified dtmf.
3119  *
3120  * @ingroup media_parameters
3121  * This function only works during calls. The dtmf is automatically played to the user.
3122  * @param lc The LinphoneCore object
3123  * @param dtmf The dtmf name specified as a char, such as '0', '#' etc...
3124  *
3125 **/
3126 void linphone_core_send_dtmf(LinphoneCore *lc, char dtmf)
3127 {
3128         LinphoneCall *call=linphone_core_get_current_call(lc);
3129         if (call==NULL){
3130                 ms_warning("linphone_core_send_dtmf(): no active call");
3131                 return;
3132         }
3133         /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/
3134         if (linphone_core_get_use_rfc2833_for_dtmf(lc)!=0 || linphone_core_get_use_info_for_dtmf(lc)==0)
3135         {
3136                 /* In Band DTMF */
3137                 if (call->audiostream!=NULL){
3138                         audio_stream_send_dtmf(call->audiostream,dtmf);
3139                 }
3140                 else
3141                 {
3142                         ms_error("we cannot send RFC2833 dtmf when we are not in communication");
3143                 }
3144         }
3145         if (linphone_core_get_use_info_for_dtmf(lc)!=0){
3146                 /* Out of Band DTMF (use INFO method) */
3147                 sal_call_send_dtmf(call->op,dtmf);
3148         }
3149 }
3150
3151 void linphone_core_set_stun_server(LinphoneCore *lc, const char *server){
3152         if (lc->net_conf.stun_server!=NULL)
3153                 ms_free(lc->net_conf.stun_server);
3154         if (server)
3155                 lc->net_conf.stun_server=ms_strdup(server);
3156         else lc->net_conf.stun_server=NULL;
3157 }
3158
3159 const char * linphone_core_get_stun_server(const LinphoneCore *lc){
3160         return lc->net_conf.stun_server;
3161 }
3162
3163 const char * linphone_core_get_relay_addr(const LinphoneCore *lc){
3164         return lc->net_conf.relay;
3165 }
3166
3167 int linphone_core_set_relay_addr(LinphoneCore *lc, const char *addr){
3168         if (lc->net_conf.relay!=NULL){
3169                 ms_free(lc->net_conf.relay);
3170                 lc->net_conf.relay=NULL;
3171         }
3172         if (addr){
3173                 lc->net_conf.relay=ms_strdup(addr);
3174         }
3175         return 0;
3176 }
3177
3178 void linphone_core_set_nat_address(LinphoneCore *lc, const char *addr)
3179 {
3180         if (lc->net_conf.nat_address!=NULL){
3181                 ms_free(lc->net_conf.nat_address);
3182         }
3183         if (addr!=NULL) lc->net_conf.nat_address=ms_strdup(addr);
3184         else lc->net_conf.nat_address=NULL;
3185         if (lc->sip_conf.contact) update_primary_contact(lc);
3186 }
3187
3188 const char *linphone_core_get_nat_address(const LinphoneCore *lc) {
3189         return lc->net_conf.nat_address;
3190 }
3191
3192 const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc)
3193 {
3194         struct sockaddr_storage ss;
3195         socklen_t ss_len;
3196         int error;
3197         char ipstring [INET6_ADDRSTRLEN];
3198
3199         if (lc->net_conf.nat_address==NULL) return NULL;
3200         
3201         if (parse_hostname_to_addr (lc->net_conf.nat_address, &ss, &ss_len)<0) {
3202                 return lc->net_conf.nat_address;
3203         }
3204
3205         error = getnameinfo((struct sockaddr *)&ss, ss_len,
3206                 ipstring, sizeof(ipstring), NULL, 0, NI_NUMERICHOST);
3207         if (error) {
3208                 return lc->net_conf.nat_address;
3209         }
3210
3211         if (lc->net_conf.nat_address_ip!=NULL){
3212                 ms_free(lc->net_conf.nat_address_ip);
3213         }
3214         lc->net_conf.nat_address_ip = ms_strdup (ipstring);
3215         return lc->net_conf.nat_address_ip;
3216 }
3217
3218 void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy pol){
3219         lc->net_conf.firewall_policy=pol;
3220         if (lc->sip_conf.contact) update_primary_contact(lc);
3221 }
3222
3223 LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc){
3224         return lc->net_conf.firewall_policy;
3225 }
3226
3227 /**
3228  * Get the list of call logs (past calls).
3229  *
3230  * @ingroup call_logs
3231 **/
3232 const MSList * linphone_core_get_call_logs(LinphoneCore *lc){
3233         lc->missed_calls=0;
3234         return lc->call_logs;
3235 }
3236
3237 /**
3238  * Erase the call log.
3239  *
3240  * @ingroup call_logs
3241 **/
3242 void linphone_core_clear_call_logs(LinphoneCore *lc){
3243         lc->missed_calls=0;
3244         ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
3245         lc->call_logs=ms_list_free(lc->call_logs);
3246         call_logs_write_to_config_file(lc);
3247 }
3248
3249 static void toggle_video_preview(LinphoneCore *lc, bool_t val){
3250 #ifdef VIDEO_ENABLED
3251         if (val){
3252                 if (lc->previewstream==NULL){
3253                         lc->previewstream=video_preview_new();
3254                         video_preview_set_size(lc->previewstream,lc->video_conf.vsize);
3255                         if (lc->video_conf.displaytype)
3256                                 video_preview_set_display_filter_name(lc->previewstream,lc->video_conf.displaytype);
3257                         if (lc->preview_window_id!=0)
3258                                 video_preview_set_native_window_id(lc->previewstream,lc->preview_window_id);
3259                         video_preview_start(lc->previewstream,lc->video_conf.device);
3260                 }
3261         }else{
3262                 if (lc->previewstream!=NULL){
3263                         video_preview_stop(lc->previewstream);
3264                         lc->previewstream=NULL;
3265                 }
3266         }
3267 #endif
3268 }
3269
3270 /**
3271  * Enables video globally.
3272  *
3273  * @ingroup media_parameters
3274  * This function does not have any effect during calls. It just indicates LinphoneCore to
3275  * initiate future calls with video or not. The two boolean parameters indicate in which
3276  * direction video is enabled. Setting both to false disables video entirely.
3277  *
3278  * @param lc The LinphoneCore object
3279  * @param vcap_enabled indicates whether video capture is enabled
3280  * @param display_enabled indicates whether video display should be shown
3281  *
3282 **/
3283 void linphone_core_enable_video(LinphoneCore *lc, bool_t vcap_enabled, bool_t display_enabled){
3284 #ifndef VIDEO_ENABLED
3285         if (vcap_enabled || display_enabled)
3286                 ms_warning("This version of linphone was built without video support.");
3287 #endif
3288         lc->video_conf.capture=vcap_enabled;
3289         lc->video_conf.display=display_enabled;
3290
3291         /* need to re-apply network bandwidth settings*/
3292         linphone_core_set_download_bandwidth(lc,
3293                 linphone_core_get_download_bandwidth(lc));
3294         linphone_core_set_upload_bandwidth(lc,
3295                 linphone_core_get_upload_bandwidth(lc));
3296 }
3297
3298 /**
3299  * Returns TRUE if video is enabled, FALSE otherwise.
3300  * @ingroup media_parameters
3301 **/
3302 bool_t linphone_core_video_enabled(LinphoneCore *lc){
3303         return (lc->video_conf.display || lc->video_conf.capture);
3304 }
3305
3306 /**
3307  * Controls video preview enablement.
3308  *
3309  * @ingroup media_parameters
3310  * Video preview refers to the action of displaying the local webcam image
3311  * to the user while not in call.
3312 **/
3313 void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t val){
3314         lc->video_conf.show_local=val;
3315 }
3316
3317 /**
3318  * Returns TRUE if video previewing is enabled.
3319  * @ingroup media_parameters
3320 **/
3321 bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc){
3322         return lc->video_conf.show_local;
3323 }
3324
3325 /**
3326  * Enables or disable self view during calls.
3327  *
3328  * @ingroup media_parameters
3329  * Self-view refers to having local webcam image inserted in corner
3330  * of the video window during calls.
3331  * This function works at any time, including during calls.
3332 **/
3333 void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val){
3334 #ifdef VIDEO_ENABLED
3335         LinphoneCall *call=linphone_core_get_current_call (lc);
3336         lc->video_conf.selfview=val;
3337         if (call && call->videostream){
3338                 video_stream_enable_self_view(call->videostream,val);
3339         }
3340 #endif
3341 }
3342
3343 /**
3344  * Returns TRUE if self-view is enabled, FALSE otherwise.
3345  *
3346  * @ingroup media_parameters
3347  *
3348  * Refer to linphone_core_enable_self_view() for details.
3349 **/
3350 bool_t linphone_core_self_view_enabled(const LinphoneCore *lc){
3351         return lc->video_conf.selfview;
3352 }
3353
3354 /**
3355  * Sets the active video device.
3356  *
3357  * @ingroup media_parameters
3358  * @param lc The LinphoneCore object
3359  * @param id the name of the video device as returned by linphone_core_get_video_devices()
3360 **/
3361 int linphone_core_set_video_device(LinphoneCore *lc, const char *id){
3362         MSWebCam *olddev=lc->video_conf.device;
3363         const char *vd;
3364         if (id!=NULL){
3365                 lc->video_conf.device=ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),id);
3366                 if (lc->video_conf.device==NULL){
3367                         ms_warning("Could not found video device %s",id);
3368                 }
3369         }
3370         if (lc->video_conf.device==NULL)
3371                 lc->video_conf.device=ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get());
3372         if (olddev!=NULL && olddev!=lc->video_conf.device){
3373                 toggle_video_preview(lc,FALSE);/*restart the video local preview*/
3374         }
3375         if ( linphone_core_ready(lc) && lc->video_conf.device){
3376                 vd=ms_web_cam_get_string_id(lc->video_conf.device);
3377                 if (vd && strstr(vd,"Static picture")!=NULL){
3378                         vd=NULL;
3379                 }
3380                 lp_config_set_string(lc->config,"video","device",vd);
3381         }
3382         return 0;
3383 }
3384
3385 /**
3386  * Returns the name of the currently active video device.
3387  *
3388  * @param lc The LinphoneCore object
3389  * @ingroup media_parameters
3390 **/
3391 const char *linphone_core_get_video_device(const LinphoneCore *lc){
3392         if (lc->video_conf.device) return ms_web_cam_get_string_id(lc->video_conf.device);
3393         return NULL;
3394 }
3395
3396 #ifdef VIDEO_ENABLED
3397 static VideoStream * get_active_video_stream(LinphoneCore *lc){
3398         VideoStream *vs = NULL;
3399         LinphoneCall *call=linphone_core_get_current_call (lc);
3400         /* Select the video stream from the call in the first place */
3401         if (call && call->videostream) {
3402                 vs = call->videostream;
3403         }
3404         /* If not in call, select the video stream from the preview */
3405         if (vs == NULL && lc->previewstream) {
3406                 vs = lc->previewstream;
3407         }
3408         return vs;
3409 }
3410 #endif
3411
3412 int linphone_core_set_static_picture(LinphoneCore *lc, const char *path) {
3413 #ifdef VIDEO_ENABLED
3414         VideoStream *vs=get_active_video_stream(lc);
3415         /* If we have a video stream (either preview, either from call), we
3416                  have a source and it is using the static picture filter, then
3417                  force the filter to use that picture. */
3418         if (vs && vs->source) {
3419                 if (ms_filter_get_id(vs->source) == MS_STATIC_IMAGE_ID) {
3420                         ms_filter_call_method(vs->source, MS_STATIC_IMAGE_SET_IMAGE,
3421                                                                                                                 (void *)path);
3422                 }
3423         }
3424         /* Tell the static image filter to use that image from now on so
3425                  that the image will be used next time it has to be read */
3426         ms_static_image_set_default_image(path);
3427 #else
3428         ms_warning("Video support not compiled.");
3429 #endif
3430         return 0;
3431 }
3432
3433 int linphone_core_set_static_picture_fps(LinphoneCore *lc, float fps) {
3434 #ifdef VIDEO_ENABLED
3435         VideoStream *vs = NULL;
3436
3437         vs=get_active_video_stream(lc);
3438
3439         /* If we have a video stream (either preview, either from call), we
3440                  have a source and it is using the static picture filter, then
3441                  force the filter to use that picture. */
3442         if (vs && vs->source) {
3443                 if (ms_filter_get_id(vs->source) == MS_STATIC_IMAGE_ID) {
3444                         ms_filter_call_method(vs->source, MS_FILTER_SET_FPS,(void *)&fps);
3445                 }
3446         }
3447 #else
3448         ms_warning("Video support not compiled.");
3449 #endif
3450         return 0;
3451 }
3452
3453 float linphone_core_get_static_picture_fps(LinphoneCore *lc) {
3454 #ifdef VIDEO_ENABLED
3455         VideoStream *vs = NULL;
3456         vs=get_active_video_stream(lc);
3457         /* If we have a video stream (either preview, either from call), we
3458                  have a source and it is using the static picture filter, then
3459                  force the filter to use that picture. */
3460         if (vs && vs->source) {
3461                 if (ms_filter_get_id(vs->source) == MS_STATIC_IMAGE_ID) {
3462
3463                         float fps;
3464
3465                         ms_filter_call_method(vs->source, MS_FILTER_GET_FPS,(void *)&fps);
3466                         return fps;
3467                 }
3468         }
3469 #else
3470         ms_warning("Video support not compiled.");
3471 #endif
3472         return 0;
3473 }
3474
3475 /**
3476  * Returns the native window handle of the video window, casted as an unsigned long.
3477  *
3478  * @ingroup media_parameters
3479 **/
3480 unsigned long linphone_core_get_native_video_window_id(const LinphoneCore *lc){
3481 #ifdef VIDEO_ENABLED
3482         LinphoneCall *call=linphone_core_get_current_call (lc);
3483         if (call && call->videostream)
3484                 return video_stream_get_native_window_id(call->videostream);
3485         if (lc->previewstream)
3486                 return video_stream_get_native_window_id(lc->previewstream);
3487 #endif
3488         return lc->video_window_id;
3489 }
3490
3491 /**
3492  * Set the native video window id where the video is to be displayed.
3493  * If not set the core will create its own window.
3494 **/
3495 void linphone_core_set_native_video_window_id(LinphoneCore *lc, unsigned long id){
3496 #ifdef VIDEO_ENABLED
3497         LinphoneCall *call=linphone_core_get_current_call(lc);
3498         lc->video_window_id=id;
3499         if (call!=NULL && call->videostream){
3500                 video_stream_set_native_window_id(call->videostream,id);
3501         }
3502 #endif
3503 }
3504
3505 /**
3506  * Returns the native window handle of the video preview window, casted as an unsigned long.
3507  *
3508  * @ingroup media_parameters
3509 **/
3510 unsigned long linphone_core_get_native_preview_window_id(const LinphoneCore *lc){
3511 #ifdef VIDEO_ENABLED
3512         LinphoneCall *call=linphone_core_get_current_call (lc);
3513         if (call && call->videostream)
3514                 return video_stream_get_native_preview_window_id(call->videostream);
3515         if (lc->previewstream)
3516                 return video_preview_get_native_window_id(lc->previewstream);
3517 #endif
3518         return lc->preview_window_id;
3519 }
3520
3521 /**
3522  * Set the native window id where the preview video (local camera) is to be displayed.
3523  * This has to be used in conjonction with linphone_core_use_preview_window().
3524  * If not set the core will create its own window.
3525 **/
3526 void linphone_core_set_native_preview_window_id(LinphoneCore *lc, unsigned long id){
3527         lc->preview_window_id=id;
3528 #ifdef VIDEO_ENABLED
3529         LinphoneCall *call=linphone_core_get_current_call(lc);
3530         if (call!=NULL && call->videostream){
3531                 video_stream_set_native_preview_window_id(call->videostream,id);
3532         }
3533 #endif
3534 }
3535
3536 /**
3537  * Tells the core to use a separate window for local camera preview video, instead of
3538  * inserting local view within the remote video window.
3539  *
3540 **/
3541 void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno){
3542         lc->use_preview_window=yesno;
3543 }
3544
3545 /**
3546  * Tells the core the device current orientation. This can be used by capture filters
3547  * on mobile devices to select between portrait/landscape mode and to produce properly
3548  * orientated images. The exact meaning of the value in rotation if left to each device
3549  * specific implementations.
3550  *
3551 **/
3552 void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) {
3553 ms_message("%s : rotation=%d\n", __FUNCTION__, rotation);
3554         lc->device_rotation = rotation;
3555 #ifdef VIDEO_ENABLED
3556         LinphoneCall *call=linphone_core_get_current_call(lc);
3557         if (call!=NULL && call->videostream){
3558                 video_stream_set_device_rotation(call->videostream,rotation);
3559         }
3560 #endif
3561 }
3562
3563 static MSVideoSizeDef supported_resolutions[]={
3564 #ifdef ENABLE_HD
3565         {       {MS_VIDEO_SIZE_1080P_W,MS_VIDEO_SIZE_1080P_H}   ,       "1080p" },
3566         {       {MS_VIDEO_SIZE_720P_W,MS_VIDEO_SIZE_720P_H}     ,       "1080p" },
3567 #endif
3568         {       {MS_VIDEO_SIZE_SVGA_W,MS_VIDEO_SIZE_SVGA_H}     ,       "svga"  },
3569         {       {MS_VIDEO_SIZE_4CIF_W,MS_VIDEO_SIZE_4CIF_H}     ,       "4cif"  },
3570         {       {MS_VIDEO_SIZE_VGA_W,MS_VIDEO_SIZE_VGA_H}       ,       "vga"   },
3571         {       {MS_VIDEO_SIZE_CIF_W,MS_VIDEO_SIZE_CIF_H}       ,       "cif"   },
3572         {       {MS_VIDEO_SIZE_QVGA_W,MS_VIDEO_SIZE_QVGA_H}     ,       "qvga"  },
3573         {       {MS_VIDEO_SIZE_QVGA_H,MS_VIDEO_SIZE_QVGA_W}     ,       "qvga-portrait" },
3574         {       {MS_VIDEO_SIZE_QCIF_W,MS_VIDEO_SIZE_QCIF_H}     ,       "qcif"  },
3575         {       {MS_VIDEO_SIZE_QCIF_H,MS_VIDEO_SIZE_QCIF_W}     ,       "qcif-portrait" },
3576         {       {0,0}                   ,       NULL    }
3577 };
3578
3579 /**
3580  * Returns the zero terminated table of supported video resolutions.
3581  *
3582  * @ingroup media_parameters
3583 **/
3584 const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc){
3585         return supported_resolutions;
3586 }
3587
3588 static MSVideoSize video_size_get_by_name(const char *name){
3589         MSVideoSizeDef *pdef=supported_resolutions;
3590         MSVideoSize null_vsize={0,0};
3591         for(;pdef->name!=NULL;pdef++){
3592                 if (strcasecmp(name,pdef->name)==0){
3593                         return pdef->vsize;
3594                 }
3595         }
3596         ms_warning("Video resolution %s is not supported in linphone.",name);
3597         return null_vsize;
3598 }
3599
3600 static const char *video_size_get_name(MSVideoSize vsize){
3601         MSVideoSizeDef *pdef=supported_resolutions;
3602         for(;pdef->name!=NULL;pdef++){
3603                 if (pdef->vsize.width==vsize.width && pdef->vsize.height==vsize.height){
3604                         return pdef->name;
3605                 }
3606         }
3607         return NULL;
3608 }
3609
3610 static bool_t video_size_supported(MSVideoSize vsize){
3611         if (video_size_get_name(vsize)) return TRUE;
3612         ms_warning("Video resolution %ix%i is not supported in linphone.",vsize.width,vsize.height);
3613         return FALSE;
3614 }
3615
3616 /**
3617  * Sets the preferred video size.
3618  *
3619  * @ingroup media_parameters
3620  * This applies only to the stream that is captured and sent to the remote party,
3621  * since we accept all standard video size on the receive path.
3622 **/
3623 void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){
3624         if (video_size_supported(vsize)){
3625                 MSVideoSize oldvsize=lc->video_conf.vsize;
3626                 lc->video_conf.vsize=vsize;
3627                 if (!ms_video_size_equal(oldvsize,vsize) && lc->previewstream!=NULL){
3628                         toggle_video_preview(lc,FALSE);
3629                         toggle_video_preview(lc,TRUE);
3630                 }
3631                 if ( linphone_core_ready(lc))
3632                         lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize));
3633         }
3634 }
3635
3636 /**
3637  * Sets the preferred video size by its name.
3638  *
3639  * @ingroup media_parameters
3640  * This is identical to linphone_core_set_preferred_video_size() except
3641  * that it takes the name of the video resolution as input.
3642  * Video resolution names are: qcif, svga, cif, vga, 4cif, svga ...
3643 **/
3644 void linphone_core_set_preferred_video_size_by_name(LinphoneCore *lc, const char *name){
3645         MSVideoSize vsize=video_size_get_by_name(name);
3646         MSVideoSize default_vsize={MS_VIDEO_SIZE_CIF_W,MS_VIDEO_SIZE_CIF_H};
3647         if (vsize.width!=0)     linphone_core_set_preferred_video_size(lc,vsize);
3648         else linphone_core_set_preferred_video_size(lc,default_vsize);
3649 }
3650
3651 /**
3652  * Returns the current preferred video size for sending.
3653  *
3654  * @ingroup media_parameters
3655 **/
3656 MSVideoSize linphone_core_get_preferred_video_size(LinphoneCore *lc){
3657         return lc->video_conf.vsize;
3658 }
3659
3660 /**
3661  * Ask the core to stream audio from and to files, instead of using the soundcard.
3662 **/
3663 void linphone_core_use_files(LinphoneCore *lc, bool_t yesno){
3664         lc->use_files=yesno;
3665 }
3666
3667 /**
3668  * Sets a wav file to be played when putting somebody on hold,
3669  * or when files are used instead of soundcards (see linphone_core_use_files()).
3670  *
3671  * The file must be a 16 bit linear wav file.
3672 **/
3673 void linphone_core_set_play_file(LinphoneCore *lc, const char *file){
3674         LinphoneCall *call=linphone_core_get_current_call(lc);
3675         if (lc->play_file!=NULL){
3676                 ms_free(lc->play_file);
3677                 lc->play_file=NULL;
3678         }
3679         if (file!=NULL) {
3680                 lc->play_file=ms_strdup(file);
3681                 if (call && call->audiostream && call->audiostream->ticker)
3682                         audio_stream_play(call->audiostream,file);
3683         }
3684 }
3685
3686
3687 /**
3688  * Sets a wav file where incoming stream is to be recorded,
3689  * when files are used instead of soundcards (see linphone_core_use_files()).
3690  *
3691  * The file must be a 16 bit linear wav file.
3692 **/
3693 void linphone_core_set_record_file(LinphoneCore *lc, const char *file){
3694         LinphoneCall *call=linphone_core_get_current_call(lc);
3695         if (lc->rec_file!=NULL){
3696                 ms_free(lc->rec_file);
3697                 lc->rec_file=NULL;
3698         }
3699         if (file!=NULL) {
3700                 lc->rec_file=ms_strdup(file);
3701                 if (call && call->audiostream)
3702                         audio_stream_record(call->audiostream,file);
3703         }
3704 }
3705
3706
3707 static MSFilter *get_dtmf_gen(LinphoneCore *lc){
3708         LinphoneCall *call=linphone_core_get_current_call (lc);
3709         AudioStream *stream=NULL;
3710         if (call){
3711                 stream=call->audiostream;
3712         }else if (linphone_core_is_in_conference(lc)){
3713                 stream=lc->conf_ctx.local_participant;
3714         }
3715         if (stream){
3716                 return stream->dtmfgen;
3717         }
3718         if (lc->ringstream==NULL){
3719                 float amp=0.1;
3720                 MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
3721                 lc->ringstream=ring_start(NULL,0,ringcard);
3722                 ms_filter_call_method(lc->ringstream->gendtmf,MS_DTMF_GEN_SET_DEFAULT_AMPLITUDE,&amp);
3723                 lc->dmfs_playing_start_time=time(NULL);
3724         }else{
3725                 if (lc->dmfs_playing_start_time!=0)
3726                         lc->dmfs_playing_start_time=time(NULL);
3727         }
3728         return lc->ringstream->gendtmf;
3729 }
3730
3731 /**
3732  * @ingroup media_parameters
3733  * Plays a dtmf sound to the local user.
3734  * @param lc #LinphoneCore
3735  * @param dtmf DTMF to play ['0'..'16'] | '#' | '#'
3736  * @param duration_ms duration in ms, -1 means play until next further call to #linphone_core_stop_dtmf()
3737 **/
3738 void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){
3739         MSFilter *f=get_dtmf_gen(lc);
3740         if (f==NULL){
3741                 ms_error("No dtmf generator at this time !");
3742                 return;
3743         }
3744
3745         if (duration_ms>0)
3746                 ms_filter_call_method(f, MS_DTMF_GEN_PLAY, &dtmf);
3747         else ms_filter_call_method(f, MS_DTMF_GEN_START, &dtmf);
3748 }
3749
3750 /**
3751  * @ingroup media_parameters
3752  * Plays a repeated tone to the local user until next further call to #linphone_core_stop_dtmf()
3753  * @param lc #LinphoneCore
3754 **/
3755 void linphone_core_play_tone(LinphoneCore *lc){
3756         MSFilter *f=get_dtmf_gen(lc);
3757         MSDtmfGenCustomTone def;
3758         if (f==NULL){
3759                 ms_error("No dtmf generator at this time !");
3760                 return;
3761         }
3762         def.duration=300;
3763         def.frequency=500;
3764         def.amplitude=1;
3765         def.interval=2000;
3766         ms_filter_call_method(f, MS_DTMF_GEN_PLAY_CUSTOM,&def);
3767 }
3768
3769 /**
3770  * @ingroup media_parameters
3771  *
3772  * Stops playing a dtmf started by linphone_core_play_dtmf().
3773 **/
3774 void linphone_core_stop_dtmf(LinphoneCore *lc){
3775         MSFilter *f=get_dtmf_gen(lc);
3776         if (f!=NULL)
3777                 ms_filter_call_method_noarg (f, MS_DTMF_GEN_STOP);
3778 }
3779
3780
3781
3782 /**
3783  * Retrieves the user pointer that was given to linphone_core_new()
3784  *
3785  * @ingroup initializing
3786 **/
3787 void *linphone_core_get_user_data(LinphoneCore *lc){
3788         return lc->data;
3789 }
3790
3791 int linphone_core_get_mtu(const LinphoneCore *lc){
3792         return lc->net_conf.mtu;
3793 }
3794
3795 void linphone_core_set_mtu(LinphoneCore *lc, int mtu){
3796         lc->net_conf.mtu=mtu;
3797         if (mtu>0){
3798                 if (mtu<500){
3799                         ms_error("MTU too small !");
3800                         mtu=500;
3801                 }
3802                 ms_set_mtu(mtu);
3803                 ms_message("MTU is supposed to be %i, rtp payload max size will be %i",mtu, ms_get_payload_max_size());
3804         }else ms_set_mtu(0);//use mediastreamer2 default value
3805 }
3806
3807 void linphone_core_set_waiting_callback(LinphoneCore *lc, LinphoneWaitingCallback cb, void *user_context){
3808         lc->wait_cb=cb;
3809         lc->wait_ctx=user_context;
3810 }
3811
3812 void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose){
3813         if (lc->wait_cb){
3814                 lc->wait_ctx=lc->wait_cb(lc,lc->wait_ctx,LinphoneWaitingStart,purpose,0);
3815         }
3816 }
3817
3818 void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progress){
3819         if (lc->wait_cb){
3820                 lc->wait_ctx=lc->wait_cb(lc,lc->wait_ctx,LinphoneWaitingProgress,purpose,progress);
3821         }else{
3822 #ifdef WIN32
3823                 Sleep(50000);
3824 #else
3825                 usleep(50000);
3826 #endif
3827         }
3828 }
3829
3830 void linphone_core_stop_waiting(LinphoneCore *lc){
3831         if (lc->wait_cb){
3832                 lc->wait_ctx=lc->wait_cb(lc,lc->wait_ctx,LinphoneWaitingFinished,NULL,0);
3833         }
3834 }
3835
3836 void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp){
3837         lc->a_rtp=rtp;
3838         lc->a_rtcp=rtcp;
3839 }
3840
3841 void linphone_core_set_video_transports(LinphoneCore *lc, RtpTransport *rtp, RtpTransport *rtcp){
3842         lc->v_rtp=rtp;
3843         lc->v_rtcp=rtcp;
3844 }
3845
3846 /**
3847  * Retrieve RTP statistics regarding current call.
3848  * @param local RTP statistics computed locally.
3849  * @param remote RTP statistics computed by far end (obtained via RTCP feedback).
3850  *
3851  * @note Remote RTP statistics is not implemented yet.
3852  *
3853  * @returns 0 or -1 if no call is running.
3854 **/
3855
3856 int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote){
3857         LinphoneCall *call=linphone_core_get_current_call (lc);
3858         if (call!=NULL){
3859                 if (call->audiostream!=NULL){
3860                         memset(remote,0,sizeof(*remote));
3861                         audio_stream_get_local_rtp_stats (call->audiostream,local);
3862                         return 0;
3863                 }
3864         }
3865         return -1;
3866 }
3867
3868 void net_config_uninit(LinphoneCore *lc)
3869 {
3870         net_config_t *config=&lc->net_conf;
3871
3872         if (config->stun_server!=NULL){
3873                 lp_config_set_string(lc->config,"net","stun_server",config->stun_server);
3874                 ms_free(lc->net_conf.stun_server);
3875         }
3876         if (config->nat_address!=NULL){
3877                 lp_config_set_string(lc->config,"net","nat_address",config->nat_address);
3878                 ms_free(lc->net_conf.nat_address);
3879         }
3880         if (lc->net_conf.nat_address_ip !=NULL){
3881                 ms_free(lc->net_conf.nat_address_ip);
3882         }
3883         lp_config_set_int(lc->config,"net","firewall_policy",config->firewall_policy);
3884         lp_config_set_int(lc->config,"net","mtu",config->mtu);
3885 }
3886
3887
3888 void sip_config_uninit(LinphoneCore *lc)
3889 {
3890         MSList *elem;
3891         int i;
3892         sip_config_t *config=&lc->sip_conf;
3893         
3894         lp_config_set_int(lc->config,"sip","guess_hostname",config->guess_hostname);
3895         lp_config_set_string(lc->config,"sip","contact",config->contact);
3896         lp_config_set_int(lc->config,"sip","inc_timeout",config->inc_timeout);
3897         lp_config_set_int(lc->config,"sip","use_info",config->use_info);
3898         lp_config_set_int(lc->config,"sip","use_rfc2833",config->use_rfc2833);
3899         lp_config_set_int(lc->config,"sip","use_ipv6",config->ipv6_enabled);
3900         lp_config_set_int(lc->config,"sip","register_only_when_network_is_up",config->register_only_when_network_is_up);
3901
3902
3903         
3904
3905         for(elem=config->proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
3906                 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
3907                 linphone_proxy_config_edit(cfg);        /* to unregister */
3908         }
3909
3910         for (i=0;i<20;i++){
3911                 sal_iterate(lc->sal);
3912 #ifndef WIN32
3913                 usleep(100000);
3914 #else
3915                 Sleep(100);
3916 #endif
3917         }
3918
3919         ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
3920         ms_list_free(config->proxies);
3921         config->proxies=NULL;
3922
3923         linphone_proxy_config_write_to_config_file(lc->config,NULL,i);  /*mark the end */
3924
3925         ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
3926         ms_list_free(lc->auth_info);
3927         lc->auth_info=NULL;
3928
3929         sal_uninit(lc->sal);
3930         lc->sal=NULL;
3931
3932         if (lc->sip_conf.guessed_contact)
3933                 ms_free(lc->sip_conf.guessed_contact);
3934         if (config->contact)
3935                 ms_free(config->contact);
3936
3937 }
3938
3939 void rtp_config_uninit(LinphoneCore *lc)
3940 {
3941         rtp_config_t *config=&lc->rtp_conf;
3942         lp_config_set_int(lc->config,"rtp","audio_rtp_port",config->audio_rtp_port);
3943         lp_config_set_int(lc->config,"rtp","video_rtp_port",config->video_rtp_port);
3944         lp_config_set_int(lc->config,"rtp","audio_jitt_comp",config->audio_jitt_comp);
3945         lp_config_set_int(lc->config,"rtp","video_jitt_comp",config->video_jitt_comp);
3946         lp_config_set_int(lc->config,"rtp","nortp_timeout",config->nortp_timeout);
3947 }
3948
3949 void sound_config_uninit(LinphoneCore *lc)
3950 {
3951         sound_config_t *config=&lc->sound_conf;
3952         ms_free(config->cards);
3953
3954         lp_config_set_string(lc->config,"sound","remote_ring",config->remote_ring);
3955
3956         if (config->local_ring) ms_free(config->local_ring);
3957         if (config->remote_ring) ms_free(config->remote_ring);
3958         ms_snd_card_manager_destroy();
3959 }
3960
3961 void video_config_uninit(LinphoneCore *lc)
3962 {
3963         lp_config_set_string(lc->config,"video","size",video_size_get_name(linphone_core_get_preferred_video_size(lc)));
3964         lp_config_set_int(lc->config,"video","display",lc->video_conf.display);
3965         lp_config_set_int(lc->config,"video","capture",lc->video_conf.capture);
3966         lp_config_set_int(lc->config,"video","show_local",linphone_core_video_preview_enabled(lc));
3967         lp_config_set_int(lc->config,"video","self_view",linphone_core_self_view_enabled(lc));
3968         if (lc->video_conf.cams)
3969                 ms_free(lc->video_conf.cams);
3970 }
3971
3972 void codecs_config_uninit(LinphoneCore *lc)
3973 {
3974         PayloadType *pt;
3975         codecs_config_t *config=&lc->codecs_conf;
3976         MSList *node;
3977         char key[50];
3978         int index;
3979         index=0;
3980         for(node=config->audio_codecs;node!=NULL;node=ms_list_next(node)){
3981                 pt=(PayloadType*)(node->data);
3982                 sprintf(key,"audio_codec_%i",index);
3983                 lp_config_set_string(lc->config,key,"mime",pt->mime_type);
3984                 lp_config_set_int(lc->config,key,"rate",pt->clock_rate);
3985                 lp_config_set_int(lc->config,key,"enabled",linphone_core_payload_type_enabled(lc,pt));
3986                 index++;
3987         }
3988         sprintf(key,"audio_codec_%i",index);
3989         lp_config_clean_section (lc->config,key);
3990
3991         index=0;
3992         for(node=config->video_codecs;node!=NULL;node=ms_list_next(node)){
3993                 pt=(PayloadType*)(node->data);
3994                 sprintf(key,"video_codec_%i",index);
3995                 lp_config_set_string(lc->config,key,"mime",pt->mime_type);
3996                 lp_config_set_int(lc->config,key,"rate",pt->clock_rate);
3997                 lp_config_set_int(lc->config,key,"enabled",linphone_core_payload_type_enabled(lc,pt));
3998                 lp_config_set_string(lc->config,key,"recv_fmtp",pt->recv_fmtp);
3999                 index++;
4000         }
4001         sprintf(key,"video_codec_%i",index);
4002         lp_config_clean_section (lc->config,key);
4003
4004         ms_list_free(lc->codecs_conf.audio_codecs);
4005         ms_list_free(lc->codecs_conf.video_codecs);
4006 }
4007
4008 void ui_config_uninit(LinphoneCore* lc)
4009 {
4010         if (lc->friends){
4011                 ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_destroy);
4012                 ms_list_free(lc->friends);
4013                 lc->friends=NULL;
4014         }
4015 }
4016
4017 /**
4018  * Returns the LpConfig object used to manage the storage (config) file.
4019  *
4020  * @ingroup misc
4021  * The application can use the LpConfig object to insert its own private
4022  * sections and pairs of key=value in the configuration file.
4023  *
4024 **/
4025 LpConfig *linphone_core_get_config(LinphoneCore *lc){
4026         return lc->config;
4027 }
4028
4029 static void linphone_core_uninit(LinphoneCore *lc)
4030 {
4031         linphone_core_free_hooks(lc);
4032         while(lc->calls)
4033         {
4034                 LinphoneCall *the_call = lc->calls->data;
4035                 linphone_core_terminate_call(lc,the_call);
4036                 linphone_core_iterate(lc);
4037 #ifdef WIN32
4038                 Sleep(50000);
4039 #else
4040                 usleep(50000);
4041 #endif
4042         }
4043         if (lc->friends)
4044                 ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
4045         linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down");
4046 #ifdef VIDEO_ENABLED
4047         if (lc->previewstream!=NULL){
4048                 video_preview_stop(lc->previewstream);
4049                 lc->previewstream=NULL;
4050         }
4051 #endif
4052         ms_event_queue_destroy(lc->msevq);
4053         lc->msevq=NULL;
4054         /* save all config */
4055         net_config_uninit(lc);
4056         rtp_config_uninit(lc);
4057         if (lc->ringstream) ring_stop(lc->ringstream);
4058         sound_config_uninit(lc);
4059         video_config_uninit(lc);
4060         codecs_config_uninit(lc);
4061         ui_config_uninit(lc);
4062         sip_config_uninit(lc);
4063         if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
4064         lp_config_destroy(lc->config);
4065         lc->config = NULL; /* Mark the config as NULL to block further calls */
4066         sip_setup_unregister_all();
4067
4068         ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy);
4069         lc->call_logs=ms_list_free(lc->call_logs);
4070
4071         linphone_core_free_payload_types(lc);
4072         ortp_exit();
4073         linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
4074 }
4075
4076 static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){
4077         ms_message("Network state is now [%s]",isReachable?"UP":"DOWN");
4078         // second get the list of available proxies
4079         const MSList *elem=linphone_core_get_proxy_config_list(lc);
4080         for(;elem!=NULL;elem=elem->next){
4081                 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
4082                 if (linphone_proxy_config_register_enabled(cfg) ) {
4083                         if (!isReachable) {
4084                                 cfg->registered=0;
4085                         }else{
4086                                 cfg->commit=TRUE;
4087                         }
4088                 }
4089         }
4090         lc->netup_time=curtime;
4091         lc->network_reachable=isReachable;
4092         if(!isReachable) {
4093                 sal_unlisten_ports (lc->sal);
4094         } else {
4095                 apply_transports(lc);
4096         }
4097
4098 }
4099 void linphone_core_refresh_registers(LinphoneCore* lc) {
4100         const MSList *elem=linphone_core_get_proxy_config_list(lc);
4101         for(;elem!=NULL;elem=elem->next){
4102                 LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
4103                 if (linphone_proxy_config_register_enabled(cfg) ) {
4104                         linphone_proxy_config_refresh_register(cfg);
4105                 }
4106         }
4107 }
4108
4109 void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t isReachable) {
4110         //first disable automatic mode
4111         if (lc->auto_net_state_mon) {
4112                 ms_message("Disabling automatic network state monitoring");
4113                 lc->auto_net_state_mon=FALSE;
4114         }
4115         set_network_reachable(lc,isReachable, ms_time(NULL));
4116 }
4117
4118 bool_t linphone_core_is_network_reachabled(LinphoneCore* lc) {
4119         return lc->network_reachable;
4120 }
4121 ortp_socket_t linphone_core_get_sip_socket(LinphoneCore *lc){
4122         return sal_get_socket(lc->sal);
4123 }
4124 /**
4125  * Destroys a LinphoneCore
4126  *
4127  * @ingroup initializing
4128 **/
4129 void linphone_core_destroy(LinphoneCore *lc){
4130         linphone_core_uninit(lc);
4131         ms_free(lc);
4132 }
4133 /**
4134  * Get the number of Call
4135  *
4136  * @ingroup call_control
4137 **/
4138 int linphone_core_get_calls_nb(const LinphoneCore *lc){
4139         return  ms_list_size(lc->calls);;
4140 }
4141
4142 /**
4143  * Check if we do not have exceed the number of simultaneous call
4144  *
4145  * @ingroup call_control
4146 **/
4147 bool_t linphone_core_can_we_add_call(LinphoneCore *lc)
4148 {
4149         if(linphone_core_get_calls_nb(lc) < lc->max_calls)
4150                 return TRUE;
4151         ms_message("Maximum amount of simultaneous calls reached !");
4152         return FALSE;
4153 }
4154
4155
4156 int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call)
4157 {
4158         if(linphone_core_can_we_add_call(lc))
4159         {
4160                 lc->calls = ms_list_append(lc->calls,call);
4161                 return 0;
4162         }
4163         return -1;
4164 }
4165
4166 int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call)
4167 {
4168         MSList *it;
4169         MSList *the_calls = lc->calls;
4170
4171         it=ms_list_find(the_calls,call);
4172         if (it)
4173         {
4174                 the_calls = ms_list_remove_link(the_calls,it);
4175         }
4176         else
4177         {
4178                 ms_warning("could not find the call into the list\n");
4179                 return -1;
4180         }
4181         lc->calls = the_calls;
4182         return 0;
4183 }
4184
4185 /**
4186  * Specifiies a ring back tone to be played to far end during incoming calls.
4187 **/
4188 void linphone_core_set_remote_ringback_tone(LinphoneCore *lc, const char *file){
4189         if (lc->sound_conf.ringback_tone){
4190                 ms_free(lc->sound_conf.ringback_tone);
4191                 lc->sound_conf.ringback_tone=NULL;
4192         }
4193         if (file)
4194                 lc->sound_conf.ringback_tone=ms_strdup(file);
4195 }
4196
4197 /**
4198  * Returns the ring back tone played to far end during incoming calls.
4199 **/
4200 const char *linphone_core_get_remote_ringback_tone(const LinphoneCore *lc){
4201         return lc->sound_conf.ringback_tone;
4202 }
4203
4204 static PayloadType* find_payload_type_from_list(const char* type, int rate,const MSList* from) {
4205         const MSList *elem;
4206         for(elem=from;elem!=NULL;elem=elem->next){
4207                 PayloadType *pt=(PayloadType*)elem->data;
4208                 if ((strcmp((char*)type, payload_type_get_mime(pt)) == 0) && (rate == -1 || rate==pt->clock_rate)) {
4209                         return pt;
4210                 }
4211         }
4212         return NULL;
4213 }
4214
4215 /**
4216  * Get payload type  from mime type and clock rate
4217  * @ingroup media_parameters
4218  * This function searches in audio and video codecs for the given payload type name and clockrate.
4219  * Returns NULL if not found.
4220  */
4221 PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate) {
4222         PayloadType* result = find_payload_type_from_list(type, rate, linphone_core_get_audio_codecs(lc));
4223         if (result)  {
4224                 return result;
4225         } else {
4226                 result = find_payload_type_from_list(type, rate, linphone_core_get_video_codecs(lc));
4227                 if (result) {
4228                         return result;
4229                 }
4230         }
4231         /*not found*/
4232         return NULL;
4233 }
4234
4235 const char *linphone_global_state_to_string(LinphoneGlobalState gs){
4236         switch(gs){
4237                 case LinphoneGlobalOff:
4238                         return "LinphoneGlobalOff";
4239                 break;
4240                 case LinphoneGlobalOn:
4241                         return "LinphoneGlobalOn";
4242                 break;
4243                 case LinphoneGlobalStartup:
4244                         return "LinphoneGlobalStartup";
4245                 break;
4246                 case LinphoneGlobalShutdown:
4247                         return "LinphoneGlobalShutdown";
4248                 break;
4249         }
4250         return NULL;
4251 }
4252
4253 LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){
4254         return lc->state;
4255 }
4256
4257 LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){
4258         LinphoneCallParams *p=ms_new0(LinphoneCallParams,1);
4259         p->has_video=linphone_core_video_enabled(lc);
4260         return p;
4261 }
4262
4263 const char *linphone_reason_to_string(LinphoneReason err){
4264         switch(err){
4265                 case LinphoneReasonNone:
4266                         return "No error";
4267                 case LinphoneReasonNoResponse:
4268                         return "No response";
4269                 case LinphoneReasonBadCredentials:
4270                         return "Bad credentials";
4271                 case LinphoneReasonDeclined:
4272                         return "Call declined";
4273         }
4274         return "unknown error";
4275 }
4276
4277 const char *linphone_error_to_string(LinphoneReason err){
4278         return linphone_reason_to_string(err);
4279 }
4280 /**
4281  * Enables signaling keep alive
4282  */
4283 void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) {
4284         if (enable > 0) {
4285                 sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
4286         } else {
4287                 sal_set_keepalive_period(lc->sal,0);
4288         }
4289 }
4290 /**
4291  * Is signaling keep alive enabled
4292  */
4293 bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) {
4294         return sal_get_keepalive_period(lc->sal) > 0;
4295 }
4296
4297 void linphone_core_start_dtmf_stream(LinphoneCore* lc) {
4298         get_dtmf_gen(lc); /*make sure ring stream is started*/
4299         lc->ringstream_autorelease=FALSE; /*disable autorelease mode*/
4300 }
4301
4302 void linphone_core_stop_dtmf_stream(LinphoneCore* lc) {
4303         if (lc->ringstream) ring_stop(lc->ringstream);
4304         lc->ringstream=NULL;
4305 }
4306
4307 int linphone_core_get_max_calls(LinphoneCore *lc) {
4308         return lc->max_calls;
4309 }
4310
4311
4312 typedef struct Hook{
4313         LinphoneCoreIterateHook fun;
4314         void *data;
4315 }Hook;
4316
4317 static Hook *hook_new(LinphoneCoreIterateHook hook, void *hook_data){
4318         Hook *h=ms_new(Hook,1);
4319         h->fun=hook;
4320         h->data=hook_data;
4321         return h;
4322 }
4323
4324 static void hook_invoke(Hook *h){
4325         h->fun(h->data);
4326 }
4327
4328 void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data){
4329         lc->hooks=ms_list_append(lc->hooks,hook_new(hook,hook_data));
4330 }
4331
4332 static void linphone_core_run_hooks(LinphoneCore *lc){
4333         ms_list_for_each(lc->hooks,(void (*)(void*))hook_invoke);
4334 }
4335
4336 static void linphone_core_free_hooks(LinphoneCore *lc){
4337         ms_list_for_each(lc->hooks,(void (*)(void*))ms_free);
4338         ms_list_free(lc->hooks);
4339         lc->hooks=NULL;
4340 }
4341
4342 void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data){
4343         MSList *elem;
4344         for(elem=lc->hooks;elem!=NULL;elem=elem->next){
4345                 Hook *h=(Hook*)elem->data;
4346                 if (h->fun==hook && h->data==hook_data){
4347                         ms_list_remove_link(lc->hooks,elem);
4348                         ms_free(h);
4349                         return;
4350                 }
4351         }
4352         ms_error("linphone_core_remove_iterate_hook(): No such hook found.");
4353 }
4354
4355 void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){
4356         if (lc->zrtp_secrets_cache != NULL) {
4357                 ms_free(lc->zrtp_secrets_cache);
4358         }
4359         lc->zrtp_secrets_cache=file ? ms_strdup(file) : NULL;
4360 }
4361
4362 //                              if (stringUri.equals(call.getRemoteAddress().asStringUriOnly())) {
4363 const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const char *uri) {
4364         if (uri == NULL) return NULL;
4365         MSList *calls=lc->calls;
4366         while(calls) {
4367                 const LinphoneCall *c=(LinphoneCall*)calls->data;
4368                 calls=calls->next;
4369                 const LinphoneAddress *address = linphone_call_get_remote_address(c);
4370                 char *current_uri=linphone_address_as_string_uri_only(address);
4371                 if (strcmp(uri,current_uri)==0) {
4372                         ms_free(current_uri);
4373                         return c;
4374                 } else {
4375                         ms_free(current_uri);
4376                 }
4377         }
4378         return NULL;
4379 }