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