]> sjero.net Git - linphone/blob - coreapi/linphonecall.c
Add mic gain db getter/setter
[linphone] / coreapi / linphonecall.c
1
2 /*
3 linphone
4 Copyright (C) 2010  Belledonne Communications SARL
5  (simon.morlat@linphone.org)
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21 #ifdef WIN32
22 #include <time.h>
23 #endif
24 #include "linphonecore.h"
25 #include "sipsetup.h"
26 #include "lpconfig.h"
27 #include "private.h"
28 #include <ortp/event.h>
29 #include <ortp/b64.h>
30 #include <math.h>
31
32 #include "mediastreamer2/mediastream.h"
33 #include "mediastreamer2/msvolume.h"
34 #include "mediastreamer2/msequalizer.h"
35 #include "mediastreamer2/msfileplayer.h"
36 #include "mediastreamer2/msjpegwriter.h"
37 #include "mediastreamer2/mseventqueue.h"
38 #include "mediastreamer2/mssndcard.h"
39
40 #ifdef VIDEO_ENABLED
41 static MSWebCam *get_nowebcam_device(){
42         return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture");
43 }
44 #endif
45
46 static bool_t generate_b64_crypto_key(int key_length, char* key_out) {
47         int b64_size;
48         uint8_t* tmp = (uint8_t*) malloc(key_length);                   
49         if (ortp_crypto_get_random(tmp, key_length)!=0) {
50                 ms_error("Failed to generate random key");
51                 free(tmp);
52                 return FALSE;
53         }
54         
55         b64_size = b64_encode((const char*)tmp, key_length, NULL, 0);
56         if (b64_size == 0) {
57                 ms_error("Failed to b64 encode key");
58                 free(tmp);
59                 return FALSE;
60         }
61         key_out[b64_size] = '\0';
62         b64_encode((const char*)tmp, key_length, key_out, 40);
63         free(tmp);
64         return TRUE;
65 }
66
67 LinphoneCore *linphone_call_get_core(const LinphoneCall *call){
68         return call->core;
69 }
70
71 const char* linphone_call_get_authentication_token(LinphoneCall *call){
72         return call->auth_token;
73 }
74
75 bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){
76         return call->auth_token_verified;
77 }
78
79 static bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call) {
80         // Check ZRTP encryption in audiostream
81         if (!call->audiostream_encrypted) {
82                 return FALSE;
83         }
84
85 #ifdef VIDEO_ENABLED
86         // If video enabled, check ZRTP encryption in videostream
87         const LinphoneCallParams *params=linphone_call_get_current_params(call);
88         if (params->has_video && !call->videostream_encrypted) {
89                 return FALSE;
90         }
91 #endif
92
93         return TRUE;
94 }
95
96 void propagate_encryption_changed(LinphoneCall *call){
97         LinphoneCore *lc=call->core;
98         if (!linphone_call_are_all_streams_encrypted(call)) {
99                 ms_message("Some streams are not encrypted");
100                 call->current_params.media_encryption=LinphoneMediaEncryptionNone;
101                 if (lc->vtable.call_encryption_changed)
102                         lc->vtable.call_encryption_changed(call->core, call, FALSE, call->auth_token);
103         } else {
104                 ms_message("All streams are encrypted");
105                 call->current_params.media_encryption=LinphoneMediaEncryptionZRTP;
106                 if (lc->vtable.call_encryption_changed)
107                         lc->vtable.call_encryption_changed(call->core, call, TRUE, call->auth_token);
108         }
109 }
110
111 #ifdef VIDEO_ENABLED
112 static void linphone_call_videostream_encryption_changed(void *data, bool_t encrypted){
113         ms_message("Video stream is %s", encrypted ? "encrypted" : "not encrypted");
114
115         LinphoneCall *call = (LinphoneCall *)data;
116         call->videostream_encrypted=encrypted;
117         propagate_encryption_changed(call);
118 }
119 #endif
120
121 static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) {
122         char status[255]={0};
123         ms_message("Audio stream is %s ", encrypted ? "encrypted" : "not encrypted");
124
125         LinphoneCall *call = (LinphoneCall *)data;
126         call->audiostream_encrypted=encrypted;
127         
128         if (encrypted && call->core->vtable.display_status != NULL) {
129                 snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token);
130                  call->core->vtable.display_status(call->core, status);
131         }
132
133         propagate_encryption_changed(call);
134
135
136 #ifdef VIDEO_ENABLED
137         // Enable video encryption
138         const LinphoneCallParams *params=linphone_call_get_current_params(call);
139         if (params->has_video) {
140                 ms_message("Trying to enable encryption on video stream");
141                 OrtpZrtpParams params;
142                 params.zid_file=NULL; //unused
143                 video_stream_enable_zrtp(call->videostream,call->audiostream,&params);
144         }
145 #endif
146 }
147
148
149 static void linphone_call_audiostream_auth_token_ready(void *data, const char* auth_token, bool_t verified) {
150         LinphoneCall *call=(LinphoneCall *)data;
151         if (call->auth_token != NULL)
152                 ms_free(call->auth_token);
153
154         call->auth_token=ms_strdup(auth_token);
155         call->auth_token_verified=verified;
156
157         ms_message("Authentication token is %s (%s)", auth_token, verified?"verified":"unverified");
158 }
159
160 void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified){
161         if (call->audiostream==NULL){
162                 ms_error("linphone_call_set_authentication_token_verified(): No audio stream");
163         }
164         if (call->audiostream->ortpZrtpContext==NULL){
165                 ms_error("linphone_call_set_authentication_token_verified(): No zrtp context.");
166         }
167         if (!call->auth_token_verified && verified){
168                 ortp_zrtp_sas_verified(call->audiostream->ortpZrtpContext);
169         }else if (call->auth_token_verified && !verified){
170                 ortp_zrtp_sas_reset_verified(call->audiostream->ortpZrtpContext);
171         }
172         call->auth_token_verified=verified;
173         propagate_encryption_changed(call);
174 }
175
176 static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate){
177         MSList *l=NULL;
178         const MSList *it;
179         if (max_sample_rate) *max_sample_rate=0;
180         for(it=codecs;it!=NULL;it=it->next){
181                 PayloadType *pt=(PayloadType*)it->data;
182                 if (pt->flags & PAYLOAD_TYPE_ENABLED){
183                         if (bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,bandwidth_limit)){
184                                 ms_message("Codec %s/%i eliminated because of audio bandwidth constraint.",pt->mime_type,pt->clock_rate);
185                                 continue;
186                         }
187                         if (linphone_core_check_payload_type_usability(lc,pt)){
188                                 l=ms_list_append(l,payload_type_clone(pt));
189                                 if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
190                         }
191                 }
192         }
193         return l;
194 }
195
196 static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
197         if (ac->port!=0){
198                 strcpy(md->streams[0].rtp_addr,ac->addr);
199                 md->streams[0].rtp_port=ac->port;
200                 if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->nstreams==1){
201                         strcpy(md->addr,ac->addr);
202                 }
203         }
204         if (vc->port!=0){
205                 strcpy(md->streams[1].rtp_addr,vc->addr);
206                 md->streams[1].rtp_port=vc->port;
207         }
208         
209 }
210
211
212 static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){
213         MSList *l;
214         PayloadType *pt;
215         int i;
216         const char *me=linphone_core_get_identity(lc);
217         LinphoneAddress *addr=linphone_address_new(me);
218         const char *username=linphone_address_get_username (addr);
219         SalMediaDescription *md=sal_media_description_new();
220         
221         if (call->ping_time>0) {
222                 linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
223         }
224
225         md->session_id=session_id;
226         md->session_ver=session_ver;
227         md->nstreams=1;
228         strncpy(md->addr,call->localip,sizeof(md->addr));
229         strncpy(md->username,username,sizeof(md->username));
230         
231         if (call->params.down_bw)
232                 md->bandwidth=call->params.down_bw;
233         else md->bandwidth=linphone_core_get_download_bandwidth(lc);
234
235         /*set audio capabilities */
236         strncpy(md->streams[0].rtp_addr,call->localip,sizeof(md->streams[0].rtp_addr));
237         strncpy(md->streams[0].rtcp_addr,call->localip,sizeof(md->streams[0].rtcp_addr));
238         md->streams[0].rtp_port=call->audio_port;
239         md->streams[0].rtcp_port=call->audio_port+1;
240         md->streams[0].proto=(call->params.media_encryption == LinphoneMediaEncryptionSRTP) ? 
241                 SalProtoRtpSavp : SalProtoRtpAvp;
242         md->streams[0].type=SalAudio;
243         if (call->params.down_ptime)
244                 md->streams[0].ptime=call->params.down_ptime;
245         else
246                 md->streams[0].ptime=linphone_core_get_download_ptime(lc);
247         l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate);
248         pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
249         l=ms_list_append(l,pt);
250         md->streams[0].payloads=l;
251         
252
253
254         if (call->params.has_video){
255                 md->nstreams++;
256                 md->streams[1].rtp_port=call->video_port;
257                 md->streams[1].rtcp_port=call->video_port+1;
258                 md->streams[1].proto=md->streams[0].proto;
259                 md->streams[1].type=SalVideo;
260                 l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL);
261                 md->streams[1].payloads=l;
262         }
263         
264         for(i=0; i<md->nstreams; i++) {
265                 if (md->streams[i].proto == SalProtoRtpSavp) {
266                         md->streams[i].crypto[0].tag = 1;
267                         md->streams[i].crypto[0].algo = AES_128_SHA1_80;
268                         if (!generate_b64_crypto_key(30, md->streams[i].crypto[0].master_key))
269                                 md->streams[i].crypto[0].algo = 0;
270                         md->streams[i].crypto[1].tag = 2;
271                         md->streams[i].crypto[1].algo = AES_128_SHA1_32;
272                         if (!generate_b64_crypto_key(30, md->streams[i].crypto[1].master_key))
273                                 md->streams[i].crypto[1].algo = 0;
274                         md->streams[i].crypto[2].algo = 0;
275                 }
276         }
277         update_media_description_from_stun(md,&call->ac,&call->vc);
278         if (call->ice_session != NULL) {
279                 linphone_core_update_local_media_description_from_ice(md, call->ice_session);
280                 linphone_core_update_ice_state_in_call_stats(call);
281         }
282         linphone_address_destroy(addr);
283         return md;
284 }
285
286 void update_local_media_description(LinphoneCore *lc, LinphoneCall *call){
287         SalMediaDescription *md=call->localdesc;
288         if (md== NULL) {
289                 call->localdesc = create_local_media_description(lc,call);
290         } else {
291                 call->localdesc = _create_local_media_description(lc,call,md->session_id,md->session_ver+1);
292                 sal_media_description_unref(md);
293         }
294 }
295
296 SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call){
297         unsigned int id=rand() & 0xfff;
298         return _create_local_media_description(lc,call,id,id);
299 }
300
301 static int find_port_offset(LinphoneCore *lc, SalStreamType type){
302         int offset;
303         MSList *elem;
304         int tried_port;
305         int existing_port;
306         bool_t already_used=FALSE;
307         for(offset=0;offset<100;offset+=2){
308                 switch (type) {
309                         default:
310                         case SalAudio:
311                                 tried_port=linphone_core_get_audio_port (lc)+offset;
312                                 break;
313                         case SalVideo:
314                                 tried_port=linphone_core_get_video_port (lc)+offset;
315                                 break;
316                 }
317                 already_used=FALSE;
318                 for(elem=lc->calls;elem!=NULL;elem=elem->next){
319                         LinphoneCall *call=(LinphoneCall*)elem->data;
320                         switch (type) {
321                                 default:
322                                 case SalAudio:
323                                         existing_port = call->audio_port;
324                                         break;
325                                 case SalVideo:
326                                         existing_port = call->video_port;
327                                         break;
328                         }
329                         if (existing_port==tried_port) {
330                                 already_used=TRUE;
331                                 break;
332                         }
333                 }
334                 if (!already_used) break;
335         }
336         if (offset==100){
337                 ms_error("Could not find any free port !");
338                 return -1;
339         }
340         return offset;
341 }
342
343 static int select_random_port(LinphoneCore *lc, SalStreamType type) {
344         MSList *elem;
345         int nb_tries;
346         int tried_port = 0;
347         int existing_port = 0;
348         int min_port = 0, max_port = 0;
349         bool_t already_used = FALSE;
350
351         switch (type) {
352                 default:
353                 case SalAudio:
354                         linphone_core_get_audio_port_range(lc, &min_port, &max_port);
355                         break;
356                 case SalVideo:
357                         linphone_core_get_video_port_range(lc, &min_port, &max_port);
358                         break;
359         }
360         tried_port = (rand() % (max_port - min_port) + min_port) & ~0x1;
361         if (tried_port < min_port) tried_port = min_port + 2;
362         for (nb_tries = 0; nb_tries < 100; nb_tries++) {
363                 for (elem = lc->calls; elem != NULL; elem = elem->next) {
364                         LinphoneCall *call = (LinphoneCall *)elem->data;
365                         switch (type) {
366                                 default:
367                                 case SalAudio:
368                                         existing_port = call->audio_port;
369                                         break;
370                                 case SalVideo:
371                                         existing_port = call->video_port;
372                                         break;
373                         }
374                         if (existing_port == tried_port) {
375                                 already_used = TRUE;
376                                 break;
377                         }
378                 }
379                 if (!already_used) break;
380         }
381         if (nb_tries == 100) {
382                 ms_error("Could not find any free port!");
383                 return -1;
384         }
385         return tried_port;
386 }
387
388 static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
389         int port_offset;
390         int min_port, max_port;
391         call->magic=linphone_call_magic;
392         call->refcnt=1;
393         call->state=LinphoneCallIdle;
394         call->transfer_state = LinphoneCallIdle;
395         call->start_time=time(NULL);
396         call->media_start_time=0;
397         call->log=linphone_call_log_new(call, from, to);
398         call->owns_call_log=TRUE;
399         linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone);
400         linphone_core_get_audio_port_range(call->core, &min_port, &max_port);
401         if (min_port == max_port) {
402                 /* Used fixed RTP audio port. */
403                 port_offset=find_port_offset (call->core, SalAudio);
404                 if (port_offset==-1) return;
405                 call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
406         } else {
407                 /* Select random RTP audio port in the specified range. */
408                 call->audio_port = select_random_port(call->core, SalAudio);
409         }
410         linphone_core_get_video_port_range(call->core, &min_port, &max_port);
411         if (min_port == max_port) {
412                 /* Used fixed RTP video port. */
413                 port_offset=find_port_offset (call->core, SalVideo);
414                 if (port_offset==-1) return;
415                 call->video_port=linphone_core_get_video_port(call->core)+port_offset;
416         } else {
417                 /* Select random RTP video port in the specified range. */
418                 call->video_port = select_random_port(call->core, SalVideo);
419         }
420         linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO], LINPHONE_CALL_STATS_AUDIO);
421         linphone_call_init_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO], LINPHONE_CALL_STATS_VIDEO);
422 }
423
424 void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
425         stats->type = type;
426         stats->received_rtcp = NULL;
427         stats->sent_rtcp = NULL;
428         stats->ice_state = LinphoneIceStateNotActivated;
429 }
430
431
432 static void discover_mtu(LinphoneCore *lc, const char *remote){
433         int mtu;
434         if (lc->net_conf.mtu==0 ){
435                 /*attempt to discover mtu*/
436                 mtu=ms_discover_mtu(remote);
437                 if (mtu>0){
438                         ms_set_mtu(mtu);
439                         ms_message("Discovered mtu is %i, RTP payload max size is %i",
440                                 mtu, ms_get_payload_max_size());
441                 }
442         }
443 }
444
445 LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params)
446 {
447         LinphoneCall *call=ms_new0(LinphoneCall,1);
448         call->dir=LinphoneCallOutgoing;
449         call->op=sal_op_new(lc->sal);
450         sal_op_set_user_pointer(call->op,call);
451         call->core=lc;
452         linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
453         linphone_call_init_common(call,from,to);
454         call->params=*params;
455         if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
456                 call->ice_session = ice_session_new();
457                 ice_session_set_role(call->ice_session, IR_Controlling);
458         }
459         if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
460                 call->ping_time=linphone_core_run_stun_tests(call->core,call);
461         }
462         call->camera_active=params->has_video;
463         
464         discover_mtu(lc,linphone_address_get_domain (to));
465         if (params->referer){
466                 sal_call_set_referer(call->op,params->referer->op);
467                 call->referer=linphone_call_ref(params->referer);
468         }
469         return call;
470 }
471
472 LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
473         LinphoneCall *call=ms_new0(LinphoneCall,1);
474         char *from_str;
475
476         call->dir=LinphoneCallIncoming;
477         sal_op_set_user_pointer(op,call);
478         call->op=op;
479         call->core=lc;
480
481         if (lc->sip_conf.ping_with_options){
482                 /*the following sends an option request back to the caller so that
483                  we get a chance to discover our nat'd address before answering.*/
484                 call->ping_op=sal_op_new(lc->sal);
485                 from_str=linphone_address_as_string_uri_only(from);
486                 sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
487                 sal_op_set_user_pointer(call->ping_op,call);
488                 sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
489                 ms_free(from_str);
490         }
491
492         linphone_address_clean(from);
493         linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
494         linphone_call_init_common(call, from, to);
495         call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
496         linphone_core_init_default_params(lc, &call->params);
497         call->params.has_video &= !!lc->video_policy.automatically_accept;
498         call->params.has_video &= linphone_core_media_description_contains_video_stream(sal_call_get_remote_media_description(op));
499         switch (linphone_core_get_firewall_policy(call->core)) {
500                 case LinphonePolicyUseIce:
501                         call->ice_session = ice_session_new();
502                         ice_session_set_role(call->ice_session, IR_Controlled);
503                         linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
504                         if (call->ice_session != NULL) {
505                                 linphone_call_init_media_streams(call);
506                                 linphone_call_start_media_streams_for_ice_gathering(call);
507                                 if (linphone_core_gather_ice_candidates(call->core,call)<0) {
508                                         /* Ice candidates gathering failed, proceed with the call anyway. */
509                                         linphone_call_delete_ice_session(call);
510                                         linphone_call_stop_media_streams_for_ice_gathering(call);
511                                 }
512                         }
513                         break;
514                 case LinphonePolicyUseStun:
515                         call->ping_time=linphone_core_run_stun_tests(call->core,call);
516                         /* No break to also destroy ice session in this case. */
517                 default:
518                         break;
519         }
520         call->camera_active=call->params.has_video;
521         
522         discover_mtu(lc,linphone_address_get_domain(from));
523         return call;
524 }
525
526 /* this function is called internally to get rid of a call.
527  It performs the following tasks:
528  - remove the call from the internal list of calls
529  - update the call logs accordingly
530 */
531
532 static void linphone_call_set_terminated(LinphoneCall *call){
533         LinphoneCore *lc=call->core;
534
535         linphone_core_update_allocated_audio_bandwidth(lc);
536
537         call->owns_call_log=FALSE;
538         linphone_call_log_completed(call);
539
540
541         if (call == lc->current_call){
542                 ms_message("Resetting the current call");
543                 lc->current_call=NULL;
544         }
545
546         if (linphone_core_del_call(lc,call) != 0){
547                 ms_error("Could not remove the call from the list !!!");
548         }
549
550         if (ms_list_size(lc->calls)==0)
551                 linphone_core_notify_all_friends(lc,lc->presence_mode);
552
553         linphone_core_conference_check_uninit(lc);
554         if (call->ringing_beep){
555                 linphone_core_stop_dtmf(lc);
556                 call->ringing_beep=FALSE;
557         }
558         if (call->referer){
559                 linphone_call_unref(call->referer);
560                 call->referer=NULL;
561         }
562 }
563
564 void linphone_call_fix_call_parameters(LinphoneCall *call){
565         call->params.has_video=call->current_params.has_video;
566         call->params.media_encryption=call->current_params.media_encryption;
567 }
568
569 const char *linphone_call_state_to_string(LinphoneCallState cs){
570         switch (cs){
571                 case LinphoneCallIdle:
572                         return "LinphoneCallIdle";
573                 case LinphoneCallIncomingReceived:
574                         return "LinphoneCallIncomingReceived";
575                 case LinphoneCallOutgoingInit:
576                         return "LinphoneCallOutgoingInit";
577                 case LinphoneCallOutgoingProgress:
578                         return "LinphoneCallOutgoingProgress";
579                 case LinphoneCallOutgoingRinging:
580                         return "LinphoneCallOutgoingRinging";
581                 case LinphoneCallOutgoingEarlyMedia:
582                         return "LinphoneCallOutgoingEarlyMedia";
583                 case LinphoneCallConnected:
584                         return "LinphoneCallConnected";
585                 case LinphoneCallStreamsRunning:
586                         return "LinphoneCallStreamsRunning";
587                 case LinphoneCallPausing:
588                         return "LinphoneCallPausing";
589                 case LinphoneCallPaused:
590                         return "LinphoneCallPaused";
591                 case LinphoneCallResuming:
592                         return "LinphoneCallResuming";
593                 case LinphoneCallRefered:
594                         return "LinphoneCallRefered";
595                 case LinphoneCallError:
596                         return "LinphoneCallError";
597                 case LinphoneCallEnd:
598                         return "LinphoneCallEnd";
599                 case LinphoneCallPausedByRemote:
600                         return "LinphoneCallPausedByRemote";
601                 case LinphoneCallUpdatedByRemote:
602                         return "LinphoneCallUpdatedByRemote";
603                 case LinphoneCallIncomingEarlyMedia:
604                         return "LinphoneCallIncomingEarlyMedia";
605                 case LinphoneCallUpdating:
606                         return "LinphoneCallUpdating";
607                 case LinphoneCallReleased:
608                         return "LinphoneCallReleased";
609         }
610         return "undefined state";
611 }
612
613 void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
614         LinphoneCore *lc=call->core;
615
616         if (call->state!=cstate){
617                 if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){
618                         if (cstate!=LinphoneCallReleased){
619                                 ms_warning("Spurious call state change from %s to %s, ignored.",linphone_call_state_to_string(call->state),
620                                    linphone_call_state_to_string(cstate));
621                                 return;
622                         }
623                 }
624                 ms_message("Call %p: moving from state %s to %s",call,linphone_call_state_to_string(call->state),
625                            linphone_call_state_to_string(cstate));
626                 if (cstate!=LinphoneCallRefered){
627                         /*LinphoneCallRefered is rather an event, not a state.
628                          Indeed it does not change the state of the call (still paused or running)*/
629                         call->state=cstate;
630                 }
631                 if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){
632                         switch(call->reason){
633                                 case LinphoneReasonDeclined:
634                                         call->log->status=LinphoneCallDeclined;
635                                         break;
636                                 case LinphoneReasonNotAnswered:
637                                         call->log->status=LinphoneCallMissed;
638                                 break;
639                                 default:
640                                 break;
641                         }
642                         linphone_call_set_terminated (call);
643                 }
644                 if (cstate == LinphoneCallConnected) {
645                         call->log->status=LinphoneCallSuccess;
646                         call->media_start_time=time(NULL);
647                 }
648
649                 if (lc->vtable.call_state_changed)
650                         lc->vtable.call_state_changed(lc,call,cstate,message);
651                 if (cstate==LinphoneCallReleased){
652                         if (call->op!=NULL) {
653                                 /* so that we cannot have anymore upcalls for SAL
654                                  concerning this call*/
655                                 sal_op_release(call->op);
656                                 call->op=NULL;
657                         }
658                         linphone_call_unref(call);
659                 }
660         }
661 }
662
663 static void linphone_call_destroy(LinphoneCall *obj)
664 {
665         linphone_call_delete_ice_session(obj);
666         if (obj->op!=NULL) {
667                 sal_op_release(obj->op);
668                 obj->op=NULL;
669         }
670         if (obj->resultdesc!=NULL) {
671                 sal_media_description_unref(obj->resultdesc);
672                 obj->resultdesc=NULL;
673         }
674         if (obj->localdesc!=NULL) {
675                 sal_media_description_unref(obj->localdesc);
676                 obj->localdesc=NULL;
677         }
678         if (obj->ping_op) {
679                 sal_op_release(obj->ping_op);
680         }
681         if (obj->refer_to){
682                 ms_free(obj->refer_to);
683         }
684         if (obj->owns_call_log)
685                 linphone_call_log_destroy(obj->log);
686         if (obj->auth_token) {
687                 ms_free(obj->auth_token);
688         }
689
690         ms_free(obj);
691 }
692
693 /**
694  * @addtogroup call_control
695  * @{
696 **/
697
698 /**
699  * Increments the call 's reference count.
700  * An application that wishes to retain a pointer to call object
701  * must use this function to unsure the pointer remains
702  * valid. Once the application no more needs this pointer,
703  * it must call linphone_call_unref().
704 **/
705 LinphoneCall * linphone_call_ref(LinphoneCall *obj){
706         obj->refcnt++;
707         return obj;
708 }
709
710 /**
711  * Decrements the call object reference count.
712  * See linphone_call_ref().
713 **/
714 void linphone_call_unref(LinphoneCall *obj){
715         obj->refcnt--;
716         if (obj->refcnt==0){
717                 linphone_call_destroy(obj);
718         }
719 }
720
721 /**
722  * Returns current parameters associated to the call.
723 **/
724 const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *call){
725         return &call->current_params;
726 }
727
728 static bool_t is_video_active(const SalStreamDescription *sd){
729         return sd->rtp_port!=0 && sd->dir!=SalStreamInactive;
730 }
731
732 /**
733  * Returns call parameters proposed by remote.
734  * 
735  * This is useful when receiving an incoming call, to know whether the remote party
736  * supports video, encryption or whatever.
737 **/
738 const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
739         LinphoneCallParams *cp=&call->remote_params;
740         memset(cp,0,sizeof(*cp));
741         if (call->op){
742                 SalMediaDescription *md=sal_call_get_remote_media_description(call->op);
743                 if (md){
744                         SalStreamDescription *asd,*vsd,*secure_asd,*secure_vsd;
745
746                         asd=sal_media_description_find_stream(md,SalProtoRtpAvp,SalAudio);
747                         vsd=sal_media_description_find_stream(md,SalProtoRtpAvp,SalVideo);
748                         secure_asd=sal_media_description_find_stream(md,SalProtoRtpSavp,SalAudio);
749                         secure_vsd=sal_media_description_find_stream(md,SalProtoRtpSavp,SalVideo);
750                         if (secure_vsd){
751                                 cp->has_video=is_video_active(secure_vsd);
752                                 if (secure_asd || asd==NULL)
753                                         cp->media_encryption=LinphoneMediaEncryptionSRTP;
754                         }else if (vsd){
755                                 cp->has_video=is_video_active(vsd);
756                         }
757                         return cp;
758                 }
759         }
760         return NULL;
761 }
762
763 /**
764  * Returns the remote address associated to this call
765  *
766 **/
767 const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call){
768         return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to;
769 }
770
771 /**
772  * Returns the remote address associated to this call as a string.
773  *
774  * The result string must be freed by user using ms_free().
775 **/
776 char *linphone_call_get_remote_address_as_string(const LinphoneCall *call){
777         return linphone_address_as_string(linphone_call_get_remote_address(call));
778 }
779
780 /**
781  * Retrieves the call's current state.
782 **/
783 LinphoneCallState linphone_call_get_state(const LinphoneCall *call){
784         return call->state;
785 }
786
787 /**
788  * Returns the reason for a call termination (either error or normal termination)
789 **/
790 LinphoneReason linphone_call_get_reason(const LinphoneCall *call){
791         return call->reason;
792 }
793
794 /**
795  * Get the user_pointer in the LinphoneCall
796  *
797  * @ingroup call_control
798  *
799  * return user_pointer an opaque user pointer that can be retrieved at any time
800 **/
801 void *linphone_call_get_user_pointer(LinphoneCall *call)
802 {
803         return call->user_pointer;
804 }
805
806 /**
807  * Set the user_pointer in the LinphoneCall
808  *
809  * @ingroup call_control
810  *
811  * the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
812 **/
813 void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer)
814 {
815         call->user_pointer = user_pointer;
816 }
817
818 /**
819  * Returns the call log associated to this call.
820 **/
821 LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call){
822         return call->log;
823 }
824
825 /**
826  * Returns the refer-to uri (if the call was transfered).
827 **/
828 const char *linphone_call_get_refer_to(const LinphoneCall *call){
829         return call->refer_to;
830 }
831
832 /**
833  * Returns direction of the call (incoming or outgoing).
834 **/
835 LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call){
836         return call->log->dir;
837 }
838
839 /**
840  * Returns the far end's user agent description string, if available.
841 **/
842 const char *linphone_call_get_remote_user_agent(LinphoneCall *call){
843         if (call->op){
844                 return sal_op_get_remote_ua (call->op);
845         }
846         return NULL;
847 }
848
849 /**
850  * Returns true if this calls has received a transfer that has not been
851  * executed yet.
852  * Pending transfers are executed when this call is being paused or closed,
853  * locally or by remote endpoint.
854  * If the call is already paused while receiving the transfer request, the
855  * transfer immediately occurs.
856 **/
857 bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
858         return call->refer_pending;
859 }
860
861 /**
862  * Returns call's duration in seconds.
863 **/
864 int linphone_call_get_duration(const LinphoneCall *call){
865         if (call->media_start_time==0) return 0;
866         return time(NULL)-call->media_start_time;
867 }
868
869 /**
870  * Returns the call object this call is replacing, if any.
871  * Call replacement can occur during call transfers.
872  * By default, the core automatically terminates the replaced call and accept the new one.
873  * This function allows the application to know whether a new incoming call is a one that replaces another one.
874 **/
875 LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){
876         SalOp *op=sal_call_get_replaces(call->op);
877         if (op){
878                 return (LinphoneCall*)sal_op_get_user_pointer(op);
879         }
880         return NULL;
881 }
882
883 /**
884  * Indicate whether camera input should be sent to remote end.
885 **/
886 void linphone_call_enable_camera (LinphoneCall *call, bool_t enable){
887 #ifdef VIDEO_ENABLED
888         if (call->videostream!=NULL && call->videostream->ticker!=NULL){
889                 LinphoneCore *lc=call->core;
890                 MSWebCam *nowebcam=get_nowebcam_device();
891                 if (call->camera_active!=enable && lc->video_conf.device!=nowebcam){
892                         video_stream_change_camera(call->videostream,
893                                      enable ? lc->video_conf.device : nowebcam);
894                 }
895         }
896         call->camera_active=enable;
897 #endif
898 }
899
900 /**
901  * Take a photo of currently received video and write it into a jpeg file.
902 **/
903 int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){
904 #ifdef VIDEO_ENABLED
905         if (call->videostream!=NULL && call->videostream->jpegwriter!=NULL){
906                 return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file);
907         }
908         ms_warning("Cannot take snapshot: no currently running video stream on this call.");
909         return -1;
910 #endif
911         return -1;
912 }
913
914 /**
915  * Returns TRUE if camera pictures are sent to the remote party.
916 **/
917 bool_t linphone_call_camera_enabled (const LinphoneCall *call){
918         return call->camera_active;
919 }
920
921 /**
922  * Enable video stream.
923 **/
924 void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
925         cp->has_video=enabled;
926 }
927
928 const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
929         return cp->audio_codec;
930 }
931
932 const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
933         return cp->video_codec;
934 }
935
936 bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) {
937         return cp->low_bandwidth;
938 }
939 /**
940  * Returns whether video is enabled.
941 **/
942 bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
943         return cp->has_video;
944 }
945
946 enum LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) {
947         return cp->media_encryption;
948 }
949
950 void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, enum LinphoneMediaEncryption e) {
951         cp->media_encryption = e;
952 }
953
954
955 /**
956  * Enable sending of real early media (during outgoing calls).
957 **/
958 void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){
959         cp->real_early_media=enabled;
960 }
961
962 bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
963         return cp->real_early_media;
964 }
965
966 /**
967  * Returns true if the call is part of the locally managed conference.
968 **/
969 bool_t linphone_call_params_local_conference_mode(const LinphoneCallParams *cp){
970         return cp->in_conference;
971 }
972
973 /**
974  * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams.
975  * As a consequence, codecs whose bitrates are not compatible with this limit won't be used.
976 **/
977 void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){
978         cp->audio_bw=bandwidth;
979 }
980
981 #ifdef VIDEO_ENABLED
982 /**
983  * Request remote side to send us a Video Fast Update.
984 **/
985 void linphone_call_send_vfu_request(LinphoneCall *call)
986 {
987         if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
988                 sal_call_send_vfu_request(call->op);
989 }
990 #endif
991
992 /**
993  *
994 **/
995 LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
996         LinphoneCallParams *ncp=ms_new0(LinphoneCallParams,1);
997         memcpy(ncp,cp,sizeof(LinphoneCallParams));
998         return ncp;
999 }
1000
1001 /**
1002  *
1003 **/
1004 void linphone_call_params_destroy(LinphoneCallParams *p){
1005         ms_free(p);
1006 }
1007
1008 /**
1009  * @}
1010 **/
1011
1012
1013 #ifdef TEST_EXT_RENDERER
1014 static void rendercb(void *data, const MSPicture *local, const MSPicture *remote){
1015         ms_message("rendercb, local buffer=%p, remote buffer=%p",
1016                    local ? local->planes[0] : NULL, remote? remote->planes[0] : NULL);
1017 }
1018 #endif
1019
1020 #ifdef VIDEO_ENABLED
1021 static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args){
1022     LinphoneCall* call = (LinphoneCall*) user_pointer;
1023         ms_warning("In linphonecall.c: video_stream_event_cb");
1024         switch (event_id) {
1025                 case MS_VIDEO_DECODER_DECODING_ERRORS:
1026                         ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS");
1027                         linphone_call_send_vfu_request(call);
1028                         break;
1029         case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED:
1030             ms_message("First video frame decoded successfully");
1031             if (call->nextVideoFrameDecoded._func != NULL)
1032                 call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data);
1033             break;
1034                 default:
1035                         ms_warning("Unhandled event %i", event_id);
1036                         break;
1037         }
1038 }
1039 #endif
1040
1041 void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) {
1042     call->nextVideoFrameDecoded._func = cb;
1043     call->nextVideoFrameDecoded._user_data = user_data;
1044 #ifdef VIDEO_ENABLED
1045     ms_filter_call_method_noarg(call->videostream->decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION);
1046 #endif
1047 }
1048
1049 void linphone_call_init_audio_stream(LinphoneCall *call){
1050         LinphoneCore *lc=call->core;
1051         AudioStream *audiostream;
1052         int dscp;
1053
1054         if (call->audiostream != NULL) return;
1055         call->audiostream=audiostream=audio_stream_new(call->audio_port,call->audio_port+1,linphone_core_ipv6_enabled(lc));
1056         dscp=linphone_core_get_audio_dscp(lc);
1057         if (dscp!=-1)
1058                 audio_stream_set_dscp(audiostream,dscp);
1059         if (linphone_core_echo_limiter_enabled(lc)){
1060                 const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
1061                 if (strcasecmp(type,"mic")==0)
1062                         audio_stream_enable_echo_limiter(audiostream,ELControlMic);
1063                 else if (strcasecmp(type,"full")==0)
1064                         audio_stream_enable_echo_limiter(audiostream,ELControlFull);
1065         }
1066         audio_stream_enable_gain_control(audiostream,TRUE);
1067         if (linphone_core_echo_cancellation_enabled(lc)){
1068                 int len,delay,framesize;
1069                 const char *statestr=lp_config_get_string(lc->config,"sound","ec_state",NULL);
1070                 len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
1071                 delay=lp_config_get_int(lc->config,"sound","ec_delay",0);
1072                 framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0);
1073                 audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize);
1074                 if (statestr && audiostream->ec){
1075                         ms_filter_call_method(audiostream->ec,MS_ECHO_CANCELLER_SET_STATE_STRING,(void*)statestr);
1076                 }
1077         }
1078         audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc));
1079         {
1080                 int enabled=lp_config_get_int(lc->config,"sound","noisegate",0);
1081                 audio_stream_enable_noise_gate(audiostream,enabled);
1082         }
1083
1084         audio_stream_set_features(audiostream,linphone_core_get_audio_features(lc));
1085
1086         if (lc->rtptf){
1087                 RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->audio_port);
1088                 RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->audio_port+1);
1089                 rtp_session_set_transports(audiostream->session,artp,artcp);
1090         }
1091         if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
1092                 rtp_session_set_pktinfo(audiostream->session, TRUE);
1093                 rtp_session_set_symmetric_rtp(audiostream->session, FALSE);
1094                 if (ice_session_check_list(call->ice_session, 0) == NULL) {
1095                         ice_session_add_check_list(call->ice_session, ice_check_list_new());
1096                 }
1097                 audiostream->ice_check_list = ice_session_check_list(call->ice_session, 0);
1098                 ice_check_list_set_rtp_session(audiostream->ice_check_list, audiostream->session);
1099         }
1100
1101         call->audiostream_app_evq = ortp_ev_queue_new();
1102         rtp_session_register_event_queue(audiostream->session,call->audiostream_app_evq);
1103 }
1104
1105 void linphone_call_init_video_stream(LinphoneCall *call){
1106 #ifdef VIDEO_ENABLED
1107         LinphoneCore *lc=call->core;
1108
1109         if (!call->params.has_video) {
1110                 linphone_call_stop_video_stream(call);
1111                 return;
1112         }
1113         if (call->videostream != NULL) return;
1114         if ((lc->video_conf.display || lc->video_conf.capture) && call->params.has_video){
1115                 int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0);
1116                 int dscp=linphone_core_get_video_dscp(lc);
1117                 
1118                 call->videostream=video_stream_new(call->video_port,call->video_port+1,linphone_core_ipv6_enabled(lc));
1119                 if (dscp!=-1)
1120                         video_stream_set_dscp(call->videostream,dscp);
1121                 video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0));
1122                 if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->session,video_recv_buf_size);
1123
1124                 if( lc->video_conf.displaytype != NULL)
1125                         video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype);
1126                 video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
1127                 if (lc->rtptf){
1128                         RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->video_port);
1129                         RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->video_port+1);
1130                         rtp_session_set_transports(call->videostream->session,vrtp,vrtcp);
1131                 }
1132                 if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)){
1133                         rtp_session_set_pktinfo(call->videostream->session, TRUE);
1134                         rtp_session_set_symmetric_rtp(call->videostream->session, FALSE);
1135                         if (ice_session_check_list(call->ice_session, 1) == NULL) {
1136                                 ice_session_add_check_list(call->ice_session, ice_check_list_new());
1137                         }
1138                         call->videostream->ice_check_list = ice_session_check_list(call->ice_session, 1);
1139                         ice_check_list_set_rtp_session(call->videostream->ice_check_list, call->videostream->session);
1140                 }
1141                 call->videostream_app_evq = ortp_ev_queue_new();
1142                 rtp_session_register_event_queue(call->videostream->session,call->videostream_app_evq);
1143 #ifdef TEST_EXT_RENDERER
1144                 video_stream_set_render_callback(call->videostream,rendercb,NULL);
1145 #endif
1146         }
1147 #else
1148         call->videostream=NULL;
1149 #endif
1150 }
1151
1152 void linphone_call_init_media_streams(LinphoneCall *call){
1153         linphone_call_init_audio_stream(call);
1154         linphone_call_init_video_stream(call);
1155 }
1156
1157
1158 static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
1159
1160 static void linphone_core_dtmf_received(LinphoneCore *lc, int dtmf){
1161         if (dtmf<0 || dtmf>15){
1162                 ms_warning("Bad dtmf value %i",dtmf);
1163                 return;
1164         }
1165         if (lc->vtable.dtmf_received != NULL)
1166                 lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]);
1167 }
1168
1169 static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
1170         if (st->equalizer){
1171                 MSFilter *f=st->equalizer;
1172                 int enabled=lp_config_get_int(lc->config,"sound","eq_active",0);
1173                 const char *gains=lp_config_get_string(lc->config,"sound","eq_gains",NULL);
1174                 ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled);
1175                 if (enabled){
1176                         if (gains){
1177                                 do{
1178                                         int bytes;
1179                                         MSEqualizerGain g;
1180                                         if (sscanf(gains,"%f:%f:%f %n",&g.frequency,&g.gain,&g.width,&bytes)==3){
1181                                                 ms_message("Read equalizer gains: %f(~%f) --> %f",g.frequency,g.width,g.gain);
1182                                                 ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN,&g);
1183                                                 gains+=bytes;
1184                                         }else break;
1185                                 }while(1);
1186                         }
1187                 }
1188         }
1189 }
1190
1191 void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){
1192         float mic_gain=lc->sound_conf.soft_mic_lev;
1193         float thres = 0;
1194         float recv_gain;
1195         float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05);
1196         float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0);
1197         int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0);
1198
1199         if (!muted)
1200                 linphone_core_set_mic_gain_db (lc, mic_gain);
1201         else
1202                 audio_stream_set_mic_gain(st,0);
1203
1204         recv_gain = lc->sound_conf.soft_play_lev;
1205         if (recv_gain != 0) {
1206                 linphone_core_set_playback_gain_db (lc,recv_gain);
1207         }
1208         
1209         if (st->volsend){
1210                 ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal);
1211                 float speed=lp_config_get_float(lc->config,"sound","el_speed",-1);
1212                 thres=lp_config_get_float(lc->config,"sound","el_thres",-1);
1213                 float force=lp_config_get_float(lc->config,"sound","el_force",-1);
1214                 int sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1);
1215                 float transmit_thres=lp_config_get_float(lc->config,"sound","el_transmit_thres",-1);
1216                 MSFilter *f=NULL;
1217                 f=st->volsend;
1218                 if (speed==-1) speed=0.03;
1219                 if (force==-1) force=25;
1220                 ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed);
1221                 ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force);
1222                 if (thres!=-1)
1223                         ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres);
1224                 if (sustain!=-1)
1225                         ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain);
1226                 if (transmit_thres!=-1)
1227                                 ms_filter_call_method(f,MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD,&transmit_thres);
1228
1229                 ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
1230                 ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain);
1231         }
1232         if (st->volrecv){
1233                 /* parameters for a limited noise-gate effect, using echo limiter threshold */
1234                 float floorgain = 1/pow(10,(mic_gain)/10);
1235                 int spk_agc=lp_config_get_int(lc->config,"sound","speaker_agc_enabled",0);
1236                 ms_filter_call_method(st->volrecv, MS_VOLUME_ENABLE_AGC, &spk_agc);
1237                 ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
1238                 ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&floorgain);
1239         }
1240         parametrize_equalizer(lc,st);
1241 }
1242
1243 static void post_configure_audio_streams(LinphoneCall*call){
1244         AudioStream *st=call->audiostream;
1245         LinphoneCore *lc=call->core;
1246         _post_configure_audio_stream(st,lc,call->audio_muted);
1247         if (lc->vtable.dtmf_received!=NULL){
1248                 /* replace by our default action*/
1249                 audio_stream_play_received_dtmfs(call->audiostream,FALSE);
1250                 /*rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);*/
1251         }
1252 }
1253
1254 static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
1255         int bw;
1256         const MSList *elem;
1257         RtpProfile *prof=rtp_profile_new("Call profile");
1258         bool_t first=TRUE;
1259         int remote_bw=0;
1260         LinphoneCore *lc=call->core;
1261         int up_ptime=0;
1262         const LinphoneCallParams *params=&call->params;
1263         *used_pt=-1;
1264
1265         for(elem=desc->payloads;elem!=NULL;elem=elem->next){
1266                 PayloadType *pt=(PayloadType*)elem->data;
1267                 int number;
1268
1269                 if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) {
1270                         if (desc->type==SalAudio){
1271                                 linphone_core_update_allocated_audio_bandwidth_in_call(call,pt);
1272                                 if (params->up_ptime)
1273                                         up_ptime=params->up_ptime;
1274                                 else up_ptime=linphone_core_get_upload_ptime(lc);
1275                         }
1276                         *used_pt=payload_type_get_number(pt);
1277                         first=FALSE;
1278                 }
1279                 if (desc->bandwidth>0) remote_bw=desc->bandwidth;
1280                 else if (md->bandwidth>0) {
1281                         /*case where b=AS is given globally, not per stream*/
1282                         remote_bw=md->bandwidth;
1283                         if (desc->type==SalVideo){
1284                                 remote_bw=get_video_bandwidth(remote_bw,call->audio_bw);
1285                         }
1286                 }
1287
1288                 if (desc->type==SalAudio){
1289                         int audio_bw=call->audio_bw;
1290                         if (params->up_bw){
1291                                 if (params->up_bw< audio_bw)
1292                                         audio_bw=params->up_bw;
1293                         }
1294                         bw=get_min_bandwidth(audio_bw,remote_bw);
1295                 }else bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw);
1296                 if (bw>0) pt->normal_bitrate=bw*1000;
1297                 else if (desc->type==SalAudio){
1298                         pt->normal_bitrate=-1;
1299                 }
1300                 if (desc->ptime>0){
1301                         up_ptime=desc->ptime;
1302                 }
1303                 if (up_ptime>0){
1304                         char tmp[40];
1305                         snprintf(tmp,sizeof(tmp),"ptime=%i",up_ptime);
1306                         payload_type_append_send_fmtp(pt,tmp);
1307                 }
1308                 number=payload_type_get_number(pt);
1309                 if (rtp_profile_get_payload(prof,number)!=NULL){
1310                         ms_warning("A payload type with number %i already exists in profile !",number);
1311                 }else
1312                         rtp_profile_set_payload(prof,number,pt);
1313         }
1314         return prof;
1315 }
1316
1317
1318 static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){
1319         int pause_time=3000;
1320         audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone);
1321         ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
1322 }
1323
1324 static bool_t linphone_call_sound_resources_available(LinphoneCall *call){
1325         LinphoneCore *lc=call->core;
1326         LinphoneCall *current=linphone_core_get_current_call(lc);
1327         return !linphone_core_is_in_conference(lc) && 
1328                 (current==NULL || current==call);
1329 }
1330 static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned char tag) {
1331     int i;
1332     for(i=0; i<SAL_CRYPTO_ALGO_MAX; i++) {
1333         if (crypto[i].tag == tag) {
1334             return i;
1335         }
1336     }
1337     return -1;
1338 }
1339 static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){
1340         LinphoneCore *lc=call->core;
1341         int used_pt=-1;
1342         char rtcp_tool[128]={0};
1343         snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
1344         /* look for savp stream first */
1345         const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
1346                                                 SalProtoRtpSavp,SalAudio);
1347         /* no savp audio stream, use avp */
1348         if (!stream)
1349                 stream=sal_media_description_find_stream(call->resultdesc,
1350                                                 SalProtoRtpAvp,SalAudio);
1351
1352         if (stream && stream->dir!=SalStreamInactive && stream->rtp_port!=0){
1353                 MSSndCard *playcard=lc->sound_conf.lsd_card ?
1354                         lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
1355                 MSSndCard *captcard=lc->sound_conf.capt_sndcard;
1356                 const char *playfile=lc->play_file;
1357                 const char *recfile=lc->rec_file;
1358                 call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
1359                 bool_t use_ec;
1360
1361                 if (used_pt!=-1){
1362                         call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt);
1363                         if (playcard==NULL) {
1364                                 ms_warning("No card defined for playback !");
1365                         }
1366                         if (captcard==NULL) {
1367                                 ms_warning("No card defined for capture !");
1368                         }
1369                         /*Replace soundcard filters by inactive file players or recorders
1370                          when placed in recvonly or sendonly mode*/
1371                         if (stream->rtp_port==0 || stream->dir==SalStreamRecvOnly){
1372                                 captcard=NULL;
1373                                 playfile=NULL;
1374                         }else if (stream->dir==SalStreamSendOnly){
1375                                 playcard=NULL;
1376                                 captcard=NULL;
1377                                 recfile=NULL;
1378                                 /*And we will eventually play "playfile" if set by the user*/
1379                                 /*playfile=NULL;*/
1380                         }
1381                         if (send_ringbacktone){
1382                                 captcard=NULL;
1383                                 playfile=NULL;/* it is setup later*/
1384                         }
1385                         /*if playfile are supplied don't use soundcards*/
1386                         if (lc->use_files) {
1387                                 captcard=NULL;
1388                                 playcard=NULL;
1389                         }
1390                         if (call->params.in_conference){
1391                                 /* first create the graph without soundcard resources*/
1392                                 captcard=playcard=NULL;
1393                         }
1394                         if (!linphone_call_sound_resources_available(call)){
1395                                 ms_message("Sound resources are used by another call, not using soundcard.");
1396                                 captcard=playcard=NULL;
1397                         }
1398                         use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc);
1399                         if (playcard &&  stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(playcard, stream->max_rate);
1400                         if (captcard &&  stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate);
1401                         audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc);
1402                         audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc));
1403                         audio_stream_start_full(
1404                                 call->audiostream,
1405                                 call->audio_profile,
1406                                 stream->rtp_addr[0]!='\0' ? stream->rtp_addr : call->resultdesc->addr,
1407                                 stream->rtp_port,
1408                                 stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr,
1409                                 linphone_core_rtcp_enabled(lc) ? (stream->rtcp_port) : 0,
1410                                 used_pt,
1411                                 linphone_core_get_audio_jittcomp(lc),
1412                                 playfile,
1413                                 recfile,
1414                                 playcard,
1415                                 captcard,
1416                                 use_ec
1417                                 );
1418                         post_configure_audio_streams(call);
1419                         if (muted && !send_ringbacktone){
1420                                 audio_stream_set_mic_gain(call->audiostream,0);
1421                         }
1422                         if (stream->dir==SalStreamSendOnly && playfile!=NULL){
1423                                 int pause_time=500;
1424                                 ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
1425                         }
1426                         if (send_ringbacktone){
1427                                 setup_ring_player(lc,call);
1428                         }
1429                         audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
1430                         
1431             /* valid local tags are > 0 */
1432                         if (stream->proto == SalProtoRtpSavp) {
1433                 const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
1434                                                                                             SalProtoRtpSavp,SalAudio);
1435                 int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
1436                 
1437                 if (crypto_idx >= 0) {
1438                     audio_stream_enable_strp(
1439                                              call->audiostream, 
1440                                              stream->crypto[0].algo,
1441                                              local_st_desc->crypto[crypto_idx].master_key,
1442                                              stream->crypto[0].master_key);
1443                     call->audiostream_encrypted=TRUE;
1444                 } else {
1445                     ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
1446                     call->audiostream_encrypted=FALSE;
1447                 }
1448                         }else call->audiostream_encrypted=FALSE;
1449                         if (call->params.in_conference){
1450                                 /*transform the graph to connect it to the conference filter */
1451                                 bool_t mute=stream->dir==SalStreamRecvOnly;
1452                                 linphone_call_add_to_conf(call, mute);
1453                         }
1454                         call->current_params.in_conference=call->params.in_conference;
1455                         call->current_params.low_bandwidth=call->params.low_bandwidth;
1456                 }else ms_warning("No audio stream accepted ?");
1457         }
1458 }
1459
1460 static void linphone_call_start_video_stream(LinphoneCall *call, const char *cname,bool_t all_inputs_muted){
1461 #ifdef VIDEO_ENABLED
1462         LinphoneCore *lc=call->core;
1463         int used_pt=-1;
1464         /* look for savp stream first */
1465         const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
1466                                                 SalProtoRtpSavp,SalVideo);
1467         char rtcp_tool[128]={0};
1468         snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version());
1469         
1470         /* no savp audio stream, use avp */
1471         if (!vstream)
1472                 vstream=sal_media_description_find_stream(call->resultdesc,
1473                                                 SalProtoRtpAvp,SalVideo);
1474                                                 
1475         /* shutdown preview */
1476         if (lc->previewstream!=NULL) {
1477                 video_preview_stop(lc->previewstream);
1478                 lc->previewstream=NULL;
1479         }
1480         
1481         if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->rtp_port!=0) {
1482                 const char *rtp_addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr;
1483                 const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr;
1484                 call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
1485                 if (used_pt!=-1){
1486                         call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
1487                         VideoStreamDir dir=VideoStreamSendRecv;
1488                         MSWebCam *cam=lc->video_conf.device;
1489                         bool_t is_inactive=FALSE;
1490
1491                         call->current_params.has_video=TRUE;
1492
1493                         video_stream_enable_adaptive_bitrate_control(call->videostream,
1494                                                                   linphone_core_adaptive_rate_control_enabled(lc));
1495                         video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc));
1496                         video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
1497                         video_stream_enable_self_view(call->videostream,lc->video_conf.selfview);
1498                         if (lc->video_window_id!=0)
1499                                 video_stream_set_native_window_id(call->videostream,lc->video_window_id);
1500                         if (lc->preview_window_id!=0)
1501                                 video_stream_set_native_preview_window_id (call->videostream,lc->preview_window_id);
1502                         video_stream_use_preview_video_window (call->videostream,lc->use_preview_window);
1503                         
1504                         if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
1505                                 cam=get_nowebcam_device();
1506                                 dir=VideoStreamSendOnly;
1507                         }else if (vstream->dir==SalStreamRecvOnly && lc->video_conf.display ){
1508                                 dir=VideoStreamRecvOnly;
1509                         }else if (vstream->dir==SalStreamSendRecv){
1510                                 if (lc->video_conf.display && lc->video_conf.capture)
1511                                         dir=VideoStreamSendRecv;
1512                                 else if (lc->video_conf.display)
1513                                         dir=VideoStreamRecvOnly;
1514                                 else
1515                                         dir=VideoStreamSendOnly;
1516                         }else{
1517                                 ms_warning("video stream is inactive.");
1518                                 /*either inactive or incompatible with local capabilities*/
1519                                 is_inactive=TRUE;
1520                         }
1521                         if (call->camera_active==FALSE || all_inputs_muted){
1522                                 cam=get_nowebcam_device();
1523                         }
1524                         if (!is_inactive){
1525                                 call->log->video_enabled = TRUE;
1526                                 video_stream_set_direction (call->videostream, dir);
1527                                 ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
1528                                 video_stream_set_device_rotation(call->videostream, lc->device_rotation);
1529                                 video_stream_start(call->videostream,
1530                                         call->video_profile, rtp_addr, vstream->rtp_port,
1531                                         rtcp_addr, linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port) : 0,
1532                                         used_pt, linphone_core_get_video_jittcomp(lc), cam);
1533                                 video_stream_set_rtcp_information(call->videostream, cname,rtcp_tool);
1534                         }
1535                         
1536                         if (vstream->proto == SalProtoRtpSavp) {
1537                                 const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
1538                                                 SalProtoRtpSavp,SalVideo);
1539                                                 
1540                                 video_stream_enable_strp(
1541                                         call->videostream, 
1542                                         vstream->crypto[0].algo,
1543                                         local_st_desc->crypto[0].master_key, 
1544                                         vstream->crypto[0].master_key
1545                                         );
1546                                 call->videostream_encrypted=TRUE;
1547                         }else{
1548                                 call->videostream_encrypted=FALSE;
1549                         }
1550                 }else ms_warning("No video stream accepted.");
1551         }else{
1552                 ms_warning("No valid video stream defined.");
1553         }
1554 #endif
1555 }
1556
1557 void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){
1558         LinphoneCore *lc=call->core;
1559
1560         call->current_params.audio_codec = NULL;
1561         call->current_params.video_codec = NULL;
1562
1563         LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
1564         char *cname;
1565         bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
1566 #ifdef VIDEO_ENABLED
1567         const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
1568                                                         SalProtoRtpAvp,SalVideo);
1569 #endif
1570
1571         if ((call->audiostream == NULL) && (call->videostream == NULL)) {
1572                 ms_fatal("start_media_stream() called without prior init !");
1573                 return;
1574         }
1575         cname=linphone_address_as_string_uri_only(me);
1576
1577 #if defined(VIDEO_ENABLED)
1578         if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){
1579                 /*when video is used, do not make adaptive rate control on audio, it is stupid.*/
1580                 use_arc=FALSE;
1581         }
1582 #endif
1583         if (call->audiostream!=NULL) {
1584                 linphone_call_start_audio_stream(call,cname,all_inputs_muted,send_ringbacktone,use_arc);
1585         }
1586         call->current_params.has_video=FALSE;
1587         if (call->videostream!=NULL) {
1588                 linphone_call_start_video_stream(call,cname,all_inputs_muted);
1589         }
1590
1591         call->all_muted=all_inputs_muted;
1592         call->playing_ringbacktone=send_ringbacktone;
1593         call->up_bw=linphone_core_get_upload_bandwidth(lc);
1594
1595         if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) {
1596                 OrtpZrtpParams params;
1597                 /*will be set later when zrtp is activated*/
1598                 call->current_params.media_encryption=LinphoneMediaEncryptionNone;
1599                 
1600                 params.zid_file=lc->zrtp_secrets_cache;
1601                 audio_stream_enable_zrtp(call->audiostream,&params);
1602         }else if (call->params.media_encryption==LinphoneMediaEncryptionSRTP){
1603                 call->current_params.media_encryption=linphone_call_are_all_streams_encrypted(call) ?
1604                         LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone;
1605         }
1606
1607         /*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again
1608          * further in the call, for example during pause,resume, conferencing reINVITEs*/
1609         linphone_call_fix_call_parameters(call);
1610         if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) {
1611                 ice_session_start_connectivity_checks(call->ice_session);
1612         }
1613
1614         goto end;
1615         end:
1616                 ms_free(cname);
1617                 linphone_address_destroy(me);
1618 }
1619
1620 void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){
1621         audio_stream_prepare_sound(call->audiostream, NULL, NULL);
1622 #ifdef VIDEO_ENABLED
1623         if (call->videostream) {
1624                 video_stream_prepare_video(call->videostream);
1625         }
1626 #endif
1627 }
1628
1629 void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){
1630         audio_stream_unprepare_sound(call->audiostream);
1631 #ifdef VIDEO_ENABLED
1632         if (call->videostream) {
1633                 video_stream_unprepare_video(call->videostream);
1634         }
1635 #endif
1636 }
1637
1638 void linphone_call_delete_ice_session(LinphoneCall *call){
1639         if (call->ice_session != NULL) {
1640                 ice_session_destroy(call->ice_session);
1641                 call->ice_session = NULL;
1642                 if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL;
1643                 if (call->videostream != NULL) call->videostream->ice_check_list = NULL;
1644                 call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateNotActivated;
1645                 call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateNotActivated;
1646         }
1647 }
1648
1649 static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
1650         audio_stream_get_local_rtp_stats (st,&log->local_stats);
1651         log->quality=audio_stream_get_average_quality_rating(st);
1652 }
1653
1654 void linphone_call_stop_audio_stream(LinphoneCall *call) {
1655         if (call->audiostream!=NULL) {
1656                 rtp_session_unregister_event_queue(call->audiostream->session,call->audiostream_app_evq);
1657                 ortp_ev_queue_flush(call->audiostream_app_evq);
1658                 ortp_ev_queue_destroy(call->audiostream_app_evq);
1659                 call->audiostream_app_evq=NULL;
1660
1661                 if (call->audiostream->ec){
1662                         const char *state_str=NULL;
1663                         ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str);
1664                         if (state_str){
1665                                 ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str));
1666                                 lp_config_set_string(call->core->config,"sound","ec_state",state_str);
1667                         }
1668                 }
1669                 linphone_call_log_fill_stats (call->log,call->audiostream);
1670                 if (call->endpoint){
1671                         linphone_call_remove_from_conf(call);
1672                 }
1673                 audio_stream_stop(call->audiostream);
1674                 call->audiostream=NULL;
1675         }
1676 }
1677
1678 void linphone_call_stop_video_stream(LinphoneCall *call) {
1679 #ifdef VIDEO_ENABLED
1680         if (call->videostream!=NULL){
1681                 rtp_session_unregister_event_queue(call->videostream->session,call->videostream_app_evq);
1682                 ortp_ev_queue_flush(call->videostream_app_evq);
1683                 ortp_ev_queue_destroy(call->videostream_app_evq);
1684                 call->videostream_app_evq=NULL;
1685                 video_stream_stop(call->videostream);
1686                 call->videostream=NULL;
1687         }
1688 #endif
1689 }
1690
1691 void linphone_call_stop_media_streams(LinphoneCall *call){
1692         linphone_call_stop_audio_stream(call);
1693         linphone_call_stop_video_stream(call);
1694         ms_event_queue_skip(call->core->msevq);
1695         
1696         if (call->audio_profile){
1697                 rtp_profile_clear_all(call->audio_profile);
1698                 rtp_profile_destroy(call->audio_profile);
1699                 call->audio_profile=NULL;
1700         }
1701         if (call->video_profile){
1702                 rtp_profile_clear_all(call->video_profile);
1703                 rtp_profile_destroy(call->video_profile);
1704                 call->video_profile=NULL;
1705         }
1706 }
1707
1708
1709
1710 void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t enable) {
1711         if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
1712                 bool_t bypass_mode = !enable;
1713                 ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_SET_BYPASS_MODE,&bypass_mode);
1714         }
1715 }
1716 bool_t linphone_call_echo_cancellation_enabled(LinphoneCall *call) {
1717         if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
1718                 bool_t val;
1719                 ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_BYPASS_MODE,&val);
1720                 return !val;
1721         } else {
1722                 return linphone_core_echo_cancellation_enabled(call->core);
1723         }
1724 }
1725
1726 void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val){
1727         if (call!=NULL && call->audiostream!=NULL ) {
1728                 if (val) {
1729                 const char *type=lp_config_get_string(call->core->config,"sound","el_type","mic");
1730                 if (strcasecmp(type,"mic")==0)
1731                         audio_stream_enable_echo_limiter(call->audiostream,ELControlMic);
1732                 else if (strcasecmp(type,"full")==0)
1733                         audio_stream_enable_echo_limiter(call->audiostream,ELControlFull);
1734                 } else {
1735                         audio_stream_enable_echo_limiter(call->audiostream,ELInactive);
1736                 }
1737         }
1738 }
1739
1740 bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call){
1741         if (call!=NULL && call->audiostream!=NULL ){
1742                 return call->audiostream->el_type !=ELInactive ;
1743         } else {
1744                 return linphone_core_echo_limiter_enabled(call->core);
1745         }
1746 }
1747
1748 /**
1749  * @addtogroup call_misc
1750  * @{
1751 **/
1752
1753 /**
1754  * Returns the measured sound volume played locally (received from remote).
1755  * It is expressed in dbm0.
1756 **/
1757 float linphone_call_get_play_volume(LinphoneCall *call){
1758         AudioStream *st=call->audiostream;
1759         if (st && st->volrecv){
1760                 float vol=0;
1761                 ms_filter_call_method(st->volrecv,MS_VOLUME_GET,&vol);
1762                 return vol;
1763
1764         }
1765         return LINPHONE_VOLUME_DB_LOWEST;
1766 }
1767
1768 /**
1769  * Returns the measured sound volume recorded locally (sent to remote).
1770  * It is expressed in dbm0.
1771 **/
1772 float linphone_call_get_record_volume(LinphoneCall *call){
1773         AudioStream *st=call->audiostream;
1774         if (st && st->volsend && !call->audio_muted && call->state==LinphoneCallStreamsRunning){
1775                 float vol=0;
1776                 ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
1777                 return vol;
1778
1779         }
1780         return LINPHONE_VOLUME_DB_LOWEST;
1781 }
1782
1783 /**
1784  * Obtain real-time quality rating of the call
1785  *
1786  * Based on local RTP statistics and RTCP feedback, a quality rating is computed and updated
1787  * during all the duration of the call. This function returns its value at the time of the function call.
1788  * It is expected that the rating is updated at least every 5 seconds or so.
1789  * The rating is a floating point number comprised between 0 and 5.
1790  *
1791  * 4-5 = good quality <br>
1792  * 3-4 = average quality <br>
1793  * 2-3 = poor quality <br>
1794  * 1-2 = very poor quality <br>
1795  * 0-1 = can't be worse, mostly unusable <br>
1796  *
1797  * @returns The function returns -1 if no quality measurement is available, for example if no
1798  * active audio stream exist. Otherwise it returns the quality rating.
1799 **/
1800 float linphone_call_get_current_quality(LinphoneCall *call){
1801         if (call->audiostream){
1802                 return audio_stream_get_quality_rating(call->audiostream);
1803         }
1804         return -1;
1805 }
1806
1807 /**
1808  * Returns call quality averaged over all the duration of the call.
1809  *
1810  * See linphone_call_get_current_quality() for more details about quality measurement.
1811 **/
1812 float linphone_call_get_average_quality(LinphoneCall *call){
1813         if (call->audiostream){
1814                 return audio_stream_get_average_quality_rating(call->audiostream);
1815         }
1816         return -1;
1817 }
1818
1819 /**
1820  * Access last known statistics for audio stream, for a given call.
1821 **/
1822 const LinphoneCallStats *linphone_call_get_audio_stats(const LinphoneCall *call) {
1823         return &call->stats[LINPHONE_CALL_STATS_AUDIO];
1824 }
1825
1826 /**
1827  * Access last known statistics for video stream, for a given call.
1828 **/
1829 const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call) {
1830         return &call->stats[LINPHONE_CALL_STATS_VIDEO];
1831 }
1832
1833
1834 /**
1835  * @}
1836 **/
1837
1838 static void report_bandwidth(LinphoneCall *call, RtpSession *as, RtpSession *vs){
1839         call->stats[LINPHONE_CALL_STATS_AUDIO].download_bandwidth=(as!=NULL) ? (rtp_session_compute_recv_bandwidth(as)*1e-3) : 0;
1840         call->stats[LINPHONE_CALL_STATS_AUDIO].upload_bandwidth=(as!=NULL) ? (rtp_session_compute_send_bandwidth(as)*1e-3) : 0;
1841         call->stats[LINPHONE_CALL_STATS_VIDEO].download_bandwidth=(vs!=NULL) ? (rtp_session_compute_recv_bandwidth(vs)*1e-3) : 0;
1842         call->stats[LINPHONE_CALL_STATS_VIDEO].upload_bandwidth=(vs!=NULL) ? (rtp_session_compute_send_bandwidth(vs)*1e-3) : 0;
1843         ms_message("bandwidth usage: audio=[d=%.1f,u=%.1f] video=[d=%.1f,u=%.1f] kbit/sec",
1844                 call->stats[LINPHONE_CALL_STATS_AUDIO].download_bandwidth,
1845                 call->stats[LINPHONE_CALL_STATS_AUDIO].upload_bandwidth ,
1846                 call->stats[LINPHONE_CALL_STATS_VIDEO].download_bandwidth,
1847                 call->stats[LINPHONE_CALL_STATS_VIDEO].upload_bandwidth
1848         );
1849 }
1850
1851 static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
1852         char temp[256];
1853         char *from=NULL;
1854         if(call)
1855                 from = linphone_call_get_remote_address_as_string(call);
1856         if (from)
1857         {
1858                 snprintf(temp,sizeof(temp),"Remote end %s seems to have disconnected, the call is going to be closed.",from);
1859                 free(from);
1860         }
1861         else
1862         {
1863                 snprintf(temp,sizeof(temp),"Remote end seems to have disconnected, the call is going to be closed.");
1864         }
1865         if (lc->vtable.display_warning!=NULL)
1866                 lc->vtable.display_warning(lc,temp);
1867         linphone_core_terminate_call(lc,call);
1868 }
1869
1870 static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
1871         OrtpEventType evt=ortp_event_get_type(ev);
1872         OrtpEventData *evd=ortp_event_get_data(ev);
1873         int ping_time;
1874
1875         if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) {
1876                 switch (ice_session_state(call->ice_session)) {
1877                         case IS_Completed:
1878                                 ice_session_select_candidates(call->ice_session);
1879                                 if (ice_session_role(call->ice_session) == IR_Controlling) {
1880                                         linphone_core_update_call(call->core, call, &call->current_params);
1881                                 }
1882                                 break;
1883                         case IS_Failed:
1884                                 if (ice_session_has_completed_check_list(call->ice_session) == TRUE) {
1885                                         ice_session_select_candidates(call->ice_session);
1886                                         if (ice_session_role(call->ice_session) == IR_Controlling) {
1887                                                 /* At least one ICE session has succeeded, so perform a call update. */
1888                                                 linphone_core_update_call(call->core, call, &call->current_params);
1889                                         }
1890                                 }
1891                                 break;
1892                         default:
1893                                 break;
1894                 }
1895                 linphone_core_update_ice_state_in_call_stats(call);
1896         } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) {
1897
1898                 if (evd->info.ice_processing_successful==TRUE) {
1899                         ice_session_compute_candidates_foundations(call->ice_session);
1900                         ice_session_eliminate_redundant_candidates(call->ice_session);
1901                         ice_session_choose_default_candidates(call->ice_session);
1902                         ping_time = ice_session_average_gathering_round_trip_time(call->ice_session);
1903                         if (ping_time >=0) {
1904                                 call->ping_time=ping_time;
1905                         }
1906                 } else {
1907                         ms_warning("No STUN answer from [%s], disabling ICE",linphone_core_get_stun_server(call->core));
1908                         linphone_call_delete_ice_session(call);
1909                 }
1910                 switch (call->state) {
1911                         case LinphoneCallUpdating:
1912                                 linphone_core_start_update_call(call->core, call);
1913                                 break;
1914                         case LinphoneCallUpdatedByRemote:
1915                                 linphone_core_start_accept_call_update(call->core, call);
1916                                 break;
1917                         case LinphoneCallOutgoingInit:
1918                                 linphone_call_stop_media_streams_for_ice_gathering(call);
1919                                 linphone_core_proceed_with_invite_if_ready(call->core, call, NULL);
1920                                 break;
1921                         case LinphoneCallIdle:
1922                                 linphone_call_stop_media_streams_for_ice_gathering(call);
1923                                 linphone_core_notify_incoming_call(call->core, call);
1924                                 break;
1925                         default:
1926                                 break;
1927                 }
1928         } else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) {
1929                 linphone_core_start_accept_call_update(call->core, call);
1930                 linphone_core_update_ice_state_in_call_stats(call);
1931         } else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) {
1932                 ice_session_restart(call->ice_session);
1933                 ice_session_set_role(call->ice_session, IR_Controlling);
1934                 linphone_core_update_call(call->core, call, &call->current_params);
1935         }
1936 }
1937
1938 void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){
1939         LinphoneCore* lc = call->core;
1940         int disconnect_timeout = linphone_core_get_nortp_timeout(call->core);
1941         bool_t disconnected=FALSE;
1942
1943         if (call->state==LinphoneCallStreamsRunning && one_second_elapsed){
1944                 RtpSession *as=NULL,*vs=NULL;
1945                 float audio_load=0, video_load=0;
1946                 if (call->audiostream!=NULL){
1947                         as=call->audiostream->session;
1948                         if (call->audiostream->ticker)
1949                                 audio_load=ms_ticker_get_average_load(call->audiostream->ticker);
1950                 }
1951                 if (call->videostream!=NULL){
1952                         if (call->videostream->ticker)
1953                                 video_load=ms_ticker_get_average_load(call->videostream->ticker);
1954                         vs=call->videostream->session;
1955                 }
1956                 report_bandwidth(call,as,vs);
1957                 ms_message("Thread processing load: audio=%f\tvideo=%f",audio_load,video_load);
1958         }
1959 #ifdef VIDEO_ENABLED
1960         if (call->videostream!=NULL) {
1961                 OrtpEvent *ev;
1962
1963                 /* Ensure there is no dangling ICE check list. */
1964                 if (call->ice_session == NULL) call->videostream->ice_check_list = NULL;
1965
1966                 // Beware that the application queue should not depend on treatments fron the
1967                 // mediastreamer queue.
1968                 video_stream_iterate(call->videostream);
1969
1970                 while (call->videostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->videostream_app_evq)))){
1971                         OrtpEventType evt=ortp_event_get_type(ev);
1972                         OrtpEventData *evd=ortp_event_get_data(ev);
1973                         if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
1974                                 linphone_call_videostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
1975                         } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
1976                                 call->stats[LINPHONE_CALL_STATS_VIDEO].round_trip_delay = rtp_session_get_round_trip_propagation(call->videostream->session);
1977                                 if(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp != NULL)
1978                                         freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
1979                                 call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
1980                                 evd->packet = NULL;
1981                                 if (lc->vtable.call_stats_updated)
1982                                         lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
1983                         } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
1984                                 memcpy(&call->stats[LINPHONE_CALL_STATS_VIDEO].jitter_stats, rtp_session_get_jitter_stats(call->videostream->session), sizeof(jitter_stats_t));
1985                                 if(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp != NULL)
1986                                         freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
1987                                 call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
1988                                 evd->packet = NULL;
1989                                 if (lc->vtable.call_stats_updated)
1990                                         lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
1991                         } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
1992                                 || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
1993                                 handle_ice_events(call, ev);
1994                         }
1995                         ortp_event_destroy(ev);
1996                 }
1997         }
1998 #endif
1999         if (call->audiostream!=NULL) {
2000                 OrtpEvent *ev;
2001
2002                 /* Ensure there is no dangling ICE check list. */
2003                 if (call->ice_session == NULL) call->audiostream->ice_check_list = NULL;
2004
2005                 // Beware that the application queue should not depend on treatments fron the
2006                 // mediastreamer queue.
2007                 audio_stream_iterate(call->audiostream);
2008
2009                 while (call->audiostream_app_evq && (NULL != (ev=ortp_ev_queue_get(call->audiostream_app_evq)))){
2010                         OrtpEventType evt=ortp_event_get_type(ev);
2011                         OrtpEventData *evd=ortp_event_get_data(ev);
2012                         if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){
2013                                 linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted);
2014                         } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) {
2015                                 linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_sas.sas, evd->info.zrtp_sas.verified);
2016                         } else if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) {
2017                                 call->stats[LINPHONE_CALL_STATS_AUDIO].round_trip_delay = rtp_session_get_round_trip_propagation(call->audiostream->session);
2018                                 if(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp != NULL)
2019                                         freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
2020                                 call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
2021                                 evd->packet = NULL;
2022                                 if (lc->vtable.call_stats_updated)
2023                                         lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
2024                         } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
2025                                 memcpy(&call->stats[LINPHONE_CALL_STATS_AUDIO].jitter_stats, rtp_session_get_jitter_stats(call->audiostream->session), sizeof(jitter_stats_t));
2026                                 if(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp != NULL)
2027                                         freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
2028                                 call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
2029                                 evd->packet = NULL;
2030                                 if (lc->vtable.call_stats_updated)
2031                                         lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
2032                         } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
2033                                 || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) {
2034                                 handle_ice_events(call, ev);
2035                         } else if (evt==ORTP_EVENT_TELEPHONE_EVENT){
2036                                 linphone_core_dtmf_received(lc,evd->info.telephone_event);
2037                         }
2038                         ortp_event_destroy(ev);
2039                 }
2040         }
2041         if (call->state==LinphoneCallStreamsRunning && one_second_elapsed && call->audiostream!=NULL && disconnect_timeout>0 )
2042                 disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout);
2043         if (disconnected)
2044                 linphone_core_disconnected(call->core,call);
2045 }
2046
2047 void linphone_call_log_completed(LinphoneCall *call){
2048         LinphoneCore *lc=call->core;
2049
2050         call->log->duration=time(NULL)-call->start_time;
2051
2052         if (call->log->status==LinphoneCallMissed){
2053                 char *info;
2054                 lc->missed_calls++;
2055                 info=ortp_strdup_printf(ngettext("You have missed %i call.",
2056                                          "You have missed %i calls.", lc->missed_calls),
2057                                 lc->missed_calls);
2058         if (lc->vtable.display_status!=NULL)
2059             lc->vtable.display_status(lc,info);
2060                 ms_free(info);
2061         }
2062         lc->call_logs=ms_list_prepend(lc->call_logs,(void *)call->log);
2063         if (ms_list_size(lc->call_logs)>lc->max_call_logs){
2064                 MSList *elem,*prevelem=NULL;
2065                 /*find the last element*/
2066                 for(elem=lc->call_logs;elem!=NULL;elem=elem->next){
2067                         prevelem=elem;
2068                 }
2069                 elem=prevelem;
2070                 linphone_call_log_destroy((LinphoneCallLog*)elem->data);
2071                 lc->call_logs=ms_list_remove_link(lc->call_logs,elem);
2072         }
2073         if (lc->vtable.call_log_updated!=NULL){
2074                 lc->vtable.call_log_updated(lc,call->log);
2075         }
2076         call_logs_write_to_config_file(lc);
2077 }
2078
2079 LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call) {
2080         return call->transfer_state;
2081 }
2082
2083 void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state) {
2084         if (state != call->transfer_state) {
2085                 LinphoneCore* lc = call->core;
2086                 call->transfer_state = state;
2087                 if (lc->vtable.transfer_state_changed)
2088                         lc->vtable.transfer_state_changed(lc, call, state);
2089         }
2090 }
2091
2092 bool_t linphone_call_is_in_conference(const LinphoneCall *call) {
2093         return call->params.in_conference;
2094 }
2095
2096
2097 /**
2098  * Perform a zoom of the video displayed during a call.
2099  * @param call the call.
2100  * @param zoom_factor a floating point number describing the zoom factor. A value 1.0 corresponds to no zoom applied.
2101  * @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0.
2102  * @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0.
2103  * 
2104  * cx and cy are updated in return in case their coordinates were to excentrated for the requested zoom factor. The zoom ensures that all the screen is fullfilled with the video.
2105 **/
2106 void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) {
2107         VideoStream* vstream = call->videostream;
2108         if (vstream) {
2109                 float zoom[3];
2110                 
2111                 if (zoom_factor < 1)
2112                         zoom_factor = 1;
2113                 float halfsize = 0.5 * 1.0 / zoom_factor;
2114
2115                 if ((*cx - halfsize) < 0)
2116                         *cx = 0 + halfsize;
2117                 if ((*cx + halfsize) > 1)
2118                         *cx = 1 - halfsize;
2119                 if ((*cy - halfsize) < 0)
2120                         *cy = 0 + halfsize;
2121                 if ((*cy + halfsize) > 1)
2122                         *cy = 1 - halfsize;
2123         
2124                 zoom[0] = zoom_factor;
2125                 zoom[1] = *cx;
2126                 zoom[2] = *cy;
2127                 ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom);
2128         }else ms_warning("Could not apply zoom: video output wasn't activated.");
2129 }
2130