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