]> sjero.net Git - linphone/blob - console/commands.c
split commands into 2 categories in linphonec
[linphone] / console / commands.c
1 /****************************************************************************
2  *
3  *  $Id: commands.c,v 1.39 2008/07/03 15:08:34 smorlat Exp $
4  *
5  *  Copyright (C) 2006-2009  Sandro Santilli <strk@keybit.net>
6  *  Copyright (C) 2004  Simon MORLAT <simon.morlat@linphone.org>
7  *
8 ****************************************************************************
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  *
24  ****************************************************************************/
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #ifndef _WIN32_WCE
30 #include <errno.h>
31 #include <unistd.h>
32 #endif /*_WIN32_WCE*/
33 #include <limits.h>
34 #include <ctype.h>
35 #include <linphonecore.h>
36 #include "linphonec.h"
37 #include "private.h"
38 #include "lpconfig.h"
39
40 #ifndef WIN32
41 #include <sys/wait.h>
42 #endif
43
44 #define AUDIO 0
45 #define VIDEO 1
46
47 /***************************************************************************
48  *
49  *  Forward declarations 
50  *
51  ***************************************************************************/
52
53 extern char *lpc_strip_blanks(char *input);
54
55 /* Command handlers */
56 static int lpc_cmd_help(LinphoneCore *, char *);
57 static int lpc_cmd_proxy(LinphoneCore *, char *);
58 static int lpc_cmd_call(LinphoneCore *, char *);
59 static int lpc_cmd_calls(LinphoneCore *, char *);
60 static int lpc_cmd_chat(LinphoneCore *, char *);
61 static int lpc_cmd_answer(LinphoneCore *, char *);
62 static int lpc_cmd_autoanswer(LinphoneCore *, char *);
63 static int lpc_cmd_terminate(LinphoneCore *, char *);
64 static int lpc_cmd_call_logs(LinphoneCore *, char *);
65 static int lpc_cmd_ipv6(LinphoneCore *, char *);
66 static int lpc_cmd_transfer(LinphoneCore *, char *);
67 static int lpc_cmd_quit(LinphoneCore *, char *);
68 static int lpc_cmd_nat(LinphoneCore *, char *);
69 static int lpc_cmd_stun(LinphoneCore *, char *);
70 static int lpc_cmd_firewall(LinphoneCore *, char *);
71 static int lpc_cmd_friend(LinphoneCore *, char*);
72 static int lpc_cmd_soundcard(LinphoneCore *, char *);
73 static int lpc_cmd_webcam(LinphoneCore *, char *);
74 static int lpc_cmd_staticpic(LinphoneCore *, char *);
75 static int lpc_cmd_play(LinphoneCore *, char *);
76 static int lpc_cmd_record(LinphoneCore *, char *);
77 static int lpc_cmd_register(LinphoneCore *, char *);
78 static int lpc_cmd_unregister(LinphoneCore *, char *);
79 static int lpc_cmd_duration(LinphoneCore *lc, char *args);
80 static int lpc_cmd_status(LinphoneCore *lc, char *args);
81 static int lpc_cmd_ports(LinphoneCore *lc, char *args);
82 static int lpc_cmd_speak(LinphoneCore *lc, char *args);
83 static int lpc_cmd_acodec(LinphoneCore *lc, char *args);
84 static int lpc_cmd_vcodec(LinphoneCore *lc, char *args);
85 static int lpc_cmd_codec(int type, LinphoneCore *lc, char *args);
86 static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args);
87 static int lpc_cmd_pause(LinphoneCore *lc, char *args);
88 static int lpc_cmd_resume(LinphoneCore *lc, char *args);
89 static int lpc_cmd_mute_mic(LinphoneCore *lc, char *args);
90 static int lpc_cmd_unmute_mic(LinphoneCore *lc, char *args);
91 static int lpc_cmd_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, char *args);
92 static int lpc_cmd_video_window(LinphoneCore *lc, char *args);
93
94 /* Command handler helpers */
95 static void linphonec_proxy_add(LinphoneCore *lc);
96 static void linphonec_proxy_display(LinphoneProxyConfig *lc);
97 static void linphonec_proxy_list(LinphoneCore *lc);
98 static void linphonec_proxy_remove(LinphoneCore *lc, int index);
99 static  int linphonec_proxy_use(LinphoneCore *lc, int index);
100 static void linphonec_proxy_show(LinphoneCore *lc,int index);
101 static void linphonec_friend_display(LinphoneFriend *fr);
102 static int linphonec_friend_list(LinphoneCore *lc, char *arg);
103 static void linphonec_display_command_help(LPC_COMMAND *cmd);
104 static int linphonec_friend_call(LinphoneCore *lc, unsigned int num);
105 #ifndef WIN32
106 static int linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr);
107 #endif
108 static int linphonec_friend_delete(LinphoneCore *lc, int num);
109 static int linphonec_friend_delete(LinphoneCore *lc, int num);
110 static void linphonec_codec_list(int type, LinphoneCore *lc);
111 static void linphonec_codec_enable(int type, LinphoneCore *lc, int index);
112 static void linphonec_codec_disable(int type, LinphoneCore *lc, int index);
113
114
115
116 /* Command table management */
117 static LPC_COMMAND *lpc_find_command(const char *name);
118
119 void linphonec_out(const char *fmt,...);
120
121
122
123 /***************************************************************************
124  *
125  *  Global variables
126  *
127  ***************************************************************************/
128
129 /*
130  * Commands table.
131  */
132 static LPC_COMMAND commands[] = {
133         { "help", lpc_cmd_help, "Print commands help, 'help advanced' for advanced features.",
134                 "'help <command>'\t: displays specific help for command.\n"
135                 "'help advanced'\t: shows advanced commands.\n"
136         },
137         { "call", lpc_cmd_call, "Call a SIP uri",
138                 "'call <sip-url>' \t: initiate a call to the specified destination.\n"
139                 "'call show' \t: show all the current calls with their id and status.\n"
140                 },
141         { "calls", lpc_cmd_calls, "Show all the current calls with their id and status.",
142                 NULL
143                 },
144         { "chat", lpc_cmd_chat, "Chat with a SIP uri",
145                 "'chat <sip-url> \"message\"' "
146                 ": send a chat message \"message\" to the specified destination."
147                 },
148         { "terminate", lpc_cmd_terminate, "Terminate a call",
149                 "'terminate' : Terminate the current call\n"
150                 "'terminate <call id>' : Terminate the call with supplied id\n"
151                 "'terminate <all>' : Terminate all the current calls\n"
152                 },
153         { "answer", lpc_cmd_answer, "Answer a call",
154                 "'answer' : Answer the current incoming call\n"
155                 "'answer <call id>' : Answer the call with given id\n"
156         },
157         { "pause", lpc_cmd_pause, "pause a call",
158                 "'pause' : pause the current call\n"},
159         { "resume", lpc_cmd_resume, "resume a call",
160                 "'resume' : resume the unique call\n"
161                 "'resume <call id>' : hold off the call with given id\n"},
162         { "mute", lpc_cmd_mute_mic, 
163           "Mute microphone and suspend voice transmission."},
164         { "unmute", lpc_cmd_unmute_mic, 
165                   "Unmute microphone and resume voice transmission."},
166         { "duration", lpc_cmd_duration, "Print duration in seconds of the last call.", NULL },
167         
168         { "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
169                 "'autoanswer'       \t: show current autoanswer mode\n"
170                 "'autoanswer enable'\t: enable autoanswer mode\n"
171                 "'autoanswer disable'\t: disable autoanswer modeĀ \n"},
172         { "proxy", lpc_cmd_proxy, "Manage proxies",
173                 "'proxy list' : list all proxy setups.\n"
174                 "'proxy add' : add a new proxy setup.\n"
175                 "'proxy remove <index>' : remove proxy setup with number index.\n"
176                 "'proxy use <index>' : use proxy with number index as default proxy.\n"
177                 "'proxy unuse' : don't use a default proxy.\n"
178                 "'proxy show <index>' : show configuration and status of the proxy numbered by index.\n"
179                 "'proxy show default' : show configuration and status of the default proxy.\n"
180         },
181         { "soundcard", lpc_cmd_soundcard, "Manage soundcards",
182                 "'soundcard list' : list all sound devices.\n"
183                 "'soundcard show' : show current sound devices configuration.\n"
184                 "'soundcard use <index>' : select a sound device.\n"
185                 "'soundcard use files' : use .wav files instead of soundcard\n"
186         },
187         { "webcam", lpc_cmd_webcam, "Manage webcams",
188                 "'webcam list' : list all known devices.\n"
189                 "'webcam use <index>' : select a video device.\n"
190         },
191         { "ipv6", lpc_cmd_ipv6, "Use IPV6",
192                 "'ipv6 status' : show ipv6 usage status.\n"
193                 "'ipv6 enable' : enable the use of the ipv6 network.\n"
194                 "'ipv6 disable' : do not use ipv6 network."
195         },
196         { "transfer", lpc_cmd_transfer,
197                 "Transfer a call to a specified destination.",
198                 "'transfer <sip-uri>' : transfers the current active call to the destination sip-uri"
199                 "'transfer <call id> <sip-uri>': transfers the call with 'id' to the destination sip-uri"
200         },
201         { "nat", lpc_cmd_nat, "Set nat address",
202                 "'nat'        : show nat settings.\n"
203                 "'nat <addr>' : set nat address.\n"
204         },
205         { "stun", lpc_cmd_stun, "Set stun server address",
206                 "'stun'        : show stun settings.\n"
207                 "'stun <addr>' : set stun server address.\n"
208         },
209         { "firewall", lpc_cmd_firewall, "Set firewall policy",
210                 "'firewall'        : show current firewall policy.\n"
211                 "'firewall none'   : use direct connection.\n"
212                 "'firewall nat'    : use nat address given with the 'nat' command.\n"
213                 "'firewall stun'   : use stun server given with the 'stun' command.\n"
214         },
215         { "call-logs", lpc_cmd_call_logs, "Calls history", NULL },
216         { "friend", lpc_cmd_friend, "Manage friends",
217                 "'friend list [<pattern>]'    : list friends.\n"
218                 "'friend call <index>'        : call a friend.\n"
219                 "'friend add <name> <addr>'   : add friend, <name> must be quoted to include\n"
220             "                               spaces, <addr> has \"sip:\" added if it isn't\n"
221             "                               there.  Don't use '<' '>' around <addr>.\n"
222                 "'friend delete <index>'      : remove friend, 'all' removes all\n"
223         },
224         { "play", lpc_cmd_play, "play a wav file",
225                 "This command has two roles:\n"
226                 "Plays a file instead of capturing from soundcard - only available in file mode (see 'help soundcard')\n"
227                 "Specifies a wav file to be played to play music to far end when putting it on hold (pause)\n"
228                 "'play <wav file>'    : play a wav file."
229         },
230         { "record", lpc_cmd_record, "record to a wav file",
231                 "This feature is available only in file mode (see 'help soundcard')\n"
232                 "'record <wav file>'    : record into wav file."
233         },
234         { "quit", lpc_cmd_quit, "Exit linphonec", NULL },
235         { (char *)NULL, (lpc_cmd_handler)NULL, (char *)NULL, (char *)NULL }
236 };
237
238
239 static LPC_COMMAND advanced_commands[] = {
240          { "codec", lpc_cmd_acodec, "Audio codec configuration",
241             "'codec list' : list audio codecs\n"
242             "'codec enable <index>' : enable available audio codec\n"
243             "'codec disable <index>' : disable audio codec" },
244     { "vcodec", lpc_cmd_vcodec, "Video codec configuration",
245             "'vcodec list' : list video codecs\n"
246             "'vcodec enable <index>' : enable available video codec\n"
247             "'vcodec disable <index>' : disable video codec" },
248         { "ec", lpc_cmd_echocancellation, "Echo cancellation",
249             "'ec on [<delay>] [<tail>] [<framesize>]' : turn EC on with given delay, tail length and framesize\n"
250             "'ec off' : turn echo cancellation (EC) off\n"
251             "'ec show' : show EC status" },
252         { "nortp-on-audio-mute", lpc_cmd_rtp_no_xmit_on_audio_mute,
253                   "Set the rtp_no_xmit_on_audio_mute configuration parameter",
254                   "   If set to 1 then rtp transmission will be muted when\n"
255                   "   audio is muted , otherwise rtp is always sent."}, 
256         { "video-window", lpc_cmd_video_window, "Control video display window", NULL },
257         { "register", lpc_cmd_register, "Register in one line to a proxy" , "register <sip identity> <sip proxy> <password>"},
258         { "unregister", lpc_cmd_unregister, "Unregister from default proxy", NULL       },
259         { "status", lpc_cmd_status, "Print various status information", 
260                         "'status register'  \t: print status concerning registration\n"
261                         "'status autoanswer'\t: tell whether autoanswer mode is enabled\n"
262                         "'status hook'      \t: print hook status\n" },
263         { "ports", lpc_cmd_ports, "Network ports configuration", 
264                         "'ports'  \t: prints current used ports.\n"
265                         "'ports sip <port number>'\t: Sets the sip port.\n" },
266         { "speak", lpc_cmd_speak, "Speak a sentence using espeak TTS engine",
267                         "This feature is available only in file mode. (see 'help soundcard')\n"
268                         "'speak <voice name> <sentence>'        : speak a text using the specified espeak voice.\n"
269                         "Example for english voice: 'speak default Hello my friend !'"
270         },
271         { "staticpic", lpc_cmd_staticpic, "Manage static pictures when nowebcam",
272                 "'staticpic set' : Set path to picture that should be used.\n"
273                 "'staticpic fps' : Get/set frames per seconds for picture emission.\n"
274         },
275         {       NULL,NULL,NULL,NULL}
276 };
277
278
279
280 /***************************************************************************
281  *
282  *  Public interface 
283  *
284  ***************************************************************************/
285
286 /*
287  * Main command dispatcher.
288  * WARNING: modifies second argument!
289  *
290  * Always return 1 currently.
291  */
292 int
293 linphonec_parse_command_line(LinphoneCore *lc, char *cl)
294 {
295         char *ptr=cl;
296         char *args=NULL;
297         LPC_COMMAND *cmd;
298
299         /* Isolate first word and args */
300         while(*ptr && !isspace(*ptr)) ++ptr;
301         if (*ptr)
302         {
303                 *ptr='\0';
304                 /* set args to first nonblank */
305                 args=ptr+1;
306                 while(*args && isspace(*args)) ++args;
307         }
308
309         /* Handle DTMF */
310         if ( isdigit(*cl) || *cl == '#' || *cl == '*' )
311         {
312                 while ( isdigit(*cl) || *cl == '#' || *cl == '*' )
313                 {
314                         linphone_core_send_dtmf(lc, *cl);
315                         linphone_core_play_dtmf (lc,*cl,100);
316                         ms_sleep(1); // be nice
317                         ++cl;
318                 }
319
320                 // discard spurious trailing chars
321                 return 1;
322         }
323
324         /* Handle other kind of commands */
325         cmd=lpc_find_command(cl);
326         if ( !cmd )
327         {
328                 linphonec_out("'%s': Cannot understand this.\n", cl);
329                 return 1;
330         }
331
332         if ( ! cmd->func(lc, args) )
333         {
334                 linphonec_out("Syntax error.\n");
335                 linphonec_display_command_help(cmd);
336         }
337
338         return 1;
339 }
340
341 /*
342  * Generator function for command completion.
343  * STATE let us know whether to start from scratch;
344  * without any state (STATE==0), then we start at the
345  * top of the list.
346  */
347 char *
348 linphonec_command_generator(const char *text, int state)
349 {
350         static int index, len, adv;
351         char *name;
352
353         if ( ! state )
354         {
355                 index=0;
356                 adv=0;
357                 len=strlen(text);
358         }
359         /*
360          * Return the next name which partially matches
361          * from the commands list
362          */
363         if (adv==0){
364                 while ((name=commands[index].name))
365                 {
366                         ++index; /* so next call get next command */
367
368                         if (strncmp(name, text, len) == 0)
369                         {
370                                 return ortp_strdup(name);
371                         }
372                 }
373                 adv=1;
374                 index=0;
375         }
376         if (adv==1){
377                 while ((name=advanced_commands[index].name))
378                 {
379                         ++index; /* so next call get next command */
380
381                         if (strncmp(name, text, len) == 0)
382                         {
383                                 return ortp_strdup(name);
384                         }
385                 }
386         }
387         return NULL;
388 }
389
390
391 /***************************************************************************
392  *
393  *  Command handlers 
394  *
395  ***************************************************************************/
396
397 static int
398 lpc_cmd_help(LinphoneCore *lc, char *arg)
399 {
400         int i=0;
401         LPC_COMMAND *cmd;
402
403         if (!arg || !*arg)
404         {
405                 linphonec_out("Commands are:\n");
406                 linphonec_out("---------------------------\n");
407
408                 while (commands[i].help)
409                 {
410                         linphonec_out("%10.10s\t%s\n", commands[i].name,
411                                 commands[i].help);
412                         i++;
413                 }
414                 
415                 linphonec_out("---------------------------\n");
416                 linphonec_out("Type 'help <command>' for more details.\n");
417
418                 return 1;
419         }
420
421         if (strcmp(arg,"advanced")==0){
422                 linphonec_out("Advanced commands are:\n");
423                 linphonec_out("---------------------------\n");
424                 i=0;
425                 while (advanced_commands[i].help)
426                 {
427                         linphonec_out("%10.10s\t%s\n", advanced_commands[i].name,
428                                 advanced_commands[i].help);
429                         i++;
430                 }
431                 
432                 linphonec_out("---------------------------\n");
433                 linphonec_out("Type 'help <command>' for more details.\n");
434
435                 return 1;
436         }
437         
438         cmd=lpc_find_command(arg);
439         if ( !cmd )
440         {
441                 linphonec_out("No such command.\n");
442                 return 1;
443         }
444
445         linphonec_display_command_help(cmd);
446         return 1;
447
448 }
449
450 static char callee_name[256]={0};
451 static char caller_name[256]={0};
452
453 static const char *get_call_status(LinphoneCall *call){
454         switch(linphone_call_get_state(call)){
455                 case LinphoneCallPaused:
456                         if (linphone_call_get_refer_to (call)!=NULL){
457                                 return "Paused (transfered)";
458                         }else{
459                                 return "Paused";
460                         }
461                 break;
462                 case LinphoneCallPausedByRemote:
463                         return "Paused by remote";
464                 break;
465                 case LinphoneCallIncomingReceived:
466                         return "Pending";
467                 break;
468                 case LinphoneCallOutgoingInit:
469                 case LinphoneCallOutgoingProgress:
470                         return "Dialing out";
471                 break;
472                 case LinphoneCallOutgoingEarlyMedia:
473                 case LinphoneCallOutgoingRinging:
474                         return "Remote ringing";
475                 break;
476                 default:
477                         if (linphone_call_has_transfer_pending(call)){
478                                 return "Running (transfer pending)";
479                         }else
480                                 return "Running";
481         }
482         return "";
483 }
484
485 static int
486 lpc_cmd_call(LinphoneCore *lc, char *args)
487 {
488         if ( ! args || ! *args )
489         {
490                 return 0;
491         }
492         {
493                 LinphoneCall *call;
494                 if ( linphone_core_in_call(lc) )
495                 {
496                         linphonec_out("Terminate or hold on the current call first.\n");
497                         return 1;
498                 }
499                 if ( NULL == (call=linphone_core_invite(lc, args)) )
500                 {
501                         linphonec_out("Error from linphone_core_invite.\n");
502                 }
503                 else
504                 {
505                         snprintf(callee_name,sizeof(callee_name),"%s",args);
506                 }
507         }
508         return 1;
509 }
510
511 static int 
512 lpc_cmd_calls(LinphoneCore *lc, char *args){
513         const MSList *calls = linphone_core_get_calls(lc);
514         if(calls)
515         {
516                 const MSList *p_calls = calls;
517                 linphonec_out("ID\t\tDestination\t\t\t\tStatus\n---------------------------------------------------------------------\n");
518                 while(p_calls != NULL)                  
519                 {
520                         LinphoneCall *call=(LinphoneCall*)p_calls->data;
521                         char *tmp=linphone_call_get_remote_address_as_string(call);
522                         linphonec_out("%li\t%s\t\t\t%s\r\n",
523                                                   (long)linphone_call_get_user_pointer (call),
524                                         tmp,
525                                         get_call_status(call));
526                         p_calls = p_calls->next;
527                         ms_free(tmp);
528                 }
529         }else
530         {
531                 linphonec_out("No active call.\n");
532         }
533         return 1;
534 }
535
536
537 static int
538 lpc_cmd_chat(LinphoneCore *lc, char *args)
539 {
540         char *arg1 = args;
541         char *arg2 = NULL;
542         char *ptr = args;
543
544         if (!args) return 0;
545
546         /* Isolate first and second arg */
547         while(*ptr && !isspace(*ptr)) ++ptr;
548         if ( *ptr )
549         {
550                 *ptr='\0';
551                 arg2=ptr+1;
552                 while(*arg2 && isspace(*arg2)) ++arg2;
553         }
554         else
555         {
556                 /* missing one parameter */
557                 return 0;
558         }
559         LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1);
560         linphone_chat_room_send_message(cr,arg2);
561         linphone_chat_room_destroy(cr);
562
563         return 1;
564 }
565
566 const char *linphonec_get_callee(){
567         return callee_name;
568 }
569
570 const char *linphonec_get_caller(){
571         return caller_name;
572 }
573
574 void linphonec_set_caller(const char *caller){
575         snprintf(caller_name,sizeof(caller_name)-1,"%s",caller);
576 }
577
578 static int
579 lpc_cmd_transfer(LinphoneCore *lc, char *args)
580 {
581         if (args){
582                 LinphoneCall *call;
583                 const char *refer_to=NULL;
584                 char arg1[256]={0};
585                 char arg2[266]={0};
586                 int n=sscanf(args,"%s %s",arg1,arg2);
587                 if (n==1 || isalpha(*arg1)){
588                         call=linphone_core_get_current_call(lc);
589                         if (call==NULL && linphone_core_get_calls_nb (lc)==1){
590                                 call=(LinphoneCall*)linphone_core_get_calls(lc)->data;
591                         }
592                         refer_to=args;
593                         if (call==NULL){
594                                 linphonec_out("No active call, please specify a call id among the ones listed by 'calls' command.\n");
595                                 return 0;
596                         }
597                 }else{
598                         long id=atoi(arg1);
599                         refer_to=args+strlen(arg1)+1;
600                         call=linphonec_get_call(id);
601                         if (call==NULL) return 0;
602                 }
603                 linphone_core_transfer_call(lc, call, refer_to);
604         }else{
605                 linphonec_out("Transfer command requires at least one argument\n");
606                 return 0;
607         }
608         return 1;
609 }
610
611 static int
612 lpc_cmd_terminate(LinphoneCore *lc, char *args)
613 {
614         if (linphone_core_get_calls(lc)==NULL){
615                 linphonec_out("No active calls");
616                 return 1;
617         }
618         if (!args)
619         {
620                 if ( -1 == linphone_core_terminate_call(lc, NULL) ){
621                         linphonec_out("Could not stop the active call.\n");
622                 }
623                 return 1;
624         }
625         
626         if(strcmp(args,"all")==0){
627                 linphonec_out("We are going to stop all the calls.\n");
628                 linphone_core_terminate_all_calls(lc);
629                 return 1;
630         }else{
631                 /*the argument is a linphonec call id */
632                 long id=atoi(args);
633                 LinphoneCall *call=linphonec_get_call(id);
634                 if (call){
635                         if (linphone_core_terminate_call(lc,call)==-1){
636                                 linphonec_out("Could not stop the call with id %li",id);
637                         }
638                 }else return 0;
639                 return 1;
640         }
641         return 0;
642         
643 }
644
645 static int
646 lpc_cmd_answer(LinphoneCore *lc, char *args){
647         if (!args)
648         {
649                 int nb=ms_list_size(linphone_core_get_calls(lc));
650                 if (nb==1){
651                         //if just one call is present answer the only one in passing NULL to the linphone_core_accept_call ...
652                         if ( -1 == linphone_core_accept_call(lc, NULL) )
653                         {
654                                 linphonec_out("Fail to accept incoming call\n");
655                         }
656                 }else if (nb==0){
657                         linphonec_out("There are no calls to answer.\n");
658                 }else{
659                         linphonec_out("Multiple calls in progress, please specify call id.\n");
660                         return 0;
661                 }
662                 return 1;
663         }else{
664                 long id;
665                 if (sscanf(args,"%li",&id)==1){
666                         LinphoneCall *call=linphonec_get_call (id);
667                         if (linphone_core_accept_call (lc,call)==-1){
668                                 linphonec_out("Fail to accept call %i\n",id);
669                         }
670                 }else return 0;
671                 return 1;
672         }
673         return 0;
674 }
675
676 static int
677 lpc_cmd_autoanswer(LinphoneCore *lc, char *args)
678 {
679         if ( ! args )
680         {
681                 if ( linphonec_get_autoanswer() ) {
682                         linphonec_out("Auto answer is enabled. Use 'autoanswer disable' to disable.\n");
683                 } else {
684                         linphonec_out("Auto answer is disabled. Use 'autoanswer enable' to enable.\n");
685                 }
686                 return 1;
687         }
688
689         if (strstr(args,"enable")){
690                 linphonec_set_autoanswer(TRUE);
691                 linphonec_out("Auto answer enabled.\n");
692         }else if (strstr(args,"disable")){
693                 linphonec_set_autoanswer(FALSE);
694                 linphonec_out("Auto answer disabled.\n");
695         }else return 0;
696         return 1;
697 }
698
699 static int
700 lpc_cmd_quit(LinphoneCore *lc, char *args)
701 {
702         linphonec_main_loop_exit();
703         return 1;
704 }
705
706 static int
707 lpc_cmd_nat(LinphoneCore *lc, char *args)
708 {
709         bool_t use;
710         const char *nat;
711
712         if ( args ) args=lpc_strip_blanks(args);
713
714         if ( args && *args )
715         {
716                 linphone_core_set_nat_address(lc, args);
717                 /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS); */
718         }
719
720         nat = linphone_core_get_nat_address(lc);
721         use = linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress;
722         linphonec_out("Nat address: %s%s\n", nat ? nat : "unspecified" , use ? "" : " (disabled - use 'firewall nat' to enable)");
723
724         return 1;
725 }
726
727 static int
728 lpc_cmd_stun(LinphoneCore *lc, char *args)
729 {
730         bool_t use;
731         const char *stun;
732
733         if ( args ) args=lpc_strip_blanks(args);
734
735         if ( args && *args )
736         {
737                 linphone_core_set_stun_server(lc, args);
738                 /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN); */
739         }
740
741         stun = linphone_core_get_stun_server(lc);
742         use = linphone_core_get_firewall_policy(lc)==LinphonePolicyUseStun;
743         linphonec_out("Stun server: %s%s\n", stun ? stun : "unspecified" , use? "" : " (disabled - use 'firewall stun' to enable)");
744
745         return 1;
746 }
747
748 static int
749 lpc_cmd_firewall(LinphoneCore *lc, char *args)
750 {
751         const char* setting=NULL;
752
753         if ( args ) args=lpc_strip_blanks(args);
754
755         if ( args && *args )
756         {
757                 if (strcmp(args,"none")==0)
758                 {
759                         linphone_core_set_firewall_policy(lc,LinphonePolicyNoFirewall);
760                 }
761                 else if (strcmp(args,"stun")==0)
762                 {
763                         setting = linphone_core_get_stun_server(lc);
764                         if ( ! setting )
765                         {
766                                 linphonec_out("No stun server address is defined, use 'stun <address>' first\n");
767                                 return 1;
768                         }
769                         linphone_core_set_firewall_policy(lc,LinphonePolicyUseStun);
770                 }
771                 else if (strcmp(args,"nat")==0)
772                 {
773                         setting = linphone_core_get_nat_address(lc);
774                         if ( ! setting )
775                         {
776                                 linphonec_out("No nat address is defined, use 'nat <address>' first");
777                                 return 1;
778                         }
779                         linphone_core_set_firewall_policy(lc,LinphonePolicyUseNatAddress);
780                 }
781         }
782
783         switch(linphone_core_get_firewall_policy(lc))
784         {
785                 case LinphonePolicyNoFirewall:
786                         linphonec_out("No firewall\n");
787                         break;
788                 case LinphonePolicyUseStun:
789                         linphonec_out("Using stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
790                         break;
791                 case LinphonePolicyUseNatAddress:
792                         linphonec_out("Using supplied nat address %s.\n", setting ? setting : linphone_core_get_nat_address(lc));
793                         break;
794         }
795         return 1;
796 }
797
798 #ifndef WIN32
799 /* Helper function for processing freind names */
800 static int
801 lpc_friend_name(char **args, char **name)
802 {
803         /* Use space as a terminator unless quoted */
804         if (('"' == **args) || ('\'' == **args)){
805                 char *end;
806                 char delim = **args;
807                 (*args)++;
808                 end = (*args);
809                 while ((delim != *end) && ('\0' != *end)) end++;
810                 if ('\0' == *end) {
811                         fprintf(stderr, "Mismatched quotes\n");
812                         return 0;
813                 }
814                 *name = *args;
815                 *end = '\0';
816                 *args = ++end;
817         } else {
818                 *name = strsep(args, " ");
819                 
820                 if (NULL == *args) { /* Means there was no separator */
821                         fprintf(stderr, "Either name or address is missing\n");
822                         return 0;
823                 }
824                 if (NULL == *name) return 0;
825         }
826         return 1;
827 }
828 #endif
829
830 static int
831 lpc_cmd_friend(LinphoneCore *lc, char *args)
832 {
833         int friend_num;
834
835         if ( args ) args=lpc_strip_blanks(args);
836
837         if ( ! args || ! *args ) return 0;
838
839         if ( !strncmp(args, "list", 4) )
840         {
841                 return linphonec_friend_list(lc, args+4);
842                 return 1;
843         }
844         else if ( !strncmp(args, "call", 4) )
845         {
846                 args+=4;
847                 if ( ! *args ) return 0;
848                 friend_num = strtol(args, NULL, 10);
849 #ifndef _WIN32_WCE              
850                 if ( errno == ERANGE ) {
851                         linphonec_out("Invalid friend number\n");
852                         return 0;
853                 }
854 #endif /*_WIN32_WCE*/
855                 linphonec_friend_call(lc, friend_num);
856                 return 1;
857         }
858         else if ( !strncmp(args, "delete", 6) )
859         {
860                 args+=6;
861                 if ( ! *args ) return 0;
862                 while (*args == ' ') args++;
863                 if ( ! *args ) return 0;
864                 if (!strncmp(args, "all", 3))
865                 {
866                         friend_num = -1;
867                 } 
868                 else
869                 {
870                         friend_num = strtol(args, NULL, 10);
871 #ifndef _WIN32_WCE              
872                         if ( errno == ERANGE ) {
873                                 linphonec_out("Invalid friend number\n");
874                                 return 0;
875                         }
876 #endif /*_WIN32_WCE*/
877                 }
878                 linphonec_friend_delete(lc, friend_num);
879                 return 1;
880         }
881         else if ( !strncmp(args, "add", 3) )
882         {
883 #ifndef WIN32
884                 char  *name;
885                 char  addr[80];
886                 char *addr_p = addr;
887                 char *addr_orig;
888
889                 args+=3;
890                 if ( ! *args ) return 0;
891                 while (*args == ' ') args++;
892                 if ( ! *args ) return 0;
893
894                 if (!lpc_friend_name(&args,  &name)) return 0;
895
896                 while (*args == ' ') args++;
897                 if ( ! *args ) return 0;
898                 if (isdigit(*args)) {
899                         strcpy (addr, "sip:");
900                         addr_p = addr + strlen("sip:");
901                 }
902                 addr_orig = strsep(&args, " ");
903                 if (1 >= strlen(addr_orig)) {
904                         fprintf(stderr, "A single-digit address is not valid\n");
905                         return 0;
906                 }
907                 strcpy(addr_p, addr_orig);
908                 linphonec_friend_add(lc, name, addr);
909 #else
910                 LinphoneFriend *new_friend;
911                 new_friend = linphone_friend_new_with_addr(args);
912                 linphone_core_add_friend(lc, new_friend);
913 #endif
914                 return 1;
915         }
916         return 0;
917 }
918
919 static int lpc_cmd_play(LinphoneCore *lc, char *args){
920         if ( args ) args=lpc_strip_blanks(args);
921         if ( ! args || ! *args ) return 0;
922         linphone_core_set_play_file(lc,args);
923         return 1;
924 }
925
926 static int lpc_cmd_record(LinphoneCore *lc, char *args){
927         if ( args ) args=lpc_strip_blanks(args);
928         if ( ! args || ! *args ) return 0;
929         linphone_core_set_record_file(lc,args);
930         return 1;
931 }
932
933 /*
934  * Modified input
935  */
936 static int
937 lpc_cmd_proxy(LinphoneCore *lc, char *args)
938 {
939         char *arg1 = args;
940         char *arg2 = NULL;
941         char *ptr = args;
942         int proxynum;
943
944         if ( ! arg1 ) return 0;
945
946         /* Isolate first and second arg */
947         while(*ptr && !isspace(*ptr)) ++ptr;
948         if ( *ptr )
949         {
950                 *ptr='\0';
951                 arg2=ptr+1;
952                 while(*arg2 && isspace(*arg2)) ++arg2;
953         }
954
955         if (strcmp(arg1,"add")==0)
956         {
957 #ifdef HAVE_READLINE
958                 rl_inhibit_completion=1;
959 #endif
960                 linphonec_proxy_add(lc);
961 #ifdef HAVE_READLINE
962                 rl_inhibit_completion=0;
963 #endif
964         }
965         else if (strcmp(arg1,"list")==0)
966         {
967                 linphonec_proxy_list(lc);
968         }
969         else if (strcmp(arg1,"remove")==0)
970         {
971                 linphonec_proxy_remove(lc,atoi(arg2));
972         }
973         else if (strcmp(arg1,"use")==0)
974         {
975                 if ( arg2 && *arg2 )
976                 {
977                         proxynum=atoi(arg2);
978                         if ( linphonec_proxy_use(lc, proxynum) )
979                                 linphonec_out("Default proxy set to %d.\n", proxynum);
980                 }
981                 else
982                 {
983                         proxynum=linphone_core_get_default_proxy(lc, NULL);
984                         if ( proxynum == -1 ) linphonec_out("No default proxy.\n");
985                         else linphonec_out("Current default proxy is %d.\n", proxynum);
986                 }
987         }else if (strcmp(arg1, "unuse")==0){
988                 linphone_core_set_default_proxy(lc, NULL);
989                 linphonec_out("Use no proxy.\n");
990         }
991
992         else if (strcmp(arg1, "show")==0)
993         {
994                 if (arg2 && *arg2)
995                 {
996                         if (strstr(arg2,"default"))
997                         {
998                 proxynum=linphone_core_get_default_proxy(lc, NULL);
999                 if ( proxynum < 0 ) {
1000                         linphonec_out("No default proxy defined\n");
1001                         return 1;
1002                 }
1003                 linphonec_proxy_show(lc,proxynum);
1004                         }
1005                         else
1006                         {
1007                 linphonec_proxy_show(lc, atoi(arg2));
1008                         }
1009                 }
1010                 else return 0; /* syntax error */
1011         }
1012
1013         else
1014         {
1015                 return 0; /* syntax error */
1016         }
1017
1018         return 1;
1019 }
1020
1021 static int
1022 lpc_cmd_call_logs(LinphoneCore *lc, char *args)
1023 {
1024         const MSList *elem=linphone_core_get_call_logs(lc);
1025         for (;elem!=NULL;elem=ms_list_next(elem))
1026         {
1027                 LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
1028                 char *str=linphone_call_log_to_str(cl);
1029                 linphonec_out("%s\n",str);
1030                 ms_free(str);
1031         }
1032         return 1;
1033 }
1034
1035 static int
1036 lpc_cmd_ipv6(LinphoneCore *lc, char *arg1)
1037 {
1038         if ( ! arg1 )
1039         {
1040                 return 0; /* syntax error */
1041         }
1042
1043         if (strcmp(arg1,"status")==0)
1044         {
1045                 linphonec_out("ipv6 use enabled: %s\n",linphone_core_ipv6_enabled(lc) ? "true":"false");
1046         }
1047         else if (strcmp(arg1,"enable")==0)
1048         {
1049                 linphone_core_enable_ipv6(lc,TRUE);
1050                 linphonec_out("ipv6 use enabled.\n");
1051         }
1052         else if (strcmp(arg1,"disable")==0)
1053         {
1054                 linphone_core_enable_ipv6(lc,FALSE);
1055                 linphonec_out("ipv6 use disabled.\n");
1056         }
1057         else
1058         {
1059                 return 0; /* syntax error */
1060         }
1061         return 1;
1062 }
1063
1064 static int devname_to_index(LinphoneCore *lc, const char *devname){
1065         const char **p;
1066         int i;
1067         for(i=0,p=linphone_core_get_sound_devices(lc);*p!=NULL;++p,++i){
1068                 if (strcmp(devname,*p)==0) return i;
1069         }
1070         return -1;
1071 }
1072
1073 static const char *index_to_devname(LinphoneCore *lc, int index){
1074         const char **p;
1075         int i;
1076         for(i=0,p=linphone_core_get_sound_devices(lc);*p!=NULL;++p,++i){
1077                 if (i==index) return *p;
1078         }
1079         return NULL;
1080 }
1081
1082 static int lpc_cmd_soundcard(LinphoneCore *lc, char *args)
1083 {
1084         int i, index;
1085         const char **dev;
1086         char *arg1 = args;
1087         char *arg2 = NULL;
1088         char *ptr = args;
1089
1090         if (!args) return 0; /* syntax error */
1091
1092         /* Isolate first and second arg */
1093         while(*ptr && !isspace(*ptr)) ++ptr;
1094         if ( *ptr )
1095         {
1096                 *ptr='\0';
1097                 arg2=ptr+1;
1098                 while(*arg2 && isspace(*arg2)) ++arg2;
1099         }
1100
1101         if (strcmp(arg1, "list")==0)
1102         {
1103                 dev=linphone_core_get_sound_devices(lc);
1104                 for(i=0; dev[i]!=NULL; ++i){
1105                         linphonec_out("%i: %s\n",i,dev[i]);
1106                 }
1107                 return 1;
1108         }
1109
1110         if (strcmp(arg1, "show")==0)
1111         {
1112                 linphonec_out("Ringer device: %s\n",
1113                         linphone_core_get_ringer_device(lc));
1114                 linphonec_out("Playback device: %s\n",
1115                         linphone_core_get_playback_device(lc));
1116                 linphonec_out("Capture device: %s\n",
1117                         linphone_core_get_capture_device(lc));
1118                 return 1;
1119         }
1120
1121         if (strcmp(arg1, "use")==0 && arg2)
1122         {
1123                 if (strcmp(arg2, "files")==0)
1124                 {
1125                         linphonec_out("Using wav files instead of soundcard.\n");
1126                         linphone_core_use_files(lc,TRUE);
1127                         return 1;
1128                 }
1129
1130                 dev=linphone_core_get_sound_devices(lc);
1131                 index=atoi(arg2); /* FIXME: handle not-a-number */
1132                 for(i=0;dev[i]!=NULL;i++)
1133                 {
1134                         if (i!=index) continue;
1135
1136                         linphone_core_set_ringer_device(lc,dev[i]);
1137                         linphone_core_set_playback_device(lc,dev[i]);
1138                         linphone_core_set_capture_device(lc,dev[i]);
1139                         linphonec_out("Using sound device %s\n",dev[i]);
1140                         return 1;
1141                 }
1142                 linphonec_out("No such sound device\n");
1143                 return 1;
1144         }
1145         if (strcmp(arg1, "capture")==0)
1146         {
1147                 const char *devname=linphone_core_get_capture_device(lc);
1148                 if (!arg2){
1149                         linphonec_out("Using capture device #%i (%s)\n",
1150                                         devname_to_index(lc,devname),devname);
1151                 }else{
1152                         index=atoi(arg2); /* FIXME: handle not-a-number */
1153                         devname=index_to_devname(lc,index);
1154                         if (devname!=NULL){
1155                                 linphone_core_set_capture_device(lc,devname);
1156                                 linphonec_out("Using capture sound device %s\n",devname);
1157                                 return 1;
1158                         }
1159                         linphonec_out("No such sound device\n");
1160                 }
1161                 return 1;
1162         }
1163         if (strcmp(arg1, "playback")==0)
1164         {
1165                 const char *devname=linphone_core_get_playback_device(lc);
1166                 if (!arg2){
1167                         linphonec_out("Using playback device #%i (%s)\n",
1168                                         devname_to_index(lc,devname),devname);
1169                 }else{
1170                         index=atoi(arg2); /* FIXME: handle not-a-number */
1171                         devname=index_to_devname(lc,index);
1172                         if (devname!=NULL){
1173                                 linphone_core_set_playback_device(lc,devname);
1174                                 linphonec_out("Using playback sound device %s\n",devname);
1175                                 return 1;
1176                         }
1177                         linphonec_out("No such sound device\n");
1178                 }
1179                 return 1;
1180         }
1181         if (strcmp(arg1, "ring")==0)
1182         {
1183                 const char *devname=linphone_core_get_ringer_device(lc);
1184                 if (!arg2){
1185                         linphonec_out("Using ring device #%i (%s)\n",
1186                                         devname_to_index(lc,devname),devname);
1187                 }else{
1188                         index=atoi(arg2); /* FIXME: handle not-a-number */
1189                         devname=index_to_devname(lc,index);
1190                         if (devname!=NULL){
1191                                 linphone_core_set_ringer_device(lc,devname);
1192                                 linphonec_out("Using ring sound device %s\n",devname);
1193                                 return 1;
1194                         }
1195                         linphonec_out("No such sound device\n");
1196                 }
1197                 return 1;
1198         }
1199         return 0; /* syntax error */
1200 }
1201
1202 static int lpc_cmd_webcam(LinphoneCore *lc, char *args)
1203 {
1204         int i, index;
1205         const char **dev;
1206         char *arg1 = args;
1207         char *arg2 = NULL;
1208         char *ptr = args;
1209
1210         if (!args) return 0; /* syntax error */
1211
1212         /* Isolate first and second arg */
1213         while(*ptr && !isspace(*ptr)) ++ptr;
1214         if ( *ptr )
1215         {
1216                 *ptr='\0';
1217                 arg2=ptr+1;
1218                 while(*arg2 && isspace(*arg2)) ++arg2;
1219         }
1220
1221         if (strcmp(arg1, "list")==0)
1222         {
1223                 dev=linphone_core_get_video_devices(lc);
1224                 for(i=0; dev[i]!=NULL; ++i){
1225                         linphonec_out("%i: %s\n",i,dev[i]);
1226                 }
1227                 return 1;
1228         }
1229
1230         if (strcmp(arg1, "use")==0 && arg2)
1231         {
1232                 dev=linphone_core_get_video_devices(lc);
1233                 index=atoi(arg2); /* FIXME: handle not-a-number */
1234                 for(i=0;dev[i]!=NULL;i++)
1235                 {
1236                         if (i!=index) continue;
1237
1238                         linphone_core_set_video_device(lc, dev[i]);
1239                         linphonec_out("Using video device %s\n",dev[i]);
1240                         return 1;
1241                 }
1242                 linphonec_out("No such video device\n");
1243                 return 1;
1244         }
1245         return 0; /* syntax error */
1246 }
1247
1248 static int
1249 lpc_cmd_staticpic(LinphoneCore *lc, char *args)
1250 {
1251         char *arg1 = args;
1252         char *arg2 = NULL;
1253         char *ptr = args;
1254
1255         if (!args) return 0;  /* Syntax error */
1256
1257         /* Isolate first and second arg */
1258         while(*ptr && !isspace(*ptr)) ++ptr;
1259         if ( *ptr )
1260         {
1261                 *ptr='\0';
1262                 arg2=ptr+1;
1263                 while(*arg2 && isspace(*arg2)) ++arg2;
1264         }
1265
1266         if (strcmp(arg1, "set")==0 && arg2) {
1267                 linphone_core_set_static_picture(lc, arg2);
1268                 return 1;
1269         }
1270
1271         if (strcmp(arg1, "fps")==0) {
1272           if (arg2) {
1273                 float fps = atof(arg2); /* FIXME: Handle not-a-float */
1274                 linphone_core_set_static_picture_fps(lc, fps);
1275                 return 1;
1276           } else {
1277                 float fps;
1278                 fps = linphone_core_get_static_picture_fps(lc);
1279                 linphonec_out("Current FPS %f\n", fps);
1280                 return 1;
1281           }
1282         }
1283
1284         return 0; /* Syntax error */
1285 }
1286
1287 static int lpc_cmd_pause(LinphoneCore *lc, char *args){
1288
1289         if(linphone_core_in_call(lc))
1290         {
1291                 linphone_core_pause_call(lc,linphone_core_get_current_call(lc));
1292                 return 1;
1293         }
1294         linphonec_out("you can only pause when a call is in process\n");
1295     return 0;
1296 }
1297
1298 static int lpc_cmd_resume(LinphoneCore *lc, char *args){
1299         
1300         if(linphone_core_in_call(lc))
1301         {
1302                 linphonec_out("There is already a call in process pause or stop it first");
1303                 return 1;
1304         }
1305         if (args)
1306         {
1307                 long id;
1308                 int n = sscanf(args, "%li", &id);
1309                 if (n == 1){
1310                         LinphoneCall *call=linphonec_get_call (id);
1311                         if (call){
1312                                 if(linphone_core_resume_call(lc,call)==-1){
1313                                         linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args);
1314                                 }
1315                         }
1316                         return 1;
1317                 }else return 0;
1318         }
1319         else
1320         {
1321                 const MSList *calls = linphone_core_get_calls(lc);
1322                 int nbcalls=ms_list_size(calls);
1323                 if( nbcalls == 1)
1324                 {
1325                         if(linphone_core_resume_call(lc,calls->data) < 0)
1326                         {
1327                                 linphonec_out("There was a problem to resume the unique call.\n");
1328                         }
1329                         return 1;
1330                 }else if (nbcalls==0){
1331                         linphonec_out("There is no calls at this time.\n");
1332                         return 1;
1333                 }else{
1334                         linphonec_out("There are %i calls at this time, please specify call id as given with 'calls' command.\n");
1335                 }
1336         }
1337         return 0;
1338     
1339 }
1340
1341 /***************************************************************************
1342  *
1343  *  Commands helper functions
1344  *
1345  ***************************************************************************/
1346
1347
1348 static void
1349 linphonec_proxy_add(LinphoneCore *lc)
1350 {
1351         bool_t enable_register=FALSE;
1352         LinphoneProxyConfig *cfg;
1353
1354         linphonec_out("Adding new proxy setup. Hit ^D to abort.\n");
1355
1356         /*
1357          * SIP Proxy address
1358          */
1359         while (1)
1360         {
1361                 char *input=linphonec_readline("Enter proxy sip address: ");
1362                 char *clean;
1363
1364                 if ( ! input ) {
1365                         linphonec_out("Aborted.\n");
1366                         return;
1367                 }
1368
1369                 /* Strip blanks */
1370                 clean=lpc_strip_blanks(input);
1371                 if ( ! *clean ) {
1372                         free(input);
1373                         continue;
1374                 }
1375
1376                 cfg=linphone_proxy_config_new();
1377                 if (linphone_proxy_config_set_server_addr(cfg,clean)<0)
1378                 {
1379                         linphonec_out("Invalid sip address (sip:sip.domain.tld).\n");
1380                         free(input);
1381                         linphone_proxy_config_destroy(cfg);
1382                         continue;
1383                 }
1384                 free(input);
1385                 break;
1386         }
1387
1388         /*
1389          * SIP Proxy identity
1390          */
1391         while (1)
1392         {
1393                 char *input=linphonec_readline("Your identity for this proxy: ");
1394                 char *clean;
1395
1396                 if ( ! input ) {
1397                         linphonec_out("Aborted.\n");
1398                         linphone_proxy_config_destroy(cfg);
1399                         return;
1400                 }
1401
1402                 /* Strip blanks */
1403                 clean=lpc_strip_blanks(input);
1404                 if ( ! *clean ) {
1405                         free(input);
1406                         continue;
1407                 }
1408
1409                 linphone_proxy_config_set_identity(cfg, clean);
1410                 if ( ! cfg->reg_identity )
1411                 {
1412                         linphonec_out("Invalid identity (sip:name@sip.domain.tld).\n");
1413                         free(input);
1414                         continue;
1415                 }
1416                 free(input);
1417                 break;
1418         }
1419
1420         /*
1421          * SIP Proxy enable register
1422          */
1423         while (1)
1424         {
1425                 char *input=linphonec_readline("Do you want to register on this proxy (yes/no): ");
1426                 char *clean;
1427
1428                 if ( ! input ) {
1429                         linphonec_out("Aborted.\n");
1430                         linphone_proxy_config_destroy(cfg);
1431                         return;
1432                 }
1433
1434                 /* Strip blanks */
1435                 clean=lpc_strip_blanks(input);
1436                 if ( ! *clean ) {
1437                         free(input);
1438                         continue;
1439                 }
1440
1441                 if ( ! strcmp(clean, "yes") ) enable_register=TRUE;
1442                 else if ( ! strcmp(clean, "no") ) enable_register=FALSE;
1443                 else {
1444                         linphonec_out("Please answer with 'yes' or 'no'\n");
1445                         free(input);
1446                         continue;
1447                 }
1448                 linphone_proxy_config_enableregister(cfg, enable_register);
1449                 free(input);
1450                 break;
1451         }
1452
1453         /*
1454          * SIP Proxy registration expiration
1455          */
1456         if ( enable_register==TRUE )
1457         {
1458                 long int expires=0;
1459                 while (1)
1460                 {
1461                         char *input=linphonec_readline("Specify register expiration time"
1462                                 " in seconds (default is 600): ");
1463
1464                         if ( ! input ) {
1465                                 linphonec_out("Aborted.\n");
1466                                 linphone_proxy_config_destroy(cfg);
1467                                 return;
1468                         }
1469
1470                         expires=strtol(input, (char **)NULL, 10);
1471                         if ( expires == LONG_MIN || expires == LONG_MAX )
1472                         {
1473                                 linphonec_out("Invalid value: %s\n", strerror(errno));
1474                                 free(input);
1475                                 continue;
1476                         }
1477
1478                         linphone_proxy_config_expires(cfg, expires);
1479                         linphonec_out("Expiration: %d seconds\n", cfg->expires);
1480
1481                         free(input);
1482                         break;
1483                 }
1484         }
1485
1486         /*
1487          * SIP proxy route
1488          */
1489         while (1)
1490         {
1491                 char *input=linphonec_readline("Specify route if needed: ");
1492                 char *clean;
1493
1494                 if ( ! input ) {
1495                         linphonec_out("Aborted.\n");
1496                         linphone_proxy_config_destroy(cfg);
1497                         return;
1498                 }
1499
1500                 /* Strip blanks */
1501                 clean=lpc_strip_blanks(input);
1502                 if ( ! *clean ) {
1503                         free(input);
1504                         linphonec_out("No route specified.\n");
1505                         break;
1506                 }
1507
1508                 linphone_proxy_config_set_route(cfg, clean);
1509                 if ( ! cfg->reg_route )
1510                 {
1511                         linphonec_out("Invalid route.\n");
1512                         free(input);
1513                         continue;
1514                 }
1515
1516                 free(input);
1517                 break;
1518         }
1519
1520         /*
1521          * Final confirmation 
1522          */
1523         while (1)
1524         {
1525                 char *input;
1526                 char *clean;
1527
1528                 linphonec_out("--------------------------------------------\n");
1529                 linphonec_proxy_display(cfg);
1530                 linphonec_out("--------------------------------------------\n");
1531                 input=linphonec_readline("Accept the above proxy configuration (yes/no) ?: ");
1532
1533
1534                 if ( ! input ) {
1535                         linphonec_out("Aborted.\n");
1536                         linphone_proxy_config_destroy(cfg);
1537                         return;
1538                 }
1539
1540                 /* Strip blanks */
1541                 clean=lpc_strip_blanks(input);
1542                 if ( ! *clean ) {
1543                         free(input);
1544                         continue;
1545                 }
1546
1547                 if ( ! strcmp(clean, "yes") ) break;
1548                 else if ( ! strcmp(clean, "no") )
1549                 {
1550                         linphonec_out("Declined.\n");
1551                         linphone_proxy_config_destroy(cfg);
1552                         free(input);
1553                         return;
1554                 }
1555
1556                 linphonec_out("Please answer with 'yes' or 'no'\n");
1557                 free(input);
1558                 continue;
1559         }
1560
1561
1562         linphone_core_add_proxy_config(lc,cfg);
1563
1564         /* automatically set the last entered proxy as the default one */
1565         linphone_core_set_default_proxy(lc,cfg);
1566
1567         linphonec_out("Proxy added.\n");
1568 }
1569
1570 static void
1571 linphonec_proxy_display(LinphoneProxyConfig *cfg)
1572 {
1573         linphonec_out("sip address: %s\nroute: %s\nidentity: %s\nregister: %s\nexpires: %i\nregistered: %s\n",
1574                         cfg->reg_proxy,
1575                         (cfg->reg_route!=NULL)?cfg->reg_route:"",
1576                         (cfg->reg_identity!=NULL)?cfg->reg_identity:"",
1577                         (cfg->reg_sendregister)?"yes":"no",
1578                         cfg->expires,
1579                         linphone_proxy_config_is_registered(cfg) ? "yes" : "no");
1580 }
1581
1582 static void linphonec_proxy_show(LinphoneCore *lc, int index)
1583 {
1584         const MSList *elem;
1585         int i;
1586         for(elem=linphone_core_get_proxy_config_list(lc),i=0;elem!=NULL;elem=elem->next,++i){
1587                 if (index==i){
1588                         LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)elem->data;
1589                         linphonec_proxy_display(cfg);
1590                         return;
1591                 }
1592         }
1593         linphonec_out("No proxy with index %i\n", index);
1594 }
1595
1596 static void
1597 linphonec_proxy_list(LinphoneCore *lc)
1598 {
1599         const MSList *proxies;
1600         int n;
1601         int def=linphone_core_get_default_proxy(lc,NULL);
1602         
1603         proxies=linphone_core_get_proxy_config_list(lc);
1604         for(n=0;proxies!=NULL;proxies=ms_list_next(proxies),n++){
1605                 if (n==def)
1606                         linphonec_out("****** Proxy %i - this is the default one - *******\n",n);
1607                 else 
1608                         linphonec_out("****** Proxy %i *******\n",n);
1609                 linphonec_proxy_display((LinphoneProxyConfig*)proxies->data);
1610         }
1611         if ( ! n ) linphonec_out("No proxies defined\n");
1612 }
1613
1614 static void
1615 linphonec_proxy_remove(LinphoneCore *lc, int index)
1616 {
1617         const MSList *proxies;
1618         LinphoneProxyConfig *cfg;
1619         proxies=linphone_core_get_proxy_config_list(lc);
1620         cfg=(LinphoneProxyConfig*)ms_list_nth_data(proxies,index);
1621         if (cfg==NULL){
1622                 linphonec_out("No such proxy.\n");
1623                 return;
1624         }
1625         linphone_core_remove_proxy_config(lc,cfg);
1626         linphonec_out("Proxy %s removed.\n", cfg->reg_proxy);
1627         linphone_proxy_config_destroy(cfg);
1628 }
1629
1630 static int
1631 linphonec_proxy_use(LinphoneCore *lc, int index)
1632 {
1633         const MSList *proxies;
1634         LinphoneProxyConfig *cfg;
1635         proxies=linphone_core_get_proxy_config_list(lc);
1636         cfg=(LinphoneProxyConfig*)ms_list_nth_data(proxies,index);
1637         if (cfg==NULL){
1638                 linphonec_out("No such proxy (try 'proxy list').");
1639                 return 0;
1640         }
1641         linphone_core_set_default_proxy(lc,cfg);
1642         return 1;
1643 }
1644
1645 static void
1646 linphonec_friend_display(LinphoneFriend *fr)
1647 {
1648         LinphoneAddress *uri=linphone_address_clone(linphone_friend_get_address(fr));
1649         char *str;
1650         
1651         linphonec_out("name: %s\n", linphone_address_get_display_name(uri));
1652         linphone_address_set_display_name(uri,NULL);
1653         str=linphone_address_as_string(uri);
1654         linphonec_out("address: %s\n", str);
1655 }
1656
1657 static int
1658 linphonec_friend_list(LinphoneCore *lc, char *pat)
1659 {
1660         const MSList *friend;
1661         int n;
1662
1663         if (pat) {
1664                 pat=lpc_strip_blanks(pat);
1665                 if (!*pat) pat = NULL;
1666         }
1667
1668         friend = linphone_core_get_friend_list(lc);
1669         for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1670         {
1671                 if ( pat ) {
1672                         const char *name = linphone_address_get_display_name(
1673                             linphone_friend_get_address((LinphoneFriend*)friend->data));
1674                         if (name && ! strstr(name, pat) ) continue;
1675                 }
1676                 linphonec_out("****** Friend %i *******\n",n);
1677                 linphonec_friend_display((LinphoneFriend*)friend->data);
1678         }
1679
1680         return 1;
1681 }
1682
1683 static int
1684 linphonec_friend_call(LinphoneCore *lc, unsigned int num)
1685 {
1686         const MSList *friend = linphone_core_get_friend_list(lc);
1687         unsigned int n;
1688         char *addr;
1689
1690         for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1691         {
1692                 if ( n == num )
1693                 {
1694                         int ret;
1695                         addr = linphone_address_as_string(linphone_friend_get_address((LinphoneFriend*)friend->data));
1696                         ret=lpc_cmd_call(lc, addr);
1697                         ms_free(addr);
1698                         return ret;
1699                 }
1700         }
1701         linphonec_out("No such friend %u\n", num);
1702         return 1;
1703 }
1704
1705 #ifndef WIN32
1706 static int
1707 linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr)
1708 {
1709         LinphoneFriend *newFriend;
1710
1711         char url[PATH_MAX];
1712
1713         snprintf(url, PATH_MAX, "%s <%s>", name, addr);
1714         newFriend = linphone_friend_new_with_addr(url);
1715         linphone_core_add_friend(lc, newFriend);
1716         return 0;
1717 }
1718 #endif
1719
1720 static int
1721 linphonec_friend_delete(LinphoneCore *lc, int num)
1722 {
1723         const MSList *friend = linphone_core_get_friend_list(lc);
1724         unsigned int n;
1725
1726         for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1727         {
1728                 if ( n == num )
1729                 {
1730                         linphone_core_remove_friend(lc, friend->data);
1731                         return 0;
1732                 }
1733         }
1734
1735         if (-1 == num) 
1736         {
1737                 unsigned int i;
1738                 for (i = 0 ; i < n ; i++)
1739                         linphonec_friend_delete(lc, 0);
1740                 return 0;
1741         }
1742
1743         linphonec_out("No such friend %u\n", num);
1744         return 1;
1745 }
1746
1747 static void
1748 linphonec_display_command_help(LPC_COMMAND *cmd)
1749 {
1750         if ( cmd->doc ) linphonec_out ("%s\n", cmd->doc);
1751         else linphonec_out("%s\n", cmd->help);
1752 }
1753
1754
1755 static int lpc_cmd_register(LinphoneCore *lc, char *args){
1756         char identity[512];
1757         char proxy[512];
1758         char passwd[512];
1759         LinphoneProxyConfig *cfg;
1760         const MSList *elem;
1761     
1762         if (!args)
1763         {
1764                 /* it means that you want to register the default proxy */
1765                 LinphoneProxyConfig *cfg=NULL;
1766                 linphone_core_get_default_proxy(lc,&cfg);
1767                 if (cfg)
1768                 {
1769                         if(!linphone_proxy_config_is_registered(cfg)) {
1770                                 linphone_proxy_config_enable_register(cfg,TRUE);
1771                                 linphone_proxy_config_done(cfg);
1772                         }else{
1773                                 linphonec_out("default proxy already registered\n");
1774                         }
1775                 }else{
1776                         linphonec_out("we do not have a default proxy\n");
1777                         return 0;
1778                 }
1779                 return 1;
1780         }
1781         passwd[0]=proxy[0]=identity[0]='\0';
1782         sscanf(args,"%s %s %s",identity,proxy,passwd);
1783         if (proxy[0]=='\0' || identity[0]=='\0'){
1784                 linphonec_out("Missing parameters, see help register\n");
1785                 return 1;
1786         }
1787         if (passwd[0]!='\0'){
1788                 LinphoneAddress *from;
1789                 LinphoneAuthInfo *info;
1790                 if ((from=linphone_address_new(identity))!=NULL){
1791                         char realm[128];
1792                         snprintf(realm,sizeof(realm)-1,"\"%s\"",linphone_address_get_domain(from));
1793                         info=linphone_auth_info_new(linphone_address_get_username(from),NULL,passwd,NULL,NULL);
1794                         linphone_core_add_auth_info(lc,info);
1795                         linphone_address_destroy(from);
1796                         linphone_auth_info_destroy(info);
1797                 }
1798         }
1799         elem=linphone_core_get_proxy_config_list(lc);
1800         if (elem) {
1801                 cfg=(LinphoneProxyConfig*)elem->data;
1802                 linphone_proxy_config_edit(cfg);
1803         }
1804         else cfg=linphone_proxy_config_new();
1805         linphone_proxy_config_set_identity(cfg,identity);
1806         linphone_proxy_config_set_server_addr(cfg,proxy);
1807         linphone_proxy_config_enable_register(cfg,TRUE);
1808         if (elem) linphone_proxy_config_done(cfg);
1809         else linphone_core_add_proxy_config(lc,cfg);
1810         linphone_core_set_default_proxy(lc,cfg);
1811         return 1;
1812 }
1813
1814 static int lpc_cmd_unregister(LinphoneCore *lc, char *args){
1815         LinphoneProxyConfig *cfg=NULL;
1816         linphone_core_get_default_proxy(lc,&cfg);
1817         if (cfg && linphone_proxy_config_is_registered(cfg)) {
1818                 linphone_proxy_config_edit(cfg);
1819                 linphone_proxy_config_enable_register(cfg,FALSE);
1820                 linphone_proxy_config_done(cfg);
1821         }else{
1822                 linphonec_out("unregistered\n");
1823         }
1824         return 1;
1825 }
1826
1827 static int lpc_cmd_duration(LinphoneCore *lc, char *args){
1828         LinphoneCallLog *cl;
1829         const MSList *elem=linphone_core_get_call_logs(lc);
1830         for(;elem!=NULL;elem=elem->next){
1831                 if (elem->next==NULL){
1832                         cl=(LinphoneCallLog*)elem->data;
1833                         linphonec_out("%i seconds\n",cl->duration);
1834                 }
1835         }
1836         return 1;
1837 }
1838
1839 static int lpc_cmd_status(LinphoneCore *lc, char *args)
1840 {
1841         LinphoneProxyConfig *cfg;
1842         
1843         if ( ! args ) return 0;
1844         linphone_core_get_default_proxy(lc,&cfg);
1845         if (strstr(args,"register"))
1846         {
1847                 if (cfg)
1848                 {
1849                         if (linphone_proxy_config_is_registered(cfg)){
1850                                 linphonec_out("registered, identity=%s duration=%i\n",
1851                                         linphone_proxy_config_get_identity(cfg),
1852                                         linphone_proxy_config_get_expires(cfg));
1853                         }else if (linphone_proxy_config_register_enabled(cfg)){
1854                                 linphonec_out("registered=-1\n");
1855                         }else linphonec_out("registered=0\n");
1856                 }
1857                 else linphonec_out("registered=0\n");
1858         }
1859         else if (strstr(args,"autoanswer"))
1860         {
1861                 if (cfg && linphone_proxy_config_is_registered(cfg))
1862                         linphonec_out("autoanswer=%i\n",linphonec_get_autoanswer());
1863                 else linphonec_out("unregistered\n");
1864         }
1865         else if (strstr(args,"hook"))
1866         {
1867                 LinphoneCall *call=linphone_core_get_current_call (lc);
1868                 LinphoneCallState call_state=LinphoneCallIdle;
1869                 if (call) call_state=linphone_call_get_state(call);
1870
1871                 switch(call_state){
1872                         case LinphoneCallOutgoingInit:
1873                         case LinphoneCallOutgoingProgress:
1874                                 linphonec_out("hook=dialing\n");
1875                         break;
1876                         case LinphoneCallIdle:
1877                                 linphonec_out("hook=offhook\n");
1878                         break;
1879                         case LinphoneCallStreamsRunning:
1880                         case LinphoneCallConnected:
1881                                 if (linphone_call_get_dir(call)==LinphoneCallOutgoing){
1882                                         linphonec_out("Call out, hook=%s duration=%i, muted=%s rtp-xmit-muted=%s\n", linphonec_get_callee(),
1883                                               linphone_core_get_current_call_duration(lc),
1884                                               linphone_core_is_mic_muted (lc) ? "yes" : "no",
1885                                               linphone_core_is_rtp_muted(lc) ? "yes"  : "no");
1886                                 }else{
1887                                         linphonec_out("hook=answered duration=%i\n" ,
1888                                                 linphone_core_get_current_call_duration(lc));
1889                                 }
1890                                 break;
1891                         case LinphoneCallIncomingReceived:
1892                                 linphonec_out("Incoming call from %s\n",linphonec_get_caller());
1893                                 break;
1894                         default:
1895                                 break;
1896                 }
1897                 
1898         }
1899         else return 0;
1900
1901         return 1;
1902 }
1903
1904 static int lpc_cmd_ports(LinphoneCore *lc, char *args)
1905 {
1906         int port;
1907         if ( ! args ){
1908                 linphonec_out("sip port = %i\naudio rtp port = %i\nvideo rtp port = %i\n",
1909                         linphone_core_get_sip_port(lc),
1910                         linphone_core_get_audio_port(lc),
1911                         linphone_core_get_video_port(lc));
1912                 return 1;
1913         }
1914         if (sscanf(args,"sip %i",&port)==1){
1915                 linphonec_out("Setting sip port to %i\n",port);
1916                 linphone_core_set_sip_port(lc,port);
1917         }else return 0;
1918
1919         return 1;
1920 }
1921
1922 static int lpc_cmd_speak(LinphoneCore *lc, char *args){
1923 #ifndef WIN32
1924         char voice[64];
1925         char *sentence;
1926         char cl[128];
1927         char *wavfile;
1928         int status;
1929         FILE *file;
1930         
1931     if (!args) return 0;
1932         memset(voice,0,sizeof(voice));
1933         sscanf(args,"%s63",voice);
1934         sentence=args+strlen(voice);
1935         wavfile=tempnam("/tmp/","linphonec-espeak-");
1936         snprintf(cl,sizeof(cl),"espeak -v %s -s 100 -w %s --stdin",voice,wavfile);
1937         file=popen(cl,"w");
1938         if (file==NULL){
1939                 ms_error("Could not open pipe to espeak !");
1940                 return 1;
1941         }
1942         fprintf(file,"%s",sentence);
1943         status=pclose(file);
1944         if (WEXITSTATUS(status)==0){
1945                 linphone_core_set_play_file(lc,wavfile);
1946         }else{
1947                 linphonec_out("espeak command failed.");
1948         }
1949 #else
1950         linphonec_out("Sorry, this command is not implemented in windows version.");
1951 #endif
1952         return 1;
1953 }
1954
1955 static int lpc_cmd_acodec(LinphoneCore *lc, char *args){
1956     return lpc_cmd_codec(AUDIO, lc, args);
1957 }
1958
1959 static int lpc_cmd_vcodec(LinphoneCore *lc, char *args){
1960     return lpc_cmd_codec(VIDEO, lc, args);
1961 }
1962
1963 static int lpc_cmd_codec(int type, LinphoneCore *lc, char *args){
1964         char *arg1 = args;
1965         char *arg2 = NULL;
1966         char *ptr = args;
1967
1968         if (!args) return 0;
1969
1970         /* Isolate first and second arg */
1971         while(*ptr && !isspace(*ptr)) ++ptr;
1972         if ( *ptr )
1973         {
1974                 *ptr='\0';
1975                 arg2=ptr+1;
1976                 while(*arg2 && isspace(*arg2)) ++arg2;
1977         }
1978
1979         if (strcmp(arg1,"enable")==0)
1980         {
1981 #ifdef HAVE_READLINE
1982                 rl_inhibit_completion=1;
1983 #endif
1984         if (!strcmp(arg2,"all")) linphonec_codec_enable(type,lc,-1);
1985         else linphonec_codec_enable(type,lc,atoi(arg2));
1986 #ifdef HAVE_READLINE
1987                 rl_inhibit_completion=0;
1988 #endif
1989         }
1990         else if (strcmp(arg1,"list")==0)
1991         {
1992                 linphonec_codec_list(type,lc);
1993         }
1994         else if (strcmp(arg1,"disable")==0)
1995         {
1996         if (!strcmp(arg2,"all")) linphonec_codec_disable(type,lc,-1);
1997         else linphonec_codec_disable(type,lc,atoi(arg2));
1998         }
1999         else
2000         {
2001                 return 0; /* syntax error */
2002         }
2003
2004         return 1;
2005 }
2006
2007 static void linphonec_codec_list(int type, LinphoneCore *lc){
2008         PayloadType *pt;
2009     codecs_config_t *config=&lc->codecs_conf;
2010         int index=0;
2011         MSList *node=NULL;
2012
2013     if (type == AUDIO) {
2014       node=config->audio_codecs;
2015     } else if(type==VIDEO) {
2016       node=config->video_codecs;
2017     }
2018
2019         for(;node!=NULL;node=ms_list_next(node)){
2020                 pt=(PayloadType*)(node->data);
2021         linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, 
2022                     linphone_core_payload_type_enabled(lc,pt) ? "enabled" : "disabled");
2023                 index++;
2024         }
2025 }
2026
2027 static void linphonec_codec_enable(int type, LinphoneCore *lc, int sel_index){
2028         PayloadType *pt;
2029     codecs_config_t *config=&lc->codecs_conf;
2030         int index=0;
2031         MSList *node=NULL;
2032
2033     if (type == AUDIO) {
2034       node=config->audio_codecs;
2035     } else if(type==VIDEO) {
2036       node=config->video_codecs;
2037     }
2038
2039     for(;node!=NULL;node=ms_list_next(node)){
2040         if (index == sel_index || sel_index == -1) {
2041                     pt=(PayloadType*)(node->data);
2042             pt->flags|=PAYLOAD_TYPE_ENABLED;
2043             linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, "enabled");
2044         }
2045                 index++;
2046         }
2047 }
2048
2049 static void linphonec_codec_disable(int type, LinphoneCore *lc, int sel_index){
2050         PayloadType *pt;
2051     codecs_config_t *config=&lc->codecs_conf;
2052         int index=0;
2053         MSList *node=NULL;
2054
2055     if (type == AUDIO) {
2056       node=config->audio_codecs;
2057     } else if(type==VIDEO) {
2058       node=config->video_codecs;
2059     }
2060
2061         for(;node!=NULL;node=ms_list_next(node)){
2062         if (index == sel_index || sel_index == -1) {
2063                 pt=(PayloadType*)(node->data);
2064             pt->flags&=~PAYLOAD_TYPE_ENABLED;
2065             linphonec_out("%2d: %s (%d) %s\n", index, pt->mime_type, pt->clock_rate, "disabled");
2066         }
2067                 index++;
2068         }
2069 }
2070
2071 static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args){
2072         char *arg1 = args;
2073         char *arg2 = NULL;
2074         char *ptr = args;
2075
2076         if (!args) return 0;
2077
2078         /* Isolate first and second arg */
2079         while(*ptr && !isspace(*ptr)) ++ptr;
2080         if ( *ptr )
2081         {
2082                 *ptr='\0';
2083                 arg2=ptr+1;
2084                 while(*arg2 && isspace(*arg2)) ++arg2;
2085         }
2086
2087         if (strcmp(arg1,"on")==0){
2088         int delay, tail_len, frame_size;
2089         int n;
2090
2091         linphone_core_enable_echo_cancellation(lc,1);
2092
2093         if (arg2 != 0) {
2094             n = sscanf(arg2, "%d %d %d", &delay, &tail_len, &frame_size);
2095
2096             if (n == 1) {   
2097                 lp_config_set_int(lc->config,"sound","ec_delay",delay);
2098             }
2099             else if (n == 2) {
2100                 lp_config_set_int(lc->config,"sound","ec_delay",delay);
2101                 lp_config_set_int(lc->config,"sound","ec_tail_len",tail_len);
2102             }
2103             else if (n == 3) {
2104                 lp_config_set_int(lc->config,"sound","ec_delay",delay);
2105                 lp_config_set_int(lc->config,"sound","ec_tail_len",tail_len);
2106                 lp_config_set_int(lc->config,"sound","ec_framesize",frame_size);
2107             }
2108         }
2109     }
2110     else if (strcmp(arg1,"off")==0){
2111         linphone_core_enable_echo_cancellation(lc,0);
2112     }
2113     else if (strcmp(arg1,"show")==0){
2114         linphonec_out("echo cancellation is %s; delay %d, tail length %d, frame size %d\n", 
2115             linphone_core_echo_cancellation_enabled(lc) ? "on" : "off",
2116             lp_config_get_int(lc->config,"sound","ec_delay",0),
2117             lp_config_get_int(lc->config,"sound","ec_tail_len",0),
2118             lp_config_get_int(lc->config,"sound","ec_framesize",0));        
2119     }
2120     else {
2121         return 0;
2122     }
2123
2124     return 1;
2125 }
2126
2127 static int lpc_cmd_mute_mic(LinphoneCore *lc, char *args)
2128 {
2129         linphone_core_mute_mic(lc, 1);
2130         return 1;
2131 }
2132
2133 static int lpc_cmd_unmute_mic(LinphoneCore *lc, char *args){
2134         linphone_core_mute_mic(lc, 0);
2135         return 1;
2136 }
2137
2138 static int lpc_cmd_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, char *args)
2139 {
2140         bool_t rtp_xmit_off=FALSE;
2141         char *status;
2142
2143         if(args){
2144                 if(strstr(args,"1"))rtp_xmit_off=TRUE;
2145                 if(linphone_core_get_current_call (lc)==NULL)
2146                         linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_xmit_off);
2147                 else 
2148                         linphonec_out("nortp-on-audio-mute: call in progress - cannot change state\n");
2149         }
2150         rtp_xmit_off=linphone_core_get_rtp_no_xmit_on_audio_mute(lc);
2151         if (rtp_xmit_off) status="off";
2152         else status="on";
2153         linphonec_out("rtp transmit %s when audio muted\n",status);
2154         return 1;
2155 }
2156
2157 static int lpc_cmd_video_window(LinphoneCore *lc, char *args){
2158         return 1;
2159 }
2160
2161 /***************************************************************************
2162  *
2163  *  Command table management funx
2164  *
2165  ***************************************************************************/
2166
2167 /*
2168  * Find a command given its name
2169  */
2170 static LPC_COMMAND *
2171 lpc_find_command(const char *name)
2172 {
2173         int i;
2174
2175         for (i=0; commands[i].name; ++i)
2176         {
2177                 if (strcmp(name, commands[i].name) == 0)
2178                         return &commands[i];
2179         }
2180
2181         for (i=0; advanced_commands[i].name; ++i)
2182         {
2183                 if (strcmp(name, advanced_commands[i].name) == 0)
2184                         return &advanced_commands[i];
2185         }
2186
2187         return (LPC_COMMAND *)NULL;
2188 }
2189
2190
2191 /****************************************************************************
2192  *
2193  * $Log: commands.c,v $
2194  * Revision 1.39  2008/07/03 15:08:34  smorlat
2195  * api cleanups, interface in progress.
2196  *
2197  * Revision 1.38  2008/06/17 20:38:59  smorlat
2198  * added missing file.
2199  *
2200  * Revision 1.37  2008/04/09 09:26:00  smorlat
2201  * merge various patches
2202  * H264 support.
2203  *
2204  * Revision 1.36  2007/08/01 14:47:53  strk
2205  *         * console/commands.c: Clean up commands 'nat', 'stun'
2206  *           and 'firewall' to be more intuitive.
2207  *
2208  * Revision 1.35  2007/06/27 09:01:25  smorlat
2209  * logging improvements.
2210  *
2211  * Revision 1.34  2007/02/20 10:17:13  smorlat
2212  * linphonec friends patch2
2213  *
2214  * Revision 1.31  2006/09/22 07:22:47  smorlat
2215  * linphonecore api changes.
2216  *
2217  * Revision 1.30  2006/09/08 15:32:57  smorlat
2218  * support for using files instead of soundcard (used by linphonec only)
2219  *
2220  * Revision 1.29  2006/08/28 14:29:07  smorlat
2221  * fix bug.
2222  *
2223  * Revision 1.28  2006/08/21 12:49:59  smorlat
2224  * merged several little patches.
2225  *
2226  * Revision 1.27  2006/07/17 18:45:00  smorlat
2227  * support for several event queues in ortp.
2228  * glib dependency removed from coreapi/ and console/
2229  *
2230  * Revision 1.26  2006/04/14 15:16:36  smorlat
2231  * soundcard use did nothing !
2232  *
2233  * Revision 1.25  2006/04/06 20:09:33  smorlat
2234  * add linphonec command to see and select sound devices.
2235  *
2236  * Revision 1.24  2006/03/04 11:17:10  smorlat
2237  * mediastreamer2 in progress.
2238  *
2239  * Revision 1.23  2006/02/20 21:14:01  strk
2240  * Handled syntax errors with 'friend' command
2241  *
2242  * Revision 1.22  2006/02/20 10:20:29  strk
2243  * Added substring-based filter support for command 'friend list'
2244  *
2245  * Revision 1.21  2006/02/02 15:39:18  strk
2246  * - Added 'friend list' and 'friend call' commands
2247  * - Allowed for multiple DTFM send in a single line
2248  * - Added status-specific callback (bare version)
2249  *
2250  * Revision 1.20  2006/01/26 11:54:34  strk
2251  * More robust 'nat' command handler (strip blanks in args)
2252  *
2253  * Revision 1.19  2006/01/26 09:48:05  strk
2254  * Added limits.h include
2255  *
2256  * Revision 1.18  2006/01/26 02:18:05  strk
2257  * Added new commands 'nat use' and 'nat unuse'.
2258  * These will required a pending patch to linphonecore.c
2259  * in order to work.
2260  *
2261  * Revision 1.17  2006/01/20 14:12:33  strk
2262  * Added linphonec_init() and linphonec_finish() functions.
2263  * Handled SIGINT and SIGTERM to invoke linphonec_finish().
2264  * Handling of auto-termination (-t) moved to linphonec_finish().
2265  * Reworked main (input read) loop to not rely on 'terminate'
2266  * and 'run' variable (dropped). configfile_name allocated on stack
2267  * using PATH_MAX limit. Changed print_usage signature to allow
2268  * for an exit_status specification.
2269  *
2270  * Revision 1.16  2006/01/18 09:25:32  strk
2271  * Command completion inhibited in proxy addition and auth request prompts.
2272  * Avoided use of linphonec_readline's internal filename completion.
2273  *
2274  * Revision 1.15  2006/01/14 13:29:32  strk
2275  * Reworked commands interface to use a table structure,
2276  * used by command line parser and help function.
2277  * Implemented first level of completion (commands).
2278  * Added notification of invalid "answer" and "terminate"
2279  * commands (no incoming call, no active call).
2280  * Forbidden "call" intialization when a call is already active.
2281  * Cleaned up all commands, adding more feedback and error checks.
2282  *
2283  * Revision 1.14  2006/01/13 13:00:29  strk
2284  * Added linphonec.h. Code layout change (added comments, forward decl,
2285  * globals on top, copyright notices and Logs). Handled out-of-memory
2286  * condition on history management. Removed assumption on sizeof(char).
2287  * Fixed bug in authentication prompt (introduced by linphonec_readline).
2288  * Added support for multiple authentication requests (up to MAX_PENDING_AUTH).
2289  *
2290  *
2291  ****************************************************************************/