]> sjero.net Git - linphone/blobdiff - console/linphonec.c
Aac-eld add missing header according to RFC3640 3.3.6
[linphone] / console / linphonec.c
index 7fcc0aa4993cdb9f1a7e1ebdea76265e402a8eae..fca5a9b86987565c02c4e5914f4a524e13d140d9 100644 (file)
@@ -34,6 +34,7 @@
 #endif /*_WIN32_WCE*/
 #include <limits.h>
 #include <ctype.h>
+#include <stdlib.h>
 
 #include <linphonecore.h>
 
@@ -79,7 +80,6 @@
 
 #ifdef HAVE_X11_XLIB_H
 #include <X11/Xlib.h>
-#include <SDL/SDL_syswm.h>
 #endif
 
 /***************************************************************************
@@ -107,7 +107,7 @@ static int copy_file(const char *from, const char *to);
 #endif /*_WIN32_WCE*/
 static int linphonec_parse_cmdline(int argc, char **argv);
 static int linphonec_init(int argc, char **argv);
-static int linphonec_main_loop (LinphoneCore * opm, char * sipAddr);
+static int linphonec_main_loop (LinphoneCore * opm);
 static int linphonec_idle_call (void);
 #ifdef HAVE_READLINE
 static int linphonec_initialize_readline(void);
@@ -130,7 +130,7 @@ static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
                LinphoneFriend *lf, const char *url);
 
 static void linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
-               const char *from, const char *msg);
+               const LinphoneAddress *from, const char *msg);
 static void linphonec_display_status (LinphoneCore * lc, const char *something);
 static void linphonec_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf);
 static void print_prompt(LinphoneCore *opm);
@@ -160,7 +160,10 @@ LPC_AUTH_STACK auth_stack;
 static int trace_level = 0;
 static char *logfile_name = NULL;
 static char configfile_name[PATH_MAX];
-static char *sipAddr = NULL; /* for autocall */
+static char zrtpsecrets[PATH_MAX];
+static const char *factory_configfile_name=NULL;
+static char *sip_addr_to_call = NULL; /* for autocall */
+static int window_id = 0; /* 0=standalone window, or window id for embedding video */
 #if !defined(_WIN32_WCE)
 static ortp_pipe_t client_sock=ORTP_PIPE_INVALID;
 #endif /*_WIN32_WCE*/
@@ -173,8 +176,9 @@ static bool_t pipe_reader_run=FALSE;
 static ortp_pipe_t server_sock;
 #endif /*_WIN32_WCE*/
 
+bool_t linphonec_camera_enabled=TRUE;
+
 
-extern VideoParams lpc_video_params;
 
 void linphonec_call_identify(LinphoneCall* call){
        static long callid=1;
@@ -190,7 +194,7 @@ LinphoneCall *linphonec_get_call(long id){
                        return call;
                }
        }
-       linphonec_out("Sorry, no call with id %i exists at this time.",id);
+       linphonec_out("Sorry, no call with id %i exists at this time.\n",id);
        return NULL;
 }
 
@@ -206,7 +210,7 @@ LinphoneCall *linphonec_get_call(long id){
 static void
 linphonec_display_refer (LinphoneCore * lc, const char *refer_to)
 {
-       linphonec_out("Receiving out of call refer to %s", refer_to);
+       linphonec_out("Receiving out of call refer to %s\n", refer_to);
 }
 
 /*
@@ -313,18 +317,36 @@ linphonec_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf,
 
 }
 
+static void linphonec_call_updated(LinphoneCall *call){
+       const LinphoneCallParams *cp=linphone_call_get_current_params(call);
+       if (!linphone_call_camera_enabled (call) && linphone_call_params_video_enabled (cp)){
+               linphonec_out("Far end requests to share video.\nType 'camera on' if you agree.\n");
+       }
+}
+
+static void linphonec_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t encrypted, const char *auth_token) {
+       long id=(long)linphone_call_get_user_pointer (call);
+       if (!encrypted) {
+               linphonec_out("Call %i is not fully encrypted and auth token is %s.\n", id,
+                               (auth_token != NULL) ? auth_token : "absent");
+       } else {
+               linphonec_out("Call %i is fully encrypted and auth token is %s.\n", id,
+                               (auth_token != NULL) ? auth_token : "absent");
+       }
+}
+
 static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState st, const char *msg){
        char *from=linphone_call_get_remote_address_as_string(call);
        long id=(long)linphone_call_get_user_pointer (call);
        switch(st){
                case LinphoneCallEnd:
-                       linphonec_out("Call %i with %s ended.\n", id, from);
+                       linphonec_out("Call %i with %s ended (%s).\n", id, from, linphone_reason_to_string(linphone_call_get_reason(call)));
                break;
                case LinphoneCallResuming:
                        linphonec_out("Resuming call %i with %s.\n", id, from);
                break;
                case LinphoneCallStreamsRunning:
-                       linphonec_out("Media streams established with %s for call %i.\n", from,id);
+                       linphonec_out("Media streams established with %s for call %i (%s).\n", from,id,( linphone_call_params_video_enabled( linphone_call_get_current_params(call)) ? "video":"audio"));
                break;
                case LinphoneCallPausing:
                        linphonec_out("Pausing call %i with %s.\n", id, from);
@@ -337,16 +359,37 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
                break;
                case LinphoneCallIncomingReceived:
                        linphonec_call_identify(call);
+                       linphone_call_enable_camera (call,linphonec_camera_enabled);
                        id=(long)linphone_call_get_user_pointer (call);
                        linphonec_set_caller(from);
                        if ( auto_answer)  {
                                answer_call=TRUE;
                        }
-                       linphonec_out("Receiving new incoming call from %s, assigned id %i", from,id);
+                       linphonec_out("Receiving new incoming call from %s, assigned id %i\n", from,id);
                break;
                case LinphoneCallOutgoingInit:
                        linphonec_call_identify(call);
+                       id=(long)linphone_call_get_user_pointer (call);
+                       linphonec_out("Establishing call id to %s, assigned id %i\n", from,id);
                break;
+               case LinphoneCallUpdatedByRemote:
+                       linphonec_call_updated(call);
+               break;
+               case LinphoneCallOutgoingProgress:
+                       linphonec_out("Call %i to %s in progress.\n", id, from);
+                       break;
+               case LinphoneCallOutgoingRinging:
+                       linphonec_out("Call %i to %s ringing.\n", id, from);
+                       break;
+               case LinphoneCallConnected:
+                       linphonec_out("Call %i with %s connected.\n", id, from);
+                       break;
+               case LinphoneCallOutgoingEarlyMedia:
+                       linphonec_out("Call %i with %s early media.\n", id, from);
+                       break;
+               case LinphoneCallError:
+                       linphonec_out("Call %i with %s error.\n", id, from);
+                       break;
                default:
                break;
        }
@@ -358,9 +401,9 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L
  */
 static void
 linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
-               const char *from, const char *msg)
+               const LinphoneAddress *from, const char *msg)
 {
-       printf("%s: %s\n", from, msg);
+       linphonec_out("Message received from %s: %s\n", linphone_address_as_string(from), msg);
        // TODO: provide mechanism for answering.. ('say' command?)
 }
 
@@ -511,7 +554,8 @@ char *linphonec_readline(char *prompt){
                }
        }else{
 #ifdef HAVE_READLINE
-               return readline(prompt);
+               char* ret=readline(prompt);
+               return ret;
 #endif
        }
 }
@@ -585,7 +629,7 @@ main (int argc, char *argv[]) {
 #endif
        linphonec_vtable.call_state_changed=linphonec_call_state_changed;
        linphonec_vtable.notify_presence_recv = linphonec_notify_presence_received;
-       linphonec_vtable.new_unknown_subscriber = linphonec_new_unknown_subscriber;
+       linphonec_vtable.new_subscription_request = linphonec_new_unknown_subscriber;
        linphonec_vtable.auth_info_requested = linphonec_prompt_for_auth;
        linphonec_vtable.display_status = linphonec_display_status;
        linphonec_vtable.display_message=linphonec_display_something;
@@ -595,10 +639,11 @@ main (int argc, char *argv[]) {
        linphonec_vtable.dtmf_received=linphonec_dtmf_received;
        linphonec_vtable.refer_received=linphonec_display_refer;
        linphonec_vtable.notify_recv=linphonec_notify_received;
+       linphonec_vtable.call_encryption_changed=linphonec_call_encryption_changed;
        
        if (! linphonec_init(argc, argv) ) exit(EXIT_FAILURE);
 
-       linphonec_main_loop (linphonec, sipAddr);
+       linphonec_main_loop (linphonec);
 
        linphonec_finish(EXIT_SUCCESS);
 
@@ -623,6 +668,8 @@ linphonec_init(int argc, char **argv)
 #ifndef _WIN32
        snprintf(configfile_name, PATH_MAX, "%s/.linphonerc",
                        getenv("HOME"));
+       snprintf(zrtpsecrets, PATH_MAX, "%s/.linphone-zidcache",
+                       getenv("HOME"));
 #elif defined(_WIN32_WCE)
        strncpy(configfile_name,PACKAGE_DIR "\\linphonerc",PATH_MAX);
        mylogfile=fopen(PACKAGE_DIR "\\" "linphonec.log","w");
@@ -630,6 +677,8 @@ linphonec_init(int argc, char **argv)
 #else
        snprintf(configfile_name, PATH_MAX, "%s/Linphone/linphonerc",
                        getenv("APPDATA"));
+       snprintf(zrtpsecrets, PATH_MAX, "%s/Linphone/linphone-zidcache",
+                       getenv("APPDATA"));
 #endif
        /* Handle configuration filename changes */
        switch (handle_configfile_migration())
@@ -683,9 +732,15 @@ linphonec_init(int argc, char **argv)
        /*
         * Initialize linphone core
         */
-       linphonec=linphone_core_new (&linphonec_vtable, configfile_name, NULL,
-                           NULL);
+       linphonec=linphone_core_new (&linphonec_vtable, configfile_name, factory_configfile_name, NULL);
+       linphone_core_set_zrtp_secrets_file(linphonec,zrtpsecrets);
        linphone_core_enable_video(linphonec,vcap_enabled,display_enabled);
+       if (display_enabled && window_id != 0) 
+       {
+               printf ("Setting window_id: 0x%x\n", window_id);
+               linphone_core_set_native_video_window_id(linphonec,window_id);
+       }
+
        linphone_core_enable_video_preview(linphonec,preview_enabled);
        if (!(vcap_enabled || display_enabled)) printf("Warning: video is disabled in linphonec, use -V or -C or -D to enable.\n");
 #ifdef HAVE_READLINE
@@ -716,6 +771,10 @@ void linphonec_main_loop_exit(void){
 void
 linphonec_finish(int exit_status)
 {
+       // Do not allow concurrent destroying to prevent glibc errors
+       static bool_t terminating=FALSE;
+       if (terminating) return; 
+       terminating=TRUE;
        linphonec_out("Terminating...\n");
 
        /* Terminate any pending call */
@@ -734,7 +793,7 @@ linphonec_finish(int exit_status)
        {
                fclose (mylogfile);
        }
-
+       printf("\n");
        exit(exit_status);
 
 }
@@ -753,11 +812,17 @@ linphonec_finish(int exit_status)
 int
 linphonec_prompt_for_auth_final(LinphoneCore *lc)
 {
+       static int reentrancy=0;
        char *input, *iptr;
        char auth_prompt[256];
 #ifdef HAVE_READLINE
        rl_hook_func_t *old_event_hook;
 #endif
+
+       if (reentrancy!=0) return 0;
+       
+       reentrancy++;
+       
        LinphoneAuthInfo *pending_auth=auth_stack.elem[auth_stack.nitems-1];
 
        snprintf(auth_prompt, 256, "Password for %s on %s: ",
@@ -830,20 +895,22 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc)
 void
 print_usage (int exit_status)
 {
-       fprintf (stdout, "\n\
-usage: linphonec [-c file] [-s sipaddr] [-a] [-V] [-d level ] [-l logfile]\n\
-       linphonec -v\n\
-\n\
-  -c  file             specify path of configuration file.\n\
-  -d  level            be verbose. 0 is no output. 6 is all output\n\
-  -l  logfile          specify the log file for your SIP phone\n\
-  -s  sipaddress       specify the sip call to do at startup\n\
-  -a                   enable auto answering for incoming calls\n\
-  -V                   enable video features globally (disabled by default)\n\
-  -C                   enable video capture only (disabled by default)\n\
-  -D                   enable video display only (disabled by default)\n\
-  -S                   show general state messages (disabled by default)\n\
-  -v or --version      display version and exits.\n");
+       fprintf (stdout, "\n"
+"usage: linphonec [-c file] [-s sipaddr] [-a] [-V] [-d level ] [-l logfile]\n"
+       "linphonec -v\n"
+"\n"
+"  -b  file             specify path of readonly factory configuration file.\n"
+"  -c  file             specify path of configuration file.\n"
+"  -d  level            be verbose. 0 is no output. 6 is all output\n"
+"  -l  logfile          specify the log file for your SIP phone\n"
+"  -s  sipaddress       specify the sip call to do at startup\n"
+"  -a                   enable auto answering for incoming calls\n"
+"  -V                   enable video features globally (disabled by default)\n"
+"  -C                   enable video capture only (disabled by default)\n"
+"  -D                   enable video display only (disabled by default)\n"
+"  -S                   show general state messages (disabled by default)\n"
+"  --wid  windowid      force embedding of video window into provided windowid (disabled by default)\n"
+"  -v or --version      display version and exits.\n");
 
        exit(exit_status);
 }
@@ -851,59 +918,71 @@ usage: linphonec [-c file] [-s sipaddr] [-a] [-V] [-d level ] [-l logfile]\n\
 #ifdef VIDEO_ENABLED
 
 #ifdef HAVE_X11_XLIB_H
-static void sdl_x11_apply_video_params(){
-       static SDL_SysWMinfo info;
-       static bool_t wminfo_ready=FALSE;
-       
-       if ( !wminfo_ready){
-               SDL_VERSION(&info.version);
-               if ( SDL_GetWMInfo(&info) ) {
-                       if ( info.subsystem == SDL_SYSWM_X11 ) {
-                               wminfo_ready=TRUE;
-                       }
-               }
+static void x11_apply_video_params(VideoParams *params, Window window){
+       XWindowChanges wc;
+       unsigned int flags=0;
+       static Display *display = NULL;
+       const char *dname=getenv("DISPLAY");
+
+       if (display==NULL && dname!=NULL){
+               XInitThreads();
+               display=XOpenDisplay(dname);
        }
-       if ( !wminfo_ready) return;
-       
-       {
-               XWindowChanges wc;
-               unsigned int flags=0;
-               Display *display = info.info.x11.display;
-               Window window = info.info.x11.wmwindow;
-               
-               memset(&wc,0,sizeof(wc));
-               wc.x=lpc_video_params.x;
-               wc.y=lpc_video_params.y;
-               wc.width=lpc_video_params.w;
-               wc.height=lpc_video_params.h;
-               if (lpc_video_params.x!=-1 ){
-                       flags|=CWX|CWY;
-               }
-               if (lpc_video_params.w!=-1){
-                       flags|=CWWidth|CWHeight;
-               }
-               info.info.x11.lock_func();
-               XConfigureWindow(display,window,flags,&wc);
-               if (lpc_video_params.show)
-                       XMapWindow(display,window);
-               else
-                       XUnmapWindow(display,window);
-               info.info.x11.unlock_func();
+
+       if (display==NULL){
+               ms_error("Could not open display %s",dname);
+               return;
        }
+       memset(&wc,0,sizeof(wc));
+       wc.x=params->x;
+       wc.y=params->y;
+       wc.width=params->w;
+       wc.height=params->h;
+       if (params->x!=-1 ){
+               flags|=CWX|CWY;
+       }
+       if (params->w!=-1){
+               flags|=CWWidth|CWHeight;
+       }
+       /*printf("XConfigureWindow x=%i,y=%i,w=%i,h=%i\n",
+              wc.x, wc.y ,wc.width, wc.height);*/
+       XConfigureWindow(display,window,flags,&wc);
+       if (params->show)
+               XMapWindow(display,window);
+       else
+               XUnmapWindow(display,window);
+       XSync(display,FALSE);
 }
 #endif
 
 
 static void lpc_apply_video_params(){
-       if (lpc_video_params.refresh){
-               unsigned long wid=linphone_core_get_native_video_window_id (linphonec);
-               if (wid!=0){
-                       lpc_video_params.refresh=FALSE;
+       static unsigned long old_wid=0,old_pwid=0;
+       unsigned long wid=linphone_core_get_native_video_window_id (linphonec);
+       unsigned long pwid=linphone_core_get_native_preview_window_id (linphonec);
+
+       if (wid!=0 && (lpc_video_params.refresh || old_wid!=wid)){
+               lpc_video_params.refresh=FALSE;
 #ifdef HAVE_X11_XLIB_H
-                       sdl_x11_apply_video_params();
+               if (lpc_video_params.wid==0){  // do not manage window if embedded
+                       x11_apply_video_params(&lpc_video_params,wid);
+               } else {
+                       linphone_core_show_video(linphonec, lpc_video_params.show);
+               }
 #endif
+       }
+       old_wid=wid;
+       if (pwid!=0 && (lpc_preview_params.refresh || old_pwid!=pwid)){
+               lpc_preview_params.refresh=FALSE;
+#ifdef HAVE_X11_XLIB_H
+               /*printf("wid=%lu pwid=%lu\n",wid,pwid);*/
+               if (lpc_preview_params.wid==0){  // do not manage window if embedded
+                       printf("Refreshing\n");
+                       x11_apply_video_params(&lpc_preview_params,pwid);
                }
+#endif
        }
+       old_pwid=pwid;
 }
 
 #endif
@@ -933,6 +1012,14 @@ linphonec_idle_call ()
                linphone_core_accept_call(opm,NULL);
                answer_call=FALSE;
        }
+       /* auto call handling */
+       if (sip_addr_to_call != NULL )
+       {
+               char buf[512];
+               snprintf (buf, sizeof(buf),"call %s", sip_addr_to_call);
+               sip_addr_to_call=NULL;
+               linphonec_parse_command_line(linphonec, buf);
+       }
 
        if ( auth_stack.nitems )
        {
@@ -1021,21 +1108,13 @@ static void print_prompt(LinphoneCore *opm){
 }
 
 static int
-linphonec_main_loop (LinphoneCore * opm, char * sipAddr)
+linphonec_main_loop (LinphoneCore * opm)
 {
-       char buf[LINE_MAX_LEN]; /* auto call handling */
        char *input;
 
        print_prompt(opm);
 
 
-       /* auto call handling */
-       if (sipAddr != NULL )
-       {
-               snprintf (buf, sizeof(buf),"call %s", sipAddr);
-               linphonec_parse_command_line(linphonec, buf);
-       }
-
        while (linphonec_running && (input=linphonec_readline(prompt)))
        {
                char *iptr; /* input and input pointer */
@@ -1125,11 +1204,25 @@ linphonec_parse_cmdline(int argc, char **argv)
 #endif /*_WIN32_WCE*/
                        snprintf(configfile_name, PATH_MAX, "%s", argv[arg_num]);
                }
+               else if (strncmp ("-b", argv[arg_num], 2) == 0)
+               {
+                       if ( ++arg_num >= argc ) print_usage(EXIT_FAILURE);
+#if !defined(_WIN32_WCE)
+                       if (access(argv[arg_num],F_OK)!=0 )
+                       {
+                               fprintf (stderr,
+                                       "Cannot open config file %s.\n",
+                                        argv[arg_num]);
+                               exit(EXIT_FAILURE);
+                       }
+#endif /*_WIN32_WCE*/
+                       factory_configfile_name = argv[arg_num];
+               }
                else if (strncmp ("-s", argv[arg_num], 2) == 0)
                {
                        arg_num++;
                        if (arg_num < argc)
-                               sipAddr = argv[arg_num];
+                               sip_addr_to_call = argv[arg_num];
                }
                 else if (strncmp ("-a", argv[arg_num], 2) == 0)
                 {
@@ -1168,6 +1261,15 @@ linphonec_parse_cmdline(int argc, char **argv)
                {
                        unix_socket=1;
                }
+               else if (strncmp ("--wid", argv[arg_num], 5) == 0)
+               {
+                       arg_num++;
+                       if (arg_num < argc) {
+                               char *tmp;
+                               window_id = strtol( argv[arg_num], &tmp, 0 );
+                               lpc_video_params.wid = window_id;
+                       }
+               }
                else if (old_arg_num == arg_num)
                {
                        fprintf (stderr, "ERROR: bad arguments\n");