]> sjero.net Git - linphone/blob - console/commands.c
Merge branch 'master' into dev_multicall
[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                 MSList *calls = linphone_core_get_calls(lc);
411                 if(calls)
412                 {
413                         MSList *p_calls = calls;
414                         linphonec_out("<remote>\t\t\t\t<status>\r\n");
415                         while(p_calls != NULL)                  
416                         {
417                                 linphonec_out("%s\t\t\t%s\r\n",
418                                                 linphone_call_get_remote_address_as_string(p_calls->data),
419                                                 (((LinphoneCall *)p_calls->data)==linphone_core_get_current_call(lc))?"yes":"no");
420                                 p_calls = p_calls->next;
421                         }
422                         ms_list_free(calls);
423                 }
424                 else
425                 {
426                         linphonec_out("No active call.\n");
427                 }
428         }
429         else
430         {
431                 if ( linphone_core_in_call(lc) )
432                 {
433                         linphonec_out("Terminate or hold on the current call first.\n");
434                         return 1;
435                 }
436                 if ( NULL == linphone_core_invite(lc, args) )
437                 {
438                         linphonec_out("Error from linphone_core_invite.\n");
439                 }
440                 else
441                 {
442                         snprintf(callee_name,sizeof(callee_name),"%s",args);
443                 }
444         }
445         return 1;
446 }
447
448 static int
449 lpc_cmd_chat(LinphoneCore *lc, char *args)
450 {
451         char *arg1 = args;
452         char *arg2 = NULL;
453         char *ptr = args;
454
455         if (!args) return 0;
456
457         /* Isolate first and second arg */
458         while(*ptr && !isspace(*ptr)) ++ptr;
459         if ( *ptr )
460         {
461                 *ptr='\0';
462                 arg2=ptr+1;
463                 while(*arg2 && isspace(*arg2)) ++arg2;
464         }
465         else
466         {
467                 /* missing one parameter */
468                 return 0;
469         }
470         LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1);
471         linphone_chat_room_send_message(cr,arg2);
472         linphone_chat_room_destroy(cr);
473
474         return 1;
475 }
476
477 const char *linphonec_get_callee(){
478         return callee_name;
479 }
480
481 const char *linphonec_get_caller(){
482         return caller_name;
483 }
484
485 void linphonec_set_caller(const char *caller){
486         snprintf(caller_name,sizeof(caller_name)-1,"%s",caller);
487 }
488
489 static int
490 lpc_cmd_refer(LinphoneCore *lc, char *args)
491 {
492         if (args)
493                 linphone_core_refer(lc, linphone_core_get_current_call(lc), args);
494         else{
495                 linphonec_out("refer needs an argument\n");
496         }
497         return 1;
498 }
499
500 static int
501 lpc_cmd_terminate(LinphoneCore *lc, char *args)
502 {
503         char *arg1 = args;
504         char *arg2 = NULL;
505         char *ptr = args;
506
507         if (!args)
508         {
509                 if(linphone_core_in_call(lc))
510                 {
511                         if ( -1 == linphone_core_terminate_call(lc, linphone_core_get_current_call(lc)) )
512                         {
513                                 linphonec_out("Could not stop the active call.\n");
514                         }
515                 }
516                 else
517                 {
518                         linphonec_out("No active call.\n");
519                 }
520                 return 1;
521         }
522         
523         /* Isolate first and second arg */
524         while(*ptr && !isspace(*ptr)) ++ptr;
525         if ( *ptr )
526         {
527                 *ptr='\0';
528                 arg2=ptr+1;
529                 while(*arg2 && isspace(*arg2)) ++arg2;
530         }
531         if (arg1 != 0)
532         {
533                 if(strcmp(arg1,"all")==0)
534                 {
535                         linphonec_out("We are going to stop all the calls.\n");
536                         return (linphone_core_terminate_all_calls(lc)==0)?1:0;
537                 }
538                 else
539                 {
540                         char the_remote_address[255];
541                         int n = sscanf(arg1, "%s", the_remote_address);
542                         if (n == 1)
543                         {
544                                 if ( -1 == linphone_core_terminate_call(lc,linphone_core_get_call_by_remote_address(lc,the_remote_address)))
545                                 {
546                                         linphonec_out("Cannot stop the call with %s.\n",the_remote_address);
547                                 }
548                                 return 1;
549                         }
550                 }
551         }
552         return 0;
553         
554 }
555
556 static int
557 lpc_cmd_answer(LinphoneCore *lc, char *args)
558 {
559         char *arg1 = args;
560         char *arg2 = NULL;
561         char *ptr = args;
562
563         if (!args)
564         {
565                 //if just one call is present answer the only one in passing NULL to the linphone_core_accept_call ...
566                 if ( -1 == linphone_core_accept_call(lc, NULL) )
567                 {
568                         linphonec_out("No incoming call.\n");
569                 }
570                 return 1;
571         }
572
573         // Isolate first and second arg
574         while(*ptr && !isspace(*ptr)) ++ptr;
575         if ( *ptr )
576         {
577                 *ptr='\0';
578                 arg2=ptr+1;
579                 while(*arg2 && isspace(*arg2)) ++arg2;
580         }
581         if (arg1 != 0)
582         {
583                 char the_remote_address[256];
584                 int n = sscanf(arg1, "%s", the_remote_address);
585                 if (n == 1)
586                 {
587                         if ( -1 == linphone_core_accept_call(lc, linphone_core_get_call_by_remote_address(lc,the_remote_address)) )
588                         {
589                                 linphonec_out("Cannot answer the call from %s.\n",the_remote_address);
590                         }
591                         return 1;
592                 }
593         }
594         return 0;
595 }
596
597 static int
598 lpc_cmd_autoanswer(LinphoneCore *lc, char *args)
599 {
600         if ( ! args )
601         {
602                 if ( linphonec_get_autoanswer() ) {
603                         linphonec_out("Auto answer is enabled. Use 'autoanswer disable' to disable.\n");
604                 } else {
605                         linphonec_out("Auto answer is disabled. Use 'autoanswer enable' to enable.\n");
606                 }
607                 return 1;
608         }
609
610         if (strstr(args,"enable")){
611                 linphonec_set_autoanswer(TRUE);
612                 linphonec_out("Auto answer enabled.\n");
613         }else if (strstr(args,"disable")){
614                 linphonec_set_autoanswer(FALSE);
615                 linphonec_out("Auto answer disabled.\n");
616         }else return 0;
617         return 1;
618 }
619
620 static int
621 lpc_cmd_quit(LinphoneCore *lc, char *args)
622 {
623         linphonec_main_loop_exit();
624         return 1;
625 }
626
627 static int
628 lpc_cmd_nat(LinphoneCore *lc, char *args)
629 {
630         bool_t use;
631         const char *nat;
632
633         if ( args ) args=lpc_strip_blanks(args);
634
635         if ( args && *args )
636         {
637                 linphone_core_set_nat_address(lc, args);
638                 /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS); */
639         }
640
641         nat = linphone_core_get_nat_address(lc);
642         use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS;
643         linphonec_out("Nat address: %s%s\n", nat ? nat : "unspecified" , use ? "" : " (disabled - use 'firewall nat' to enable)");
644
645         return 1;
646 }
647
648 static int
649 lpc_cmd_stun(LinphoneCore *lc, char *args)
650 {
651         bool_t use;
652         const char *stun;
653
654         if ( args ) args=lpc_strip_blanks(args);
655
656         if ( args && *args )
657         {
658                 linphone_core_set_stun_server(lc, args);
659                 /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN); */
660         }
661
662         stun = linphone_core_get_stun_server(lc);
663         use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_STUN;
664         linphonec_out("Stun server: %s%s\n", stun ? stun : "unspecified" , use? "" : " (disabled - use 'firewall stun' to enable)");
665
666         return 1;
667 }
668
669 static int
670 lpc_cmd_firewall(LinphoneCore *lc, char *args)
671 {
672         const char* setting=NULL;
673
674         if ( args ) args=lpc_strip_blanks(args);
675
676         if ( args && *args )
677         {
678                 if (strcmp(args,"none")==0)
679                 {
680                         linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_NO_FIREWALL);
681                 }
682                 else if (strcmp(args,"stun")==0)
683                 {
684                         setting = linphone_core_get_stun_server(lc);
685                         if ( ! setting )
686                         {
687                                 linphonec_out("No stun server address is defined, use 'stun <address>' first\n");
688                                 return 1;
689                         }
690                         linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN);
691                 }
692                 else if (strcmp(args,"nat")==0)
693                 {
694                         setting = linphone_core_get_nat_address(lc);
695                         if ( ! setting )
696                         {
697                                 linphonec_out("No nat address is defined, use 'nat <address>' first");
698                                 return 1;
699                         }
700                         linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS);
701                 }
702         }
703
704         switch(linphone_core_get_firewall_policy(lc))
705         {
706                 case LINPHONE_POLICY_NO_FIREWALL:
707                         linphonec_out("No firewall\n");
708                         break;
709                 case LINPHONE_POLICY_USE_STUN:
710                         linphonec_out("Using stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
711                         break;
712                 case LINPHONE_POLICY_USE_NAT_ADDRESS:
713                         linphonec_out("Using supplied nat address %s.\n", setting ? setting : linphone_core_get_nat_address(lc));
714                         break;
715         }
716         return 1;
717 }
718
719 #ifndef WIN32
720 /* Helper function for processing freind names */
721 static int
722 lpc_friend_name(char **args, char **name)
723 {
724         /* Use space as a terminator unless quoted */
725         if (('"' == **args) || ('\'' == **args)){
726                 char *end;
727                 char delim = **args;
728                 (*args)++;
729                 end = (*args);
730                 while ((delim != *end) && ('\0' != *end)) end++;
731                 if ('\0' == *end) {
732                         fprintf(stderr, "Mismatched quotes\n");
733                         return 0;
734                 }
735                 *name = *args;
736                 *end = '\0';
737                 *args = ++end;
738         } else {
739                 *name = strsep(args, " ");
740                 
741                 if (NULL == *args) { /* Means there was no separator */
742                         fprintf(stderr, "Either name or address is missing\n");
743                         return 0;
744                 }
745                 if (NULL == *name) return 0;
746         }
747         return 1;
748 }
749 #endif
750
751 static int
752 lpc_cmd_friend(LinphoneCore *lc, char *args)
753 {
754         int friend_num;
755
756         if ( args ) args=lpc_strip_blanks(args);
757
758         if ( ! args || ! *args ) return 0;
759
760         if ( !strncmp(args, "list", 4) )
761         {
762                 return linphonec_friend_list(lc, args+4);
763                 return 1;
764         }
765         else if ( !strncmp(args, "call", 4) )
766         {
767                 args+=4;
768                 if ( ! *args ) return 0;
769                 friend_num = strtol(args, NULL, 10);
770 #ifndef _WIN32_WCE              
771                 if ( errno == ERANGE ) {
772                         linphonec_out("Invalid friend number\n");
773                         return 0;
774                 }
775 #endif /*_WIN32_WCE*/
776                 linphonec_friend_call(lc, friend_num);
777                 return 1;
778         }
779         else if ( !strncmp(args, "delete", 6) )
780         {
781                 args+=6;
782                 if ( ! *args ) return 0;
783                 while (*args == ' ') args++;
784                 if ( ! *args ) return 0;
785                 if (!strncmp(args, "all", 3))
786                 {
787                         friend_num = -1;
788                 } 
789                 else
790                 {
791                         friend_num = strtol(args, NULL, 10);
792 #ifndef _WIN32_WCE              
793                         if ( errno == ERANGE ) {
794                                 linphonec_out("Invalid friend number\n");
795                                 return 0;
796                         }
797 #endif /*_WIN32_WCE*/
798                 }
799                 linphonec_friend_delete(lc, friend_num);
800                 return 1;
801         }
802         else if ( !strncmp(args, "add", 3) )
803         {
804 #ifndef WIN32
805                 char  *name;
806                 char  addr[80];
807                 char *addr_p = addr;
808                 char *addr_orig;
809
810                 args+=3;
811                 if ( ! *args ) return 0;
812                 while (*args == ' ') args++;
813                 if ( ! *args ) return 0;
814
815                 if (!lpc_friend_name(&args,  &name)) return 0;
816
817                 while (*args == ' ') args++;
818                 if ( ! *args ) return 0;
819                 if (isdigit(*args)) {
820                         strcpy (addr, "sip:");
821                         addr_p = addr + strlen("sip:");
822                 }
823                 addr_orig = strsep(&args, " ");
824                 if (1 >= strlen(addr_orig)) {
825                         fprintf(stderr, "A single-digit address is not valid\n");
826                         return 0;
827                 }
828                 strcpy(addr_p, addr_orig);
829                 linphonec_friend_add(lc, name, addr);
830 #else
831                 LinphoneFriend *new_friend;
832                 new_friend = linphone_friend_new_with_addr(args);
833                 linphone_core_add_friend(lc, new_friend);
834 #endif
835                 return 1;
836         }
837         return 0;
838 }
839
840 static int lpc_cmd_play(LinphoneCore *lc, char *args){
841         if ( args ) args=lpc_strip_blanks(args);
842         if ( ! args || ! *args ) return 0;
843         linphone_core_set_play_file(lc,args);
844         return 1;
845 }
846
847 static int lpc_cmd_record(LinphoneCore *lc, char *args){
848         if ( args ) args=lpc_strip_blanks(args);
849         if ( ! args || ! *args ) return 0;
850         linphone_core_set_record_file(lc,args);
851         return 1;
852 }
853
854 /*
855  * Modified input
856  */
857 static int
858 lpc_cmd_proxy(LinphoneCore *lc, char *args)
859 {
860         char *arg1 = args;
861         char *arg2 = NULL;
862         char *ptr = args;
863         int proxynum;
864
865         if ( ! arg1 ) return 0;
866
867         /* Isolate first and second arg */
868         while(*ptr && !isspace(*ptr)) ++ptr;
869         if ( *ptr )
870         {
871                 *ptr='\0';
872                 arg2=ptr+1;
873                 while(*arg2 && isspace(*arg2)) ++arg2;
874         }
875
876         if (strcmp(arg1,"add")==0)
877         {
878 #ifdef HAVE_READLINE
879                 rl_inhibit_completion=1;
880 #endif
881                 linphonec_proxy_add(lc);
882 #ifdef HAVE_READLINE
883                 rl_inhibit_completion=0;
884 #endif
885         }
886         else if (strcmp(arg1,"list")==0)
887         {
888                 linphonec_proxy_list(lc);
889         }
890         else if (strcmp(arg1,"remove")==0)
891         {
892                 linphonec_proxy_remove(lc,atoi(arg2));
893         }
894         else if (strcmp(arg1,"use")==0)
895         {
896                 if ( arg2 && *arg2 )
897                 {
898                         proxynum=atoi(arg2);
899                         if ( linphonec_proxy_use(lc, proxynum) )
900                                 linphonec_out("Default proxy set to %d.\n", proxynum);
901                 }
902                 else
903                 {
904                         proxynum=linphone_core_get_default_proxy(lc, NULL);
905                         if ( proxynum == -1 ) linphonec_out("No default proxy.\n");
906                         else linphonec_out("Current default proxy is %d.\n", proxynum);
907                 }
908         }else if (strcmp(arg1, "unuse")==0){
909                 linphone_core_set_default_proxy(lc, NULL);
910                 linphonec_out("Use no proxy.\n");
911         }
912
913         else if (strcmp(arg1, "show")==0)
914         {
915                 if (arg2 && *arg2)
916                 {
917                         if (strstr(arg2,"default"))
918                         {
919                 proxynum=linphone_core_get_default_proxy(lc, NULL);
920                 if ( proxynum < 0 ) {
921                         linphonec_out("No default proxy defined\n");
922                         return 1;
923                 }
924                 linphonec_proxy_show(lc,proxynum);
925                         }
926                         else
927                         {
928                 linphonec_proxy_show(lc, atoi(arg2));
929                         }
930                 }
931                 else return 0; /* syntax error */
932         }
933
934         else
935         {
936                 return 0; /* syntax error */
937         }
938
939         return 1;
940 }
941
942 static int
943 lpc_cmd_call_logs(LinphoneCore *lc, char *args)
944 {
945         const MSList *elem=linphone_core_get_call_logs(lc);
946         for (;elem!=NULL;elem=ms_list_next(elem))
947         {
948                 LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
949                 char *str=linphone_call_log_to_str(cl);
950                 linphonec_out("%s\n",str);
951                 ms_free(str);
952         }
953         return 1;
954 }
955
956 static int
957 lpc_cmd_ipv6(LinphoneCore *lc, char *arg1)
958 {
959         if ( ! arg1 )
960         {
961                 return 0; /* syntax error */
962         }
963
964         if (strcmp(arg1,"status")==0)
965         {
966                 linphonec_out("ipv6 use enabled: %s\n",linphone_core_ipv6_enabled(lc) ? "true":"false");
967         }
968         else if (strcmp(arg1,"enable")==0)
969         {
970                 linphone_core_enable_ipv6(lc,TRUE);
971                 linphonec_out("ipv6 use enabled.\n");
972         }
973         else if (strcmp(arg1,"disable")==0)
974         {
975                 linphone_core_enable_ipv6(lc,FALSE);
976                 linphonec_out("ipv6 use disabled.\n");
977         }
978         else
979         {
980                 return 0; /* syntax error */
981         }
982         return 1;
983 }
984
985 static int devname_to_index(LinphoneCore *lc, const char *devname){
986         const char **p;
987         int i;
988         for(i=0,p=linphone_core_get_sound_devices(lc);*p!=NULL;++p,++i){
989                 if (strcmp(devname,*p)==0) return i;
990         }
991         return -1;
992 }
993
994 static const char *index_to_devname(LinphoneCore *lc, int index){
995         const char **p;
996         int i;
997         for(i=0,p=linphone_core_get_sound_devices(lc);*p!=NULL;++p,++i){
998                 if (i==index) return *p;
999         }
1000         return NULL;
1001 }
1002
1003 static int lpc_cmd_soundcard(LinphoneCore *lc, char *args)
1004 {
1005         int i, index;
1006         const char **dev;
1007         char *arg1 = args;
1008         char *arg2 = NULL;
1009         char *ptr = args;
1010
1011         if (!args) return 0; /* syntax error */
1012
1013         /* Isolate first and second arg */
1014         while(*ptr && !isspace(*ptr)) ++ptr;
1015         if ( *ptr )
1016         {
1017                 *ptr='\0';
1018                 arg2=ptr+1;
1019                 while(*arg2 && isspace(*arg2)) ++arg2;
1020         }
1021
1022         if (strcmp(arg1, "list")==0)
1023         {
1024                 dev=linphone_core_get_sound_devices(lc);
1025                 for(i=0; dev[i]!=NULL; ++i){
1026                         linphonec_out("%i: %s\n",i,dev[i]);
1027                 }
1028                 return 1;
1029         }
1030
1031         if (strcmp(arg1, "show")==0)
1032         {
1033                 linphonec_out("Ringer device: %s\n",
1034                         linphone_core_get_ringer_device(lc));
1035                 linphonec_out("Playback device: %s\n",
1036                         linphone_core_get_playback_device(lc));
1037                 linphonec_out("Capture device: %s\n",
1038                         linphone_core_get_capture_device(lc));
1039                 return 1;
1040         }
1041
1042         if (strcmp(arg1, "use")==0 && arg2)
1043         {
1044                 if (strcmp(arg2, "files")==0)
1045                 {
1046                         linphonec_out("Using wav files instead of soundcard.\n");
1047                         linphone_core_use_files(lc,TRUE);
1048                         return 1;
1049                 }
1050
1051                 dev=linphone_core_get_sound_devices(lc);
1052                 index=atoi(arg2); /* FIXME: handle not-a-number */
1053                 for(i=0;dev[i]!=NULL;i++)
1054                 {
1055                         if (i!=index) continue;
1056
1057                         linphone_core_set_ringer_device(lc,dev[i]);
1058                         linphone_core_set_playback_device(lc,dev[i]);
1059                         linphone_core_set_capture_device(lc,dev[i]);
1060                         linphonec_out("Using sound device %s\n",dev[i]);
1061                         return 1;
1062                 }
1063                 linphonec_out("No such sound device\n");
1064                 return 1;
1065         }
1066         if (strcmp(arg1, "capture")==0)
1067         {
1068                 const char *devname=linphone_core_get_capture_device(lc);
1069                 if (!arg2){
1070                         linphonec_out("Using capture device #%i (%s)\n",
1071                                         devname_to_index(lc,devname),devname);
1072                 }else{
1073                         index=atoi(arg2); /* FIXME: handle not-a-number */
1074                         devname=index_to_devname(lc,index);
1075                         if (devname!=NULL){
1076                                 linphone_core_set_capture_device(lc,devname);
1077                                 linphonec_out("Using capture sound device %s\n",devname);
1078                                 return 1;
1079                         }
1080                         linphonec_out("No such sound device\n");
1081                 }
1082                 return 1;
1083         }
1084         if (strcmp(arg1, "playback")==0)
1085         {
1086                 const char *devname=linphone_core_get_playback_device(lc);
1087                 if (!arg2){
1088                         linphonec_out("Using playback device #%i (%s)\n",
1089                                         devname_to_index(lc,devname),devname);
1090                 }else{
1091                         index=atoi(arg2); /* FIXME: handle not-a-number */
1092                         devname=index_to_devname(lc,index);
1093                         if (devname!=NULL){
1094                                 linphone_core_set_playback_device(lc,devname);
1095                                 linphonec_out("Using playback sound device %s\n",devname);
1096                                 return 1;
1097                         }
1098                         linphonec_out("No such sound device\n");
1099                 }
1100                 return 1;
1101         }
1102         if (strcmp(arg1, "ring")==0)
1103         {
1104                 const char *devname=linphone_core_get_ringer_device(lc);
1105                 if (!arg2){
1106                         linphonec_out("Using ring device #%i (%s)\n",
1107                                         devname_to_index(lc,devname),devname);
1108                 }else{
1109                         index=atoi(arg2); /* FIXME: handle not-a-number */
1110                         devname=index_to_devname(lc,index);
1111                         if (devname!=NULL){
1112                                 linphone_core_set_ringer_device(lc,devname);
1113                                 linphonec_out("Using ring sound device %s\n",devname);
1114                                 return 1;
1115                         }
1116                         linphonec_out("No such sound device\n");
1117                 }
1118                 return 1;
1119         }
1120         return 0; /* syntax error */
1121 }
1122
1123 static int lpc_cmd_webcam(LinphoneCore *lc, char *args)
1124 {
1125         int i, index;
1126         const char **dev;
1127         char *arg1 = args;
1128         char *arg2 = NULL;
1129         char *ptr = args;
1130
1131         if (!args) return 0; /* syntax error */
1132
1133         /* Isolate first and second arg */
1134         while(*ptr && !isspace(*ptr)) ++ptr;
1135         if ( *ptr )
1136         {
1137                 *ptr='\0';
1138                 arg2=ptr+1;
1139                 while(*arg2 && isspace(*arg2)) ++arg2;
1140         }
1141
1142         if (strcmp(arg1, "list")==0)
1143         {
1144                 dev=linphone_core_get_video_devices(lc);
1145                 for(i=0; dev[i]!=NULL; ++i){
1146                         linphonec_out("%i: %s\n",i,dev[i]);
1147                 }
1148                 return 1;
1149         }
1150
1151         if (strcmp(arg1, "use")==0 && arg2)
1152         {
1153                 dev=linphone_core_get_video_devices(lc);
1154                 index=atoi(arg2); /* FIXME: handle not-a-number */
1155                 for(i=0;dev[i]!=NULL;i++)
1156                 {
1157                         if (i!=index) continue;
1158
1159                         linphone_core_set_video_device(lc, dev[i]);
1160                         linphonec_out("Using video device %s\n",dev[i]);
1161                         return 1;
1162                 }
1163                 linphonec_out("No such video device\n");
1164                 return 1;
1165         }
1166         return 0; /* syntax error */
1167 }
1168
1169 static int
1170 lpc_cmd_staticpic(LinphoneCore *lc, char *args)
1171 {
1172         char *arg1 = args;
1173         char *arg2 = NULL;
1174         char *ptr = args;
1175
1176         if (!args) return 0;  /* Syntax error */
1177
1178         /* Isolate first and second arg */
1179         while(*ptr && !isspace(*ptr)) ++ptr;
1180         if ( *ptr )
1181         {
1182                 *ptr='\0';
1183                 arg2=ptr+1;
1184                 while(*arg2 && isspace(*arg2)) ++arg2;
1185         }
1186
1187         if (strcmp(arg1, "set")==0 && arg2) {
1188                 linphone_core_set_static_picture(lc, arg2);
1189                 return 1;
1190         }
1191
1192         return 0; /* Syntax error */
1193 }
1194
1195 static int lpc_cmd_pause(LinphoneCore *lc, char *args){
1196
1197         if(linphone_core_in_call(lc))
1198         {
1199                 linphone_core_pause_call(lc,linphone_core_get_current_call(lc));
1200                 return 1;
1201         }
1202         linphonec_out("you can only pause when a call is in process\n");
1203     return 0;
1204 }
1205
1206 static int lpc_cmd_resume(LinphoneCore *lc, char *args){
1207         
1208         if(linphone_core_in_call(lc))
1209         {
1210                 linphonec_out("There is already a call in process pause or stop it first");
1211         }
1212         if (args)
1213         {
1214                 char the_remote_address[255];
1215                 int n = sscanf(args, "%s", the_remote_address);
1216                 if (n == 1)
1217                 {
1218                         if(linphone_core_resume_call(lc,linphone_core_get_call_by_remote_address(lc,the_remote_address)) < 0)
1219                         {
1220                                 linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args);
1221                                 return 0;
1222                         }
1223                         else
1224                         {
1225                                 return 1;
1226                         }
1227                 }
1228         }
1229         else
1230         {
1231                 int returned = 0;
1232                 MSList *calls = linphone_core_get_calls(lc);
1233                 if(ms_list_size(calls) == 1)
1234                 {
1235                         if(linphone_core_resume_call(lc,calls->data) < 0)
1236                         {
1237                                 linphonec_out("There was a problem to resume the unique call \n");
1238                                 returned = 0;
1239                         }
1240                         else
1241                         {
1242                                 returned = 1;
1243                         }
1244                         ms_list_free(calls);
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                 gstate_t call_state=linphone_core_get_state(lc,GSTATE_GROUP_CALL);
1779 /*
1780                 if (!cfg || !linphone_proxy_config_is_registered(cfg)){
1781                         linphonec_out("unregistered\n");
1782                         return 1;
1783                 }
1784  */
1785                 switch(call_state){
1786                         case GSTATE_CALL_OUT_INVITE:
1787                                 linphonec_out("hook=dialing\n");
1788                         break;
1789                         case GSTATE_CALL_IDLE:
1790                                 linphonec_out("hook=offhook\n");
1791                         break;
1792                         case GSTATE_CALL_OUT_CONNECTED:
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                                               lc->audio_muted ? "yes" : "no",
1796                                               linphone_core_is_rtp_muted(lc) ? "yes"  : "no");
1797                         break;
1798                         case GSTATE_CALL_IN_CONNECTED:
1799                                 linphonec_out("hook=answered duration=%i\n" ,
1800                                         linphone_core_get_current_call_duration(lc));
1801                                 break;
1802                         case GSTATE_CALL_IN_INVITE:
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   gstate_t call_state=linphone_core_get_state(lc,GSTATE_GROUP_CALL);
2054
2055   if(args){
2056     if(strstr(args,"1"))rtp_xmit_off=TRUE;
2057     if(call_state == GSTATE_CALL_IDLE)
2058       linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_xmit_off);
2059     else 
2060       linphonec_out("nortp-on-audio-mute: call in progress - cannot change state\n");
2061   }
2062   rtp_xmit_off=linphone_core_get_rtp_no_xmit_on_audio_mute(lc);
2063   if(rtp_xmit_off)status="off";
2064   else status="on";
2065   linphonec_out("rtp transmit %s when audio muted\n",status);
2066   return 1;
2067 }
2068
2069
2070 /***************************************************************************
2071  *
2072  *  Command table management funx
2073  *
2074  ***************************************************************************/
2075
2076 /*
2077  * Find a command given its name
2078  */
2079 static LPC_COMMAND *
2080 lpc_find_command(const char *name)
2081 {
2082         int i;
2083
2084         for (i=0; commands[i].name; ++i)
2085         {
2086                 if (strcmp(name, commands[i].name) == 0)
2087                         return &commands[i];
2088         }
2089
2090         return (LPC_COMMAND *)NULL;
2091 }
2092
2093
2094 /****************************************************************************
2095  *
2096  * $Log: commands.c,v $
2097  * Revision 1.39  2008/07/03 15:08:34  smorlat
2098  * api cleanups, interface in progress.
2099  *
2100  * Revision 1.38  2008/06/17 20:38:59  smorlat
2101  * added missing file.
2102  *
2103  * Revision 1.37  2008/04/09 09:26:00  smorlat
2104  * merge various patches
2105  * H264 support.
2106  *
2107  * Revision 1.36  2007/08/01 14:47:53  strk
2108  *         * console/commands.c: Clean up commands 'nat', 'stun'
2109  *           and 'firewall' to be more intuitive.
2110  *
2111  * Revision 1.35  2007/06/27 09:01:25  smorlat
2112  * logging improvements.
2113  *
2114  * Revision 1.34  2007/02/20 10:17:13  smorlat
2115  * linphonec friends patch2
2116  *
2117  * Revision 1.31  2006/09/22 07:22:47  smorlat
2118  * linphonecore api changes.
2119  *
2120  * Revision 1.30  2006/09/08 15:32:57  smorlat
2121  * support for using files instead of soundcard (used by linphonec only)
2122  *
2123  * Revision 1.29  2006/08/28 14:29:07  smorlat
2124  * fix bug.
2125  *
2126  * Revision 1.28  2006/08/21 12:49:59  smorlat
2127  * merged several little patches.
2128  *
2129  * Revision 1.27  2006/07/17 18:45:00  smorlat
2130  * support for several event queues in ortp.
2131  * glib dependency removed from coreapi/ and console/
2132  *
2133  * Revision 1.26  2006/04/14 15:16:36  smorlat
2134  * soundcard use did nothing !
2135  *
2136  * Revision 1.25  2006/04/06 20:09:33  smorlat
2137  * add linphonec command to see and select sound devices.
2138  *
2139  * Revision 1.24  2006/03/04 11:17:10  smorlat
2140  * mediastreamer2 in progress.
2141  *
2142  * Revision 1.23  2006/02/20 21:14:01  strk
2143  * Handled syntax errors with 'friend' command
2144  *
2145  * Revision 1.22  2006/02/20 10:20:29  strk
2146  * Added substring-based filter support for command 'friend list'
2147  *
2148  * Revision 1.21  2006/02/02 15:39:18  strk
2149  * - Added 'friend list' and 'friend call' commands
2150  * - Allowed for multiple DTFM send in a single line
2151  * - Added status-specific callback (bare version)
2152  *
2153  * Revision 1.20  2006/01/26 11:54:34  strk
2154  * More robust 'nat' command handler (strip blanks in args)
2155  *
2156  * Revision 1.19  2006/01/26 09:48:05  strk
2157  * Added limits.h include
2158  *
2159  * Revision 1.18  2006/01/26 02:18:05  strk
2160  * Added new commands 'nat use' and 'nat unuse'.
2161  * These will required a pending patch to linphonecore.c
2162  * in order to work.
2163  *
2164  * Revision 1.17  2006/01/20 14:12:33  strk
2165  * Added linphonec_init() and linphonec_finish() functions.
2166  * Handled SIGINT and SIGTERM to invoke linphonec_finish().
2167  * Handling of auto-termination (-t) moved to linphonec_finish().
2168  * Reworked main (input read) loop to not rely on 'terminate'
2169  * and 'run' variable (dropped). configfile_name allocated on stack
2170  * using PATH_MAX limit. Changed print_usage signature to allow
2171  * for an exit_status specification.
2172  *
2173  * Revision 1.16  2006/01/18 09:25:32  strk
2174  * Command completion inhibited in proxy addition and auth request prompts.
2175  * Avoided use of linphonec_readline's internal filename completion.
2176  *
2177  * Revision 1.15  2006/01/14 13:29:32  strk
2178  * Reworked commands interface to use a table structure,
2179  * used by command line parser and help function.
2180  * Implemented first level of completion (commands).
2181  * Added notification of invalid "answer" and "terminate"
2182  * commands (no incoming call, no active call).
2183  * Forbidden "call" intialization when a call is already active.
2184  * Cleaned up all commands, adding more feedback and error checks.
2185  *
2186  * Revision 1.14  2006/01/13 13:00:29  strk
2187  * Added linphonec.h. Code layout change (added comments, forward decl,
2188  * globals on top, copyright notices and Logs). Handled out-of-memory
2189  * condition on history management. Removed assumption on sizeof(char).
2190  * Fixed bug in authentication prompt (introduced by linphonec_readline).
2191  * Added support for multiple authentication requests (up to MAX_PENDING_AUTH).
2192  *
2193  *
2194  ****************************************************************************/