forked from mirrors/linphone-iphone
Merge branch 'dev_multicall'
and improve documentation Conflicts: coreapi/callbacks.c coreapi/linphonecore.c coreapi/linphonecore.h
This commit is contained in:
commit
d4a57fff79
39 changed files with 2871 additions and 2598 deletions
|
|
@ -1,6 +1,6 @@
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT([linphone],[3.3.2],[linphone-developers@nongnu.org])
|
||||
AC_INIT([linphone],[3.3.99.1],[linphone-developers@nongnu.org])
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
||||
dnl Source packaging numbers
|
||||
|
|
@ -15,7 +15,12 @@ LINPHONE_VERSION=$LINPHONE_MAJOR_VERSION.$LINPHONE_MINOR_VERSION.${LINPHONE_MICR
|
|||
if test "$LINPHONE_EXTRA_VERSION" != "" ;then
|
||||
LINPHONE_VERSION=$LINPHONE_VERSION.${LINPHONE_EXTRA_VERSION}
|
||||
fi
|
||||
LIBLINPHONE_SO_VERSION=`expr $LINPHONE_MINOR_VERSION + $LINPHONE_MAJOR_VERSION`:$LINPHONE_MICRO_VERSION:$LINPHONE_MINOR_VERSION
|
||||
|
||||
LIBLINPHONE_SO_CURRENT=4 dnl increment this number when you add/change/remove an interface
|
||||
LIBLINPHONE_SO_REVISION=0 dnl increment this number when you change source code, without changing interfaces; set to 0 when incrementing CURRENT
|
||||
LIBLINPHONE_SO_AGE=0 dnl increment this number when you add an interface, set to 0 if you remove an interface
|
||||
|
||||
LIBLINPHONE_SO_VERSION=$LIBLINPHONE_SO_CURRENT:$LIBLINPHONE_SO_REVISION:$LIBLINPHONE_SO_AGE
|
||||
|
||||
AC_SUBST(LIBLINPHONE_SO_VERSION, $LIBLINPHONE_SO_VERSION)
|
||||
AC_SUBST(LINPHONE_VERSION)
|
||||
|
|
|
|||
|
|
@ -56,13 +56,14 @@ extern char *lpc_strip_blanks(char *input);
|
|||
static int lpc_cmd_help(LinphoneCore *, char *);
|
||||
static int lpc_cmd_proxy(LinphoneCore *, char *);
|
||||
static int lpc_cmd_call(LinphoneCore *, char *);
|
||||
static int lpc_cmd_calls(LinphoneCore *, char *);
|
||||
static int lpc_cmd_chat(LinphoneCore *, char *);
|
||||
static int lpc_cmd_answer(LinphoneCore *, char *);
|
||||
static int lpc_cmd_autoanswer(LinphoneCore *, char *);
|
||||
static int lpc_cmd_terminate(LinphoneCore *, char *);
|
||||
static int lpc_cmd_call_logs(LinphoneCore *, char *);
|
||||
static int lpc_cmd_ipv6(LinphoneCore *, char *);
|
||||
static int lpc_cmd_refer(LinphoneCore *, char *);
|
||||
static int lpc_cmd_transfer(LinphoneCore *, char *);
|
||||
static int lpc_cmd_quit(LinphoneCore *, char *);
|
||||
static int lpc_cmd_nat(LinphoneCore *, char *);
|
||||
static int lpc_cmd_stun(LinphoneCore *, char *);
|
||||
|
|
@ -83,6 +84,8 @@ static int lpc_cmd_acodec(LinphoneCore *lc, char *args);
|
|||
static int lpc_cmd_vcodec(LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_codec(int type, LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_pause(LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_resume(LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_mute_mic(LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_unmute_mic(LinphoneCore *lc, char *args);
|
||||
static int lpc_cmd_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, char *args);
|
||||
|
|
@ -128,17 +131,24 @@ void linphonec_out(const char *fmt,...);
|
|||
LPC_COMMAND commands[] = {
|
||||
{ "help", lpc_cmd_help, "Print commands help", NULL },
|
||||
{ "call", lpc_cmd_call, "Call a SIP uri",
|
||||
"'call <sip-url>' "
|
||||
": initiate a call to the specified destination."
|
||||
"'call <sip-url>' \t: initiate a call to the specified destination.\n"
|
||||
"'call show' \t: show all the current calls with their id and status.\n"
|
||||
},
|
||||
{ "calls", lpc_cmd_calls, "Show all the current calls with their id and status.\n",
|
||||
NULL
|
||||
},
|
||||
{ "chat", lpc_cmd_chat, "Chat with a SIP uri",
|
||||
"'chat <sip-url> \"message\"' "
|
||||
": send a chat message \"message\" to the specified destination."
|
||||
},
|
||||
{ "terminate", lpc_cmd_terminate, "Terminate the current call",
|
||||
NULL },
|
||||
{ "terminate", lpc_cmd_terminate, "Terminate a call",
|
||||
"'terminate' : Terminate the current call\n"
|
||||
"'terminate <call id>' : Terminate the call with supplied id\n"
|
||||
"'terminate <all>' : Terminate all the current calls\n"
|
||||
},
|
||||
{ "answer", lpc_cmd_answer, "Answer a call",
|
||||
"Accept an incoming call."
|
||||
"'answer' : Answer the current incoming call\n"
|
||||
"'answer <call id>' : Answer the call with given id\n"
|
||||
},
|
||||
{ "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
|
||||
"'autoanswer' \t: show current autoanswer mode\n"
|
||||
|
|
@ -171,10 +181,10 @@ LPC_COMMAND commands[] = {
|
|||
"'ipv6 enable' : enable the use of the ipv6 network.\n"
|
||||
"'ipv6 disable' : do not use ipv6 network."
|
||||
},
|
||||
{ "refer", lpc_cmd_refer,
|
||||
"Refer the current call to the specified destination.",
|
||||
"'refer <sip-url>' or 'r <sip-url>' "
|
||||
": refer the current call to the specified destination."
|
||||
{ "transfer", lpc_cmd_transfer,
|
||||
"Transfer a call to a specified destination.",
|
||||
"'transfer <sip-uri>' : transfers the current active call to the destination sip-uri"
|
||||
"'transfer <call id> <sip-uri>': transfers the call with 'id' to the destination sip-uri"
|
||||
},
|
||||
{ "nat", lpc_cmd_nat, "Set nat address",
|
||||
"'nat' : show nat settings.\n"
|
||||
|
|
@ -231,19 +241,24 @@ LPC_COMMAND commands[] = {
|
|||
"'vcodec list' : list video codecs\n"
|
||||
"'vcodec enable <index>' : enable available video codec\n"
|
||||
"'vcodec disable <index>' : disable video codec" },
|
||||
{ "ec", lpc_cmd_echocancellation, "Echo cancellation",
|
||||
"'ec on [<delay>] [<tail>] [<framesize>]' : turn EC on with given delay, tail length and framesize\n"
|
||||
"'ec off' : turn echo cancellation (EC) off\n"
|
||||
"'ec show' : show EC status" },
|
||||
{ "ec", lpc_cmd_echocancellation, "Echo cancellation",
|
||||
"'ec on [<delay>] [<tail>] [<framesize>]' : turn EC on with given delay, tail length and framesize\n"
|
||||
"'ec off' : turn echo cancellation (EC) off\n"
|
||||
"'ec show' : show EC status" },
|
||||
{ "pause", lpc_cmd_pause, "pause a call",
|
||||
"'pause' : pause the current call\n"},
|
||||
{ "resume", lpc_cmd_resume, "resume a call",
|
||||
"'resume' : resume the unique call\n"
|
||||
"'resume <call id>' : hold off the call with given id\n"},
|
||||
{ "mute", lpc_cmd_mute_mic,
|
||||
"Mute microphone and suspend voice transmission."},
|
||||
{ "unmute", lpc_cmd_unmute_mic,
|
||||
"Unmute microphone and resume voice transmission."},
|
||||
"Unmute microphone and resume voice transmission."},
|
||||
{ "nortp-on-audio-mute", lpc_cmd_rtp_no_xmit_on_audio_mute,
|
||||
"Set the rtp_no_xmit_on_audio_mute configuration parameter",
|
||||
" If set to 1 then rtp transmission will be muted when\n"
|
||||
" audio is muted , otherwise rtp is always sent."},
|
||||
{ (char *)NULL, (lpc_cmd_handler)NULL, (char *)NULL, (char *)NULL }
|
||||
"Set the rtp_no_xmit_on_audio_mute configuration parameter",
|
||||
" If set to 1 then rtp transmission will be muted when\n"
|
||||
" audio is muted , otherwise rtp is always sent."},
|
||||
{ (char *)NULL, (lpc_cmd_handler)NULL, (char *)NULL, (char *)NULL }
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
|
|
@ -388,6 +403,35 @@ lpc_cmd_help(LinphoneCore *lc, char *arg)
|
|||
static char callee_name[256]={0};
|
||||
static char caller_name[256]={0};
|
||||
|
||||
static const char *get_call_status(LinphoneCall *call){
|
||||
switch(linphone_call_get_state(call)){
|
||||
case LinphoneCallPaused:
|
||||
if (linphone_call_get_refer_to (call)!=NULL){
|
||||
return "Paused (transfered)";
|
||||
}else{
|
||||
return "Paused";
|
||||
}
|
||||
break;
|
||||
case LinphoneCallIncomingReceived:
|
||||
return "Pending";
|
||||
break;
|
||||
case LinphoneCallOutgoingInit:
|
||||
case LinphoneCallOutgoingProgress:
|
||||
return "Dialing out";
|
||||
break;
|
||||
case LinphoneCallOutgoingEarlyMedia:
|
||||
case LinphoneCallOutgoingRinging:
|
||||
return "Remote ringing";
|
||||
break;
|
||||
default:
|
||||
if (linphone_call_has_transfer_pending(call)){
|
||||
return "Running (transfer pending)";
|
||||
}else
|
||||
return "Running";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static int
|
||||
lpc_cmd_call(LinphoneCore *lc, char *args)
|
||||
{
|
||||
|
|
@ -395,14 +439,14 @@ lpc_cmd_call(LinphoneCore *lc, char *args)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( lc->call != NULL )
|
||||
{
|
||||
linphonec_out("Terminate current call first.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( -1 == linphone_core_invite(lc, args) )
|
||||
LinphoneCall *call;
|
||||
if ( linphone_core_in_call(lc) )
|
||||
{
|
||||
linphonec_out("Terminate or hold on the current call first.\n");
|
||||
return 1;
|
||||
}
|
||||
if ( NULL == (call=linphone_core_invite(lc, args)) )
|
||||
{
|
||||
linphonec_out("Error from linphone_core_invite.\n");
|
||||
}
|
||||
|
|
@ -414,6 +458,32 @@ lpc_cmd_call(LinphoneCore *lc, char *args)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lpc_cmd_calls(LinphoneCore *lc, char *args){
|
||||
const MSList *calls = linphone_core_get_calls(lc);
|
||||
if(calls)
|
||||
{
|
||||
const MSList *p_calls = calls;
|
||||
linphonec_out("ID\t\tDestination\t\t\t\tStatus\n---------------------------------------------------------------------\n");
|
||||
while(p_calls != NULL)
|
||||
{
|
||||
LinphoneCall *call=(LinphoneCall*)p_calls->data;
|
||||
char *tmp=linphone_call_get_remote_address_as_string(call);
|
||||
linphonec_out("%li\t%s\t\t\t%s\r\n",
|
||||
(long)linphone_call_get_user_pointer (call),
|
||||
tmp,
|
||||
get_call_status(call));
|
||||
p_calls = p_calls->next;
|
||||
ms_free(tmp);
|
||||
}
|
||||
}else
|
||||
{
|
||||
linphonec_out("No active call.\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lpc_cmd_chat(LinphoneCore *lc, char *args)
|
||||
{
|
||||
|
|
@ -456,12 +526,34 @@ void linphonec_set_caller(const char *caller){
|
|||
}
|
||||
|
||||
static int
|
||||
lpc_cmd_refer(LinphoneCore *lc, char *args)
|
||||
lpc_cmd_transfer(LinphoneCore *lc, char *args)
|
||||
{
|
||||
if (args)
|
||||
linphone_core_refer(lc, args);
|
||||
else{
|
||||
linphonec_out("refer needs an argument\n");
|
||||
if (args){
|
||||
LinphoneCall *call;
|
||||
const char *refer_to=NULL;
|
||||
char arg1[256]={0};
|
||||
char arg2[266]={0};
|
||||
int n=sscanf(args,"%s %s",arg1,arg2);
|
||||
if (n==1 || isalpha(*arg1)){
|
||||
call=linphone_core_get_current_call(lc);
|
||||
if (call==NULL && linphone_core_get_calls_nb (lc)==1){
|
||||
call=(LinphoneCall*)linphone_core_get_calls(lc)->data;
|
||||
}
|
||||
refer_to=args;
|
||||
if (call==NULL){
|
||||
linphonec_out("No active call, please specify a call id among the ones listed by 'calls' command.\n");
|
||||
return 0;
|
||||
}
|
||||
}else{
|
||||
long id=atoi(arg1);
|
||||
refer_to=args+strlen(arg1)+1;
|
||||
call=linphonec_get_call(id);
|
||||
if (call==NULL) return 0;
|
||||
}
|
||||
linphone_core_transfer_call(lc, call, refer_to);
|
||||
}else{
|
||||
linphonec_out("Transfer command requires at least one argument\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -469,21 +561,66 @@ lpc_cmd_refer(LinphoneCore *lc, char *args)
|
|||
static int
|
||||
lpc_cmd_terminate(LinphoneCore *lc, char *args)
|
||||
{
|
||||
if ( -1 == linphone_core_terminate_call(lc, NULL) )
|
||||
{
|
||||
linphonec_out("No active call.\n");
|
||||
if (linphone_core_get_calls(lc)==NULL){
|
||||
linphonec_out("No active calls");
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
if (!args)
|
||||
{
|
||||
if ( -1 == linphone_core_terminate_call(lc, NULL) ){
|
||||
linphonec_out("Could not stop the active call.\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(strcmp(args,"all")==0){
|
||||
linphonec_out("We are going to stop all the calls.\n");
|
||||
linphone_core_terminate_all_calls(lc);
|
||||
return 1;
|
||||
}else{
|
||||
/*the argument is a linphonec call id */
|
||||
long id=atoi(args);
|
||||
LinphoneCall *call=linphonec_get_call(id);
|
||||
if (call){
|
||||
if (linphone_core_terminate_call(lc,call)==-1){
|
||||
linphonec_out("Could not stop the call with id %li",id);
|
||||
}
|
||||
}else return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
lpc_cmd_answer(LinphoneCore *lc, char *args)
|
||||
{
|
||||
if ( -1 == linphone_core_accept_call(lc, NULL) )
|
||||
lpc_cmd_answer(LinphoneCore *lc, char *args){
|
||||
if (!args)
|
||||
{
|
||||
linphonec_out("No incoming call.\n");
|
||||
int nb=ms_list_size(linphone_core_get_calls(lc));
|
||||
if (nb==1){
|
||||
//if just one call is present answer the only one in passing NULL to the linphone_core_accept_call ...
|
||||
if ( -1 == linphone_core_accept_call(lc, NULL) )
|
||||
{
|
||||
linphonec_out("Fail to accept incoming call\n");
|
||||
}
|
||||
}else if (nb==0){
|
||||
linphonec_out("There are no calls to answer.\n");
|
||||
}else{
|
||||
linphonec_out("Multiple calls in progress, please specify call id.\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}else{
|
||||
long id;
|
||||
if (sscanf(args,"%li",&id)==1){
|
||||
LinphoneCall *call=linphonec_get_call (id);
|
||||
if (linphone_core_accept_call (lc,call)==-1){
|
||||
linphonec_out("Fail to accept call %i\n",id);
|
||||
}
|
||||
}else return 0;
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -531,7 +668,7 @@ lpc_cmd_nat(LinphoneCore *lc, char *args)
|
|||
}
|
||||
|
||||
nat = linphone_core_get_nat_address(lc);
|
||||
use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS;
|
||||
use = linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress;
|
||||
linphonec_out("Nat address: %s%s\n", nat ? nat : "unspecified" , use ? "" : " (disabled - use 'firewall nat' to enable)");
|
||||
|
||||
return 1;
|
||||
|
|
@ -552,7 +689,7 @@ lpc_cmd_stun(LinphoneCore *lc, char *args)
|
|||
}
|
||||
|
||||
stun = linphone_core_get_stun_server(lc);
|
||||
use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_STUN;
|
||||
use = linphone_core_get_firewall_policy(lc)==LinphonePolicyUseStun;
|
||||
linphonec_out("Stun server: %s%s\n", stun ? stun : "unspecified" , use? "" : " (disabled - use 'firewall stun' to enable)");
|
||||
|
||||
return 1;
|
||||
|
|
@ -569,7 +706,7 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
|
|||
{
|
||||
if (strcmp(args,"none")==0)
|
||||
{
|
||||
linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_NO_FIREWALL);
|
||||
linphone_core_set_firewall_policy(lc,LinphonePolicyNoFirewall);
|
||||
}
|
||||
else if (strcmp(args,"stun")==0)
|
||||
{
|
||||
|
|
@ -579,7 +716,7 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
|
|||
linphonec_out("No stun server address is defined, use 'stun <address>' first\n");
|
||||
return 1;
|
||||
}
|
||||
linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN);
|
||||
linphone_core_set_firewall_policy(lc,LinphonePolicyUseStun);
|
||||
}
|
||||
else if (strcmp(args,"nat")==0)
|
||||
{
|
||||
|
|
@ -589,19 +726,19 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
|
|||
linphonec_out("No nat address is defined, use 'nat <address>' first");
|
||||
return 1;
|
||||
}
|
||||
linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS);
|
||||
linphone_core_set_firewall_policy(lc,LinphonePolicyUseNatAddress);
|
||||
}
|
||||
}
|
||||
|
||||
switch(linphone_core_get_firewall_policy(lc))
|
||||
{
|
||||
case LINPHONE_POLICY_NO_FIREWALL:
|
||||
case LinphonePolicyNoFirewall:
|
||||
linphonec_out("No firewall\n");
|
||||
break;
|
||||
case LINPHONE_POLICY_USE_STUN:
|
||||
case LinphonePolicyUseStun:
|
||||
linphonec_out("Using stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
|
||||
break;
|
||||
case LINPHONE_POLICY_USE_NAT_ADDRESS:
|
||||
case LinphonePolicyUseNatAddress:
|
||||
linphonec_out("Using supplied nat address %s.\n", setting ? setting : linphone_core_get_nat_address(lc));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1084,7 +1221,59 @@ lpc_cmd_staticpic(LinphoneCore *lc, char *args)
|
|||
return 0; /* Syntax error */
|
||||
}
|
||||
|
||||
static int lpc_cmd_pause(LinphoneCore *lc, char *args){
|
||||
|
||||
if(linphone_core_in_call(lc))
|
||||
{
|
||||
linphone_core_pause_call(lc,linphone_core_get_current_call(lc));
|
||||
return 1;
|
||||
}
|
||||
linphonec_out("you can only pause when a call is in process\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpc_cmd_resume(LinphoneCore *lc, char *args){
|
||||
|
||||
if(linphone_core_in_call(lc))
|
||||
{
|
||||
linphonec_out("There is already a call in process pause or stop it first");
|
||||
return 1;
|
||||
}
|
||||
if (args)
|
||||
{
|
||||
long id;
|
||||
int n = sscanf(args, "%li", &id);
|
||||
if (n == 1){
|
||||
LinphoneCall *call=linphonec_get_call (id);
|
||||
if (call){
|
||||
if(linphone_core_resume_call(lc,call)==-1){
|
||||
linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}else return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const MSList *calls = linphone_core_get_calls(lc);
|
||||
int nbcalls=ms_list_size(calls);
|
||||
if( nbcalls == 1)
|
||||
{
|
||||
if(linphone_core_resume_call(lc,calls->data) < 0)
|
||||
{
|
||||
linphonec_out("There was a problem to resume the unique call.\n");
|
||||
}
|
||||
return 1;
|
||||
}else if (nbcalls==0){
|
||||
linphonec_out("There is no calls at this time.\n");
|
||||
return 1;
|
||||
}else{
|
||||
linphonec_out("There are %i calls at this time, please specify call id as given with 'calls' command.\n");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
|
|
@ -1612,31 +1801,31 @@ 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;
|
||||
}
|
||||
*/
|
||||
LinphoneCall *call=linphone_core_get_current_call (lc);
|
||||
LinphoneCallState call_state=LinphoneCallIdle;
|
||||
if (call) call_state=linphone_call_get_state(call);
|
||||
|
||||
switch(call_state){
|
||||
case GSTATE_CALL_OUT_INVITE:
|
||||
case LinphoneCallOutgoingInit:
|
||||
case LinphoneCallOutgoingProgress:
|
||||
linphonec_out("hook=dialing\n");
|
||||
break;
|
||||
case GSTATE_CALL_IDLE:
|
||||
case LinphoneCallIdle:
|
||||
linphonec_out("hook=offhook\n");
|
||||
break;
|
||||
case GSTATE_CALL_OUT_CONNECTED:
|
||||
linphonec_out("Call out, hook=%s duration=%i, muted=%s rtp-xmit-muted=%s\n", linphonec_get_callee(),
|
||||
case LinphoneCallStreamsRunning:
|
||||
case LinphoneCallConnected:
|
||||
if (linphone_call_get_dir(call)==LinphoneCallOutgoing){
|
||||
linphonec_out("Call out, hook=%s duration=%i, muted=%s rtp-xmit-muted=%s\n", linphonec_get_callee(),
|
||||
linphone_core_get_current_call_duration(lc),
|
||||
lc->audio_muted ? "yes" : "no",
|
||||
linphone_core_is_mic_muted (lc) ? "yes" : "no",
|
||||
linphone_core_is_rtp_muted(lc) ? "yes" : "no");
|
||||
break;
|
||||
case GSTATE_CALL_IN_CONNECTED:
|
||||
linphonec_out("hook=answered duration=%i\n" ,
|
||||
linphone_core_get_current_call_duration(lc));
|
||||
}else{
|
||||
linphonec_out("hook=answered duration=%i\n" ,
|
||||
linphone_core_get_current_call_duration(lc));
|
||||
}
|
||||
break;
|
||||
case GSTATE_CALL_IN_INVITE:
|
||||
case LinphoneCallIncomingReceived:
|
||||
linphonec_out("Incoming call from %s\n",linphonec_get_caller());
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1874,36 +2063,32 @@ static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args){
|
|||
|
||||
static int lpc_cmd_mute_mic(LinphoneCore *lc, char *args)
|
||||
{
|
||||
if ( lc->call != NULL )
|
||||
linphone_core_mute_mic(lc, 1);
|
||||
return 1;
|
||||
linphone_core_mute_mic(lc, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lpc_cmd_unmute_mic(LinphoneCore *lc, char *args)
|
||||
{
|
||||
if ( lc->call != NULL )
|
||||
linphone_core_mute_mic(lc, 0);
|
||||
return 1;
|
||||
static int lpc_cmd_unmute_mic(LinphoneCore *lc, char *args){
|
||||
linphone_core_mute_mic(lc, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lpc_cmd_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, char *args)
|
||||
{
|
||||
bool_t rtp_xmit_off=FALSE;
|
||||
char *status;
|
||||
gstate_t call_state=linphone_core_get_state(lc,GSTATE_GROUP_CALL);
|
||||
bool_t rtp_xmit_off=FALSE;
|
||||
char *status;
|
||||
|
||||
if(args){
|
||||
if(strstr(args,"1"))rtp_xmit_off=TRUE;
|
||||
if(call_state == GSTATE_CALL_IDLE)
|
||||
linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_xmit_off);
|
||||
else
|
||||
linphonec_out("nortp-on-audio-mute: call in progress - cannot change state\n");
|
||||
}
|
||||
rtp_xmit_off=linphone_core_get_rtp_no_xmit_on_audio_mute(lc);
|
||||
if(rtp_xmit_off)status="off";
|
||||
else status="on";
|
||||
linphonec_out("rtp transmit %s when audio muted\n",status);
|
||||
return 1;
|
||||
if(args){
|
||||
if(strstr(args,"1"))rtp_xmit_off=TRUE;
|
||||
if(linphone_core_get_current_call (lc)==NULL)
|
||||
linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_xmit_off);
|
||||
else
|
||||
linphonec_out("nortp-on-audio-mute: call in progress - cannot change state\n");
|
||||
}
|
||||
rtp_xmit_off=linphone_core_get_rtp_no_xmit_on_audio_mute(lc);
|
||||
if (rtp_xmit_off) status="off";
|
||||
else status="on";
|
||||
linphonec_out("rtp transmit %s when audio muted\n",status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -112,25 +112,24 @@ static char **linephonec_readline_completion(const char *text,
|
|||
#endif
|
||||
|
||||
/* These are callback for linphone core */
|
||||
static void linphonec_call_received(LinphoneCore *lc, const char *from);
|
||||
static void linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm,
|
||||
const char *username);
|
||||
static void linphonec_display_refer (LinphoneCore * lc,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_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, const char *from);
|
||||
|
||||
static void linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
|
||||
const char *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,...);
|
||||
/***************************************************************************
|
||||
*
|
||||
* Global variables
|
||||
|
|
@ -170,34 +169,23 @@ static ortp_pipe_t server_sock;
|
|||
#endif /*_WIN32_WCE*/
|
||||
|
||||
|
||||
LinphoneCoreVTable linphonec_vtable
|
||||
#if !defined (_MSC_VER)
|
||||
= {
|
||||
.show =(ShowInterfaceCb) stub,
|
||||
.inv_recv = linphonec_call_received,
|
||||
.bye_recv = linphonec_bye_received,
|
||||
.notify_recv = linphonec_notify_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
|
||||
void linphonec_call_identify(LinphoneCall* call){
|
||||
static long callid=1;
|
||||
linphone_call_set_user_pointer (call,(void*)callid);
|
||||
callid++;
|
||||
}
|
||||
#endif /*_WIN32_WCE*/
|
||||
;
|
||||
|
||||
|
||||
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.",id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
*
|
||||
|
|
@ -209,10 +197,9 @@ LinphoneCoreVTable linphonec_vtable
|
|||
* Linphone core callback
|
||||
*/
|
||||
static void
|
||||
linphonec_display_refer (LinphoneCore * lc,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", refer_to);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -254,19 +241,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, const char *from)
|
||||
{
|
||||
linphonec_set_caller(from);
|
||||
if ( auto_answer) {
|
||||
answer_call=TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Linphone core callback
|
||||
*/
|
||||
|
|
@ -296,16 +270,16 @@ 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"))
|
||||
if(!strcmp(event,"refer"))
|
||||
{
|
||||
printf("The distant SIP end point get the refer we can close the call\n");
|
||||
linphonec_parse_command_line(linphonec, "terminate");
|
||||
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
|
||||
*/
|
||||
|
|
@ -332,17 +306,41 @@ linphonec_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf,
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Linphone core callback
|
||||
*/
|
||||
static void
|
||||
linphonec_bye_received(LinphoneCore *lc, const char *from)
|
||||
{
|
||||
// Should change prompt back to original maybe
|
||||
|
||||
// printing this is unneeded as we'd get a "Communication ended"
|
||||
// message trough display_status callback anyway
|
||||
//printf("Bye received from %s\n", from);
|
||||
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);
|
||||
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);
|
||||
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 LinphoneCallIncomingReceived:
|
||||
linphonec_call_identify(call);
|
||||
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);
|
||||
break;
|
||||
case LinphoneCallOutgoingInit:
|
||||
linphonec_call_identify(call);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ms_free(from);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -357,64 +355,11 @@ linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
|
|||
}
|
||||
|
||||
|
||||
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];
|
||||
|
|
@ -596,6 +541,8 @@ bool_t linphonec_get_autoanswer(){
|
|||
return auto_answer;
|
||||
}
|
||||
|
||||
LinphoneCoreVTable linphonec_vtable={0};
|
||||
|
||||
/***************************************************************************/
|
||||
/*
|
||||
* Main
|
||||
|
|
@ -621,31 +568,24 @@ 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;
|
||||
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.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.auth_info_requested = linphonec_prompt_for_auth;
|
||||
linphonec_vtable.display_status = linphonec_display_status;
|
||||
linphonec_vtable.display_message=linphonec_display_something;
|
||||
linphonec_vtable.display_warning=linphonec_display_warning;
|
||||
linphonec_vtable.display_url=linphonec_display_url;
|
||||
linphonec_vtable.text_received=linphonec_text_received;
|
||||
linphonec_vtable.dtmf_received=linphonec_dtmf_received;
|
||||
linphonec_vtable.refer_received=linphonec_display_refer;
|
||||
linphonec_vtable.notify_recv=linphonec_notify_received;
|
||||
|
||||
if (! linphonec_init(argc, argv) ) exit(EXIT_FAILURE);
|
||||
|
||||
linphonec_main_loop (linphonec, sipAddr);
|
||||
|
|
@ -766,11 +706,10 @@ void linphonec_main_loop_exit(void){
|
|||
void
|
||||
linphonec_finish(int exit_status)
|
||||
{
|
||||
printf("Terminating...\n");
|
||||
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
|
||||
|
|
|
|||
|
|
@ -112,6 +112,8 @@ void linphonec_set_autoanswer(bool_t enabled);
|
|||
bool_t linphonec_get_autoanswer();
|
||||
void linphonec_command_finished(void);
|
||||
void linphonec_set_caller(const char *caller);
|
||||
LinphoneCall *linphonec_get_call(long id);
|
||||
void linphonec_call_identify(LinphoneCall* call);
|
||||
|
||||
#endif /* def LINPHONEC_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ EXTRA_DIST=linphonecore_jni.cc
|
|||
## Process this file with automake to produce Makefile.in
|
||||
linphone_includedir=$(includedir)/linphone
|
||||
|
||||
linphone_include_HEADERS=linphonecore.h ../config.h lpconfig.h sipsetup.h
|
||||
linphone_include_HEADERS=linphonecore.h linphonecore_utils.h ../config.h lpconfig.h sipsetup.h
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)\
|
||||
|
|
@ -32,9 +32,10 @@ liblinphone_la_SOURCES=\
|
|||
authentication.c \
|
||||
lpconfig.c lpconfig.h \
|
||||
chat.c \
|
||||
general_state.c \
|
||||
linphonecall.c \
|
||||
sipsetup.c sipsetup.h \
|
||||
siplogin.c
|
||||
siplogin.c \
|
||||
lsd.c linphonecore_utils.h
|
||||
|
||||
|
||||
liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
|
||||
|
|
@ -48,6 +49,11 @@ if BUILD_WIN32
|
|||
liblinphone_la_LIBADD+=$(top_builddir)/oRTP/src/libortp.la
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS=test_lsd
|
||||
|
||||
test_lsd_SOURCES=test_lsd.c
|
||||
|
||||
test_lsd_LDADD=liblinphone.la
|
||||
|
||||
AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
|
||||
$(ORTP_CFLAGS) \
|
||||
|
|
|
|||
|
|
@ -26,16 +26,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
|
||||
static void linphone_connect_incoming(LinphoneCore *lc, LinphoneCall *call){
|
||||
if (lc->vtable.show)
|
||||
lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Connected."));
|
||||
call->state=LCStateAVRunning;
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_start_media_streams(lc,call);
|
||||
linphone_call_start_media_streams(call);
|
||||
}
|
||||
|
||||
static void call_received(SalOp *h){
|
||||
|
|
@ -47,26 +42,22 @@ static void call_received(SalOp *h){
|
|||
LinphoneAddress *from_parsed;
|
||||
|
||||
/* first check if we can answer successfully to this invite */
|
||||
if (lc->presence_mode!=LINPHONE_STATUS_ONLINE){
|
||||
ms_message("Not present !! presence mode : %d\n",lc->presence_mode);
|
||||
if (lc->presence_mode==LINPHONE_STATUS_BUSY)
|
||||
if (lc->presence_mode==LinphoneStatusBusy ||
|
||||
lc->presence_mode==LinphoneStatusOffline ||
|
||||
lc->presence_mode==LinphoneStatusDoNotDisturb ||
|
||||
lc->presence_mode==LinphoneStatusMoved){
|
||||
if (lc->presence_mode==LinphoneStatusBusy )
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
else if (lc->presence_mode==LINPHONE_STATUS_AWAY
|
||||
||lc->presence_mode==LINPHONE_STATUS_BERIGHTBACK
|
||||
||lc->presence_mode==LINPHONE_STATUS_ONTHEPHONE
|
||||
||lc->presence_mode==LINPHONE_STATUS_OUTTOLUNCH
|
||||
||lc->presence_mode==LINPHONE_STATUS_OFFLINE)
|
||||
else if (lc->presence_mode==LinphoneStatusOffline)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->presence_mode==LINPHONE_STATUS_NOT_DISTURB)
|
||||
else if (lc->presence_mode==LinphoneStatusDoNotDisturb)
|
||||
sal_call_decline(h,SalReasonTemporarilyUnavailable,NULL);
|
||||
else if (lc->alt_contact!=NULL && lc->presence_mode==LINPHONE_STATUS_MOVED)
|
||||
else if (lc->alt_contact!=NULL && lc->presence_mode==LinphoneStatusMoved)
|
||||
sal_call_decline(h,SalReasonRedirect,lc->alt_contact);
|
||||
else
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(h);
|
||||
return;
|
||||
}
|
||||
if (lc->call!=NULL){/*busy*/
|
||||
if (!linphone_core_can_we_add_call(lc)){/*busy*/
|
||||
sal_call_decline(h,SalReasonBusy,NULL);
|
||||
sal_op_release(h);
|
||||
return;
|
||||
|
|
@ -75,56 +66,72 @@ static void call_received(SalOp *h){
|
|||
to=sal_op_get_to(h);
|
||||
|
||||
call=linphone_call_new_incoming(lc,linphone_address_new(from),linphone_address_new(to),h);
|
||||
lc->call=call;
|
||||
|
||||
sal_call_set_local_media_description(h,call->localdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(h);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
if (call->resultdesc && sal_media_description_empty(call->resultdesc)){
|
||||
sal_call_decline(h,SalReasonMedia,NULL);
|
||||
linphone_call_destroy(call);
|
||||
lc->call=NULL;
|
||||
linphone_call_unref(call);
|
||||
return;
|
||||
}
|
||||
/* the call is acceptable so we can now add it to our list */
|
||||
if(linphone_core_add_call(lc,call)!= 0)
|
||||
{
|
||||
ms_warning("we cannot handle anymore call\n");
|
||||
sal_call_decline(h,SalReasonMedia,NULL);
|
||||
linphone_call_unref(call);
|
||||
return;
|
||||
}
|
||||
|
||||
from_parsed=linphone_address_new(sal_op_get_from(h));
|
||||
linphone_address_clean(from_parsed);
|
||||
tmp=linphone_address_as_string(from_parsed);
|
||||
linphone_address_destroy(from_parsed);
|
||||
gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp);
|
||||
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
|
||||
barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"),
|
||||
(sal_call_autoanswer_asked(h)) ?_(" and asked autoanswer."):_("."));
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,barmesg);
|
||||
|
||||
/* play the ring */
|
||||
if (lc->sound_conf.ring_sndcard!=NULL){
|
||||
/* play the ring if this is the only call*/
|
||||
if (lc->sound_conf.ring_sndcard!=NULL && ms_list_size(lc->calls)==1){
|
||||
if (lc->ringstream && lc->dmfs_playing_start_time!=0){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
lc->dmfs_playing_start_time=0;
|
||||
}
|
||||
ms_message("Starting local ring...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,lc->sound_conf.ring_sndcard);
|
||||
if(lc->ringstream==NULL){
|
||||
MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
|
||||
ms_message("Starting local ring...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.local_ring,2000,ringcard);
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_message("the local ring is already started");
|
||||
}
|
||||
}else{
|
||||
/*TODO : play a tone within the context of the current call */
|
||||
}
|
||||
linphone_call_set_state(call,LCStateRinging);
|
||||
sal_call_notify_ringing(h);
|
||||
#if !(__IPHONE_OS_VERSION_MIN_REQUIRED >= 40000)
|
||||
linphone_core_init_media_streams(lc,lc->call);
|
||||
linphone_call_init_media_streams(call);
|
||||
#endif
|
||||
if (lc->vtable.inv_recv) lc->vtable.inv_recv(lc,tmp);
|
||||
ms_free(barmesg);
|
||||
ms_free(tmp);
|
||||
}
|
||||
|
||||
static void call_ringing(SalOp *h){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
|
||||
LinphoneCall *call=lc->call;
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h);
|
||||
SalMediaDescription *md;
|
||||
|
||||
if (call==NULL) return;
|
||||
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Remote ringing."));
|
||||
|
||||
md=sal_call_get_final_media_description(h);
|
||||
if (md==NULL){
|
||||
if (lc->ringstream && lc->dmfs_playing_start_time!=0){
|
||||
|
|
@ -134,13 +141,14 @@ static void call_ringing(SalOp *h){
|
|||
}
|
||||
if (lc->ringstream!=NULL) return; /*already ringing !*/
|
||||
if (lc->sound_conf.play_sndcard!=NULL){
|
||||
MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
|
||||
ms_message("Remote ringing...");
|
||||
lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,lc->sound_conf.play_sndcard);
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_RINGING, NULL);
|
||||
lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard);
|
||||
linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing");
|
||||
}
|
||||
}else{
|
||||
/*accept early media */
|
||||
if (lc->audiostream && lc->audiostream->ticker!=NULL){
|
||||
if (call->audiostream && call->audiostream->ticker!=NULL){
|
||||
/*streams already started */
|
||||
ms_message("Early media already started.");
|
||||
return;
|
||||
|
|
@ -150,36 +158,34 @@ static void call_ringing(SalOp *h){
|
|||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("Early media."));
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_RINGING, NULL);
|
||||
linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media");
|
||||
if (lc->ringstream!=NULL){
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
ms_message("Doing early media...");
|
||||
linphone_core_start_media_streams(lc,call);
|
||||
linphone_call_start_media_streams(call);
|
||||
call->media_pending=TRUE;
|
||||
}
|
||||
call->state=LCStateRinging;
|
||||
}
|
||||
|
||||
/*
|
||||
* could be reach :
|
||||
* - when the call is accepted
|
||||
* - when a request is accepted (pause, resume)
|
||||
*/
|
||||
static void call_accepted(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=lc->call;
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (call==NULL){
|
||||
ms_warning("No call to accept.");
|
||||
return ;
|
||||
}
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_accepted: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (call->state==LCStateAVRunning){
|
||||
return ; /*already accepted*/
|
||||
}
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
if ((call->audiostream!=NULL) && (call->audiostream->ticker!=NULL)){
|
||||
/*case where we accepted early media or already in call*/
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_call_init_media_streams(call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
|
|
@ -188,32 +194,55 @@ static void call_accepted(SalOp *op){
|
|||
sal_media_description_ref(call->resultdesc);
|
||||
call->media_pending=FALSE;
|
||||
}
|
||||
if (call->state==LinphoneCallOutgoingProgress ||
|
||||
call->state==LinphoneCallOutgoingRinging ||
|
||||
call->state==LinphoneCallOutgoingEarlyMedia){
|
||||
linphone_call_set_state(call,LinphoneCallConnected,"Connected");
|
||||
}
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL);
|
||||
linphone_connect_incoming(lc,call);
|
||||
if (sal_media_description_has_dir(call->resultdesc,SalStreamSendOnly)){
|
||||
/*we initiated a pause*/
|
||||
if (lc->vtable.display_status){
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp);
|
||||
lc->vtable.display_status(lc,msg);
|
||||
ms_free(tmp);
|
||||
ms_free(msg);
|
||||
}
|
||||
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
|
||||
}else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
|
||||
/*we are put on hold when the call is initially accepted */
|
||||
if (lc->vtable.display_status){
|
||||
char *tmp=linphone_call_get_remote_address_as_string (call);
|
||||
char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp);
|
||||
lc->vtable.display_status(lc,msg);
|
||||
ms_free(tmp);
|
||||
ms_free(msg);
|
||||
}
|
||||
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
|
||||
}else{
|
||||
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}
|
||||
linphone_connect_incoming (lc,call);
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
linphone_core_abort_call(lc,call,"No codec intersection");
|
||||
}
|
||||
}
|
||||
|
||||
static void call_ack(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=lc->call;
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (call==NULL){
|
||||
ms_warning("No call to be ACK'd");
|
||||
return ;
|
||||
}
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_ack: ignoring.");
|
||||
return;
|
||||
}
|
||||
if (call->media_pending){
|
||||
if (lc->audiostream->ticker!=NULL){
|
||||
if (call->audiostream->ticker!=NULL){
|
||||
/*case where we accepted early media */
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
linphone_call_stop_media_streams(call);
|
||||
linphone_call_init_media_streams(call);
|
||||
}
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
|
|
@ -221,62 +250,86 @@ static void call_ack(SalOp *op){
|
|||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc)){
|
||||
gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL);
|
||||
linphone_connect_incoming(lc,call);
|
||||
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}else{
|
||||
/*send a bye*/
|
||||
ms_error("Incompatible SDP response received in ACK, need to abort the call");
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
linphone_core_abort_call(lc,call,"No codec intersection");
|
||||
return;
|
||||
}
|
||||
call->media_pending=FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void call_updated(SalOp *op){
|
||||
/* this callback is called when an incoming re-INVITE modifies the session*/
|
||||
static void call_updating(SalOp *op){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
linphone_core_init_media_streams(lc,call);
|
||||
if (call->resultdesc)
|
||||
sal_media_description_unref(call->resultdesc);
|
||||
call->resultdesc=sal_call_get_final_media_description(op);
|
||||
if (call->resultdesc){
|
||||
if (call->resultdesc)
|
||||
sal_media_description_ref(call->resultdesc);
|
||||
if (!sal_media_description_empty(call->resultdesc)){
|
||||
linphone_connect_incoming(lc,call);
|
||||
|
||||
if (call->resultdesc && !sal_media_description_empty(call->resultdesc))
|
||||
{
|
||||
if (call->state==LinphoneCallPaused &&
|
||||
sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && strcmp(call->resultdesc->addr,"0.0.0.0")!=0){
|
||||
/*make sure we can be resumed */
|
||||
if (lc->current_call!=NULL && lc->current_call!=call){
|
||||
ms_warning("Attempt to be resumed but already in call with somebody else!");
|
||||
/*we are actively running another call, reject with a busy*/
|
||||
sal_call_decline (op,SalReasonBusy,NULL);
|
||||
return;
|
||||
}
|
||||
if(lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("We have been resumed..."));
|
||||
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
|
||||
}
|
||||
else if(call->state==LinphoneCallStreamsRunning &&
|
||||
sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly) && !strcmp(call->resultdesc->addr,"0.0.0.0")){
|
||||
if(lc->vtable.display_status)
|
||||
lc->vtable.display_status(lc,_("We are being paused..."));
|
||||
linphone_call_set_state (call,LinphoneCallPaused,"Call paused");
|
||||
if (lc->current_call!=call){
|
||||
ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call);
|
||||
}
|
||||
lc->current_call=NULL;
|
||||
}
|
||||
/*accept the modification (sends a 200Ok)*/
|
||||
sal_call_accept(op);
|
||||
linphone_call_stop_media_streams (call);
|
||||
linphone_call_init_media_streams (call);
|
||||
linphone_call_start_media_streams (call);
|
||||
}
|
||||
if (lc->current_call==NULL) linphone_core_start_pending_refered_calls (lc);
|
||||
}
|
||||
|
||||
static void call_terminated(SalOp *op, const char *from){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (linphone_call_get_state(call)==LinphoneCallEnd || linphone_call_get_state(call)==LinphoneCallError){
|
||||
ms_warning("call_terminated: ignoring.");
|
||||
return;
|
||||
}
|
||||
ms_message("Current call terminated...");
|
||||
if (lc->ringstream!=NULL) {
|
||||
//we stop the call only if we have this current call or if we are in call
|
||||
if (lc->ringstream!=NULL && ( (ms_list_size(lc->calls) == 1) || linphone_core_in_call(lc) )) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc,lc->call);
|
||||
lc->vtable.show(lc);
|
||||
lc->vtable.display_status(lc,_("Call terminated."));
|
||||
gstate_new_state(lc, GSTATE_CALL_END, NULL);
|
||||
if (lc->vtable.bye_recv!=NULL){
|
||||
LinphoneAddress *addr=linphone_address_new(from);
|
||||
char *tmp;
|
||||
linphone_address_clean(addr);
|
||||
tmp=linphone_address_as_string(addr);
|
||||
lc->vtable.bye_recv(lc,tmp);
|
||||
ms_free(tmp);
|
||||
linphone_address_destroy(addr);
|
||||
}
|
||||
linphone_call_destroy(lc->call);
|
||||
lc->call=NULL;
|
||||
linphone_call_stop_media_streams(call);
|
||||
if (lc->vtable.show!=NULL)
|
||||
lc->vtable.show(lc);
|
||||
if (lc->vtable.display_status!=NULL)
|
||||
lc->vtable.display_status(lc,_("Call terminated."));
|
||||
|
||||
linphone_call_set_state(call, LinphoneCallEnd,"Call ended");
|
||||
}
|
||||
|
||||
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details){
|
||||
static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details, int code){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
char *msg486=_("User is busy.");
|
||||
char *msg480=_("User is temporarily unavailable.");
|
||||
|
|
@ -284,12 +337,13 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
|
|||
char *msg600=_("User does not want to be disturbed.");
|
||||
char *msg603=_("Call declined.");
|
||||
const char *msg=details;
|
||||
LinphoneCall *call=lc->call;
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (sal_op_get_user_pointer(op)!=lc->call){
|
||||
ms_warning("call_failure: ignoring.");
|
||||
return;
|
||||
if (call==NULL){
|
||||
ms_warning("Call faillure reported on already cleaned call ?");
|
||||
return ;
|
||||
}
|
||||
|
||||
if (lc->vtable.show) lc->vtable.show(lc);
|
||||
|
||||
if (error==SalErrorNoResponse){
|
||||
|
|
@ -342,17 +396,15 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
|
|||
lc->vtable.display_status(lc,_("Call failed."));
|
||||
}
|
||||
}
|
||||
|
||||
if (lc->ringstream!=NULL) {
|
||||
ring_stop(lc->ringstream);
|
||||
lc->ringstream=NULL;
|
||||
}
|
||||
linphone_core_stop_media_streams(lc,call);
|
||||
if (call!=NULL) {
|
||||
linphone_call_destroy(call);
|
||||
if (sr!=SalReasonDeclined) gstate_new_state(lc, GSTATE_CALL_ERROR, msg);
|
||||
else gstate_new_state(lc, GSTATE_CALL_END, msg);
|
||||
lc->call=NULL;
|
||||
}
|
||||
linphone_call_stop_media_streams (call);
|
||||
if (sr!=SalReasonDeclined) linphone_call_set_state(call,LinphoneCallError,msg);
|
||||
else linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
|
||||
|
||||
}
|
||||
|
||||
static void auth_requested(SalOp *h, const char *realm, const char *username){
|
||||
|
|
@ -387,42 +439,77 @@ static void register_success(SalOp *op, bool_t registered){
|
|||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
|
||||
char *msg;
|
||||
|
||||
cfg->registered=registered;
|
||||
gstate_new_state(lc, GSTATE_REG_OK, NULL);
|
||||
if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op));
|
||||
else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op));
|
||||
if (lc->vtable.display_status)
|
||||
linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared ,
|
||||
registered ? "Registration sucessful" : "Unregistration done");
|
||||
if (lc->vtable.display_status){
|
||||
if (cfg->registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op));
|
||||
else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op));
|
||||
lc->vtable.display_status(lc,msg);
|
||||
ms_free(msg);
|
||||
ms_free(msg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void register_failure(SalOp *op, SalError error, SalReason reason, const char *details){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),(details!=NULL) ? details : _("no response timeout"));
|
||||
if (lc->vtable.display_status) lc->vtable.display_status(lc,msg);
|
||||
gstate_new_state(lc, GSTATE_REG_FAILED, msg);
|
||||
ms_free(msg);
|
||||
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op);
|
||||
|
||||
if (cfg==NULL){
|
||||
ms_warning("Registration failed for unknown proxy config.");
|
||||
return ;
|
||||
}
|
||||
if (details==NULL)
|
||||
details=_("no response timeout");
|
||||
|
||||
if (lc->vtable.display_status) {
|
||||
char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op),details );
|
||||
lc->vtable.display_status(lc,msg);
|
||||
ms_free(msg);
|
||||
}
|
||||
linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details);
|
||||
}
|
||||
|
||||
static void vfu_request(SalOp *op){
|
||||
#ifdef VIDEO_ENABLED
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
if (lc->videostream)
|
||||
video_stream_send_vfu(lc->videostream);
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op);
|
||||
if (call==NULL){
|
||||
ms_warning("VFU request but no call !");
|
||||
return ;
|
||||
}
|
||||
if (call->videostream)
|
||||
video_stream_send_vfu(call->videostream);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void dtmf_received(SalOp *op, char dtmf){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (lc->vtable.dtmf_received != NULL)
|
||||
lc->vtable.dtmf_received(lc, dtmf);
|
||||
lc->vtable.dtmf_received(lc, call, dtmf);
|
||||
}
|
||||
|
||||
static void refer_received(Sal *sal, SalOp *op, const char *referto){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
|
||||
if (lc->vtable.refer_received){
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
|
||||
if (call){
|
||||
if (call->refer_to!=NULL){
|
||||
ms_free(call->refer_to);
|
||||
}
|
||||
call->refer_to=ms_strdup(referto);
|
||||
call->refer_pending=TRUE;
|
||||
linphone_call_set_state(call,LinphoneCallRefered,"Refered");
|
||||
if (lc->vtable.display_status){
|
||||
char *msg=ms_strdup_printf(_("We are transferred to %s"),referto);
|
||||
lc->vtable.display_status(lc,msg);
|
||||
ms_free(msg);
|
||||
}
|
||||
if (lc->current_call==NULL) linphone_core_start_pending_refered_calls (lc);
|
||||
sal_refer_accept(op);
|
||||
}else if (lc->vtable.refer_received){
|
||||
lc->vtable.refer_received(lc,referto);
|
||||
if (op) sal_refer_accept(op);
|
||||
sal_refer_accept(op);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -433,10 +520,10 @@ static void text_received(Sal *sal, const char *from, const char *msg){
|
|||
|
||||
static void notify(SalOp *op, const char *from, const char *msg){
|
||||
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
|
||||
|
||||
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op);
|
||||
ms_message("get a %s notify from %s",msg,from);
|
||||
if(lc->vtable.notify_recv)
|
||||
lc->vtable.notify_recv(lc,from,msg);
|
||||
lc->vtable.notify_recv(lc,call,from,msg);
|
||||
}
|
||||
|
||||
static void notify_presence(SalOp *op, SalSubscribeState ss, SalPresenceStatus status, const char *msg){
|
||||
|
|
@ -464,10 +551,14 @@ static void ping_reply(SalOp *op){
|
|||
LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op);
|
||||
ms_message("ping reply !");
|
||||
if (call){
|
||||
if (call->state==LCStatePreEstablishing){
|
||||
if (call->state==LinphoneCallOutgoingInit){
|
||||
linphone_core_start_invite(call->core,call,NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ms_warning("ping reply without call attached...");
|
||||
}
|
||||
}
|
||||
|
||||
SalCallbacks linphone_sal_callbacks={
|
||||
|
|
@ -475,7 +566,7 @@ SalCallbacks linphone_sal_callbacks={
|
|||
call_ringing,
|
||||
call_accepted,
|
||||
call_ack,
|
||||
call_updated,
|
||||
call_updating,
|
||||
call_terminated,
|
||||
call_failure,
|
||||
auth_requested,
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg){
|
|||
if(linphone_core_is_in_communication_with(cr->lc,cr->peer))
|
||||
{
|
||||
ms_message("send SIP message into the call\n");
|
||||
op = cr->lc->call->op;
|
||||
op = (linphone_core_get_current_call(cr->lc))->op;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
1189
coreapi/exevents.c
1189
coreapi/exevents.c
File diff suppressed because it is too large
Load diff
|
|
@ -29,37 +29,37 @@
|
|||
const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){
|
||||
const char *str=NULL;
|
||||
switch(ss){
|
||||
case LINPHONE_STATUS_ONLINE:
|
||||
case LinphoneStatusOnline:
|
||||
str=_("Online");
|
||||
break;
|
||||
case LINPHONE_STATUS_BUSY:
|
||||
case LinphoneStatusBusy:
|
||||
str=_("Busy");
|
||||
break;
|
||||
case LINPHONE_STATUS_BERIGHTBACK:
|
||||
case LinphoneStatusBeRightBack:
|
||||
str=_("Be right back");
|
||||
break;
|
||||
case LINPHONE_STATUS_AWAY:
|
||||
case LinphoneStatusAway:
|
||||
str=_("Away");
|
||||
break;
|
||||
case LINPHONE_STATUS_ONTHEPHONE:
|
||||
case LinphoneStatusOnThePhone:
|
||||
str=_("On the phone");
|
||||
break;
|
||||
case LINPHONE_STATUS_OUTTOLUNCH:
|
||||
case LinphoneStatusOutToLunch:
|
||||
str=_("Out to lunch");
|
||||
break;
|
||||
case LINPHONE_STATUS_NOT_DISTURB:
|
||||
case LinphoneStatusDoNotDisturb:
|
||||
str=_("Do not disturb");
|
||||
break;
|
||||
case LINPHONE_STATUS_MOVED:
|
||||
case LinphoneStatusMoved:
|
||||
str=_("Moved");
|
||||
break;
|
||||
case LINPHONE_STATUS_ALT_SERVICE:
|
||||
case LinphoneStatusAltService:
|
||||
str=_("Using another messaging service");
|
||||
break;
|
||||
case LINPHONE_STATUS_OFFLINE:
|
||||
case LinphoneStatusOffline:
|
||||
str=_("Offline");
|
||||
break;
|
||||
case LINPHONE_STATUS_PENDING:
|
||||
case LinphoneStatusPending:
|
||||
str=_("Pending");
|
||||
break;
|
||||
default:
|
||||
|
|
@ -138,7 +138,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
|
|||
}else from=linphone_core_get_primary_contact(fr->lc);
|
||||
if (fr->outsub==NULL){
|
||||
/* people for which we don't have yet an answer should appear as offline */
|
||||
fr->status=LINPHONE_STATUS_OFFLINE;
|
||||
fr->status=LinphoneStatusOffline;
|
||||
/*
|
||||
if (fr->lc->vtable.notify_recv)
|
||||
fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr);
|
||||
|
|
@ -157,7 +157,7 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){
|
|||
LinphoneFriend * linphone_friend_new(){
|
||||
LinphoneFriend *obj=ms_new0(LinphoneFriend,1);
|
||||
obj->pol=LinphoneSPAccept;
|
||||
obj->status=LINPHONE_STATUS_OFFLINE;
|
||||
obj->status=LinphoneStatusOffline;
|
||||
obj->subscribe=TRUE;
|
||||
return obj;
|
||||
}
|
||||
|
|
@ -243,37 +243,37 @@ int linphone_friend_set_inc_subscribe_policy(LinphoneFriend *fr, LinphoneSubscri
|
|||
|
||||
SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){
|
||||
switch(os){
|
||||
case LINPHONE_STATUS_OFFLINE:
|
||||
case LinphoneStatusOffline:
|
||||
return SalPresenceOffline;
|
||||
break;
|
||||
case LINPHONE_STATUS_ONLINE:
|
||||
case LinphoneStatusOnline:
|
||||
return SalPresenceOnline;
|
||||
break;
|
||||
case LINPHONE_STATUS_BUSY:
|
||||
case LinphoneStatusBusy:
|
||||
return SalPresenceBusy;
|
||||
break;
|
||||
case LINPHONE_STATUS_BERIGHTBACK:
|
||||
case LinphoneStatusBeRightBack:
|
||||
return SalPresenceBerightback;
|
||||
break;
|
||||
case LINPHONE_STATUS_AWAY:
|
||||
case LinphoneStatusAway:
|
||||
return SalPresenceAway;
|
||||
break;
|
||||
case LINPHONE_STATUS_ONTHEPHONE:
|
||||
case LinphoneStatusOnThePhone:
|
||||
return SalPresenceOnthephone;
|
||||
break;
|
||||
case LINPHONE_STATUS_OUTTOLUNCH:
|
||||
case LinphoneStatusOutToLunch:
|
||||
return SalPresenceOuttolunch;
|
||||
break;
|
||||
case LINPHONE_STATUS_NOT_DISTURB:
|
||||
case LinphoneStatusDoNotDisturb:
|
||||
return SalPresenceDonotdisturb;
|
||||
break;
|
||||
case LINPHONE_STATUS_MOVED:
|
||||
case LinphoneStatusMoved:
|
||||
return SalPresenceMoved;
|
||||
break;
|
||||
case LINPHONE_STATUS_ALT_SERVICE:
|
||||
case LinphoneStatusAltService:
|
||||
return SalPresenceAltService;
|
||||
break;
|
||||
case LINPHONE_STATUS_PENDING:
|
||||
case LinphoneStatusPending:
|
||||
return SalPresenceOffline;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -347,7 +347,7 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
|
|||
if (fr->inc_subscribe_pending){
|
||||
switch(fr->pol){
|
||||
case LinphoneSPWait:
|
||||
linphone_friend_notify(fr,LINPHONE_STATUS_PENDING);
|
||||
linphone_friend_notify(fr,LinphoneStatusPending);
|
||||
break;
|
||||
case LinphoneSPAccept:
|
||||
if (fr->lc!=NULL)
|
||||
|
|
@ -356,7 +356,7 @@ void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc){
|
|||
}
|
||||
break;
|
||||
case LinphoneSPDeny:
|
||||
linphone_friend_notify(fr,LINPHONE_STATUS_OFFLINE);
|
||||
linphone_friend_notify(fr,LinphoneStatusOffline);
|
||||
break;
|
||||
}
|
||||
fr->inc_subscribe_pending=FALSE;
|
||||
|
|
|
|||
|
|
@ -83,35 +83,36 @@ static void linphone_core_set_state(LinphoneCore *lc, gstate_group_t group, gsta
|
|||
|
||||
void gstate_new_state(struct _LinphoneCore *lc,
|
||||
gstate_t new_state,
|
||||
LinphoneGeneralStateContext gctx,
|
||||
const char *message) {
|
||||
LinphoneGeneralState states_arg;
|
||||
|
||||
/* determine the affected group */
|
||||
if (new_state < GSTATE_REG_NONE)
|
||||
states_arg.group = GSTATE_GROUP_POWER;
|
||||
else if (new_state < GSTATE_CALL_IDLE)
|
||||
states_arg.group = GSTATE_GROUP_REG;
|
||||
else
|
||||
states_arg.group = GSTATE_GROUP_CALL;
|
||||
|
||||
/* store the new state while remembering the old one */
|
||||
states_arg.new_state = new_state;
|
||||
states_arg.old_state = linphone_core_get_state(lc,states_arg.group);
|
||||
linphone_core_set_state(lc, states_arg.group,new_state);
|
||||
states_arg.message = message;
|
||||
|
||||
/*printf("gstate_new_state: %s\t-> %s\t(%s)\n",
|
||||
_gstates_text[states_arg.old_state],
|
||||
_gstates_text[states_arg.new_state],
|
||||
message);*/
|
||||
LinphoneGeneralState states_arg;
|
||||
|
||||
/* call the virtual method */
|
||||
if (lc->vtable.general_state)
|
||||
lc->vtable.general_state(lc, &states_arg);
|
||||
|
||||
/* immediately proceed to idle state */
|
||||
if (new_state == GSTATE_CALL_END ||
|
||||
new_state == GSTATE_CALL_ERROR)
|
||||
gstate_new_state(lc, GSTATE_CALL_IDLE, NULL);
|
||||
/* determine the affected group */
|
||||
if (new_state < GSTATE_REG_NONE)
|
||||
states_arg.group = GSTATE_GROUP_POWER;
|
||||
else if (new_state < GSTATE_CALL_IDLE)
|
||||
states_arg.group = GSTATE_GROUP_REG;
|
||||
else
|
||||
states_arg.group = GSTATE_GROUP_CALL;
|
||||
|
||||
/* store the new state while remembering the old one */
|
||||
states_arg.new_state = new_state;
|
||||
states_arg.old_state = linphone_core_get_state(lc,states_arg.group);
|
||||
linphone_core_set_state(lc, states_arg.group,new_state);
|
||||
states_arg.message = message;
|
||||
|
||||
/*printf("gstate_new_state: %s\t-> %s\t(%s)\n",
|
||||
_gstates_text[states_arg.old_state],
|
||||
_gstates_text[states_arg.new_state],
|
||||
message);*/
|
||||
|
||||
/* call the virtual method */
|
||||
if (lc->vtable.general_state)
|
||||
lc->vtable.general_state(lc, &states_arg, gctx);
|
||||
|
||||
/* immediately proceed to idle state */
|
||||
if (new_state == GSTATE_CALL_END ||
|
||||
new_state == GSTATE_CALL_ERROR)
|
||||
gstate_new_state(lc, GSTATE_CALL_IDLE, gctx, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ RECURSIVE = NO
|
|||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH = ../
|
||||
EXAMPLE_PATH = ../../ .
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
|
|
|
|||
|
|
@ -31,3 +31,22 @@ endif
|
|||
|
||||
clean-local:
|
||||
rm -rf doc
|
||||
|
||||
noinst_PROGRAMS=helloworld
|
||||
|
||||
helloworld_SOURCES=helloworld.c
|
||||
|
||||
helloworld_LDADD=$(top_builddir)/coreapi/liblinphone.la
|
||||
|
||||
INCLUDES=-I$(top_srcdir)/coreapi
|
||||
|
||||
AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
|
||||
$(ORTP_CFLAGS) \
|
||||
$(OSIP_CFLAGS) \
|
||||
$(EXOSIP_CFLAGS) \
|
||||
-DENABLE_TRACE \
|
||||
-DLOG_DOMAIN=\"LinphoneCore\" \
|
||||
$(IPV6_CFLAGS) \
|
||||
-DORTP_INET6 \
|
||||
$(VIDEO_CFLAGS)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,64 +29,11 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @defgroup tutorial_liblinphone Tutorial: Placing and receiving calls with liblinphone
|
||||
*
|
||||
|
||||
<H1>Initialize liblinphone</H1>
|
||||
|
||||
The first thing to do is to initialize the library passing it a set of callbacks functions to receive
|
||||
various notifications: incoming calls, progress of calls etc...
|
||||
These callbacks are all grouped in the LinphoneCoreVTable structure.
|
||||
All are optionnals (use NULL if you don't need them).
|
||||
The following code shows how initialize liblinphone:
|
||||
|
||||
<PRE>
|
||||
##include <linphonecore.h>
|
||||
|
||||
//callback function for notification of incoming calls
|
||||
static void on_invite_recv(LinphoneCore *lc, const char *from){
|
||||
printf("Receiving a call from %s\n",from);
|
||||
}
|
||||
|
||||
//callback function for notification end of calls (by remote)
|
||||
static void on_bye_recv(LinphoneCore *lc, const char *from){
|
||||
printf("Remote end hangup\n");
|
||||
}
|
||||
|
||||
/
|
||||
static void on_display_status(LinphoneCore *lc, const char *msg){
|
||||
printf("%s",msg);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
LinphoneCoreVTable vtable;
|
||||
|
||||
memset(&vtable,0,sizeof(vtable));
|
||||
vtable.inv_recv=&on_invite_recv;
|
||||
vtable.bye_recv=&on_bye_recv;
|
||||
vtable.display_status=&on_display_status;
|
||||
|
||||
}
|
||||
|
||||
</PRE>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup initializing Initialization and destruction
|
||||
*
|
||||
* @defgroup initializing Initializing liblinphone
|
||||
**/
|
||||
|
||||
/**
|
||||
* @defgroup call_control Call control
|
||||
*
|
||||
* The application can initiate outgoing calls with linphone_core_invite().
|
||||
* It is notified of incoming call thanks to the inv_recv callback of the LinphoneCoreVTable
|
||||
* structure that is passed at creation of the LinphoneCore object.
|
||||
* It can then answer calls with linphone_core_accept_call().
|
||||
* Calls can be terminated or declined with linphone_core_terminate_call().
|
||||
* The application is notified when the remote party hangups thanks to
|
||||
* bye_recv callback of the #LinphoneCoreVTable.
|
||||
* @defgroup call_control Placing and receiving calls
|
||||
**/
|
||||
|
||||
/**
|
||||
|
|
@ -109,6 +56,7 @@ The following code shows how initialize liblinphone:
|
|||
* @defgroup call_logs Managing call logs
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup linphone_address SIP address parser API.
|
||||
* This api is useful for manipulating SIP addresses ('from' or 'to' headers).
|
||||
|
|
@ -117,3 +65,14 @@ The following code shows how initialize liblinphone:
|
|||
/**
|
||||
* @defgroup misc Miscenalleous: logs, version strings, config storage
|
||||
**/
|
||||
|
||||
/**
|
||||
* @defgroup tutorial_liblinphone Tutorial: Placing calls with liblinphone
|
||||
*
|
||||
* The minimalist program below illustrates how to initialize liblinphone and place and outgoing call.
|
||||
* @include helloworld.c
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
723
coreapi/linphonecall.c
Normal file
723
coreapi/linphonecall.c
Normal file
|
|
@ -0,0 +1,723 @@
|
|||
|
||||
/*
|
||||
linphone
|
||||
Copyright (C) 2010 Belledonne Communications SARL
|
||||
(simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifdef WIN32
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include "linphonecore.h"
|
||||
#include "sipsetup.h"
|
||||
#include "lpconfig.h"
|
||||
#include "private.h"
|
||||
|
||||
|
||||
#include "mediastreamer2/mediastream.h"
|
||||
#include "mediastreamer2/msvolume.h"
|
||||
#include "mediastreamer2/msequalizer.h"
|
||||
|
||||
|
||||
|
||||
static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, bool_t only_one_codec){
|
||||
MSList *l=NULL;
|
||||
const MSList *it;
|
||||
for(it=codecs;it!=NULL;it=it->next){
|
||||
PayloadType *pt=(PayloadType*)it->data;
|
||||
if ((pt->flags & PAYLOAD_TYPE_ENABLED) && linphone_core_check_payload_type_usability(lc,pt)){
|
||||
l=ms_list_append(l,payload_type_clone(pt));
|
||||
if (only_one_codec) break;
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
static SalMediaDescription *create_local_media_description(LinphoneCore *lc,
|
||||
LinphoneCall *call, const char *username, bool_t only_one_codec){
|
||||
MSList *l;
|
||||
PayloadType *pt;
|
||||
SalMediaDescription *md=sal_media_description_new();
|
||||
md->nstreams=1;
|
||||
strncpy(md->addr,call->localip,sizeof(md->addr));
|
||||
strncpy(md->username,username,sizeof(md->username));
|
||||
md->bandwidth=linphone_core_get_download_bandwidth(lc);
|
||||
/*set audio capabilities */
|
||||
strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr));
|
||||
md->streams[0].port=call->audio_port;
|
||||
md->streams[0].proto=SalProtoRtpAvp;
|
||||
md->streams[0].type=SalAudio;
|
||||
md->streams[0].ptime=lc->net_conf.down_ptime;
|
||||
l=make_codec_list(lc,lc->codecs_conf.audio_codecs,only_one_codec);
|
||||
pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
|
||||
l=ms_list_append(l,pt);
|
||||
md->streams[0].payloads=l;
|
||||
|
||||
if (lc->dw_audio_bw>0)
|
||||
md->streams[0].bandwidth=lc->dw_audio_bw;
|
||||
|
||||
if (linphone_core_video_enabled (lc)){
|
||||
md->nstreams++;
|
||||
md->streams[1].port=call->video_port;
|
||||
md->streams[1].proto=SalProtoRtpAvp;
|
||||
md->streams[1].type=SalVideo;
|
||||
l=make_codec_list(lc,lc->codecs_conf.video_codecs,only_one_codec);
|
||||
md->streams[1].payloads=l;
|
||||
if (lc->dw_video_bw)
|
||||
md->streams[1].bandwidth=lc->dw_video_bw;
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
static int find_port_offset(LinphoneCore *lc){
|
||||
int offset;
|
||||
MSList *elem;
|
||||
int audio_port;
|
||||
bool_t already_used=FALSE;
|
||||
for(offset=0;offset<100;offset+=2){
|
||||
audio_port=linphone_core_get_audio_port (lc)+offset;
|
||||
already_used=FALSE;
|
||||
for(elem=lc->calls;elem!=NULL;elem=elem->next){
|
||||
LinphoneCall *call=(LinphoneCall*)elem->data;
|
||||
if (call->audio_port==audio_port) {
|
||||
already_used=TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!already_used) break;
|
||||
}
|
||||
if (offset==100){
|
||||
ms_error("Could not find any free port !");
|
||||
return -1;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){
|
||||
int port_offset;
|
||||
call->refcnt=1;
|
||||
call->state=LinphoneCallIdle;
|
||||
call->start_time=time(NULL);
|
||||
call->media_start_time=0;
|
||||
call->log=linphone_call_log_new(call, from, to);
|
||||
linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone);
|
||||
port_offset=find_port_offset (call->core);
|
||||
if (port_offset==-1) return;
|
||||
call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
|
||||
call->video_port=linphone_core_get_video_port(call->core)+port_offset;
|
||||
|
||||
}
|
||||
|
||||
static void discover_mtu(LinphoneCore *lc, const char *remote){
|
||||
int mtu;
|
||||
if (lc->net_conf.mtu==0 ){
|
||||
/*attempt to discover mtu*/
|
||||
mtu=ms_discover_mtu(remote);
|
||||
if (mtu>0){
|
||||
ms_set_mtu(mtu);
|
||||
ms_message("Discovered mtu is %i, RTP payload max size is %i",
|
||||
mtu, ms_get_payload_max_size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to)
|
||||
{
|
||||
LinphoneCall *call=ms_new0(LinphoneCall,1);
|
||||
call->dir=LinphoneCallOutgoing;
|
||||
call->op=sal_op_new(lc->sal);
|
||||
sal_op_set_user_pointer(call->op,call);
|
||||
call->core=lc;
|
||||
linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
|
||||
linphone_call_init_common(call,from,to);
|
||||
call->localdesc=create_local_media_description (lc,call,
|
||||
linphone_address_get_username(from),FALSE);
|
||||
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
discover_mtu(lc,linphone_address_get_domain (to));
|
||||
return call;
|
||||
}
|
||||
|
||||
LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){
|
||||
LinphoneCall *call=ms_new0(LinphoneCall,1);
|
||||
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
char *to_str;
|
||||
char *from_str;
|
||||
|
||||
call->dir=LinphoneCallIncoming;
|
||||
sal_op_set_user_pointer(op,call);
|
||||
call->op=op;
|
||||
call->core=lc;
|
||||
|
||||
if (lc->sip_conf.ping_with_options){
|
||||
/*the following sends an option request back to the caller so that
|
||||
we get a chance to discover our nat'd address before answering.*/
|
||||
call->ping_op=sal_op_new(lc->sal);
|
||||
to_str=linphone_address_as_string(to);
|
||||
from_str=linphone_address_as_string(from);
|
||||
sal_op_set_route(call->ping_op,sal_op_get_network_origin(call->op));
|
||||
sal_op_set_user_pointer(call->ping_op,call);
|
||||
sal_ping(call->ping_op,to_str,from_str);
|
||||
ms_free(to_str);
|
||||
ms_free(from_str);
|
||||
}
|
||||
|
||||
linphone_address_clean(from);
|
||||
linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
|
||||
linphone_call_init_common(call, from, to);
|
||||
call->localdesc=create_local_media_description (lc,call,
|
||||
linphone_address_get_username(me),lc->sip_conf.only_one_codec);
|
||||
if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseStun)
|
||||
linphone_core_run_stun_tests(call->core,call);
|
||||
discover_mtu(lc,linphone_address_get_domain(from));
|
||||
linphone_address_destroy(me);
|
||||
return call;
|
||||
}
|
||||
|
||||
/* this function is called internally to get rid of a call.
|
||||
It performs the following tasks:
|
||||
- remove the call from the internal list of calls
|
||||
- unref the LinphoneCall object
|
||||
- update the call logs accordingly
|
||||
*/
|
||||
|
||||
static void linphone_call_set_terminated(LinphoneCall *call){
|
||||
LinphoneCallStatus status=LinphoneCallAborted;
|
||||
LinphoneCore *lc=call->core;
|
||||
|
||||
linphone_core_update_allocated_audio_bandwidth(lc);
|
||||
if (call->state==LinphoneCallEnd){
|
||||
status=LinphoneCallSuccess;
|
||||
|
||||
}
|
||||
linphone_call_log_completed(call->log,call, status);
|
||||
|
||||
if (call == lc->current_call){
|
||||
ms_message("Resetting the current call");
|
||||
lc->current_call=NULL;
|
||||
linphone_core_start_pending_refered_calls(lc);
|
||||
}
|
||||
|
||||
if (linphone_core_del_call(lc,call) != 0){
|
||||
ms_error("Could not remove the call from the list !!!");
|
||||
}
|
||||
|
||||
if (ms_list_size(lc->calls)==0)
|
||||
linphone_core_notify_all_friends(lc,lc->presence_mode);
|
||||
|
||||
if (call->op!=NULL) {
|
||||
/* so that we cannot have anymore upcalls for SAL
|
||||
concerning this call*/
|
||||
sal_op_release(call->op);
|
||||
call->op=NULL;
|
||||
}
|
||||
linphone_call_unref(call);
|
||||
}
|
||||
|
||||
void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
|
||||
LinphoneCore *lc=call->core;
|
||||
if (call->state!=cstate){
|
||||
if (cstate!=LinphoneCallRefered){
|
||||
/*LinphoneCallRefered is rather an event, not a state.
|
||||
Indeed it does not change the state of the call (still paused or running)*/
|
||||
call->state=cstate;
|
||||
}
|
||||
if (lc->vtable.call_state_changed)
|
||||
lc->vtable.call_state_changed(lc,call,cstate,message);
|
||||
}
|
||||
if (call->state==LinphoneCallEnd || call->state==LinphoneCallError)
|
||||
linphone_call_set_terminated (call);
|
||||
}
|
||||
|
||||
static void linphone_call_destroy(LinphoneCall *obj)
|
||||
{
|
||||
if (obj->op!=NULL) {
|
||||
sal_op_release(obj->op);
|
||||
obj->op=NULL;
|
||||
}
|
||||
if (obj->resultdesc!=NULL) {
|
||||
sal_media_description_unref(obj->resultdesc);
|
||||
obj->resultdesc=NULL;
|
||||
}
|
||||
if (obj->localdesc!=NULL) {
|
||||
sal_media_description_unref(obj->localdesc);
|
||||
obj->localdesc=NULL;
|
||||
}
|
||||
if (obj->ping_op) {
|
||||
sal_op_release(obj->ping_op);
|
||||
}
|
||||
if (obj->refer_to){
|
||||
ms_free(obj->refer_to);
|
||||
}
|
||||
ms_free(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @addtogroup call_control
|
||||
* @{
|
||||
**/
|
||||
|
||||
/**
|
||||
* Increments the call 's reference count.
|
||||
* An application that wishes to retain a pointer to call object
|
||||
* must use this function to unsure the pointer remains
|
||||
* valid. Once the application no more needs this pointer,
|
||||
* it must call linphone_call_unref().
|
||||
**/
|
||||
void linphone_call_ref(LinphoneCall *obj){
|
||||
obj->refcnt++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrements the call object reference count.
|
||||
* See linphone_call_ref().
|
||||
**/
|
||||
void linphone_call_unref(LinphoneCall *obj){
|
||||
obj->refcnt--;
|
||||
if (obj->refcnt==0)
|
||||
linphone_call_destroy(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remote address associated to this call
|
||||
*
|
||||
**/
|
||||
const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call){
|
||||
return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remote address associated to this call as a string.
|
||||
*
|
||||
* The result string must be freed by user using ms_free().
|
||||
**/
|
||||
char *linphone_call_get_remote_address_as_string(const LinphoneCall *call){
|
||||
return linphone_address_as_string(linphone_call_get_remote_address(call));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the call's current state.
|
||||
**/
|
||||
LinphoneCallState linphone_call_get_state(const LinphoneCall *call){
|
||||
return call->state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user_pointer in the LinphoneCall
|
||||
*
|
||||
* @ingroup call_control
|
||||
*
|
||||
* return user_pointer an opaque user pointer that can be retrieved at any time
|
||||
**/
|
||||
void *linphone_call_get_user_pointer(LinphoneCall *call)
|
||||
{
|
||||
return call->user_pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user_pointer in the LinphoneCall
|
||||
*
|
||||
* @ingroup call_control
|
||||
*
|
||||
* the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall
|
||||
**/
|
||||
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer)
|
||||
{
|
||||
call->user_pointer = user_pointer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the call log associated to this call.
|
||||
**/
|
||||
LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call){
|
||||
return call->log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the refer-to uri (if the call was transfered).
|
||||
**/
|
||||
const char *linphone_call_get_refer_to(const LinphoneCall *call){
|
||||
return call->refer_to;
|
||||
}
|
||||
|
||||
LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call){
|
||||
return call->log->dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this calls has received a transfer that has not been
|
||||
* executed yet.
|
||||
* Pending transfers are executed when this call is being paused or closed,
|
||||
* locally or by remote endpoint.
|
||||
* If the call is already paused while receiving the transfer request, the
|
||||
* transfer immediately occurs.
|
||||
**/
|
||||
bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
|
||||
return call->refer_pending;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
**/
|
||||
|
||||
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
static void rendercb(void *data, const MSPicture *local, const MSPicture *remote){
|
||||
ms_message("rendercb, local buffer=%p, remote buffer=%p",
|
||||
local ? local->planes[0] : NULL, remote? remote->planes[0] : NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
void linphone_call_init_media_streams(LinphoneCall *call){
|
||||
LinphoneCore *lc=call->core;
|
||||
SalMediaDescription *md=call->localdesc;
|
||||
AudioStream *audiostream;
|
||||
|
||||
call->audiostream=audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));
|
||||
if (linphone_core_echo_limiter_enabled(lc)){
|
||||
const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
|
||||
if (strcasecmp(type,"mic")==0)
|
||||
audio_stream_enable_echo_limiter(audiostream,ELControlMic);
|
||||
else if (strcasecmp(type,"full")==0)
|
||||
audio_stream_enable_echo_limiter(audiostream,ELControlFull);
|
||||
}
|
||||
audio_stream_enable_gain_control(audiostream,TRUE);
|
||||
if (linphone_core_echo_cancellation_enabled(lc)){
|
||||
int len,delay,framesize;
|
||||
len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
|
||||
delay=lp_config_get_int(lc->config,"sound","ec_delay",0);
|
||||
framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0);
|
||||
audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize);
|
||||
}
|
||||
audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc));
|
||||
{
|
||||
int enabled=lp_config_get_int(lc->config,"sound","noisegate",0);
|
||||
audio_stream_enable_noise_gate(audiostream,enabled);
|
||||
}
|
||||
if (lc->a_rtp)
|
||||
rtp_session_set_transports(audiostream->session,lc->a_rtp,lc->a_rtcp);
|
||||
|
||||
#ifdef VIDEO_ENABLED
|
||||
if ((lc->video_conf.display || lc->video_conf.capture) && md->streams[1].port>0){
|
||||
call->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc));
|
||||
#ifdef TEST_EXT_RENDERER
|
||||
video_stream_set_render_callback(call->videostream,rendercb,NULL);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
call->videostream=NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'};
|
||||
|
||||
static void linphone_core_dtmf_received(RtpSession* s, int dtmf, void* user_data){
|
||||
LinphoneCore* lc = (LinphoneCore*)user_data;
|
||||
if (dtmf<0 || dtmf>15){
|
||||
ms_warning("Bad dtmf value %i",dtmf);
|
||||
return;
|
||||
}
|
||||
if (lc->vtable.dtmf_received != NULL)
|
||||
lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]);
|
||||
}
|
||||
|
||||
static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){
|
||||
if (st->equalizer){
|
||||
MSFilter *f=st->equalizer;
|
||||
int enabled=lp_config_get_int(lc->config,"sound","eq_active",0);
|
||||
const char *gains=lp_config_get_string(lc->config,"sound","eq_gains",NULL);
|
||||
ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled);
|
||||
if (enabled){
|
||||
if (gains){
|
||||
do{
|
||||
int bytes;
|
||||
MSEqualizerGain g;
|
||||
if (sscanf(gains,"%f:%f:%f %n",&g.frequency,&g.gain,&g.width,&bytes)==3){
|
||||
ms_message("Read equalizer gains: %f(~%f) --> %f",g.frequency,g.width,g.gain);
|
||||
ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN,&g);
|
||||
gains+=bytes;
|
||||
}else break;
|
||||
}while(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void post_configure_audio_streams(LinphoneCall*call){
|
||||
AudioStream *st=call->audiostream;
|
||||
LinphoneCore *lc=call->core;
|
||||
float mic_gain=lp_config_get_float(lc->config,"sound","mic_gain",1);
|
||||
float thres = 0;
|
||||
float recv_gain;
|
||||
float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05);
|
||||
float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0);
|
||||
int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0);
|
||||
|
||||
if (mic_gain!=-1)
|
||||
audio_stream_set_mic_gain(st,mic_gain);
|
||||
call->audio_muted=FALSE;
|
||||
|
||||
recv_gain = lc->sound_conf.soft_play_lev;
|
||||
if (recv_gain != 0) {
|
||||
linphone_core_set_playback_gain_db (lc,recv_gain);
|
||||
}
|
||||
if (st->volsend){
|
||||
ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal);
|
||||
}
|
||||
if (linphone_core_echo_limiter_enabled(lc)){
|
||||
float speed=lp_config_get_float(lc->config,"sound","el_speed",-1);
|
||||
thres=lp_config_get_float(lc->config,"sound","el_thres",-1);
|
||||
float force=lp_config_get_float(lc->config,"sound","el_force",-1);
|
||||
int sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1);
|
||||
MSFilter *f=NULL;
|
||||
if (st->el_type!=ELInactive){
|
||||
f=st->volsend;
|
||||
if (speed==-1) speed=0.03;
|
||||
if (force==-1) force=25;
|
||||
ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed);
|
||||
ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force);
|
||||
if (thres!=-1)
|
||||
ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres);
|
||||
if (sustain!=-1)
|
||||
ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain);
|
||||
}
|
||||
}
|
||||
|
||||
if (st->volsend){
|
||||
ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
|
||||
ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain);
|
||||
}
|
||||
if (st->volrecv){
|
||||
/* parameters for a limited noise-gate effect, using echo limiter threshold */
|
||||
float floorgain = 1/mic_gain;
|
||||
ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&thres);
|
||||
ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&floorgain);
|
||||
}
|
||||
parametrize_equalizer(lc,st);
|
||||
if (lc->vtable.dtmf_received!=NULL){
|
||||
/* replace by our default action*/
|
||||
audio_stream_play_received_dtmfs(call->audiostream,FALSE);
|
||||
rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
|
||||
int bw;
|
||||
const MSList *elem;
|
||||
RtpProfile *prof=rtp_profile_new("Call profile");
|
||||
bool_t first=TRUE;
|
||||
int remote_bw=0;
|
||||
*used_pt=-1;
|
||||
|
||||
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
|
||||
PayloadType *pt=(PayloadType*)elem->data;
|
||||
|
||||
if (first) {
|
||||
if (desc->type==SalAudio){
|
||||
linphone_core_update_allocated_audio_bandwidth_in_call(lc,pt);
|
||||
}
|
||||
*used_pt=payload_type_get_number(pt);
|
||||
first=FALSE;
|
||||
}
|
||||
if (desc->bandwidth>0) remote_bw=desc->bandwidth;
|
||||
else if (md->bandwidth>0) {
|
||||
/*case where b=AS is given globally, not per stream*/
|
||||
remote_bw=md->bandwidth;
|
||||
if (desc->type==SalVideo){
|
||||
remote_bw-=lc->audio_bw;
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->type==SalAudio){
|
||||
bw=get_min_bandwidth(lc->up_audio_bw,remote_bw);
|
||||
}else bw=get_min_bandwidth(lc->up_video_bw,remote_bw);
|
||||
if (bw>0) pt->normal_bitrate=bw*1000;
|
||||
else if (desc->type==SalAudio){
|
||||
pt->normal_bitrate=-1;
|
||||
}
|
||||
if (desc->ptime>0){
|
||||
char tmp[40];
|
||||
snprintf(tmp,sizeof(tmp),"ptime=%i",desc->ptime);
|
||||
payload_type_append_send_fmtp(pt,tmp);
|
||||
}
|
||||
rtp_profile_set_payload(prof,payload_type_get_number(pt),pt);
|
||||
}
|
||||
return prof;
|
||||
}
|
||||
|
||||
void linphone_call_start_media_streams(LinphoneCall *call){
|
||||
LinphoneCore *lc=call->core;
|
||||
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
|
||||
const char *tool="linphone-" LINPHONE_VERSION;
|
||||
char *cname;
|
||||
int used_pt=-1;
|
||||
if(call->audiostream == NULL)
|
||||
{
|
||||
ms_fatal("start_media_stream() called without prior init !");
|
||||
return;
|
||||
}
|
||||
/* adjust rtp jitter compensation. It must be at least the latency of the sound card */
|
||||
int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp);
|
||||
|
||||
if (call->media_start_time==0) call->media_start_time=time(NULL);
|
||||
|
||||
cname=linphone_address_as_string_uri_only(me);
|
||||
{
|
||||
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalAudio);
|
||||
if (stream){
|
||||
MSSndCard *playcard=lc->sound_conf.lsd_card ?
|
||||
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
|
||||
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
|
||||
const char *playfile=lc->play_file;
|
||||
const char *recfile=lc->rec_file;
|
||||
call->audio_profile=make_profile(lc,call->resultdesc,stream,&used_pt);
|
||||
if (used_pt!=-1){
|
||||
if (playcard==NULL) {
|
||||
ms_warning("No card defined for playback !");
|
||||
}
|
||||
if (captcard==NULL) {
|
||||
ms_warning("No card defined for capture !");
|
||||
}
|
||||
ms_message("streamdir is %i",stream->dir);
|
||||
/*Replace soundcard filters by inactive file players or recorders
|
||||
when placed in recvonly or sendonly mode*/
|
||||
if (stream->port==0 || stream->dir==SalStreamRecvOnly){
|
||||
captcard=NULL;
|
||||
playfile=NULL;
|
||||
}else if (stream->dir==SalStreamSendOnly){
|
||||
playcard=NULL;
|
||||
captcard=NULL;
|
||||
recfile=NULL;
|
||||
}
|
||||
/*if playfile are supplied don't use soundcards*/
|
||||
if (lc->use_files) {
|
||||
captcard=NULL;
|
||||
playcard=NULL;
|
||||
}
|
||||
audio_stream_start_full(
|
||||
call->audiostream,
|
||||
call->audio_profile,
|
||||
stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr,
|
||||
stream->port,
|
||||
stream->port+1,
|
||||
used_pt,
|
||||
jitt_comp,
|
||||
playfile,
|
||||
recfile,
|
||||
playcard,
|
||||
captcard,
|
||||
linphone_core_echo_cancellation_enabled(lc));
|
||||
post_configure_audio_streams(call);
|
||||
audio_stream_set_rtcp_information(call->audiostream, cname, tool);
|
||||
}else ms_warning("No audio stream accepted ?");
|
||||
}
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
{
|
||||
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
|
||||
SalProtoRtpAvp,SalVideo);
|
||||
used_pt=-1;
|
||||
/* shutdown preview */
|
||||
if (lc->previewstream!=NULL) {
|
||||
video_preview_stop(lc->previewstream);
|
||||
lc->previewstream=NULL;
|
||||
}
|
||||
if (stream) {
|
||||
const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr;
|
||||
call->video_profile=make_profile(lc,call->resultdesc,stream,&used_pt);
|
||||
if (used_pt!=-1){
|
||||
VideoStreamDir dir=VideoStreamSendRecv;
|
||||
MSWebCam *cam=lc->video_conf.device;
|
||||
bool_t is_inactive=FALSE;
|
||||
|
||||
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
|
||||
video_stream_enable_self_view(call->videostream,lc->video_conf.selfview);
|
||||
|
||||
if (stream->dir==SalStreamSendOnly && lc->video_conf.capture ){
|
||||
cam=ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"Static picture");
|
||||
dir=VideoStreamSendOnly;
|
||||
}else if (stream->dir==SalStreamRecvOnly && lc->video_conf.display ){
|
||||
dir=VideoStreamRecvOnly;
|
||||
}else if (stream->dir==SalStreamSendRecv){
|
||||
if (lc->video_conf.display && lc->video_conf.capture)
|
||||
dir=VideoStreamSendRecv;
|
||||
else if (lc->video_conf.display)
|
||||
dir=VideoStreamRecvOnly;
|
||||
else
|
||||
dir=VideoStreamSendOnly;
|
||||
}else{
|
||||
ms_warning("video stream is inactive.");
|
||||
/*either inactive or incompatible with local capabilities*/
|
||||
is_inactive=TRUE;
|
||||
}
|
||||
if (!is_inactive){
|
||||
video_stream_set_direction (call->videostream, dir);
|
||||
video_stream_start(call->videostream,
|
||||
call->video_profile, addr, stream->port,
|
||||
stream->port+1,
|
||||
used_pt, jitt_comp, cam);
|
||||
video_stream_set_rtcp_information(call->videostream, cname,tool);
|
||||
}
|
||||
}else ms_warning("No video stream accepted.");
|
||||
}else{
|
||||
ms_warning("No valid video stream defined.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
goto end;
|
||||
end:
|
||||
ms_free(cname);
|
||||
linphone_address_destroy(me);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
|
||||
audio_stream_get_local_rtp_stats (st,&log->local_stats);
|
||||
}
|
||||
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call){
|
||||
if (call->audiostream!=NULL) {
|
||||
linphone_call_log_fill_stats (call->log,call->audiostream);
|
||||
audio_stream_stop(call->audiostream);
|
||||
call->audiostream=NULL;
|
||||
}
|
||||
#ifdef VIDEO_ENABLED
|
||||
if (call->videostream!=NULL){
|
||||
video_stream_stop(call->videostream);
|
||||
call->videostream=NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
if (call->audio_profile){
|
||||
rtp_profile_clear_all(call->audio_profile);
|
||||
rtp_profile_destroy(call->audio_profile);
|
||||
call->audio_profile=NULL;
|
||||
}
|
||||
if (call->video_profile){
|
||||
rtp_profile_clear_all(call->video_profile);
|
||||
rtp_profile_destroy(call->video_profile);
|
||||
call->video_profile=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -97,14 +97,7 @@ void linphone_address_destroy(LinphoneAddress *u);
|
|||
|
||||
struct _SipSetupContext;
|
||||
|
||||
/**
|
||||
* The LinphoneCall object represents a call issued or received by the LinphoneCore
|
||||
**/
|
||||
struct _LinphoneCall;
|
||||
typedef struct _LinphoneCall LinphoneCall;
|
||||
|
||||
bool_t linphone_call_asked_to_autoanswer(struct _LinphoneCall *call);
|
||||
|
||||
/**
|
||||
* Enum representing the direction of a call.
|
||||
* @ingroup call_logs
|
||||
|
|
@ -161,6 +154,28 @@ const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
|
|||
const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl);
|
||||
char * linphone_call_log_to_str(LinphoneCallLog *cl);
|
||||
|
||||
|
||||
/**
|
||||
* The LinphoneCall object represents a call issued or received by the LinphoneCore
|
||||
**/
|
||||
struct _LinphoneCall;
|
||||
typedef struct _LinphoneCall LinphoneCall;
|
||||
|
||||
|
||||
enum _LinphoneCallState linphone_call_get_state(const LinphoneCall *call);
|
||||
bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call);
|
||||
const LinphoneAddress * linphone_core_get_current_call_remote_address(struct _LinphoneCore *lc);
|
||||
const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call);
|
||||
char *linphone_call_get_remote_address_as_string(const LinphoneCall *call);
|
||||
LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call);
|
||||
void linphone_call_ref(LinphoneCall *call);
|
||||
void linphone_call_unref(LinphoneCall *call);
|
||||
LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call);
|
||||
const char *linphone_call_get_refer_to(const LinphoneCall *call);
|
||||
bool_t linphone_call_has_transfer_pending(const LinphoneCall *call);
|
||||
void *linphone_call_get_user_pointer(LinphoneCall *call);
|
||||
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
|
||||
|
||||
typedef enum{
|
||||
LinphoneSPWait,
|
||||
LinphoneSPDeny,
|
||||
|
|
@ -168,18 +183,18 @@ typedef enum{
|
|||
}LinphoneSubscribePolicy;
|
||||
|
||||
typedef enum _LinphoneOnlineStatus{
|
||||
LINPHONE_STATUS_OFFLINE,
|
||||
LINPHONE_STATUS_ONLINE,
|
||||
LINPHONE_STATUS_BUSY,
|
||||
LINPHONE_STATUS_BERIGHTBACK,
|
||||
LINPHONE_STATUS_AWAY,
|
||||
LINPHONE_STATUS_ONTHEPHONE,
|
||||
LINPHONE_STATUS_OUTTOLUNCH,
|
||||
LINPHONE_STATUS_NOT_DISTURB,
|
||||
LINPHONE_STATUS_MOVED,
|
||||
LINPHONE_STATUS_ALT_SERVICE,
|
||||
LINPHONE_STATUS_PENDING,
|
||||
LINPHONE_STATUS_END
|
||||
LinphoneStatusOffline,
|
||||
LinphoneStatusOnline,
|
||||
LinphoneStatusBusy,
|
||||
LinphoneStatusBeRightBack,
|
||||
LinphoneStatusAway,
|
||||
LinphoneStatusOnThePhone,
|
||||
LinphoneStatusOutToLunch,
|
||||
LinphoneStatusDoNotDisturb,
|
||||
LinphoneStatusMoved,
|
||||
LinphoneStatusAltService,
|
||||
LinphoneStatusPending,
|
||||
LinphoneStatusEnd
|
||||
}LinphoneOnlineStatus;
|
||||
|
||||
const char *linphone_online_status_to_string(LinphoneOnlineStatus ss);
|
||||
|
|
@ -350,72 +365,62 @@ void linphone_chat_room_destroy(LinphoneChatRoom *cr);
|
|||
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
|
||||
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr);
|
||||
|
||||
/* describes the different groups of states */
|
||||
typedef enum _gstate_group {
|
||||
GSTATE_GROUP_POWER,
|
||||
GSTATE_GROUP_REG,
|
||||
GSTATE_GROUP_CALL
|
||||
} gstate_group_t;
|
||||
typedef enum _LinphoneCallState{
|
||||
LinphoneCallIdle,
|
||||
LinphoneCallIncomingReceived,
|
||||
LinphoneCallOutgoingInit,
|
||||
LinphoneCallOutgoingProgress,
|
||||
LinphoneCallOutgoingRinging,
|
||||
LinphoneCallOutgoingEarlyMedia,
|
||||
LinphoneCallConnected,
|
||||
LinphoneCallStreamsRunning,
|
||||
LinphoneCallPausing,
|
||||
LinphoneCallPaused,
|
||||
LinphoneCallResuming,
|
||||
LinphoneCallRefered,
|
||||
LinphoneCallError,
|
||||
LinphoneCallEnd,
|
||||
} LinphoneCallState;
|
||||
|
||||
typedef enum _gstate {
|
||||
/* states for GSTATE_GROUP_POWER */
|
||||
GSTATE_POWER_OFF = 0, /* initial state */
|
||||
GSTATE_POWER_STARTUP,
|
||||
GSTATE_POWER_ON,
|
||||
GSTATE_POWER_SHUTDOWN,
|
||||
/* states for GSTATE_GROUP_REG */
|
||||
GSTATE_REG_NONE = 10, /* initial state */
|
||||
GSTATE_REG_OK,
|
||||
GSTATE_REG_FAILED,
|
||||
GSTATE_REG_PENDING, /* a registration request is ongoing*/
|
||||
/* states for GSTATE_GROUP_CALL */
|
||||
GSTATE_CALL_IDLE = 20, /* initial state */
|
||||
GSTATE_CALL_OUT_INVITE,
|
||||
GSTATE_CALL_OUT_CONNECTED,
|
||||
GSTATE_CALL_IN_INVITE,
|
||||
GSTATE_CALL_IN_CONNECTED,
|
||||
GSTATE_CALL_END,
|
||||
GSTATE_CALL_ERROR,
|
||||
GSTATE_INVALID,
|
||||
GSTATE_CALL_OUT_RINGING /*remote ringing*/
|
||||
} gstate_t;
|
||||
typedef enum _LinphoneGlobalState{
|
||||
LinphoneGlobalOff,
|
||||
LinphoneGlobalStartup,
|
||||
LinphoneGlobalOn,
|
||||
LinphoneGlobalShutdown
|
||||
}LinphoneGlobalState;
|
||||
|
||||
struct _LinphoneGeneralState {
|
||||
gstate_t old_state;
|
||||
gstate_t new_state;
|
||||
gstate_group_t group;
|
||||
const char *message;
|
||||
};
|
||||
typedef struct _LinphoneGeneralState LinphoneGeneralState;
|
||||
|
||||
/* private: set a new state */
|
||||
void gstate_new_state(struct _LinphoneCore *lc, gstate_t new_state, const char *message);
|
||||
/*private*/
|
||||
void gstate_initialize(struct _LinphoneCore *lc) ;
|
||||
typedef enum _LinphoneRegistrationState{
|
||||
LinphoneRegistrationNone,
|
||||
LinphoneRegistrationProgress,
|
||||
LinphoneRegistrationOk,
|
||||
LinphoneRegistrationCleared,
|
||||
LinphoneRegistrationFailed
|
||||
}LinphoneRegistrationState;
|
||||
|
||||
/**
|
||||
* @addtogroup initializing
|
||||
* @{
|
||||
**/
|
||||
|
||||
|
||||
/**Call state notification callback prototype*/
|
||||
typedef void (*LinphoneGlobalStateCb)(struct _LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
|
||||
/**Call state notification callback prototype*/
|
||||
typedef void (*LinphoneCallStateCb)(struct _LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message);
|
||||
/**Registration state notification callback prototype*/
|
||||
typedef void (*LinphoneRegistrationStateCb)(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneCallState cstate, const char *message);
|
||||
/** Callback prototype */
|
||||
typedef void (*ShowInterfaceCb)(struct _LinphoneCore *lc);
|
||||
/** Callback prototype */
|
||||
typedef void (*InviteReceivedCb)(struct _LinphoneCore *lc, const char *from);
|
||||
/** Callback prototype */
|
||||
typedef void (*ByeReceivedCb)(struct _LinphoneCore *lc, const char *from);
|
||||
/** Callback prototype */
|
||||
typedef void (*DisplayStatusCb)(struct _LinphoneCore *lc, const char *message);
|
||||
/** Callback prototype */
|
||||
typedef void (*DisplayMessageCb)(struct _LinphoneCore *lc, const char *message);
|
||||
/** Callback prototype */
|
||||
typedef void (*DisplayUrlCb)(struct _LinphoneCore *lc, const char *message, const char *url);
|
||||
/** Callback prototype */
|
||||
typedef void (*DisplayQuestionCb)(struct _LinphoneCore *lc, const char *message);
|
||||
/** Callback prototype */
|
||||
typedef void (*LinphoneCoreCbFunc)(struct _LinphoneCore *lc,void * user_data);
|
||||
/** Callback prototype */
|
||||
typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, const char *from, const char *msg);
|
||||
typedef void (*NotifyReceivedCb)(struct _LinphoneCore *lc, LinphoneCall *call, const char *from, const char *event);
|
||||
/** Callback prototype */
|
||||
typedef void (*NotifyPresenceReceivedCb)(struct _LinphoneCore *lc, LinphoneFriend * fid);
|
||||
/** Callback prototype */
|
||||
|
|
@ -427,9 +432,7 @@ typedef void (*CallLogUpdated)(struct _LinphoneCore *lc, struct _LinphoneCallLog
|
|||
/** Callback prototype */
|
||||
typedef void (*TextMessageReceived)(struct _LinphoneCore *lc, LinphoneChatRoom *room, const char *from, const char *message);
|
||||
/** Callback prototype */
|
||||
typedef void (*GeneralStateChange)(struct _LinphoneCore *lc, LinphoneGeneralState *gstate);
|
||||
/** Callback prototype */
|
||||
typedef void (*DtmfReceived)(struct _LinphoneCore* lc, int dtmf);
|
||||
typedef void (*DtmfReceived)(struct _LinphoneCore* lc, LinphoneCall *call, int dtmf);
|
||||
/** Callback prototype */
|
||||
typedef void (*ReferReceived)(struct _LinphoneCore *lc, const char *refer_to);
|
||||
/** Callback prototype */
|
||||
|
|
@ -437,28 +440,26 @@ typedef void (*BuddyInfoUpdated)(struct _LinphoneCore *lc, LinphoneFriend *lf);
|
|||
|
||||
/**
|
||||
* This structure holds all callbacks that the application should implement.
|
||||
*
|
||||
* None is mandatory.
|
||||
**/
|
||||
typedef struct _LinphoneVTable
|
||||
{
|
||||
ShowInterfaceCb show; /**< Notifies the application that it should show up*/
|
||||
InviteReceivedCb inv_recv; /**< Notifies incoming calls */
|
||||
ByeReceivedCb bye_recv; /**< Notify calls terminated by far end*/
|
||||
typedef struct _LinphoneVTable{
|
||||
LinphoneGlobalStateCb global_state_changed; /**<Notifies globlal state changes*/
|
||||
LinphoneRegistrationStateCb registration_state_changed;/**<Notifies registration state changes*/
|
||||
LinphoneCallStateCb call_state_changed;/**<Notifies call state changes*/
|
||||
NotifyPresenceReceivedCb notify_presence_recv; /**< Notify received presence events*/
|
||||
NewUnknownSubscriberCb new_unknown_subscriber; /**< Notify about unknown subscriber */
|
||||
AuthInfoRequested auth_info_requested; /**< Ask the application some authentication information */
|
||||
CallLogUpdated call_log_updated; /**< Notifies that call log list has been updated */
|
||||
TextMessageReceived text_received; /**< A text message has been received */
|
||||
DtmfReceived dtmf_received; /**< A dtmf has been received received */
|
||||
ReferReceived refer_received; /**< An out of call refer was received */
|
||||
BuddyInfoUpdated buddy_info_updated; /**< a LinphoneFriend's BuddyInfo has changed*/
|
||||
NotifyReceivedCb notify_recv; /**< Other notifications*/
|
||||
DisplayStatusCb display_status; /**< Callback that notifies various events with human readable text.*/
|
||||
DisplayMessageCb display_message;/**< Callback to display a message to the user */
|
||||
DisplayMessageCb display_warning;/** Callback to display a warning to the user */
|
||||
DisplayUrlCb display_url;
|
||||
DisplayQuestionCb display_question;
|
||||
CallLogUpdated call_log_updated; /**< Notifies that call log list has been updated */
|
||||
TextMessageReceived text_received; /**< A text message has been received */
|
||||
GeneralStateChange general_state; /**< State notification callback */
|
||||
DtmfReceived dtmf_received; /**< A dtmf has been received received */
|
||||
ReferReceived refer_received; /**< A refer was received */
|
||||
BuddyInfoUpdated buddy_info_updated; /**< a LinphoneFriend's BuddyInfo has changed*/
|
||||
NotifyReceivedCb notify_recv; /**< Other notifications*/
|
||||
ShowInterfaceCb show; /**< Notifies the application that it should show up*/
|
||||
} LinphoneCoreVTable;
|
||||
|
||||
/**
|
||||
|
|
@ -474,9 +475,9 @@ typedef struct _LCCallbackObj
|
|||
|
||||
|
||||
typedef enum _LinphoneFirewallPolicy{
|
||||
LINPHONE_POLICY_NO_FIREWALL,
|
||||
LINPHONE_POLICY_USE_NAT_ADDRESS,
|
||||
LINPHONE_POLICY_USE_STUN
|
||||
LinphonePolicyNoFirewall,
|
||||
LinphonePolicyUseNatAddress,
|
||||
LinphonePolicyUseStun
|
||||
} LinphoneFirewallPolicy;
|
||||
|
||||
typedef enum _LinphoneWaitingState{
|
||||
|
|
@ -505,21 +506,29 @@ void linphone_core_iterate(LinphoneCore *lc);
|
|||
|
||||
LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url);
|
||||
|
||||
int linphone_core_invite(LinphoneCore *lc, const char *url);
|
||||
LinphoneCall * linphone_core_invite(LinphoneCore *lc, const char *url);
|
||||
|
||||
int linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr);
|
||||
LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr);
|
||||
|
||||
int linphone_core_refer(LinphoneCore *lc, const char *url);
|
||||
int linphone_core_transfer_call(LinphoneCore *lc, LinphoneCall *call, const char *refer_to);
|
||||
|
||||
bool_t linphone_core_inc_invite_pending(LinphoneCore*lc);
|
||||
|
||||
bool_t linphone_core_in_call(const LinphoneCore *lc);
|
||||
|
||||
LinphoneCall *linphone_core_get_current_call(LinphoneCore *lc);
|
||||
LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc);
|
||||
|
||||
int linphone_core_accept_call(LinphoneCore *lc, const char *url);
|
||||
int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
int linphone_core_terminate_call(LinphoneCore *lc, const char *url);
|
||||
int linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
int linphone_core_terminate_all_calls(LinphoneCore *lc);
|
||||
|
||||
int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
|
||||
|
||||
void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf);
|
||||
|
||||
|
|
@ -553,13 +562,6 @@ void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime);
|
|||
*/
|
||||
int linphone_core_get_download_ptime(LinphoneCore *lc);
|
||||
|
||||
#ifdef VINCENT_MAURY_RSVP
|
||||
/* QoS functions */
|
||||
int linphone_core_set_rpc_mode(LinphoneCore *lc, int on); /* on = 1 (RPC_ENABLE = 1) */
|
||||
int linphone_core_set_rsvp_mode(LinphoneCore *lc, int on); /* on = 1 (RSVP_ENABLE = 1) */
|
||||
int linphone_core_change_qos(LinphoneCore *lc, int answer); /* answer = 1 for yes, 0 for no */
|
||||
#endif
|
||||
|
||||
/* returns a MSList of PayloadType */
|
||||
const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc);
|
||||
|
||||
|
|
@ -573,12 +575,6 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, PayloadType *pt);
|
|||
|
||||
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable);
|
||||
|
||||
/*
|
||||
* get payload type from mime type an clock rate
|
||||
* @ingroup media_parameters
|
||||
* iterates both audio an video
|
||||
* return NULL if not found
|
||||
*/
|
||||
PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate) ;
|
||||
|
||||
const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt);
|
||||
|
|
@ -773,12 +769,12 @@ void linphone_core_use_files(LinphoneCore *lc, bool_t yesno);
|
|||
void linphone_core_set_play_file(LinphoneCore *lc, const char *file);
|
||||
void linphone_core_set_record_file(LinphoneCore *lc, const char *file);
|
||||
|
||||
gstate_t linphone_core_get_state(const LinphoneCore *lc, gstate_group_t group);
|
||||
void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms);
|
||||
void linphone_core_stop_dtmf(LinphoneCore *lc);
|
||||
|
||||
|
||||
int linphone_core_get_current_call_duration(const LinphoneCore *lc);
|
||||
const LinphoneAddress *linphone_core_get_remote_uri(LinphoneCore *lc);
|
||||
const LinphoneAddress *linphone_core_get_remote_address(LinphoneCore *lc);
|
||||
|
||||
int linphone_core_get_mtu(const LinphoneCore *lc);
|
||||
void linphone_core_set_mtu(LinphoneCore *lc, int mtu);
|
||||
|
|
@ -824,8 +820,12 @@ void linphone_core_set_audio_transports(LinphoneCore *lc, RtpTransport *rtp, Rtp
|
|||
|
||||
int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote);
|
||||
|
||||
const MSList *linphone_core_get_calls(LinphoneCore *lc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
52
coreapi/linphonecore_utils.h
Normal file
52
coreapi/linphonecore_utils.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2010 Simon MORLAT (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef LINPHONECORE_UTILS_H
|
||||
#define LINPHONECORE_UTILS_H
|
||||
|
||||
#ifdef IN_LINPHONE
|
||||
#include "linphonecore.h"
|
||||
#else
|
||||
#include "linphone/linphonecore.h"
|
||||
#endif
|
||||
|
||||
typedef struct _LsdPlayer LsdPlayer;
|
||||
typedef struct _LinphoneSoundDaemon LinphoneSoundDaemon;
|
||||
|
||||
typedef void (*LsdEndOfPlayCallback)(LsdPlayer *p);
|
||||
|
||||
void lsd_player_set_callback(LsdPlayer *p, LsdEndOfPlayCallback cb);
|
||||
void lsd_player_set_user_pointer(LsdPlayer *p, void *up);
|
||||
void *lsd_player_get_user_pointer(const LsdPlayer *p);
|
||||
int lsd_player_play(LsdPlayer *p, const char *filename);
|
||||
int lsd_player_stop(LsdPlayer *p);
|
||||
void lsd_player_enable_loop(LsdPlayer *p, bool_t loopmode);
|
||||
bool_t lsd_player_loop_enabled(const LsdPlayer *p);
|
||||
void lsd_player_set_gain(LsdPlayer *p, float gain);
|
||||
LinphoneSoundDaemon *lsd_player_get_daemon(const LsdPlayer *p);
|
||||
|
||||
LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate, int nchannels);
|
||||
LsdPlayer * linphone_sound_daemon_get_player(LinphoneSoundDaemon *lsd);
|
||||
void linphone_sound_daemon_release_player(LinphoneSoundDaemon *lsd, LsdPlayer *lsdplayer);
|
||||
void linphone_sound_daemon_stop_all_players(LinphoneSoundDaemon *obj);
|
||||
void linphone_sound_daemon_release_all_players(LinphoneSoundDaemon *obj);
|
||||
void linphone_core_use_sound_daemon(LinphoneCore *lc, LinphoneSoundDaemon *lsd);
|
||||
void linphone_sound_daemon_destroy(LinphoneSoundDaemon *obj);
|
||||
|
||||
#endif
|
||||
308
coreapi/lsd.c
Normal file
308
coreapi/lsd.c
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2010 Simon MORLAT (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Linphone Sound Daemon: is a lightweight utility to play sounds to speaker during a conversation.
|
||||
This is useful for embedded platforms, where sound apis are not performant enough to allow
|
||||
simultaneous sound access.
|
||||
*/
|
||||
|
||||
#include "linphonecore_utils.h"
|
||||
#include "private.h"
|
||||
#include "mediastreamer2/msticker.h"
|
||||
#include "mediastreamer2/mssndcard.h"
|
||||
#include "mediastreamer2/msaudiomixer.h"
|
||||
#include "mediastreamer2/mschanadapter.h"
|
||||
#include "mediastreamer2/msfileplayer.h"
|
||||
#include "mediastreamer2/msitc.h"
|
||||
|
||||
|
||||
static struct _MSSndCard *linphone_sound_daemon_get_proxy_card(LinphoneSoundDaemon *obj);
|
||||
|
||||
#define MAX_BRANCHES 10
|
||||
|
||||
|
||||
struct _LsdPlayer{
|
||||
struct _LinphoneSoundDaemon *lsd;
|
||||
MSFilter *player;
|
||||
MSFilter *rateconv;
|
||||
MSFilter *chanadapter;
|
||||
LsdEndOfPlayCallback eop_cb;
|
||||
int mixer_pin;
|
||||
void *user_data;
|
||||
bool_t loop;
|
||||
bool_t pad[3];
|
||||
};
|
||||
|
||||
struct _LinphoneSoundDaemon {
|
||||
int out_rate;
|
||||
int out_nchans;
|
||||
MSFilter *mixer;
|
||||
MSFilter *soundout;
|
||||
MSTicker *ticker;
|
||||
MSSndCard *proxycard;
|
||||
LsdPlayer branches[MAX_BRANCHES];
|
||||
};
|
||||
|
||||
static MSFilter *create_writer(MSSndCard *c){
|
||||
LinphoneSoundDaemon *lsd=(LinphoneSoundDaemon*)c->data;
|
||||
MSFilter *itcsink=ms_filter_new(MS_ITC_SINK_ID);
|
||||
ms_filter_call_method(itcsink,MS_ITC_SINK_CONNECT,lsd->branches[0].player);
|
||||
return itcsink;
|
||||
}
|
||||
|
||||
static MSSndCardDesc proxycard={
|
||||
"Linphone Sound Daemon",
|
||||
/*detect*/ NULL,
|
||||
/*init*/ NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
/*create_reader*/ NULL,
|
||||
create_writer,
|
||||
/*uninit,*/
|
||||
};
|
||||
|
||||
LsdPlayer *linphone_sound_daemon_get_player(LinphoneSoundDaemon *obj){
|
||||
int i;
|
||||
for(i=1;i<MAX_BRANCHES;++i){
|
||||
LsdPlayer *b=&obj->branches[i];
|
||||
MSFilter *p=b->player;
|
||||
int state;
|
||||
ms_filter_call_method(p,MS_PLAYER_GET_STATE,&state);
|
||||
if (state==MSPlayerClosed){
|
||||
lsd_player_set_gain(b,1);
|
||||
lsd_player_enable_loop (b,FALSE);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
ms_warning("No more free players !");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linphone_sound_daemon_release_player(LinphoneSoundDaemon *obj, LsdPlayer * player){
|
||||
int state;
|
||||
ms_filter_call_method(player->player,MS_PLAYER_GET_STATE,&state);
|
||||
if (state!=MSPlayerClosed){
|
||||
ms_filter_call_method(player->player,MS_PLAYER_CLOSE,&state);
|
||||
}
|
||||
}
|
||||
|
||||
LinphoneSoundDaemon *lsd_player_get_daemon(const LsdPlayer *p){
|
||||
return p->lsd;
|
||||
}
|
||||
|
||||
int lsd_player_stop(LsdPlayer *p){
|
||||
ms_filter_call_method_noarg(p->player,MS_PLAYER_PAUSE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lsd_player_init(LsdPlayer *p, MSConnectionPoint mixer, MSFilterId playerid, LinphoneSoundDaemon *lsd){
|
||||
MSConnectionHelper h;
|
||||
p->player=ms_filter_new(playerid);
|
||||
p->rateconv=ms_filter_new(MS_RESAMPLE_ID);
|
||||
p->chanadapter=ms_filter_new(MS_CHANNEL_ADAPTER_ID);
|
||||
|
||||
ms_connection_helper_start(&h);
|
||||
ms_connection_helper_link(&h,p->player,-1,0);
|
||||
ms_connection_helper_link(&h,p->rateconv,0,0);
|
||||
ms_connection_helper_link(&h,p->chanadapter,0,0);
|
||||
ms_connection_helper_link(&h,mixer.filter,mixer.pin,-1);
|
||||
p->mixer_pin=mixer.pin;
|
||||
p->loop=FALSE;
|
||||
p->lsd=lsd;
|
||||
}
|
||||
|
||||
static void lsd_player_uninit(LsdPlayer *p, MSConnectionPoint mixer){
|
||||
MSConnectionHelper h;
|
||||
|
||||
ms_connection_helper_start(&h);
|
||||
ms_connection_helper_unlink (&h,p->player,-1,0);
|
||||
ms_connection_helper_unlink(&h,p->rateconv,0,0);
|
||||
ms_connection_helper_unlink(&h,p->chanadapter,0,0);
|
||||
ms_connection_helper_unlink(&h,mixer.filter,mixer.pin,-1);
|
||||
|
||||
ms_filter_destroy(p->player);
|
||||
ms_filter_destroy(p->rateconv);
|
||||
ms_filter_destroy(p->chanadapter);
|
||||
}
|
||||
|
||||
void lsd_player_set_callback(LsdPlayer *p, LsdEndOfPlayCallback cb){
|
||||
p->eop_cb=cb;
|
||||
}
|
||||
|
||||
void lsd_player_set_user_pointer(LsdPlayer *p, void *up){
|
||||
p->user_data=up;
|
||||
}
|
||||
|
||||
void *lsd_player_get_user_pointer(const LsdPlayer *p){
|
||||
return p->user_data;
|
||||
}
|
||||
|
||||
static void lsd_player_on_eop(void * userdata, unsigned int id, void *arg){
|
||||
LsdPlayer *p=(LsdPlayer *)userdata;
|
||||
if (p->eop_cb!=NULL)
|
||||
p->eop_cb(p);
|
||||
}
|
||||
|
||||
static void lsd_player_configure(LsdPlayer *b){
|
||||
int rate,chans;
|
||||
LinphoneSoundDaemon *lsd=b->lsd;
|
||||
|
||||
if (ms_filter_get_id(b->player)==MS_ITC_SOURCE_ID)
|
||||
ms_message("Configuring branch coming from audio call...");
|
||||
|
||||
ms_filter_call_method(b->player,MS_FILTER_GET_SAMPLE_RATE,&rate);
|
||||
ms_filter_call_method(b->player,MS_FILTER_GET_NCHANNELS,&chans);
|
||||
|
||||
|
||||
ms_filter_call_method(b->rateconv,MS_FILTER_SET_SAMPLE_RATE,&rate);
|
||||
ms_filter_call_method(b->rateconv,MS_FILTER_SET_NCHANNELS,&chans);
|
||||
ms_filter_call_method(b->rateconv,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&lsd->out_rate);
|
||||
|
||||
ms_filter_call_method(b->chanadapter,MS_FILTER_SET_NCHANNELS,&chans);
|
||||
ms_filter_call_method(b->chanadapter,MS_CHANNEL_ADAPTER_SET_OUTPUT_NCHANNELS,&lsd->out_nchans);
|
||||
ms_message("player configured for rate=%i, channels=%i",rate,chans);
|
||||
}
|
||||
|
||||
int lsd_player_play(LsdPlayer *b, const char *filename ){
|
||||
int state;
|
||||
|
||||
ms_filter_call_method(b->player,MS_PLAYER_GET_STATE,&state);
|
||||
if (state!=MSPlayerClosed){
|
||||
ms_filter_call_method_noarg(b->player,MS_PLAYER_CLOSE);
|
||||
}
|
||||
|
||||
if (ms_filter_call_method(b->player,MS_PLAYER_OPEN,(void*)filename)!=0){
|
||||
ms_warning("Could not play %s",filename);
|
||||
return -1;
|
||||
}
|
||||
ms_filter_set_notify_callback (b->player,lsd_player_on_eop,b);
|
||||
lsd_player_configure(b);
|
||||
ms_filter_call_method_noarg (b->player,MS_PLAYER_START);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lsd_player_enable_loop(LsdPlayer *p, bool_t loopmode){
|
||||
if (ms_filter_get_id(p->player)==MS_FILE_PLAYER_ID){
|
||||
int arg=loopmode ? 0 : -1;
|
||||
ms_filter_call_method(p->player,MS_FILE_PLAYER_LOOP,&arg);
|
||||
p->loop=loopmode;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t lsd_player_loop_enabled(const LsdPlayer *p){
|
||||
return p->loop;
|
||||
}
|
||||
|
||||
void lsd_player_set_gain(LsdPlayer *p, float gain){
|
||||
MSAudioMixerCtl gainctl;
|
||||
gainctl.pin=p->mixer_pin;
|
||||
gainctl.gain=gain;
|
||||
ms_filter_call_method(p->lsd->mixer,MS_AUDIO_MIXER_SET_INPUT_GAIN,&gainctl);
|
||||
}
|
||||
|
||||
LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate, int nchannels){
|
||||
int i;
|
||||
MSConnectionPoint mp;
|
||||
LinphoneSoundDaemon *lsd;
|
||||
MSSndCard *card=ms_snd_card_manager_get_card(
|
||||
ms_snd_card_manager_get(),
|
||||
cardname);
|
||||
if (card==NULL){
|
||||
card=ms_snd_card_manager_get_default_playback_card (
|
||||
ms_snd_card_manager_get());
|
||||
if (card==NULL){
|
||||
ms_error("linphone_sound_daemon_new(): No playback soundcard available");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lsd=ms_new0(LinphoneSoundDaemon,1);
|
||||
lsd->soundout=ms_snd_card_create_writer(card);
|
||||
lsd->mixer=ms_filter_new(MS_AUDIO_MIXER_ID);
|
||||
lsd->out_rate=rate;
|
||||
lsd->out_nchans=nchannels;
|
||||
ms_filter_call_method(lsd->soundout,MS_FILTER_SET_SAMPLE_RATE,&lsd->out_rate);
|
||||
ms_filter_call_method(lsd->soundout,MS_FILTER_SET_NCHANNELS,&lsd->out_nchans);
|
||||
ms_filter_call_method(lsd->mixer,MS_FILTER_SET_SAMPLE_RATE,&lsd->out_rate);
|
||||
ms_filter_call_method(lsd->mixer,MS_FILTER_SET_NCHANNELS,&lsd->out_nchans);
|
||||
|
||||
mp.filter=lsd->mixer;
|
||||
mp.pin=0;
|
||||
|
||||
lsd_player_init(&lsd->branches[0],mp,MS_ITC_SOURCE_ID,lsd);
|
||||
ms_filter_set_notify_callback(lsd->branches[0].player,(MSFilterNotifyFunc)lsd_player_configure,&lsd->branches[0]);
|
||||
ms_filter_enable_synchronous_notifcations (lsd->branches[0].player,TRUE);
|
||||
for(i=1;i<MAX_BRANCHES;++i){
|
||||
mp.pin=i;
|
||||
lsd_player_init(&lsd->branches[i],mp,MS_FILE_PLAYER_ID,lsd);
|
||||
}
|
||||
ms_filter_link(lsd->mixer,0,lsd->soundout,0);
|
||||
lsd->ticker=ms_ticker_new();
|
||||
ms_ticker_attach(lsd->ticker,lsd->soundout);
|
||||
|
||||
lsd->proxycard=ms_snd_card_new(&proxycard);
|
||||
lsd->proxycard->data=lsd;
|
||||
ms_message("LinphoneSoundDaemon started with rate=%i, nchannels=%i",rate,nchannels);
|
||||
return lsd;
|
||||
}
|
||||
|
||||
void linphone_sound_daemon_stop_all_players(LinphoneSoundDaemon *obj){
|
||||
int i;
|
||||
for(i=1;i<MAX_BRANCHES;++i){
|
||||
lsd_player_stop(&obj->branches[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_sound_daemon_release_all_players(LinphoneSoundDaemon *obj){
|
||||
int i;
|
||||
for(i=1;i<MAX_BRANCHES;++i){
|
||||
linphone_sound_daemon_release_player(obj,&obj->branches[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_sound_daemon_destroy(LinphoneSoundDaemon *obj){
|
||||
int i;
|
||||
MSConnectionPoint mp;
|
||||
ms_ticker_detach(obj->ticker,obj->soundout);
|
||||
mp.filter=obj->mixer;
|
||||
for(i=0;i<MAX_BRANCHES;++i){
|
||||
mp.pin=i;
|
||||
if (i!=0) linphone_sound_daemon_release_player(obj,&obj->branches[i]);
|
||||
lsd_player_uninit (&obj->branches[i],mp);
|
||||
}
|
||||
ms_filter_unlink(obj->mixer,0,obj->soundout,0);
|
||||
ms_ticker_destroy(obj->ticker);
|
||||
ms_filter_destroy(obj->soundout);
|
||||
ms_filter_destroy(obj->mixer);
|
||||
}
|
||||
|
||||
MSSndCard *linphone_sound_daemon_get_proxy_card(LinphoneSoundDaemon *lsd){
|
||||
return lsd->proxycard;
|
||||
}
|
||||
|
||||
void linphone_core_use_sound_daemon(LinphoneCore *lc, LinphoneSoundDaemon *lsd){
|
||||
if (lsd!=NULL){
|
||||
lc->sound_conf.lsd_card=linphone_sound_daemon_get_proxy_card (lsd);
|
||||
}else {
|
||||
lc->sound_conf.lsd_card=NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -497,10 +497,10 @@ void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){
|
|||
lc->vtable.display_status(lc,_("Stun lookup in progress..."));
|
||||
|
||||
/*create the two audio and video RTP sockets, and send STUN message to our stun server */
|
||||
sock1=create_socket(linphone_core_get_audio_port(lc));
|
||||
sock1=create_socket(call->audio_port);
|
||||
if (sock1<0) return;
|
||||
if (video_enabled){
|
||||
sock2=create_socket(linphone_core_get_video_port(lc));
|
||||
sock2=create_socket(call->video_port);
|
||||
if (sock2<0) return ;
|
||||
}
|
||||
sendStunRequest(sock1,(struct sockaddr*)&ss,ss_len,11,TRUE);
|
||||
|
|
|
|||
|
|
@ -29,7 +29,10 @@ static PayloadType * find_payload_type_best_match(const MSList *l, const Payload
|
|||
|
||||
for (elem=l;elem!=NULL;elem=elem->next){
|
||||
pt=(PayloadType*)elem->data;
|
||||
if (strcasecmp(pt->mime_type,refpt->mime_type)==0 && pt->clock_rate==refpt->clock_rate){
|
||||
/* the compare between G729 and G729A is for some stupid uncompliant phone*/
|
||||
if ( (strcasecmp(pt->mime_type,refpt->mime_type)==0 ||
|
||||
(strcasecmp(pt->mime_type, "G729") == 0 && strcasecmp(refpt->mime_type, "G729A") == 0 ))
|
||||
&& pt->clock_rate==refpt->clock_rate){
|
||||
candidate=pt;
|
||||
/*good candidate, check fmtp for H264 */
|
||||
if (strcasecmp(pt->mime_type,"H264")==0){
|
||||
|
|
@ -85,6 +88,8 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
|
|||
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads);
|
||||
result->proto=local_offer->proto;
|
||||
result->type=local_offer->type;
|
||||
result->dir=local_offer->dir;
|
||||
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
strcpy(result->addr,remote_answer->addr);
|
||||
result->port=remote_answer->port;
|
||||
|
|
@ -102,6 +107,13 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
|
|||
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads);
|
||||
result->proto=local_cap->proto;
|
||||
result->type=local_cap->type;
|
||||
if (remote_offer->dir==SalStreamSendOnly)
|
||||
result->dir=SalStreamRecvOnly;
|
||||
else if (remote_offer->dir==SalStreamRecvOnly){
|
||||
result->dir=SalStreamSendOnly;
|
||||
}else if (remote_offer->dir==SalStreamInactive){
|
||||
result->dir=SalStreamInactive;
|
||||
}else result->dir=SalStreamSendRecv;
|
||||
if (result->payloads && !only_telephone_event(result->payloads)){
|
||||
strcpy(result->addr,local_cap->addr);
|
||||
result->port=local_cap->port;
|
||||
|
|
|
|||
|
|
@ -92,36 +92,36 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, Sal
|
|||
char *tmp;
|
||||
LinphoneFriend *lf;
|
||||
LinphoneAddress *friend=NULL;
|
||||
LinphoneOnlineStatus estatus=LINPHONE_STATUS_OFFLINE;
|
||||
LinphoneOnlineStatus estatus=LinphoneStatusOffline;
|
||||
|
||||
switch(sal_status){
|
||||
case SalPresenceOffline:
|
||||
estatus=LINPHONE_STATUS_OFFLINE;
|
||||
estatus=LinphoneStatusOffline;
|
||||
break;
|
||||
case SalPresenceOnline:
|
||||
estatus=LINPHONE_STATUS_ONLINE;
|
||||
estatus=LinphoneStatusOnline;
|
||||
break;
|
||||
case SalPresenceBusy:
|
||||
estatus=LINPHONE_STATUS_BUSY;
|
||||
estatus=LinphoneStatusBusy;
|
||||
break;
|
||||
case SalPresenceBerightback:
|
||||
estatus=LINPHONE_STATUS_AWAY;
|
||||
estatus=LinphoneStatusBeRightBack;
|
||||
break;
|
||||
case SalPresenceAway:
|
||||
estatus=LINPHONE_STATUS_AWAY;
|
||||
estatus=LinphoneStatusAway;
|
||||
break;
|
||||
case SalPresenceOnthephone:
|
||||
estatus=LINPHONE_STATUS_ONTHEPHONE;
|
||||
estatus=LinphoneStatusOnThePhone;
|
||||
break;
|
||||
case SalPresenceOuttolunch:
|
||||
estatus=LINPHONE_STATUS_OUTTOLUNCH;
|
||||
estatus=LinphoneStatusOutToLunch;
|
||||
break;
|
||||
case SalPresenceDonotdisturb:
|
||||
estatus=LINPHONE_STATUS_BUSY;
|
||||
estatus=LinphoneStatusDoNotDisturb;
|
||||
break;
|
||||
case SalPresenceMoved:
|
||||
case SalPresenceAltService:
|
||||
estatus=LINPHONE_STATUS_AWAY;
|
||||
estatus=LinphoneStatusMoved;
|
||||
break;
|
||||
}
|
||||
lf=linphone_find_friend_by_out_subscribe(lc->friends,op);
|
||||
|
|
@ -130,7 +130,8 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeState ss, Sal
|
|||
tmp=linphone_address_as_string(friend);
|
||||
lf->status=estatus;
|
||||
lf->subscribe_active=TRUE;
|
||||
lc->vtable.notify_presence_recv(lc,(LinphoneFriend*)lf);
|
||||
if (lc->vtable.notify_presence_recv)
|
||||
lc->vtable.notify_presence_recv(lc,(LinphoneFriend*)lf);
|
||||
ms_free(tmp);
|
||||
}else{
|
||||
ms_message("But this person is not part of our friend list, so we don't care.");
|
||||
|
|
|
|||
|
|
@ -54,14 +54,6 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
typedef enum _LCState{
|
||||
LCStateInit,
|
||||
LCStatePreEstablishing,
|
||||
LCStateRinging,
|
||||
LCStateAVRunning
|
||||
}LCState;
|
||||
|
||||
|
||||
struct _LinphoneCall
|
||||
{
|
||||
struct _LinphoneCore *core;
|
||||
|
|
@ -76,29 +68,36 @@ struct _LinphoneCall
|
|||
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
|
||||
time_t start_time; /*time at which the call was initiated*/
|
||||
time_t media_start_time; /*time at which it was accepted, media streams established*/
|
||||
LCState state;
|
||||
LinphoneCallState state;
|
||||
int refcnt;
|
||||
void * user_pointer;
|
||||
int audio_port;
|
||||
int video_port;
|
||||
struct _AudioStream *audiostream; /**/
|
||||
struct _VideoStream *videostream;
|
||||
char *refer_to;
|
||||
bool_t refer_pending;
|
||||
bool_t media_pending;
|
||||
bool_t audio_muted;
|
||||
};
|
||||
|
||||
LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to);
|
||||
LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op);
|
||||
#define linphone_call_set_state(lcall,st) (lcall)->state=(st)
|
||||
void linphone_call_destroy(struct _LinphoneCall *obj);
|
||||
void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message);
|
||||
|
||||
/* private: */
|
||||
LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *local, LinphoneAddress * remote);
|
||||
void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call);
|
||||
void linphone_call_log_completed(LinphoneCallLog *calllog, LinphoneCall *call, LinphoneCallStatus status);
|
||||
void linphone_call_log_destroy(LinphoneCallLog *cl);
|
||||
|
||||
|
||||
void linphone_core_init_media_streams(LinphoneCore *lc, LinphoneCall *call);
|
||||
|
||||
void linphone_auth_info_write_config(struct _LpConfig *config, LinphoneAuthInfo *obj, int pos);
|
||||
|
||||
void linphone_core_update_proxy_register(LinphoneCore *lc);
|
||||
void linphone_core_refresh_subscribes(LinphoneCore *lc);
|
||||
int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *error);
|
||||
|
||||
int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphoneOnlineStatus os);
|
||||
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message);
|
||||
|
||||
int linphone_online_status_to_eXosip(LinphoneOnlineStatus os);
|
||||
void linphone_friend_close_subscriptions(LinphoneFriend *lf);
|
||||
|
|
@ -173,8 +172,11 @@ int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char
|
|||
|
||||
void linphone_core_text_received(LinphoneCore *lc, const char *from, const char *msg);
|
||||
|
||||
void linphone_core_start_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
|
||||
void linphone_core_stop_media_streams(LinphoneCore *lc, struct _LinphoneCall *call);
|
||||
void linphone_call_init_media_streams(LinphoneCall *call);
|
||||
void linphone_call_start_media_streams(LinphoneCall *call);
|
||||
void linphone_call_set_media_streams_dir(LinphoneCall *call, SalStreamDir dir);
|
||||
void linphone_call_stop_media_streams(LinphoneCall *call);
|
||||
|
||||
const char * linphone_core_get_identity(LinphoneCore *lc);
|
||||
const char * linphone_core_get_route(LinphoneCore *lc);
|
||||
bool_t linphone_core_is_in_communication_with(LinphoneCore *lc, const char *to);
|
||||
|
|
@ -183,7 +185,7 @@ void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float
|
|||
void linphone_core_stop_waiting(LinphoneCore *lc);
|
||||
|
||||
int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, LinphoneProxyConfig *dest_proxy);
|
||||
|
||||
void linphone_core_start_pending_refered_calls(LinphoneCore *lc);
|
||||
extern SalCallbacks linphone_sal_callbacks;
|
||||
|
||||
|
||||
|
|
@ -297,6 +299,7 @@ typedef struct sound_config
|
|||
struct _MSSndCard * ring_sndcard; /* the playback sndcard currently used */
|
||||
struct _MSSndCard * play_sndcard; /* the playback sndcard currently used */
|
||||
struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */
|
||||
struct _MSSndCard * lsd_card; /* dummy playback card for Linphone Sound Daemon extension */
|
||||
const char **cards;
|
||||
int latency; /* latency in samples of the current used sound device */
|
||||
char rec_lev;
|
||||
|
|
@ -366,21 +369,20 @@ struct _LinphoneCore
|
|||
struct _RingStream *ringstream;
|
||||
time_t dmfs_playing_start_time;
|
||||
LCCallbackObj preview_finished_cb;
|
||||
struct _LinphoneCall *call; /* the current call, in the future it will be a list of calls (conferencing)*/
|
||||
LinphoneCall *current_call; /* the current call */
|
||||
MSList *calls; /* all the processed calls */
|
||||
MSList *queued_calls; /* used by the autoreplier */
|
||||
MSList *call_logs;
|
||||
MSList *chatrooms;
|
||||
int max_call_logs;
|
||||
int missed_calls;
|
||||
struct _AudioStream *audiostream; /**/
|
||||
struct _VideoStream *videostream;
|
||||
struct _VideoStream *previewstream;
|
||||
struct _MSEventQueue *msevq;
|
||||
RtpTransport *a_rtp,*a_rtcp;
|
||||
MSList *bl_reqs;
|
||||
MSList *subscribers; /* unknown subscribers */
|
||||
int minutes_away;
|
||||
LinphoneOnlineStatus presence_mode;
|
||||
LinphoneOnlineStatus prev_mode;
|
||||
char *alt_contact;
|
||||
void *data;
|
||||
char *play_file;
|
||||
|
|
@ -391,9 +393,6 @@ struct _LinphoneCore
|
|||
int dw_video_bw;
|
||||
int up_video_bw;
|
||||
int audio_bw;
|
||||
gstate_t gstate_power;
|
||||
gstate_t gstate_reg;
|
||||
gstate_t gstate_call;
|
||||
LinphoneWaitingCallback wait_cb;
|
||||
void *wait_ctx;
|
||||
bool_t use_files;
|
||||
|
|
@ -403,7 +402,21 @@ struct _LinphoneCore
|
|||
bool_t preview_finished;
|
||||
bool_t auto_net_state_mon;
|
||||
bool_t network_reachable;
|
||||
bool_t audio_muted;
|
||||
};
|
||||
|
||||
bool_t linphone_core_can_we_add_call(LinphoneCore *lc);
|
||||
int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_set_as_current_call(LinphoneCore *lc, LinphoneCall *call);
|
||||
int linphone_core_get_calls_nb(const LinphoneCore *lc);
|
||||
|
||||
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
|
||||
|
||||
#define HOLD_OFF (0)
|
||||
#define HOLD_ON (1)
|
||||
|
||||
#ifndef NB_MAX_CALLS
|
||||
#define NB_MAX_CALLS (10)
|
||||
#endif
|
||||
|
||||
#endif /* _PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -263,6 +263,7 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){
|
|||
|
||||
static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
|
||||
const char *id_str;
|
||||
|
||||
if (obj->reg_identity!=NULL) id_str=obj->reg_identity;
|
||||
else id_str=linphone_core_get_primary_contact(obj->lc);
|
||||
if (obj->reg_sendregister){
|
||||
|
|
@ -274,10 +275,10 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){
|
|||
sal_op_set_contact(obj->op,contact);
|
||||
ms_free(contact);
|
||||
sal_op_set_user_pointer(obj->op,obj);
|
||||
if (!sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)) {
|
||||
gstate_new_state(obj->lc,GSTATE_REG_PENDING,NULL);
|
||||
if (sal_register(obj->op,obj->reg_proxy,obj->reg_identity,obj->expires)==0) {
|
||||
linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress");
|
||||
} else {
|
||||
gstate_new_state(obj->lc,GSTATE_REG_FAILED,NULL);
|
||||
linphone_proxy_config_set_state(obj,LinphoneRegistrationFailed,"Registration failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -796,6 +797,12 @@ void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) {
|
|||
return cr->user_data;
|
||||
}
|
||||
|
||||
void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){
|
||||
LinphoneCore *lc=cfg->lc;
|
||||
if (lc && lc->vtable.registration_state_changed){
|
||||
lc->vtable.registration_state_changed(lc,cfg,state,message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -62,11 +62,28 @@ const SalStreamDescription *sal_media_description_find_stream(const SalMediaDesc
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool_t sal_media_description_empty(SalMediaDescription *md){
|
||||
bool_t sal_media_description_empty(const SalMediaDescription *md){
|
||||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
const SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->port!=0) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
|
||||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->port!=0) return FALSE;
|
||||
ss->dir=stream_dir;
|
||||
}
|
||||
}
|
||||
|
||||
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
|
||||
int i;
|
||||
for(i=0;i<md->nstreams;++i){
|
||||
const SalStreamDescription *ss=&md->streams[i];
|
||||
if (ss->dir!=stream_dir) return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,13 @@ typedef enum{
|
|||
SalProtoRtpSavp
|
||||
}SalMediaProto;
|
||||
|
||||
typedef enum{
|
||||
SalStreamSendRecv,
|
||||
SalStreamSendOnly,
|
||||
SalStreamRecvOnly,
|
||||
SalStreamInactive
|
||||
}SalStreamDir;
|
||||
|
||||
typedef struct SalEndpointCandidate{
|
||||
char addr[64];
|
||||
int port;
|
||||
|
|
@ -102,6 +109,7 @@ typedef struct SalStreamDescription{
|
|||
int bandwidth;
|
||||
int ptime;
|
||||
SalEndpointCandidate candidates[SAL_ENDPOINT_CANDIDATE_MAX];
|
||||
SalStreamDir dir;
|
||||
} SalStreamDescription;
|
||||
|
||||
#define SAL_MEDIA_DESCRIPTION_MAX_STREAMS 4
|
||||
|
|
@ -118,9 +126,11 @@ typedef struct SalMediaDescription{
|
|||
SalMediaDescription *sal_media_description_new();
|
||||
void sal_media_description_ref(SalMediaDescription *md);
|
||||
void sal_media_description_unref(SalMediaDescription *md);
|
||||
bool_t sal_media_description_empty(SalMediaDescription *md);
|
||||
bool_t sal_media_description_empty(const SalMediaDescription *md);
|
||||
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir dir);
|
||||
const SalStreamDescription *sal_media_description_find_stream(const SalMediaDescription *md,
|
||||
SalMediaProto proto, SalStreamType type);
|
||||
void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir);
|
||||
|
||||
/*this structure must be at the first byte of the SalOp structure defined by implementors*/
|
||||
typedef struct SalOpBase{
|
||||
|
|
@ -177,9 +187,9 @@ typedef void (*SalOnCallReceived)(SalOp *op);
|
|||
typedef void (*SalOnCallRinging)(SalOp *op);
|
||||
typedef void (*SalOnCallAccepted)(SalOp *op);
|
||||
typedef void (*SalOnCallAck)(SalOp *op);
|
||||
typedef void (*SalOnCallUpdated)(SalOp *op);
|
||||
typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE is received*/
|
||||
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
|
||||
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details);
|
||||
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details, int code);
|
||||
typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnAuthSuccess)(SalOp *op, const char *realm, const char *username);
|
||||
typedef void (*SalOnRegisterSuccess)(SalOp *op, bool_t registered);
|
||||
|
|
@ -200,7 +210,7 @@ typedef struct SalCallbacks{
|
|||
SalOnCallRinging call_ringing;
|
||||
SalOnCallAccepted call_accepted;
|
||||
SalOnCallAck call_ack;
|
||||
SalOnCallUpdated call_updated;
|
||||
SalOnCallUpdating call_updating;
|
||||
SalOnCallTerminated call_terminated;
|
||||
SalOnCallFailure call_failure;
|
||||
SalOnAuthRequested auth_requested;
|
||||
|
|
@ -263,8 +273,10 @@ void *sal_op_get_user_pointer(const SalOp *op);
|
|||
int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc);
|
||||
int sal_call(SalOp *h, const char *from, const char *to);
|
||||
int sal_call_notify_ringing(SalOp *h);
|
||||
/*accept an incoming call or, during a call accept a reINVITE*/
|
||||
int sal_call_accept(SalOp*h);
|
||||
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
|
||||
int sal_call_hold(SalOp *h, bool_t holdon);
|
||||
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
|
||||
int sal_refer(SalOp *h, const char *refer_to);
|
||||
int sal_refer_accept(SalOp *h);
|
||||
|
|
@ -306,5 +318,4 @@ void __sal_op_init(SalOp *b, Sal *sal);
|
|||
void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/);
|
||||
void __sal_op_free(SalOp *b);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -284,8 +284,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
|
|||
ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
|
||||
if (ctx->callbacks.call_terminated==NULL)
|
||||
ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
|
||||
if (ctx->callbacks.call_updated==NULL)
|
||||
ctx->callbacks.call_updated=(SalOnCallUpdated)unimplemented_stub;
|
||||
if (ctx->callbacks.call_updating==NULL)
|
||||
ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_requested==NULL)
|
||||
ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub;
|
||||
if (ctx->callbacks.auth_success==NULL)
|
||||
|
|
@ -654,9 +654,13 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){
|
|||
}
|
||||
|
||||
int sal_call_terminate(SalOp *h){
|
||||
int err;
|
||||
eXosip_lock();
|
||||
eXosip_call_terminate(h->cid,h->did);
|
||||
err=eXosip_call_terminate(h->cid,h->did);
|
||||
eXosip_unlock();
|
||||
if (err!=0){
|
||||
ms_warning("Exosip could not terminate the call: cid=%i did=%i", h->cid,h->did);
|
||||
}
|
||||
sal_remove_call(h->base.root,h);
|
||||
h->cid=-1;
|
||||
return 0;
|
||||
|
|
@ -769,35 +773,27 @@ static void handle_reinvite(Sal *sal, eXosip_event_t *ev){
|
|||
sal_media_description_unref(op->base.remote_media);
|
||||
op->base.remote_media=NULL;
|
||||
}
|
||||
eXosip_lock();
|
||||
eXosip_call_build_answer(ev->tid,200,&msg);
|
||||
eXosip_unlock();
|
||||
if (msg==NULL) return;
|
||||
if (op->base.root->session_expires!=0){
|
||||
if (op->supports_session_timers) osip_message_set_supported(msg, "timer");
|
||||
}
|
||||
if (op->base.contact){
|
||||
_osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
|
||||
osip_message_set_contact(msg,op->base.contact);
|
||||
if (op->result){
|
||||
sal_media_description_unref(op->result);
|
||||
op->result=NULL;
|
||||
}
|
||||
if (sdp){
|
||||
op->sdp_offering=FALSE;
|
||||
op->base.remote_media=sal_media_description_new();
|
||||
sdp_to_media_description(sdp,op->base.remote_media);
|
||||
sdp_message_free(sdp);
|
||||
sdp_process(op);
|
||||
if (op->sdp_answer!=NULL){
|
||||
set_sdp(msg,op->sdp_answer);
|
||||
sdp_message_free(op->sdp_answer);
|
||||
op->sdp_answer=NULL;
|
||||
}
|
||||
sal->callbacks.call_updating(op);
|
||||
}else {
|
||||
op->sdp_offering=TRUE;
|
||||
set_sdp_from_desc(msg,op->base.local_media);
|
||||
eXosip_lock();
|
||||
eXosip_call_build_answer(ev->tid,200,&msg);
|
||||
if (msg!=NULL){
|
||||
set_sdp_from_desc(msg,op->base.local_media);
|
||||
eXosip_call_send_answer(ev->tid,200,msg);
|
||||
}
|
||||
eXosip_unlock();
|
||||
}
|
||||
eXosip_lock();
|
||||
eXosip_call_send_answer(ev->tid,200,msg);
|
||||
eXosip_unlock();
|
||||
|
||||
}
|
||||
|
||||
static void handle_ack(Sal *sal, eXosip_event_t *ev){
|
||||
|
|
@ -816,7 +812,7 @@ static void handle_ack(Sal *sal, eXosip_event_t *ev){
|
|||
sdp_message_free(sdp);
|
||||
}
|
||||
if (op->reinvite){
|
||||
sal->callbacks.call_updated(op);
|
||||
if (sdp) sal->callbacks.call_updating(op);
|
||||
op->reinvite=FALSE;
|
||||
}else{
|
||||
sal->callbacks.call_ack(op);
|
||||
|
|
@ -855,7 +851,8 @@ static int call_proceeding(Sal *sal, eXosip_event_t *ev){
|
|||
eXosip_unlock();
|
||||
return -1;
|
||||
}
|
||||
op->did=ev->did;
|
||||
if (ev->did>0)
|
||||
op->did=ev->did;
|
||||
op->tid=ev->tid;
|
||||
|
||||
/* update contact if received and rport are set by the server
|
||||
|
|
@ -938,7 +935,7 @@ static void call_released(Sal *sal, eXosip_event_t *ev){
|
|||
}
|
||||
op->cid=-1;
|
||||
if (op->did==-1)
|
||||
sal->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,NULL);
|
||||
sal->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,NULL, 487);
|
||||
}
|
||||
|
||||
static int get_auth_data_from_response(osip_message_t *resp, const char **realm, const char **username){
|
||||
|
|
@ -1100,7 +1097,7 @@ static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
|
|||
sr=SalReasonUnknown;
|
||||
}else error=SalErrorNoResponse;
|
||||
}
|
||||
sal->callbacks.call_failure(op,error,sr,reason);
|
||||
sal->callbacks.call_failure(op,error,sr,reason,code);
|
||||
if (computedReason != NULL){
|
||||
ms_free(computedReason);
|
||||
}
|
||||
|
|
@ -1777,3 +1774,32 @@ int sal_address_get_port_int(const SalAddress *uri) {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a re-Invite used to hold the current call
|
||||
*/
|
||||
int sal_call_hold(SalOp *h, bool_t holdon)
|
||||
{
|
||||
int err=0;
|
||||
|
||||
osip_message_t *reinvite=NULL;
|
||||
if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != OSIP_SUCCESS || reinvite==NULL)
|
||||
return -1;
|
||||
osip_message_set_subject(reinvite,osip_strdup("Phone Call Hold"));
|
||||
osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
|
||||
if (h->base.root->session_expires!=0){
|
||||
osip_message_set_header(reinvite, "Session-expires", "200");
|
||||
osip_message_set_supported(reinvite, "timer");
|
||||
}
|
||||
//add something to say that the distant sip phone will be in sendonly/sendrecv mode
|
||||
if (h->base.local_media){
|
||||
h->sdp_offering=TRUE;
|
||||
sal_media_description_set_dir(h->base.local_media, holdon ? SalStreamSendOnly : SalStreamSendRecv);
|
||||
set_sdp_from_desc(reinvite,h->base.local_media);
|
||||
}else h->sdp_offering=FALSE;
|
||||
eXosip_lock();
|
||||
err = eXosip_call_send_request(h->did, reinvite);
|
||||
eXosip_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,6 +106,23 @@ static int _sdp_message_get_a_ptime(sdp_message_t *sdp, int mline){
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int _sdp_message_get_mline_dir(sdp_message_t *sdp, int mline){
|
||||
int i;
|
||||
sdp_attribute_t *attr;
|
||||
for (i=0;(attr=sdp_message_attribute_get(sdp,mline,i))!=NULL;i++){
|
||||
if (keywordcmp("sendrecv",attr->a_att_field)==0){
|
||||
return SalStreamSendRecv;
|
||||
}else if (keywordcmp("sendonly",attr->a_att_field)==0){
|
||||
return SalStreamSendOnly;
|
||||
}else if (keywordcmp("recvonly",attr->a_att_field)==0){
|
||||
return SalStreamSendOnly;
|
||||
}else if (keywordcmp("inactive",attr->a_att_field)==0){
|
||||
return SalStreamInactive;
|
||||
}
|
||||
}
|
||||
return SalStreamSendRecv;
|
||||
}
|
||||
|
||||
static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
||||
{
|
||||
sdp_message_t *local;
|
||||
|
|
@ -121,12 +138,21 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
|
|||
osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr));
|
||||
sdp_message_s_name_set (local, osip_strdup ("A conversation"));
|
||||
sdp_message_c_connection_add (local, -1,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr), NULL, NULL);
|
||||
if(!sal_media_description_has_dir (desc,SalStreamSendOnly))
|
||||
{
|
||||
sdp_message_c_connection_add (local, -1,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
osip_strdup (desc->addr), NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdp_message_c_connection_add (local, -1,
|
||||
osip_strdup ("IN"), inet6 ? osip_strdup ("IP6") : osip_strdup ("IP4"),
|
||||
inet6 ? osip_strdup ("::0") : osip_strdup ("0.0.0.0"), NULL, NULL);
|
||||
}
|
||||
sdp_message_t_time_descr_add (local, osip_strdup ("0"), osip_strdup ("0"));
|
||||
if (desc->bandwidth>0) sdp_message_b_bandwidth_add (local, -1, osip_strdup ("AS"),
|
||||
int_2char(desc->bandwidth));
|
||||
int_2char(desc->bandwidth));
|
||||
return local;
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +184,7 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
const char *mt=desc->type==SalAudio ? "audio" : "video";
|
||||
const MSList *elem;
|
||||
const char *addr;
|
||||
const char *dir="sendrecv";
|
||||
int port;
|
||||
if (desc->candidates[0].addr[0]!='\0'){
|
||||
addr=desc->candidates[0].addr;
|
||||
|
|
@ -186,6 +213,21 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
|
|||
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
|
||||
add_payload(msg, lineno, (PayloadType*)elem->data);
|
||||
}
|
||||
switch(desc->dir){
|
||||
case SalStreamSendRecv:
|
||||
dir="sendrecv";
|
||||
break;
|
||||
case SalStreamRecvOnly:
|
||||
dir="recvonly";
|
||||
break;
|
||||
case SalStreamSendOnly:
|
||||
dir="sendonly";
|
||||
break;
|
||||
case SalStreamInactive:
|
||||
dir="inactive";
|
||||
break;
|
||||
}
|
||||
sdp_message_a_attribute_add (msg, lineno, osip_strdup (dir),NULL);
|
||||
}
|
||||
|
||||
sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
|
||||
|
|
@ -272,6 +314,7 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
|
|||
for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
|
||||
if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
|
||||
}
|
||||
stream->dir=_sdp_message_get_mline_dir(msg,i);
|
||||
/* for each payload type */
|
||||
for (j=0;((number=sdp_message_m_payload_get (msg, i,j)) != NULL); j++){
|
||||
const char *rtpmap,*fmtp;
|
||||
|
|
|
|||
103
coreapi/test_lsd.c
Normal file
103
coreapi/test_lsd.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
linphone
|
||||
Copyright (C) 2010 Simon MORLAT (simon.morlat@linphone.org)
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* Linphone Sound Daemon: is a lightweight utility to play sounds to speaker during a conversation.
|
||||
This is useful for embedded platforms, where sound apis are not performant enough to allow
|
||||
simultaneous sound access.
|
||||
|
||||
This file is a test program that plays several sound files and places a call simultatenously.
|
||||
*/
|
||||
|
||||
#include "linphonecore_utils.h"
|
||||
|
||||
static void play_finished(LsdPlayer *p){
|
||||
const char *filename=(const char *)lsd_player_get_user_pointer (p);
|
||||
ms_message("Playing of %s is finished.",filename);
|
||||
if (!lsd_player_loop_enabled (p)){
|
||||
linphone_sound_daemon_release_player (lsd_player_get_daemon(p),p);
|
||||
}
|
||||
}
|
||||
|
||||
static void wait_a_bit(LinphoneCore *lc, int seconds){
|
||||
time_t orig=time(NULL);
|
||||
while(time(NULL)-orig<seconds){
|
||||
/* we need to call iterate to receive notifications */
|
||||
linphone_core_iterate(lc);
|
||||
ms_usleep (50000);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
LinphoneCore *lc;
|
||||
LinphoneCoreVTable vtable={0};
|
||||
LinphoneSoundDaemon *lsd;
|
||||
LsdPlayer *p;
|
||||
|
||||
linphone_core_enable_logs(stdout);
|
||||
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
|
||||
lsd=linphone_sound_daemon_new (NULL,44100,1);
|
||||
|
||||
linphone_core_use_sound_daemon(lc,lsd);
|
||||
|
||||
/* start a play */
|
||||
p=linphone_sound_daemon_get_player(lsd);
|
||||
lsd_player_set_callback (p,play_finished);
|
||||
lsd_player_set_user_pointer (p,"share/hello8000.wav");
|
||||
lsd_player_play (p,"share/hello8000.wav");
|
||||
wait_a_bit (lc,2);
|
||||
|
||||
/*start another one */
|
||||
p=linphone_sound_daemon_get_player(lsd);
|
||||
lsd_player_set_callback (p,play_finished);
|
||||
lsd_player_set_user_pointer (p,"share/hello16000.wav");
|
||||
lsd_player_enable_loop (p,TRUE);
|
||||
lsd_player_play (p,"share/hello16000.wav");
|
||||
|
||||
/* after a few seconds decrease the volume */
|
||||
wait_a_bit (lc,3);
|
||||
lsd_player_set_gain (p,0.3);
|
||||
wait_a_bit(lc,5);
|
||||
|
||||
/*now play some stereo music*/
|
||||
p=linphone_sound_daemon_get_player(lsd);
|
||||
lsd_player_set_callback (p,play_finished);
|
||||
lsd_player_set_user_pointer (p,"share/rings/rock.wav");
|
||||
lsd_player_play(p,"share/rings/rock.wav");
|
||||
wait_a_bit(lc,2);
|
||||
|
||||
/*now play some stereo music at 22khz in order to test
|
||||
stereo resampling */
|
||||
p=linphone_sound_daemon_get_player(lsd);
|
||||
lsd_player_set_callback (p,play_finished);
|
||||
lsd_player_set_user_pointer (p,"share/rings/bigben.wav");
|
||||
lsd_player_play(p,"share/rings/bigben.wav");
|
||||
wait_a_bit(lc,6);
|
||||
|
||||
/* now place an outgoing call if sip address argument is given */
|
||||
if (argc>1){
|
||||
linphone_core_invite(lc,argv[1]);
|
||||
wait_a_bit(lc,10);
|
||||
linphone_core_terminate_call(lc,NULL);
|
||||
}
|
||||
linphone_core_use_sound_daemon(lc,NULL);
|
||||
linphone_sound_daemon_destroy(lsd);
|
||||
linphone_core_destroy(lc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -39,18 +39,18 @@ typedef struct _status_picture_tab_t{
|
|||
} status_picture_tab_t;
|
||||
|
||||
status_picture_tab_t status_picture_tab[]={
|
||||
{ LINPHONE_STATUS_ONLINE, "status-green.png" },
|
||||
{ LINPHONE_STATUS_BUSY, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_BERIGHTBACK, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_AWAY, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_ONTHEPHONE, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_OUTTOLUNCH, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_NOT_DISTURB, "status-red.png" },
|
||||
{ LINPHONE_STATUS_MOVED, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_ALT_SERVICE, "status-orange.png" },
|
||||
{ LINPHONE_STATUS_OFFLINE, "status-offline.png" },
|
||||
{ LINPHONE_STATUS_PENDING, "status-offline.png" },
|
||||
{ LINPHONE_STATUS_END, NULL },
|
||||
{ LinphoneStatusOnline, "status-green.png" },
|
||||
{ LinphoneStatusBusy, "status-orange.png" },
|
||||
{ LinphoneStatusBeRightBack, "status-orange.png" },
|
||||
{ LinphoneStatusAway, "status-orange.png" },
|
||||
{ LinphoneStatusOnThePhone, "status-orange.png" },
|
||||
{ LinphoneStatusOutToLunch, "status-orange.png" },
|
||||
{ LinphoneStatusDoNotDisturb, "status-red.png" },
|
||||
{ LinphoneStatusMoved, "status-orange.png" },
|
||||
{ LinphoneStatusAltService, "status-orange.png" },
|
||||
{ LinphoneStatusOffline, "status-offline.png" },
|
||||
{ LinphoneStatusPending, "status-offline.png" },
|
||||
{ LinphoneStatusEnd, NULL },
|
||||
};
|
||||
|
||||
static GdkPixbuf *create_status_picture(LinphoneOnlineStatus ss){
|
||||
|
|
@ -132,7 +132,7 @@ static GtkWidget * create_presence_menu(){
|
|||
GdkPixbuf *pbuf;
|
||||
status_picture_tab_t *t;
|
||||
for(t=status_picture_tab;t->img!=NULL;++t){
|
||||
if (t->status==LINPHONE_STATUS_PENDING){
|
||||
if (t->status==LinphoneStatusPending){
|
||||
continue;
|
||||
}
|
||||
menu_item=gtk_image_menu_item_new_with_label(linphone_online_status_to_string(t->status));
|
||||
|
|
@ -317,7 +317,7 @@ void linphone_gtk_show_friends(void){
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (!online_only || (linphone_friend_get_status(lf)!=LINPHONE_STATUS_OFFLINE)){
|
||||
if (!online_only || (linphone_friend_get_status(lf)!=LinphoneStatusOffline)){
|
||||
BuddyInfo *bi;
|
||||
if (name==NULL || name[0]=='\0') display=uri;
|
||||
gtk_list_store_append(store,&iter);
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ void linphone_gtk_in_call_view_set_in_call(){
|
|||
GtkWidget *duration=linphone_gtk_get_widget(main_window,"in_call_duration");
|
||||
GtkWidget *animation=linphone_gtk_get_widget(main_window,"in_call_animation");
|
||||
GdkPixbufAnimation *pbuf=create_pixbuf_animation("incall_anim.gif");
|
||||
const LinphoneAddress *uri=linphone_core_get_remote_uri(lc);
|
||||
const LinphoneAddress *uri=linphone_core_get_current_call_remote_address(lc);
|
||||
char *tmp=linphone_address_as_string(uri);
|
||||
display_peer_name_in_label(callee,tmp);
|
||||
ms_free(tmp);
|
||||
|
|
@ -137,7 +137,9 @@ void linphone_gtk_in_call_view_set_in_call(){
|
|||
g_object_unref(G_OBJECT(pbuf));
|
||||
}else gtk_image_set_from_stock(GTK_IMAGE(animation),GTK_STOCK_INFO,GTK_ICON_SIZE_DIALOG);
|
||||
linphone_gtk_enable_mute_button(
|
||||
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,"incall_mute")),TRUE);
|
||||
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,"incall_mute")),TRUE);
|
||||
linphone_gtk_enable_hold_button(
|
||||
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,"hold_call")),TRUE);
|
||||
}
|
||||
|
||||
void linphone_gtk_in_call_view_update_duration(int duration){
|
||||
|
|
@ -175,6 +177,8 @@ void linphone_gtk_in_call_view_terminate(const char *error_msg){
|
|||
}
|
||||
linphone_gtk_enable_mute_button(
|
||||
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,"incall_mute")),FALSE);
|
||||
linphone_gtk_enable_hold_button(
|
||||
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,"hold_call")),FALSE);
|
||||
g_timeout_add_seconds(2,(GSourceFunc)in_call_view_terminated,NULL);
|
||||
}
|
||||
|
||||
|
|
@ -202,7 +206,54 @@ void linphone_gtk_mute_toggled(GtkToggleButton *button){
|
|||
linphone_gtk_draw_mute_button(button,active);
|
||||
}
|
||||
|
||||
void linphone_gtk_enable_mute_button(GtkToggleButton *button, gboolean sensitive){
|
||||
void linphone_gtk_enable_mute_button(GtkToggleButton *button, gboolean sensitive)
|
||||
{
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);
|
||||
linphone_gtk_draw_mute_button(button,FALSE);
|
||||
}
|
||||
|
||||
void linphone_gtk_draw_hold_button(GtkToggleButton *button, gboolean active){
|
||||
if (active){
|
||||
GtkWidget *image=create_pixmap("hold_off.png");
|
||||
gtk_button_set_label(GTK_BUTTON(button),_("HoldOff"));
|
||||
if (image!=NULL) {
|
||||
gtk_button_set_image(GTK_BUTTON(button),image);
|
||||
gtk_widget_show(image);
|
||||
}
|
||||
}else{
|
||||
GtkWidget *image=create_pixmap("hold_on.png");
|
||||
gtk_button_set_label(GTK_BUTTON(button),_("HoldOn"));
|
||||
if (image!=NULL) {
|
||||
gtk_button_set_image(GTK_BUTTON(button),image);
|
||||
gtk_widget_show(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void linphone_gtk_hold_toggled(GtkToggleButton *button){
|
||||
gboolean active=gtk_toggle_button_get_active(button);
|
||||
|
||||
if(active)
|
||||
{
|
||||
LinphoneCall *call=linphone_core_get_current_call (linphone_gtk_get_core());
|
||||
if (call==NULL) return;
|
||||
linphone_core_pause_call(linphone_gtk_get_core(),call);
|
||||
}
|
||||
else
|
||||
{
|
||||
const MSList *calls=linphone_core_get_calls(linphone_gtk_get_core());
|
||||
if (calls==NULL) return;
|
||||
if (ms_list_size(calls)>1){
|
||||
g_warning("Simultaneously calls not yet implemented in gtk ui.");
|
||||
return;
|
||||
}
|
||||
/*we are supposed to have only one */
|
||||
linphone_core_resume_call(linphone_gtk_get_core(),(LinphoneCall*)calls->data);
|
||||
}
|
||||
linphone_gtk_draw_hold_button(button,active);
|
||||
}
|
||||
|
||||
void linphone_gtk_enable_hold_button(GtkToggleButton *button, gboolean sensitive){
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);
|
||||
linphone_gtk_draw_hold_button(button,FALSE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ void linphone_gtk_in_call_view_set_in_call(void);
|
|||
void linphone_gtk_in_call_view_update_duration(int duration);
|
||||
void linphone_gtk_in_call_view_terminate(const char *error_msg);
|
||||
void linphone_gtk_enable_mute_button(GtkToggleButton *button, gboolean sensitive);
|
||||
void linphone_gtk_enable_hold_button(GtkToggleButton *button, gboolean sensitive);
|
||||
|
||||
void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,7 @@ static LinphoneCore *the_core=NULL;
|
|||
static GtkWidget *the_ui=NULL;
|
||||
|
||||
static void linphone_gtk_show(LinphoneCore *lc);
|
||||
static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from);
|
||||
static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from);
|
||||
static void linphone_gtk_inv_recv(LinphoneCore *lc, LinphoneCall *call);
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid);
|
||||
static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url);
|
||||
static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username);
|
||||
|
|
@ -51,30 +50,11 @@ static void linphone_gtk_display_status(LinphoneCore *lc, const char *status);
|
|||
static void linphone_gtk_display_message(LinphoneCore *lc, const char *msg);
|
||||
static void linphone_gtk_display_warning(LinphoneCore *lc, const char *warning);
|
||||
static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const char *url);
|
||||
static void linphone_gtk_display_question(LinphoneCore *lc, const char *question);
|
||||
static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl);
|
||||
static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate);
|
||||
static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to);
|
||||
static void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to);
|
||||
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg);
|
||||
static gboolean linphone_gtk_auto_answer(GtkWidget *incall_window);
|
||||
|
||||
static LinphoneCoreVTable vtable={
|
||||
.show=linphone_gtk_show,
|
||||
.inv_recv=linphone_gtk_inv_recv,
|
||||
.bye_recv=linphone_gtk_bye_recv,
|
||||
.notify_presence_recv=linphone_gtk_notify_recv,
|
||||
.new_unknown_subscriber=linphone_gtk_new_unknown_subscriber,
|
||||
.auth_info_requested=linphone_gtk_auth_info_requested,
|
||||
.display_status=linphone_gtk_display_status,
|
||||
.display_message=linphone_gtk_display_message,
|
||||
.display_warning=linphone_gtk_display_warning,
|
||||
.display_url=linphone_gtk_display_url,
|
||||
.display_question=linphone_gtk_display_question,
|
||||
.call_log_updated=linphone_gtk_call_log_updated,
|
||||
.text_received=linphone_gtk_text_received,
|
||||
.general_state=linphone_gtk_general_state,
|
||||
.refer_received=linphone_gtk_refer_received,
|
||||
.buddy_info_updated=linphone_gtk_buddy_info_updated
|
||||
};
|
||||
|
||||
static gboolean verbose=0;
|
||||
static gboolean auto_answer = 0;
|
||||
|
|
@ -211,6 +191,22 @@ static const char *linphone_gtk_get_factory_config_file(){
|
|||
|
||||
static void linphone_gtk_init_liblinphone(const char *config_file,
|
||||
const char *factory_config_file) {
|
||||
LinphoneCoreVTable vtable={0};
|
||||
|
||||
vtable.call_state_changed=linphone_gtk_call_state_changed;
|
||||
vtable.show=linphone_gtk_show;
|
||||
vtable.notify_presence_recv=linphone_gtk_notify_recv;
|
||||
vtable.new_unknown_subscriber=linphone_gtk_new_unknown_subscriber;
|
||||
vtable.auth_info_requested=linphone_gtk_auth_info_requested;
|
||||
vtable.display_status=linphone_gtk_display_status;
|
||||
vtable.display_message=linphone_gtk_display_message;
|
||||
vtable.display_warning=linphone_gtk_display_warning;
|
||||
vtable.display_url=linphone_gtk_display_url;
|
||||
vtable.call_log_updated=linphone_gtk_call_log_updated;
|
||||
vtable.text_received=linphone_gtk_text_received;
|
||||
vtable.refer_received=linphone_gtk_refer_received;
|
||||
vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
|
||||
|
||||
linphone_core_set_user_agent("Linphone", LINPHONE_VERSION);
|
||||
the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL);
|
||||
linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL);
|
||||
|
|
@ -390,7 +386,7 @@ static void set_video_window_decorations(GdkWindow *w){
|
|||
gdk_window_set_keep_above(w, FALSE);
|
||||
}else{
|
||||
LinphoneAddress *uri =
|
||||
linphone_address_clone(linphone_core_get_remote_uri(linphone_gtk_get_core()));
|
||||
linphone_address_clone(linphone_core_get_current_call_remote_address(linphone_gtk_get_core()));
|
||||
char *display_name;
|
||||
|
||||
linphone_address_clean(uri);
|
||||
|
|
@ -588,7 +584,7 @@ static void linphone_gtk_call_started(GtkWidget *mw){
|
|||
|
||||
static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
|
||||
const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
|
||||
if (linphone_core_invite(linphone_gtk_get_core(),entered)==0) {
|
||||
if (linphone_core_invite(linphone_gtk_get_core(),entered)!=NULL) {
|
||||
completion_add_text(GTK_ENTRY(uri_bar),entered);
|
||||
}else{
|
||||
linphone_gtk_call_terminated(NULL);
|
||||
|
|
@ -643,7 +639,9 @@ void linphone_gtk_uri_bar_activate(GtkWidget *w){
|
|||
|
||||
|
||||
void linphone_gtk_terminate_call(GtkWidget *button){
|
||||
linphone_core_terminate_call(linphone_gtk_get_core(),NULL);
|
||||
const MSList *elem=linphone_core_get_calls(linphone_gtk_get_core());
|
||||
if (elem==NULL) return;
|
||||
linphone_core_terminate_call(linphone_gtk_get_core(),(LinphoneCall*)elem->data);
|
||||
}
|
||||
|
||||
void linphone_gtk_decline_call(GtkWidget *button){
|
||||
|
|
@ -704,10 +702,11 @@ static void linphone_gtk_show(LinphoneCore *lc){
|
|||
linphone_gtk_show_main_window();
|
||||
}
|
||||
|
||||
static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from){
|
||||
static void linphone_gtk_inv_recv(LinphoneCore *lc, LinphoneCall *call){
|
||||
GtkWidget *w=linphone_gtk_create_window("incoming_call");
|
||||
GtkWidget *label;
|
||||
gchar *msg;
|
||||
char *from=linphone_call_get_remote_address_as_string(call);
|
||||
|
||||
if (auto_answer){
|
||||
g_timeout_add(2000,(GSourceFunc)linphone_gtk_auto_answer,w);
|
||||
|
|
@ -727,10 +726,7 @@ static void linphone_gtk_inv_recv(LinphoneCore *lc, const char *from){
|
|||
g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"incoming_call",w);
|
||||
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),
|
||||
from);
|
||||
}
|
||||
|
||||
static void linphone_gtk_bye_recv(LinphoneCore *lc, const char *from){
|
||||
|
||||
ms_free(from);
|
||||
}
|
||||
|
||||
static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){
|
||||
|
|
@ -868,31 +864,29 @@ static void linphone_gtk_display_url(LinphoneCore *lc, const char *msg, const ch
|
|||
linphone_gtk_display_something(GTK_MESSAGE_INFO,richtext);
|
||||
}
|
||||
|
||||
static void linphone_gtk_display_question(LinphoneCore *lc, const char *question){
|
||||
linphone_gtk_display_something(GTK_MESSAGE_QUESTION,question);
|
||||
}
|
||||
|
||||
static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl){
|
||||
GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"call_logs");
|
||||
if (w) linphone_gtk_call_log_update(w);
|
||||
}
|
||||
|
||||
static void linphone_gtk_general_state(LinphoneCore *lc, LinphoneGeneralState *gstate){
|
||||
switch(gstate->new_state){
|
||||
case GSTATE_CALL_OUT_CONNECTED:
|
||||
case GSTATE_CALL_IN_CONNECTED:
|
||||
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg){
|
||||
switch(cs){
|
||||
case LinphoneCallConnected:
|
||||
if (linphone_gtk_use_in_call_view())
|
||||
linphone_gtk_in_call_view_set_in_call();
|
||||
linphone_gtk_enable_mute_button(
|
||||
GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
|
||||
TRUE);
|
||||
break;
|
||||
case GSTATE_CALL_ERROR:
|
||||
linphone_gtk_call_terminated(gstate->message);
|
||||
case LinphoneCallError:
|
||||
linphone_gtk_call_terminated(msg);
|
||||
break;
|
||||
case GSTATE_CALL_END:
|
||||
case LinphoneCallEnd:
|
||||
linphone_gtk_call_terminated(NULL);
|
||||
break;
|
||||
case LinphoneCallIncomingReceived:
|
||||
linphone_gtk_inv_recv (lc,call);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1145,6 +1139,8 @@ static void linphone_gtk_init_main_window(){
|
|||
"main_mute")),FALSE);
|
||||
linphone_gtk_enable_mute_button(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,
|
||||
"incall_mute")),FALSE);
|
||||
linphone_gtk_enable_hold_button(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(main_window,
|
||||
"hold_call")),FALSE);
|
||||
if (!linphone_gtk_use_in_call_view()) {
|
||||
gtk_widget_show(linphone_gtk_get_widget(main_window, "main_mute"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1190,6 +1190,7 @@ Fiber Channel</property>
|
|||
<child>
|
||||
<widget class="GtkHButtonBox" id="hbuttonbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">spread</property>
|
||||
<child>
|
||||
<widget class="GtkToggleButton" id="incall_mute">
|
||||
<property name="label" translatable="yes">Mute</property>
|
||||
|
|
@ -1205,6 +1206,21 @@ Fiber Channel</property>
|
|||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkToggleButton" id="hold_call">
|
||||
<property name="label" translatable="yes">HoldOn</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">True</property>
|
||||
<signal name="toggled" handler="linphone_gtk_hold_toggled"/>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
|||
|
|
@ -119,17 +119,17 @@ void linphone_gtk_video_port_changed(GtkWidget *w){
|
|||
|
||||
void linphone_gtk_no_firewall_toggled(GtkWidget *w){
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LINPHONE_POLICY_NO_FIREWALL);
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyNoFirewall);
|
||||
}
|
||||
|
||||
void linphone_gtk_use_nat_address_toggled(GtkWidget *w){
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LINPHONE_POLICY_USE_NAT_ADDRESS);
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseNatAddress);
|
||||
}
|
||||
|
||||
void linphone_gtk_use_stun_toggled(GtkWidget *w){
|
||||
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LINPHONE_POLICY_USE_STUN);
|
||||
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseStun);
|
||||
}
|
||||
|
||||
void linphone_gtk_mtu_changed(GtkWidget *w){
|
||||
|
|
@ -762,13 +762,13 @@ void linphone_gtk_show_parameters(void){
|
|||
if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"stun_server")),tmp);
|
||||
pol=linphone_core_get_firewall_policy(lc);
|
||||
switch(pol){
|
||||
case LINPHONE_POLICY_NO_FIREWALL:
|
||||
case LinphonePolicyNoFirewall:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"no_nat")),TRUE);
|
||||
break;
|
||||
case LINPHONE_POLICY_USE_NAT_ADDRESS:
|
||||
case LinphonePolicyUseNatAddress:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_nat_address")),TRUE);
|
||||
break;
|
||||
case LINPHONE_POLICY_USE_STUN:
|
||||
case LinphonePolicyUseStun:
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_stun")),TRUE);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 332d79209b333bd8ded5b16a7b9dcfe2c0aedc63
|
||||
Subproject commit ea7ca97aaaa6f191dfec112f137fb048a4ef2139
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
pixmapdir=$(datadir)/pixmaps/linphone
|
||||
|
||||
pixmap_DATA= \
|
||||
hold_on.png hold_off.png \
|
||||
mic_muted.png mic_active.png \
|
||||
linphone-3-250x130.png linphone-3.png linphone2-57x57.png \
|
||||
linphone.png linphone-banner.png \
|
||||
|
|
|
|||
BIN
pixmaps/hold_off.png
Normal file
BIN
pixmaps/hold_off.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
BIN
pixmaps/hold_on.png
Normal file
BIN
pixmaps/hold_on.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -72,3 +72,5 @@ mediastreamer2/src/audiomixer.c
|
|||
mediastreamer2/src/chanadapt.c
|
||||
mediastreamer2/src/itc.c
|
||||
mediastreamer2/src/extdisplay.c
|
||||
mediastreamer2/src/msiounit.c
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue