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