]> sjero.net Git - linphone/blobdiff - console/linphonec.c
Fix bug report
[linphone] / console / linphonec.c
index 024075cf06843a0f3e9f288fc9bff4e390b6dcf3..60c3c2af11c48256e6af0ccfaa290d702e683b05 100644 (file)
@@ -34,6 +34,7 @@
 #endif /*_WIN32_WCE*/
 #include <limits.h>
 #include <ctype.h>
+#include <stdlib.h>
 
 #include <linphonecore.h>
 
 #define PACKAGE_DIR ""
 #endif
 
+#ifdef HAVE_X11_XLIB_H
+#include <X11/Xlib.h>
+#endif
+
 /***************************************************************************
  *
  *  Types
@@ -102,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);
@@ -112,28 +117,22 @@ static char **linephonec_readline_completion(const char *text,
 #endif
 
 /* These are callback for linphone core */
-static void linphonec_call_received(LinphoneCore *lc, LinphoneCall *call);
-static void linphonec_paused_received(LinphoneCore *lc, LinphoneCall *call);
-static void linphonec_resumed_received(LinphoneCore *lc, LinphoneCall *call);
 static void linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm,
        const char *username);
-static void linphonec_display_refer (LinphoneCore * lc,LinphoneCall *call, const char *refer_to);
+static void linphonec_display_refer (LinphoneCore * lc, const char *refer_to);
 static void linphonec_display_something (LinphoneCore * lc, const char *something);
 static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url);
 static void linphonec_display_warning (LinphoneCore * lc, const char *something);
-static void stub () {}
-static void linphonec_notify_received(LinphoneCore *lc,const char *from,const char *msg);
-static void linphonec_ack_paused_received(LinphoneCore *lc, LinphoneCall *call);
-static void linphonec_ack_resumed_received(LinphoneCore *lc, LinphoneCall *call);
+static void linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event);
+
 static void linphonec_notify_presence_received(LinphoneCore *lc,LinphoneFriend *fid);
 static void linphonec_new_unknown_subscriber(LinphoneCore *lc,
                LinphoneFriend *lf, const char *url);
-static void linphonec_bye_received(LinphoneCore *lc, LinphoneCall *call);
+
 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_general_state (LinphoneCore * lc, LinphoneGeneralState *gstate);
-static void linphonec_dtmf_received(LinphoneCore *lc, int dtmf);
+static void linphonec_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf);
 static void print_prompt(LinphoneCore *opm);
 void linphonec_out(const char *fmt,...);
 /***************************************************************************
@@ -161,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*/
@@ -174,42 +176,27 @@ static bool_t pipe_reader_run=FALSE;
 static ortp_pipe_t server_sock;
 #endif /*_WIN32_WCE*/
 
+bool_t linphonec_camera_enabled=TRUE;
+
 
-LinphoneCoreVTable linphonec_vtable
-#if !defined (_MSC_VER)
-= {
-       .show =(ShowInterfaceCb) stub,
-       .inv_recv = linphonec_call_received,
-       .bye_recv = linphonec_bye_received,
-       .ringing_recv = (RingingReceivedCb) stub,
-       .connected_recv = (ConnectedReceivedCb) stub,
-       .failure_recv = (FailureReceivedCb) stub,
-       .paused_recv = linphonec_paused_received,
-       .resumed_recv = linphonec_resumed_received,
-       .notify_recv = linphonec_notify_received,
-       .ack_paused_recv = linphonec_ack_paused_received,
-       .ack_resumed_recv = linphonec_ack_resumed_received,
-       .notify_presence_recv = linphonec_notify_presence_received,
-       .new_unknown_subscriber = linphonec_new_unknown_subscriber,
-       .auth_info_requested = linphonec_prompt_for_auth,
-       .display_status = linphonec_display_status,
-       .display_message=linphonec_display_something,
-#ifdef VINCENT_MAURY_RSVP
-       /* the yes/no dialog box */
-       .display_yes_no= (DisplayMessageCb) stub,
-#endif
-       .display_warning=linphonec_display_warning,
-       .display_url=linphonec_display_url,
-       .display_question=(DisplayQuestionCb)stub,
-       .text_received=linphonec_text_received,
-       .general_state=linphonec_general_state,
-       .dtmf_received=linphonec_dtmf_received,
-       .refer_received=linphonec_display_refer
-}
-#endif /*_WIN32_WCE*/
-;
 
+void linphonec_call_identify(LinphoneCall* call){
+       static long callid=1;
+       linphone_call_set_user_pointer (call,(void*)callid);
+       callid++;
+}
 
+LinphoneCall *linphonec_get_call(long id){
+       const MSList *elem=linphone_core_get_calls(linphonec);
+       for (;elem!=NULL;elem=elem->next){
+               LinphoneCall *call=(LinphoneCall*)elem->data;
+               if (linphone_call_get_user_pointer (call)==(void*)id){
+                       return call;
+               }
+       }
+       linphonec_out("Sorry, no call with id %i exists at this time.\n",id);
+       return NULL;
+}
 
 /***************************************************************************
  *
@@ -221,10 +208,9 @@ LinphoneCoreVTable linphonec_vtable
  * Linphone core callback
  */
 static void
-linphonec_display_refer (LinphoneCore * lc,LinphoneCall *call, const char *refer_to)
+linphonec_display_refer (LinphoneCore * lc, const char *refer_to)
 {
-       fprintf (stdout, "The distant end point asked to transfer the call to %s,don't forget to terminate the call if not\n%s", refer_to,prompt);
-       fflush(stdout);
+       linphonec_out("Receiving out of call refer to %s\n", refer_to);
 }
 
 /*
@@ -266,49 +252,6 @@ linphonec_display_url (LinphoneCore * lc, const char *something, const char *url
        fprintf (stdout, "%s : %s\n", something, url);
 }
 
-
-/*
- * Linphone core callback
- */
-static void
-linphonec_call_received(LinphoneCore *lc, LinphoneCall *call)
-{
-       char *from=linphone_call_get_remote_address_as_string(call);
-       linphonec_set_caller(from);
-       ms_free(from);
-       if ( auto_answer)  {
-               answer_call=TRUE;
-       }
-}
-/*
- * Linphone core callback
- */
-static void
-linphonec_paused_received(LinphoneCore *lc, LinphoneCall *call)
-{
-       char *from=linphone_call_get_remote_address_as_string(call);
-       if(from)
-       {
-               linphonec_out("the call from %s have been paused\n",from);
-               ms_free(from);
-       }
-}
-/*
- * Linphone core callback
- */
-static void
-linphonec_resumed_received(LinphoneCore *lc, LinphoneCall *call)
-{
-       char *from=linphone_call_get_remote_address_as_string(call);
-       if(from)
-       {
-               linphonec_out("the call from %s have been resumed\n",from);
-               ms_free(from);
-       }
-}
-
-
-
 /*
  * Linphone core callback
  */
@@ -338,43 +281,15 @@ linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *usern
  * Linphone core callback
  */
 static void
-linphonec_notify_received(LinphoneCore *lc,const char *from,const char *msg)
+linphonec_notify_received(LinphoneCore *lc, LinphoneCall *call, const char *from,const char *event)
 {
-       printf("Notify type %s from %s\n", msg, from);
-       if(!strcmp(msg,"refer"))
-       {
-               printf("The distant SIP end point get the refer we can close the call\n");
-               linphonec_parse_command_line(linphonec, "terminate");
-       }
-}
-
-/*
- * Linphone core callback
- */
-static void
-linphonec_ack_paused_received(LinphoneCore *lc, LinphoneCall *call)
-{
-       char *from=linphone_call_get_remote_address_as_string(call);
-       if(from)
+       if(!strcmp(event,"refer"))
        {
-               linphonec_out("the previous pause sent to %s has been acknowledged\n",from);
-               ms_free(from);
+               linphonec_out("The distand endpoint %s of call %li has been transfered, you can safely close the call.\n",
+                             from,(long)linphone_call_get_user_pointer (call));
        }
 }
 
-/*
- * Linphone core callback
- */
-static void
-linphonec_ack_resumed_received(LinphoneCore *lc, LinphoneCall *call)
-{
-       char *from=linphone_call_get_remote_address_as_string(call);
-       if(from)
-       {
-               linphonec_out("the previous resume sent to %s has been acknowledged\n",from);
-               ms_free(from);
-       }
-}
 
 /*
  * Linphone core callback
@@ -402,18 +317,82 @@ linphonec_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf,
 
 }
 
-/*
- * Linphone core callback
- */
-static void
-linphonec_bye_received(LinphoneCore *lc, LinphoneCall *call)
-{
-       // Should change prompt back to original maybe
+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");
+       }
+}
 
-       // printing this is unneeded as we'd get a "Communication ended"
-       // message trough display_status callback anyway
+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);
-       printf("Bye received from %s\n", from);
+       long id=(long)linphone_call_get_user_pointer (call);
+       switch(st){
+               case LinphoneCallEnd:
+                       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 (%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);
+               break;
+               case LinphoneCallPaused:
+                       linphonec_out("Call %i with %s is now paused.\n", id, from);
+               break;
+               case LinphoneCallPausedByRemote:
+                       linphonec_out("Call %i has been paused by %s.\n",id,from);
+               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\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;
+       }
        ms_free(from);
 }
 
@@ -422,71 +401,18 @@ linphonec_bye_received(LinphoneCore *lc, LinphoneCall *call)
  */
 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?)
 }
 
 
-static void linphonec_dtmf_received(LinphoneCore *lc, int dtmf){
-       fprintf(stdout,"Receiving tone %c\n",dtmf);
+static void linphonec_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf){
+       char *from=linphone_call_get_remote_address_as_string(call);
+       fprintf(stdout,"Receiving tone %c from %s\n",dtmf,from);
        fflush(stdout);
-}
-
-static void
-linphonec_general_state (LinphoneCore * lc, LinphoneGeneralState *gstate)
-{
-        if (show_general_state) {
-          switch(gstate->new_state) {
-           case GSTATE_POWER_OFF:
-             printf("GSTATE_POWER_OFF");
-             break;
-           case GSTATE_POWER_STARTUP:
-             printf("GSTATE_POWER_STARTUP");
-             break;
-           case GSTATE_POWER_ON:
-             printf("GSTATE_POWER_ON");
-             break;
-           case GSTATE_POWER_SHUTDOWN:
-             printf("GSTATE_POWER_SHUTDOWN");
-             break;
-           case GSTATE_REG_NONE:
-             printf("GSTATE_REG_NONE");
-             break;
-           case GSTATE_REG_OK:
-             printf("GSTATE_REG_OK");
-             break;
-           case GSTATE_REG_FAILED:
-             printf("GSTATE_REG_FAILED");
-             break;
-           case GSTATE_CALL_IDLE:
-             printf("GSTATE_CALL_IDLE");
-             break;
-           case GSTATE_CALL_OUT_INVITE:
-             printf("GSTATE_CALL_OUT_INVITE");
-             break;
-           case GSTATE_CALL_OUT_CONNECTED:
-             printf("GSTATE_CALL_OUT_CONNECTED");
-             break;
-           case GSTATE_CALL_IN_INVITE:
-             printf("GSTATE_CALL_IN_INVITE");
-             break;
-           case GSTATE_CALL_IN_CONNECTED:
-             printf("GSTATE_CALL_IN_CONNECTED");
-             break;
-           case GSTATE_CALL_END:
-             printf("GSTATE_CALL_END");
-             break;
-           case GSTATE_CALL_ERROR:
-             printf("GSTATE_CALL_ERROR");
-             break;
-           default:
-              printf("GSTATE_UNKNOWN_%d",gstate->new_state);
-          }
-          if (gstate->message) printf(" %s", gstate->message);
-          printf("\n");
-        }
+       ms_free(from);
 }
 
 static char received_prompt[PROMPT_MAX_LEN];
@@ -628,7 +554,8 @@ char *linphonec_readline(char *prompt){
                }
        }else{
 #ifdef HAVE_READLINE
-               return readline(prompt);
+               char* ret=readline(prompt);
+               return ret;
 #endif
        }
 }
@@ -668,6 +595,8 @@ bool_t linphonec_get_autoanswer(){
        return auto_answer;
 }
 
+LinphoneCoreVTable linphonec_vtable={0};
+
 /***************************************************************************/
 /*
  * Main
@@ -693,34 +622,28 @@ char **convert_args_to_ascii(int argc, _TCHAR **wargv){
 int _tmain(int argc, _TCHAR* wargv[]) {
        char **argv=convert_args_to_ascii(argc,wargv);
        trace_level=6;
-       linphonec_vtable.show =(ShowInterfaceCb) stub;
-       linphonec_vtable.inv_recv = linphonec_call_received;
-       linphonec_vtable.bye_recv = linphonec_bye_received;
-       linphonec_vtable.notify_presence_recv = linphonec_notify_received;
-       linphonec_vtable.new_unknown_subscriber = linphonec_new_unknown_subscriber;
+
+#else
+int
+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_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;
-#ifdef VINCENT_MAURY_RSVP
-       /* the yes/no dialog box */
-       linphonec_vtable.display_yes_no= (DisplayMessageCb) stub;
-#endif
        linphonec_vtable.display_warning=linphonec_display_warning;
        linphonec_vtable.display_url=linphonec_display_url;
-       linphonec_vtable.display_question=(DisplayQuestionCb)stub;
        linphonec_vtable.text_received=linphonec_text_received;
-       linphonec_vtable.general_state=linphonec_general_state;
        linphonec_vtable.dtmf_received=linphonec_dtmf_received;
-
-#else
-int
-main (int argc, char *argv[]) {
-#endif
-
-
+       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);
 
@@ -745,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");
@@ -752,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())
@@ -805,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
@@ -838,11 +771,14 @@ void linphonec_main_loop_exit(void){
 void
 linphonec_finish(int exit_status)
 {
-       printf("Terminating...\n");
+       // 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 */
-       linphonec_parse_command_line(linphonec, "terminate");
-       linphonec_command_finished();
+       linphone_core_terminate_all_calls(linphonec);
 #ifdef HAVE_READLINE
        linphonec_finish_readline();
 #endif
@@ -857,7 +793,7 @@ linphonec_finish(int exit_status)
        {
                fclose (mylogfile);
        }
-
+       printf("\n");
        exit(exit_status);
 
 }
@@ -876,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: ",
@@ -953,24 +895,98 @@ 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);
 }
 
+#ifdef VIDEO_ENABLED
+
+#ifdef HAVE_X11_XLIB_H
+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 (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(){
+       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
+               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
+
 
 /*
  *
@@ -996,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 )
        {
@@ -1012,6 +1036,10 @@ linphonec_idle_call ()
 #endif
        }
 
+#ifdef VIDEO_ENABLED
+       lpc_apply_video_params();
+#endif
+
        return 0;
 }
 
@@ -1080,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 */
@@ -1184,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)
                 {
@@ -1227,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");
@@ -1357,6 +1400,7 @@ copy_file(const char *from, const char *to)
                snprintf(message, 255, "Can't open %s for writing: %s\n",
                        to, strerror(errno));
                fprintf(stderr, "%s", message);
+               fclose(in);
                return 0;
        }
 
@@ -1365,6 +1409,8 @@ copy_file(const char *from, const char *to)
        {
                if ( ! fwrite(buf, 1, n, out) )
                {
+                       fclose(in);
+                       fclose(out);
                        return 0;
                }
        }