Commit 4496bcfc authored by smorlat's avatar smorlat
Browse files

merge patch from Jim Diammond to allow remote calling for the gtk interface.

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@592 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
parent b127b27d
......@@ -1428,11 +1428,13 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args)
else if (strstr(args,"hook"))
{
gstate_t call_state=linphone_core_get_state(lc,GSTATE_GROUP_CALL);
/*
if (!cfg || !linphone_proxy_config_is_registered(cfg)){
linphonec_out("unregistered\n");
return 1;
}
switch(call_state){
*/
switch(call_state){
case GSTATE_CALL_OUT_INVITE:
linphonec_out("hook=dialing\n");
break;
......
......@@ -164,6 +164,13 @@ LinphoneCoreVTable linphonec_vtable = {
.dtmf_received=linphonec_dtmf_received
};
/* zsd: called from exevents, only interesting to gui */
void linphone_call_started_remotely(const char * url)
{
}
/***************************************************************************
*
* Linphone core callbacks
......
......@@ -22,6 +22,11 @@ call.
#include <eXosip2/eXosip.h>
/* zsd: called from exevents, only interesting to gui */
void linphone_call_started_remotely(const char * url)
{
}
int run_cond=1;
Sipomatic sipomatic;
......
......@@ -25,6 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <osipparser2/osip_message.h>
#include <osipparser2/osip_parser.h>
/* zsd: only want to do something here if the GUI is active */
void linphone_call_started_remotely(const char * URL);
static int linphone_answer_sdp(LinphoneCore *lc, eXosip_event_t *ev, sdp_message_t *sdp);
static bool_t linphone_call_matches_event(LinphoneCall *call, eXosip_event_t *ev){
......@@ -333,19 +337,28 @@ int linphone_inc_new_call(LinphoneCore *lc, eXosip_event_t *ev)
barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you."));
lc->vtable.show(lc);
lc->vtable.display_status(lc,barmesg);
lc->vtable.inv_recv(lc,tmp);
ms_free(barmesg);
osip_free(tmp);
linphone_call_set_state(lc->call,LCStateRinging);
eXosip_lock();
eXosip_call_send_answer(ev->tid,180,NULL);
eXosip_unlock();
/* play the ring */
/*
* zsd moved this statement and the next four from the bottom of
* this block so that the gui inv_recv function could automatically
* answer.
* With this below, the ringing didn't start until after the
* auto-answer, which caused the ring to time out and terminate the
* call.
*/
if (lc->sound_conf.ring_sndcard!=NULL){
ms_message("Starting local ring...");
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
}
linphone_call_set_state(lc->call,LCStateRinging);
eXosip_lock();
eXosip_call_send_answer(ev->tid,180,NULL);
eXosip_unlock();
lc->vtable.inv_recv(lc,tmp);
ms_free(barmesg);
osip_free(tmp);
}else{
ms_error("Error during sdp negociation. ");
eXosip_lock();
......@@ -1016,7 +1029,64 @@ static void linphone_other_request(LinphoneCore *lc, eXosip_event_t *ev){
ms_message("Receiving WAKEUP request !");
if (lc->vtable.show)
lc->vtable.show(lc);
}else {
}
/* zsd addition: allow a "remote" call request */
/*
* The current implementation of the feature is a horrible kludge:
* rather than extracting the URL from the body, get it from the SIP
* method... it is all the chars after "CALL".
*/
else if (strncmp(ev->request->sip_method, "CALL", 4) == 0
&& comes_from_local_if(ev->request))
{
char * sip_method = ev->request->sip_method;
eXosip_message_send_answer(ev->tid, 200, NULL);
ms_message("Received CALL request.");
/*
fprintf(stderr, "Received CALL request!\n");
fprintf(stderr, "addr to call is |%s|\n", &ev->request->sip_method[4]);
fprintf(stderr, "addr to call is |%s|\n", &sip_method[4]);
*/
/*
* The following two lines of code should probably be wrapped into
* something and then put in a new slot in the vtable.
*/
linphone_core_invite(lc, &sip_method[4]);
linphone_call_started_remotely(&sip_method[4]);
#if 0
fprintf(stderr, "textinfo is |%s|\n", ev->textinfo);
fprintf(stderr, "request content_length is |%s|\n",
ev->request->content_length->value);
/*
* The following code (in the braces) was snarfled off the web, as
* an example of how to get at the body content.
* It didn't work for me.
*/
{
int pos = 0;
while (!osip_list_eol (&ev->request->bodies, pos))
{
osip_body_t * oldbody;
oldbody = (osip_body_t *)osip_list_get(&ev->request->bodies,
pos);
pos++;
/* !!!! -> body is here: "oldbody->body" */
fprintf(stderr, "oldbody->length = %d\n", oldbody->length);
fprintf(stderr, "oldbody->body = %s\n", oldbody->body);
}
}
fprintf(stderr, "request is |%s|\n", ev->request->message);
#endif
if (lc->vtable.show)
lc->vtable.show(lc);
}
else {
char *tmp=NULL;
size_t msglen=0;
osip_message_to_str(ev->request,&tmp,&msglen);
......
......@@ -788,7 +788,13 @@ struct _LpConfig *linphone_core_get_config(LinphoneCore *lc);
/* attempts to wake up another linphone engine already running.
The "show" callback is called for the other linphone, causing gui to show up.
The method returns 0 if an already running linphone was found*/
/* zsd: old code was
int linphone_core_wake_up_possible_already_running_instance(const char *config_file);
* new code: If the second arg is non-null, pass the call addr to the
* already-running instance.
*/
int linphone_core_wake_up_possible_already_running_instance(
const char * config_file, const char * call_addr);
/*set a callback for some blocking operations, it takes you informed of the progress of the operation*/
void linphone_core_set_waiting_callback(LinphoneCore *lc, LinphoneWaitingCallback cb, void *user_context);
......
......@@ -679,7 +679,10 @@ static int extract_sip_port(const char *config){
return ret;
}
int linphone_core_wake_up_possible_already_running_instance(const char *config_file){
/* zsd added "addr_to_call" to this function. */
int linphone_core_wake_up_possible_already_running_instance(
const char * config_file, const char * addr_to_call)
{
int port=extract_sip_port(config_file);
const char *wakeup="WAKEUP sip:127.0.0.1 SIP/2.0\r\n"
"Via: SIP/2.0/UDP 127.0.0.1:%i;rport;branch=z9hG4bK%u\r\n"
......@@ -688,6 +691,19 @@ int linphone_core_wake_up_possible_already_running_instance(const char *config_f
"CSeq: 1 WAKEUP\r\n"
"Call-ID: %u@onsantape\r\n"
"Content-length: 0\r\n\r\n";
/*
* zsd: is this the worst kludge ever?
* Q: How do you extract the body of the message at the other end??
* (Use "...Content-length: %d\r\n\r\n%s\r\n", strlen(a_to_c)+2, a_to_c
* to put stuff in the body, assuming content length includes the \r\n.)
*/
const char * call = "CALL%s sip:127.0.0.1 SIP/2.0\r\n"
"Via: SIP/2.0/UDP 127.0.0.1:%i;rport;branch=z9hG4bK%u\r\n"
"From: <sip:another_linphone@127.0.0.1>;tag=%u\r\n"
"To: <sip:you@127.0.0.1>\r\n"
"CSeq: 1 CALL\r\n"
"Call-ID: %u@onsantape\r\n" "Content-length: 0\r\n\r\n";
/*make sure ortp is initialized (it initializes win32 socket api)*/
ortp_init();
if (port>0){
......@@ -701,7 +717,15 @@ int linphone_core_wake_up_possible_already_running_instance(const char *config_f
if (sock<0) sock=create_socket(++locport);
if (sock>=0){
char req[512];
snprintf(req,sizeof(req),wakeup,locport,random(),random(),random());
/* zsd */
if (addr_to_call != NULL)
snprintf(req, sizeof(req), call, addr_to_call, locport,
random(), random(), random());
else
snprintf(req, sizeof(req), wakeup, locport,
random(), random(), random());
//fprintf(stderr, "linphone_core_wake_up_... MAY send\n|%s|\n", req); /* zsd */
//original line of code: snprintf(req,sizeof(req),wakeup,locport,random(),random(),random());
if (connect(sock,(struct sockaddr*)&ss,sslen)<0){
fprintf(stderr,"connect failed: %s\n",getSocketError());
}else if (send(sock,req,strlen(req),0)>0){
......@@ -710,8 +734,11 @@ int linphone_core_wake_up_possible_already_running_instance(const char *config_f
for(i=0;i<10;++i){
if (recv(sock,req,sizeof(req),0)>0){
close_socket(sock);
//fprintf(stderr, "GOT A RESPONSE to the wake-up message\n"); /* zsd */
return 0;
}else if (getSocketErrorCode()!=EWOULDBLOCK){
/* zsd */
// fprintf(stderr, "l_c_w_u_p_a_r_i: WOULDN'T BLOCK!\n");
break;
}
#ifdef WIN32
......@@ -720,10 +747,21 @@ int linphone_core_wake_up_possible_already_running_instance(const char *config_f
usleep(100000);
#endif
}
}else ms_message("sendto() of WAKEUP request failed, nobody to wakeup.");
}else
{
/* zsd fprintf() */
// fprintf(stderr, "sendto() of WAKEUP request failed\n");
ms_message("sendto() of WAKEUP request failed, nobody to wakeup.");
}
}
// else /* zsd */
// fprintf(stderr, "l_c_w_u_p_a_r_i: unable to create socket\n");
close_socket(sock);
}
}
/* zsd */
// else
// fprintf(stderr, "l_c_w_u_p_a_r_i: port <= 0 !!!!!!!\n");
return -1;
}
......@@ -70,14 +70,31 @@ static LinphoneCoreVTable vtable={
};
static gboolean verbose=0;
static GOptionEntry linphone_options[2]={
static gboolean auto_answer = 0; /* zsd */
static gchar * addr_to_call = NULL; /* zsd: FIXME: is this correct??? */
static GOptionEntry linphone_options[]={ /* zsd deleted array size 2 */
{
.long_name="verbose",
.short_name= '\0',
.arg=G_OPTION_ARG_NONE,
.arg_data= (gpointer)&verbose,
.description="log to stdout some debug information while running."
}
},
{ /* zsd addition */
.long_name = "call",
.short_name = 'c',
.arg = G_OPTION_ARG_STRING,
.arg_data = &addr_to_call, /* zsd: FIXME: is this correct??? */
.description = "address to call right now"
},
{ /* zsd addition */
.long_name = "auto-answer",
.short_name = 'a',
.arg = G_OPTION_ARG_NONE,
.arg_data = (gpointer) & auto_answer,
.description = "if set, automatically answer incoming calls"
},
{0}
};
#define INSTALLED_XML_DIR PACKAGE_DATA_DIR "/linphone"
......@@ -505,6 +522,9 @@ void linphone_gtk_terminate_call(GtkWidget *button){
void linphone_gtk_decline_call(GtkWidget *button){
linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
/* zsd note: there was a big here in 3.0.0 which caused an abort if
* someone clicked "decline"... the following line of code looks
* like a fix for that. */
gtk_widget_destroy(gtk_widget_get_toplevel(button));
}
......@@ -556,6 +576,23 @@ static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from){
GtkWidget *w=linphone_gtk_create_window("incoming_call");
GtkWidget *label;
gchar *msg;
if (auto_answer) // zsd addition
{
/*
* Let the phone ring a bit before the auto-answer so that the
* local user knows something is happening.
*/
//fflush(stdout);fprintf(stderr, "******************** sleep(2)\n");
sleep(2);
//fflush(stdout);fprintf(stderr, "******************** calling linphone_core_accept_call()\n");
linphone_core_accept_call(linphone_gtk_get_core(), NULL);
//fflush(stdout);fprintf(stderr, "******************** calling linphone_gtk_call_started()\n");
linphone_gtk_call_started(linphone_gtk_get_main_window());
return;
}
gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(linphone_gtk_get_main_window()));
gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER_ON_PARENT);
......@@ -968,22 +1005,64 @@ void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
linphone_gtk_log_push(lev,fmt,args);
}
/* zsd added this */
void linphone_call_started_remotely(const char * url)
{
GtkEntry * uri_bar =
GTK_ENTRY(linphone_gtk_get_widget
(linphone_gtk_get_main_window(), "uribar"));
gtk_entry_set_text(uri_bar, url);
linphone_gtk_call_started(linphone_gtk_get_main_window());
}
int main(int argc, char *argv[]){
#ifdef ENABLE_NLS
void *p;
#endif
const char *config_file;
const char *lang;
int i; // zsd
g_thread_init(NULL);
gdk_threads_init();
config_file=linphone_gtk_get_config_file();
if (linphone_core_wake_up_possible_already_running_instance(config_file)==0){
/*
* zsd addition:
* Did the user ask for an-already running instance to make a call?
* Look thru the args the old-fashioned way.
*/
for (i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-call") == 0)
{
if (i + 1 < argc)
addr_to_call = argv[i + 1];
i = argc + 1;
}
}
// fprintf(stderr, "addr_to_call is |%s|\n", addr_to_call);
// zsd replaced this line
// if (linphone_core_wake_up_possible_already_running_instance(config_file)==0){
if (linphone_core_wake_up_possible_already_running_instance(
config_file, addr_to_call) == 0)
{
// and zsd added this if stmt and the braces
if (addr_to_call == NULL)
{
g_warning("Another running instance of linphone has been detected. It has been woken-up.");
g_warning("This instance is going to exit now.");
return 0;
}
return 0;
}
#ifdef WIN32
/*workaround for windows: sometimes LANG is defined to an integer value, not understood by gtk */
if ((lang=getenv("LANG"))!=NULL){
......@@ -1016,13 +1095,22 @@ int main(int argc, char *argv[]){
#ifdef WIN32
gtk_rc_add_default_file("./gtkrc");
#endif
// fprintf(stderr, "about to call gdk_threads_enter()\n"); //zsd
gdk_threads_enter();
// fprintf(stderr, "AFTER call gdk_threads_enter()\n");
// fprintf(stderr, "b4 !gtk_init_with_args() addr_to_call is |%s|\n",
// addr_to_call); /* zsd */
if (!gtk_init_with_args(&argc,&argv,_("A free SIP video-phone"),
linphone_options,NULL,NULL)){
fprintf(stderr, "IN !gtk_init_with_args() if clause\n"); /* zsd */
gdk_threads_leave();
return -1;
}
/* zsd: we don't get here if the args were not OK */
// fprintf(stderr, "AFTER !gtk_init_with_args() addr_to_call is |%s|\n",
// addr_to_call); /* zsd */
add_pixmap_directory("pixmaps");
add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone");
......@@ -1039,6 +1127,30 @@ int main(int argc, char *argv[]){
linphone_gtk_init_status_icon();
linphone_gtk_show_main_window();
linphone_gtk_check_for_new_version();
/* zsd additions for calling a URL given as an argument */
/*
* Comment from linphone 3.0.0:
* With this here, the video window never shows up, altho the
* main window does. Why is that?
if (addr_to_call != NULL)
{
linphone_core_invite(linphone_gtk_get_core(), addr_to_call);
linphone_call_started_remotely(addr_to_call);
}
*/
/* Horrible, horrible kludge since the above doesn't work: */
if (addr_to_call != NULL)
{
char buf[512];
snprintf(buf, sizeof(buf),
"(sleep 2; %s -c %s)&", argv[0], addr_to_call);
if (system(buf))
linphone_gtk_display_warning(linphone_gtk_get_core(),
"Unable to perform remote call!");
}
gtk_main();
gdk_threads_leave();
linphone_gtk_destroy_log_window();
......@@ -1047,5 +1159,3 @@ int main(int argc, char *argv[]){
gtk_status_icon_set_visible(icon,FALSE);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment