printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "zRTP encryption (GPLv3)" $zrtp
+printf "* %-30s %s\n" "uPnP support" $build_upnp
if test "$enable_tunnel" = "true" ; then
printf "* Tunnel support\t\ttrue\n"
}
}
+static int linphone_conference_get_size(LinphoneConference *conf){
+ if (conf->conf == NULL) {
+ return 0;
+ }
+ return ms_audio_conference_get_size(conf->conf) - (conf->record_endpoint ? 1 : 0);
+}
+
static int remote_participants_count(LinphoneConference *ctx) {
- if (!ctx->conf || ms_audio_conference_get_size(ctx->conf)==0) return 0;
- if (!ctx->local_participant) return ms_audio_conference_get_size(ctx->conf);
- return ms_audio_conference_get_size(ctx->conf) -1;
+ int count=linphone_conference_get_size(ctx);
+ if (count==0) return 0;
+ if (!ctx->local_participant) return count;
+ return count -1;
}
void linphone_core_conference_check_uninit(LinphoneCore *lc){
LinphoneConference *ctx=&lc->conf_ctx;
if (ctx->conf){
- ms_message("conference_check_uninit(): nmembers=%i",ms_audio_conference_get_size(ctx->conf));
- if (remote_participants_count(ctx)==1){
+ int remote_count=remote_participants_count(ctx);
+ ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx));
+ if (remote_count==1){
convert_conference_to_call(lc);
}
- if (ms_audio_conference_get_size(ctx->conf)==1 && ctx->local_participant!=NULL){
- remove_local_endpoint(ctx);
+ if (remote_count==0){
+ if (ctx->local_participant!=NULL)
+ remove_local_endpoint(ctx);
+ if (ctx->record_endpoint){
+ ms_audio_conference_remove_member(ctx->conf,ctx->record_endpoint);
+ ms_audio_endpoint_destroy(ctx->record_endpoint);
+ ctx->record_endpoint=NULL;
+ }
}
+
if (ms_audio_conference_get_size(ctx->conf)==0){
ms_audio_conference_destroy(ctx->conf);
ctx->conf=NULL;
* @returns the number of participants to the conference
**/
int linphone_core_get_conference_size(LinphoneCore *lc) {
- if (lc->conf_ctx.conf == NULL) {
- return 0;
+ LinphoneConference *conf=&lc->conf_ctx;
+ return linphone_conference_get_size(conf);
+}
+
+
+int linphone_core_start_conference_recording(LinphoneCore *lc, const char *path){
+ LinphoneConference *conf=&lc->conf_ctx;
+ if (conf->conf == NULL) {
+ ms_warning("linphone_core_start_conference_recording(): no conference now.");
+ return -1;
+ }
+ if (conf->record_endpoint==NULL){
+ conf->record_endpoint=ms_audio_endpoint_new_recorder();
+ ms_audio_conference_add_member(conf->conf,conf->record_endpoint);
}
- return ms_audio_conference_get_size(lc->conf_ctx.conf);
+ ms_audio_recorder_endpoint_start(conf->record_endpoint,path);
+ return 0;
+}
+
+int linphone_core_stop_conference_recording(LinphoneCore *lc){
+ LinphoneConference *conf=&lc->conf_ctx;
+ if (conf->conf == NULL) {
+ ms_warning("linphone_core_stop_conference_recording(): no conference now.");
+ return -1;
+ }
+ if (conf->record_endpoint==NULL){
+ ms_warning("linphone_core_stop_conference_recording(): no record active.");
+ return -1;
+ }
+ ms_audio_recorder_endpoint_stop(conf->record_endpoint);
+ return 0;
}
/**
static void on_tone_sent(void *data, MSFilter *f, unsigned int event_id, void *arg){
MSDtmfGenEvent *ev=(MSDtmfGenEvent*)arg;
EcCalibrator *ecc=(EcCalibrator*)data;
- ecc->sent_count++;
ecc->acc-=ev->tone_start_time;
ms_message("Sent tone at %u",(unsigned int)ev->tone_start_time);
}
+static bool_t is_valid_tone(EcCalibrator *ecc, MSToneDetectorEvent *ev){
+ bool_t *toneflag=NULL;
+ if (strcmp(ev->tone_name,"freq1")==0){
+ toneflag=&ecc->freq1;
+ }else if (strcmp(ev->tone_name,"freq2")==0){
+ toneflag=&ecc->freq2;
+ }else if (strcmp(ev->tone_name,"freq3")==0){
+ toneflag=&ecc->freq3;
+ }else{
+ ms_error("Calibrator bug.");
+ return FALSE;
+ }
+ if (*toneflag){
+ ms_message("Duplicated tone event, ignored.");
+ return FALSE;
+ }
+ *toneflag=TRUE;
+ return TRUE;
+}
+
static void on_tone_received(void *data, MSFilter *f, unsigned int event_id, void *arg){
MSToneDetectorEvent *ev=(MSToneDetectorEvent*)arg;
EcCalibrator *ecc=(EcCalibrator*)data;
- ecc->recv_count++;
- ecc->acc+=ev->tone_start_time;
- ms_message("Received tone at %u",(unsigned int)ev->tone_start_time);
+ if (is_valid_tone(ecc,ev)){
+ ecc->acc+=ev->tone_start_time;
+ ms_message("Received tone at %u",(unsigned int)ev->tone_start_time);
+ }
}
static void ecc_play_tones(EcCalibrator *ecc){
ms_filter_set_notify_callback(ecc->det,on_tone_received,ecc);
+ /* configure the tones to be scanned */
+
+ strncpy(expected_tone.tone_name,"freq1",sizeof(expected_tone.tone_name));
expected_tone.frequency=2000;
expected_tone.min_duration=40;
- expected_tone.min_amplitude=0.02;
+ expected_tone.min_amplitude=0.1;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
- tone.frequency=1300;
- tone.duration=1000;
- tone.amplitude=1.0;
+ strncpy(expected_tone.tone_name,"freq2",sizeof(expected_tone.tone_name));
+ expected_tone.frequency=2300;
+ expected_tone.min_duration=40;
+ expected_tone.min_amplitude=0.1;
+ ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
+
+ strncpy(expected_tone.tone_name,"freq3",sizeof(expected_tone.tone_name));
+ expected_tone.frequency=2500;
+ expected_tone.min_duration=40;
+ expected_tone.min_amplitude=0.1;
+
+ ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
+
/*play an initial tone to startup the audio playback/capture*/
+
+ tone.frequency=140;
+ tone.duration=1000;
+ tone.amplitude=0.5;
+
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(2);
ms_filter_set_notify_callback(ecc->gen,on_tone_sent,ecc);
+
+ /* play the three tones*/
+
tone.frequency=2000;
tone.duration=100;
-
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
- ms_sleep(1);
+ ms_usleep(300000);
+
+ tone.frequency=2300;
+ tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
- ms_sleep(1);
+ ms_usleep(300000);
+
+ tone.frequency=2500;
+ tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(1);
-
- if (ecc->sent_count==3) {
- if (ecc->recv_count==3){
- int delay=ecc->acc/3;
- if (delay<0){
- ms_error("Quite surprising calibration result, delay=%i",delay);
- ecc->status=LinphoneEcCalibratorFailed;
- }else{
- ms_message("Echo calibration estimated delay to be %i ms",delay);
- ecc->delay=delay;
- ecc->status=LinphoneEcCalibratorDone;
- }
- } else if (ecc->recv_count == 0) {
+
+ if (ecc->freq1 && ecc->freq2 && ecc->freq3) {
+ int delay=ecc->acc/3;
+ if (delay<0){
+ ms_error("Quite surprising calibration result, delay=%i",delay);
+ ecc->status=LinphoneEcCalibratorFailed;
+ }else{
+ ms_message("Echo calibration estimated delay to be %i ms",delay);
+ ecc->delay=delay;
+ ecc->status=LinphoneEcCalibratorDone;
+ }
+ } else if ((ecc->freq1 || ecc->freq2 || ecc->freq3)==FALSE) {
ms_message("Echo calibration succeeded, no echo has been detected");
ecc->status = LinphoneEcCalibratorDoneNoEcho;
- } else {
+ } else {
ecc->status = LinphoneEcCalibratorFailed;
- }
- }else{
- ecc->status=LinphoneEcCalibratorFailed;
}
+
if (ecc->status == LinphoneEcCalibratorFailed) {
- ms_error("Echo calibration failed, tones received = %i",ecc->recv_count);
+ ms_error("Echo calibration failed.");
}
}
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);
- from_str=linphone_address_as_string_uri_only(from);
- sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
- sal_op_set_user_pointer(call->ping_op,call);
- sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
- ms_free(from_str);
+#ifdef BUILD_UPNP
+ if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
+ linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
+#else //BUILD_UPNP
+ {
+#endif //BUILD_UPNP
+ /*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);
+ from_str=linphone_address_as_string_uri_only(from);
+ sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
+ sal_op_set_user_pointer(call->ping_op,call);
+ sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
+ ms_free(from_str);
+ }
}
linphone_address_clean(from);
params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value);
}
-const char *linphone_call_params_get_custom_header(LinphoneCallParams *params, const char *header_name){
+const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){
return sal_custom_header_find(params->custom_headers,header_name);
}
/*prevent a gcc bug with %c*/
static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){
-#if !defined(_WIN32_WCE)
return strftime(s, max, fmt, tm);
-#else
- return 0;
- /*FIXME*/
-#endif /*_WIN32_WCE*/
}
static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){
set_call_log_date(cl,cl->start_date_time);
cl->from=from;
cl->to=to;
- cl->status=LinphoneCallAborted; /*default status*/
+ cl->status=LinphoneCallAborted; /*default status*/
return cl;
}
tmp=lp_config_get_int(lc->config,"sip","in_call_timeout",0);
linphone_core_set_in_call_timeout(lc,tmp);
+
+ tmp=lp_config_get_int(lc->config,"sip","delayed_timeout",4);
+ linphone_core_set_delayed_timeout(lc,tmp);
/* get proxies config */
for(i=0;; i++){
lc->tunnel=linphone_core_tunnel_new(lc);
if (lc->tunnel) linphone_tunnel_configure(lc->tunnel);
#endif
-#ifdef BUILD_UPNP
- lc->upnp = linphone_upnp_context_new(lc);
-#endif //BUILD_UPNP
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Ready"));
lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon;
lc->ecc->cb(lc,ecs,lc->ecc->delay,lc->ecc->cb_data);
if (ecs==LinphoneEcCalibratorDone){
int len=lp_config_get_int(lc->config,"sound","ec_tail_len",0);
- lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-(len/2),0));
+ int margin=len/2;
+
+ lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-margin,0));
} else if (ecs == LinphoneEcCalibratorFailed) {
- lp_config_set_int(lc->config, "sound", "ec_delay", LP_CONFIG_DEFAULT_INT(lc->config, "ec_delay", 250));
+ lp_config_set_int(lc->config, "sound", "ec_delay", -1);/*use default value from soundcard*/
} else if (ecs == LinphoneEcCalibratorDoneNoEcho) {
linphone_core_enable_echo_cancellation(lc, FALSE);
}
linphone_core_start_invite() */
calls=calls->next;
linphone_call_background_tasks(call,one_second_elapsed);
- if (call->state==LinphoneCallOutgoingInit && (elapsed>=4)){
+ if (call->state==LinphoneCallOutgoingInit && (elapsed>=lc->sip_conf.delayed_timeout)){
/*start the call even if the OPTIONS reply did not arrive*/
if (call->ice_session != NULL) {
ms_warning("ICE candidates gathering from [%s] has not finished yet, proceed with the call without ICE anyway."
}
if (call->dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){
- /*defer the start of the call after the OPTIONS ping*/
- call->ping_replied=FALSE;
- call->ping_op=sal_op_new(lc->sal);
- sal_ping(call->ping_op,from,real_url);
- sal_op_set_user_pointer(call->ping_op,call);
- call->start_time=time(NULL);
- }else{
- if (defer==FALSE) linphone_core_start_invite(lc,call);
+#ifdef BUILD_UPNP
+ if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
+ linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
+#else //BUILD_UPNP
+ {
+#endif //BUILD_UPNP
+ /*defer the start of the call after the OPTIONS ping*/
+ call->ping_replied=FALSE;
+ call->ping_op=sal_op_new(lc->sal);
+ sal_ping(call->ping_op,from,real_url);
+ sal_op_set_user_pointer(call->ping_op,call);
+ call->start_time=time(NULL);
+ defer = TRUE;
+ }
}
+
+ if (defer==FALSE) linphone_core_start_invite(lc,call);
if (real_url!=NULL) ms_free(real_url);
return call;
return lc->sip_conf.in_call_timeout;
}
+/**
+ * Returns the delayed timeout
+ *
+ * @ingroup call_control
+ * See linphone_core_set_delayed_timeout() for details.
+**/
+int linphone_core_get_delayed_timeout(LinphoneCore *lc){
+ return lc->sip_conf.delayed_timeout;
+}
+
+/**
+ * Set the in delayed timeout in seconds.
+ *
+ * @ingroup call_control
+ * After this timeout period, a delayed call (internal call initialisation or resolution) is resumed.
+**/
+void linphone_core_set_delayed_timeout(LinphoneCore *lc, int seconds){
+ lc->sip_conf.delayed_timeout=seconds;
+}
+
void linphone_core_set_presence_info(LinphoneCore *lc,int minutes_away,
const char *contact,
LinphoneOnlineStatus presence_mode)
}
#endif //BUILD_UPNP
lc->net_conf.firewall_policy=pol;
+#ifdef BUILD_UPNP
+ if(pol == LinphonePolicyUseUpnp) {
+ if(lc->upnp == NULL) {
+ lc->upnp = linphone_upnp_context_new(lc);
+ }
+ } else {
+ if(lc->upnp != NULL) {
+ linphone_upnp_context_destroy(lc->upnp);
+ lc->upnp = NULL;
+ }
+ }
+ linphone_core_enable_keep_alive(lc, (lc->sip_conf.keepalive_period > 0));
+#endif //BUILD_UPNP
if (lc->sip_conf.contact) update_primary_contact(lc);
if (linphone_core_ready(lc))
lp_config_set_int(lc->config,"net","firewall_policy",pol);
lp_config_set_string(lc->config,"sip","contact",config->contact);
lp_config_set_int(lc->config,"sip","inc_timeout",config->inc_timeout);
lp_config_set_int(lc->config,"sip","in_call_timeout",config->in_call_timeout);
+ lp_config_set_int(lc->config,"sip","delayed_timeout",config->delayed_timeout);
lp_config_set_int(lc->config,"sip","use_info",config->use_info);
lp_config_set_int(lc->config,"sip","use_rfc2833",config->use_rfc2833);
lp_config_set_int(lc->config,"sip","use_ipv6",config->ipv6_enabled);
usleep(50000);
#endif
}
-
#ifdef BUILD_UPNP
- linphone_upnp_context_destroy(lc->upnp);
- lc->upnp = NULL;
+ if(lc->upnp != NULL) {
+ linphone_upnp_context_destroy(lc->upnp);
+ lc->upnp = NULL;
+ }
#endif //BUILD_UPNP
if (lc->friends)
ms_list_for_each(lc->last_recv_msg_ids,ms_free);
lc->last_recv_msg_ids=ms_list_free(lc->last_recv_msg_ids);
+
+ // Free struct variable
+ if(lc->zrtp_secrets_cache != NULL) {
+ ms_free(lc->zrtp_secrets_cache);
+ }
+ if(lc->play_file!=NULL){
+ ms_free(lc->play_file);
+ }
+ if(lc->rec_file!=NULL){
+ ms_free(lc->rec_file);
+ }
linphone_core_free_payload_types(lc);
ortp_exit();
* Enables signaling keep alive
*/
void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) {
+#ifdef BUILD_UPNP
+ if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp) {
+ enable = FALSE;
+ }
+#endif //BUILD_UPNP
if (enable > 0) {
sal_use_tcp_tls_keepalive(lc->sal,lc->sip_conf.tcp_tls_keepalive);
sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
for(elem=lc->hooks;elem!=NULL;elem=elem->next){
Hook *h=(Hook*)elem->data;
if (h->fun==hook && h->data==hook_data){
- ms_list_remove_link(lc->hooks,elem);
+ lc->hooks = ms_list_remove_link(lc->hooks,elem);
ms_free(h);
return;
}
extern "C" {
#endif
-struct _MSSndCard;
struct _LinphoneCore;
/**
* Linphone core main object created by function linphone_core_new() .
* @ingroup initializing
*/
typedef struct _LinphoneCore LinphoneCore;
-struct SalOp;
struct _LpConfig;
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path);
const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp);
void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value);
-const char *linphone_call_params_get_custom_header(LinphoneCallParams *params, const char *header_name);
+const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name);
/**
* Enum describing failure reasons.
* @ingroup initializing
int linphone_core_get_in_call_timeout(LinphoneCore *lc);
+void linphone_core_set_delayed_timeout(LinphoneCore *lc, int seconds);
+
+int linphone_core_get_delayed_timeout(LinphoneCore *lc);
+
void linphone_core_set_stun_server(LinphoneCore *lc, const char *server);
const char * linphone_core_get_stun_server(const LinphoneCore *lc);
int linphone_core_terminate_conference(LinphoneCore *lc);
int linphone_core_get_conference_size(LinphoneCore *lc);
+int linphone_core_start_conference_recording(LinphoneCore *lc, const char *path);
+int linphone_core_stop_conference_recording(LinphoneCore *lc);
int linphone_core_get_max_calls(LinphoneCore *lc);
void linphone_core_set_max_calls(LinphoneCore *lc, int max);
linphone_core_terminate_call((LinphoneCore*)lc,(LinphoneCall*)call);
}
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_declineCall( JNIEnv* env
+ ,jobject thiz
+ ,jlong lc
+ ,jlong call, jint reason) {
+ linphone_core_decline_call((LinphoneCore*)lc,(LinphoneCall*)call,(LinphoneReason)reason);
+}
+
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getRemoteAddress( JNIEnv* env
,jobject thiz
,jlong lc) {
}
+extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_needsEchoCalibration(JNIEnv *env, jobject thiz, jlong lc){
+ MSSndCard *sndcard;
+ MSSndCardManager *m=ms_snd_card_manager_get();
+ const char *card=linphone_core_get_capture_device((LinphoneCore*)lc);
+ sndcard=ms_snd_card_manager_get_card(m,card);
+ if (sndcard == NULL){
+ ms_error("Could not get soundcard.");
+ return TRUE;
+ }
+ return (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER) || (ms_snd_card_get_minimal_latency(sndcard)>0);
+}
+
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryption(JNIEnv* env
,jobject thiz
,jlong lc
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addAllToConference(JNIEnv *env,jobject thiz,jlong pCore) {
linphone_core_add_all_to_conference((LinphoneCore *) pCore);
}
+
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addToConference(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall) {
linphone_core_add_to_conference((LinphoneCore *) pCore, (LinphoneCall *) pCall);
}
+
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeFromConference(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall) {
linphone_core_remove_from_conference((LinphoneCore *) pCore, (LinphoneCall *) pCall);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getConferenceSize(JNIEnv *env,jobject thiz,jlong pCore) {
return (jint)linphone_core_get_conference_size((LinphoneCore *) pCore);
}
+
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startConferenceRecording(JNIEnv *env,jobject thiz,jlong pCore, jstring jpath){
+ int err=-1;
+ if (jpath){
+ const char *path=env->GetStringUTFChars(jpath, NULL);
+ err=linphone_core_start_conference_recording((LinphoneCore*)pCore,path);
+ env->ReleaseStringUTFChars(jpath,path);
+ }
+ return err;
+}
+
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_stopConferenceRecording(JNIEnv *env,jobject thiz,jlong pCore){
+ int err=linphone_core_stop_conference_recording((LinphoneCore*)pCore);
+ return err;
+}
+
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_terminateAllCalls(JNIEnv *env,jobject thiz,jlong pCore) {
linphone_core_terminate_all_calls((LinphoneCore *) pCore);
}
MSList *deleted_proxies;
int inc_timeout; /*timeout after an un-answered incoming call is rejected*/
int in_call_timeout; /*timeout after a call is hangup */
+ int delayed_timeout; /*timeout after a delayed call is resumed */
unsigned int keepalive_period; /* interval in ms between keep alive messages sent to the proxy server*/
LCSipTransports transports;
bool_t use_info;
MSAudioConference *conf;
AudioStream *local_participant;
MSAudioEndpoint *local_endpoint;
+ MSAudioEndpoint *record_endpoint;
RtpProfile *local_dummy_profile;
bool_t local_muted;
};
MSTicker *ticker;
LinphoneEcCalibrationCallback cb;
void *cb_data;
- int recv_count;
- int sent_count;
int64_t acc;
int delay;
unsigned int rate;
LinphoneEcCalibratorStatus status;
+ bool_t freq1,freq2,freq3;
};
typedef struct _EcCalibrator EcCalibrator;
if (proxy==NULL) return NULL;
host=linphone_address_get_domain (proxy);
if (host!=NULL){
- char localip[LINPHONE_IPADDR_SIZE];
+ int localport = -1;
+ char localip_tmp[LINPHONE_IPADDR_SIZE] = {'\0'};
+ const char *localip = NULL;
char *tmp;
LCSipTransports tr;
LinphoneAddress *contact;
- linphone_core_get_local_ip(obj->lc,host,localip);
contact=linphone_address_new(obj->reg_identity);
- linphone_address_set_domain (contact,localip);
- linphone_address_set_port_int(contact,linphone_core_get_sip_port(obj->lc));
+#ifdef BUILD_UPNP
+ if (obj->lc->upnp != NULL && linphone_core_get_firewall_policy(obj->lc)==LinphonePolicyUseUpnp &&
+ linphone_upnp_context_get_state(obj->lc->upnp) == LinphoneUpnpStateOk) {
+ localip = linphone_upnp_context_get_external_ipaddress(obj->lc->upnp);
+ localport = linphone_upnp_context_get_external_port(obj->lc->upnp);
+ }
+#endif //BUILD_UPNP
+ if(localip == NULL) {
+ localip = localip_tmp;
+ linphone_core_get_local_ip(obj->lc,host,localip_tmp);
+ }
+ if(localport == -1) {
+ localport = linphone_core_get_sip_port(obj->lc);
+ }
+ linphone_address_set_port_int(contact,localport);
+ linphone_address_set_domain(contact,localip);
linphone_address_set_display_name(contact,NULL);
linphone_core_get_sip_transports(obj->lc,&tr);
if (cfg->type && cfg->ssctx==NULL){
linphone_proxy_config_activate_sip_setup(cfg);
}
- if ((!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable) &&
- (!lc->sip_conf.register_only_when_upnp_is_ok || linphone_core_get_upnp_state(lc) == LinphoneUpnpStateOk))
- linphone_proxy_config_register(cfg);
+ switch(linphone_core_get_firewall_policy(lc)) {
+ case LinphonePolicyUseUpnp:
+#ifdef BUILD_UPNP
+ if(!lc->sip_conf.register_only_when_upnp_is_ok ||
+ (lc->upnp != NULL && !linphone_upnp_context_is_ready_for_register(lc->upnp))) {
+ break;
+ }
+#endif //BUILD_UPNP
+ default:
+ if ((!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable)) {
+ linphone_proxy_config_register(cfg);
+ }
+ }
if (cfg->publish && cfg->publish_op==NULL){
linphone_proxy_config_send_publish(cfg,lc->presence_mode);
}
#include "private.h"
#include "lpconfig.h"
-#define UPNP_ADD_MAX_RETRY 4
+#define UPNP_ADD_MAX_RETRY 4
#define UPNP_REMOVE_MAX_RETRY 4
-#define UPNP_SECTION_NAME "uPnP"
+#define UPNP_SECTION_NAME "uPnP"
+#define UPNP_CORE_READY_CHECK 1
+#define UPNP_CORE_RETRY_DELAY 4
+#define UPNP_CALL_RETRY_DELAY 1
/*
* uPnP Definitions
int ref;
bool_t to_remove;
bool_t to_add;
+ time_t last_update;
} UpnpPortBinding;
typedef struct _UpnpStream {
ms_mutex_t mutex;
ms_cond_t empty_cond;
-
+
+ time_t last_ready_check;
+ LinphoneUpnpState last_ready_state;
};
void linphone_core_upnp_refresh(UpnpContext *ctx);
UpnpPortBinding *linphone_upnp_port_binding_new();
+UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_protocol protocol, int local_port, int external_port);
+UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port);
UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port);
bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2);
UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(MSList *list, const UpnpPortBinding *port);
UpnpPortBinding *linphone_upnp_port_binding_retain(UpnpPortBinding *port);
+void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay);
void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port);
void linphone_upnp_port_binding_release(UpnpPortBinding *port);
+void linphone_upnp_update_config(UpnpContext *lupnp);
+// Configuration
MSList *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc);
void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port);
void linphone_upnp_config_remove_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port);
-int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port);
-int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port);
+// uPnP
+int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry);
+int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry);
/**
mapping = (upnp_igd_port_mapping *) arg;
port_mapping = (UpnpPortBinding*) mapping->cookie;
port_mapping->external_port = -1; //Force random external port
- if(linphone_upnp_context_send_add_port_binding(lupnp, port_mapping) != 0) {
+ if(linphone_upnp_context_send_add_port_binding(lupnp, port_mapping, TRUE) != 0) {
linphone_upnp_port_binding_log(ORTP_ERROR, "Can't add port binding", port_mapping);
}
case UPNP_IGD_PORT_MAPPING_REMOVE_FAILURE:
mapping = (upnp_igd_port_mapping *) arg;
port_mapping = (UpnpPortBinding*) mapping->cookie;
- if(linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping) != 0) {
+ if(linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, TRUE) != 0) {
linphone_upnp_port_binding_log(ORTP_ERROR, "Can't remove port binding", port_mapping);
linphone_upnp_config_remove_port_binding(lupnp, port_mapping);
}
if(port_mapping->to_remove) {
if(port_mapping->state == LinphoneUpnpStateOk) {
port_mapping->to_remove = FALSE;
- linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping);
+ linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, FALSE);
} else if(port_mapping->state == LinphoneUpnpStateKo) {
port_mapping->to_remove = FALSE;
}
if(port_mapping->to_add) {
if(port_mapping->state == LinphoneUpnpStateIdle || port_mapping->state == LinphoneUpnpStateKo) {
port_mapping->to_add = FALSE;
- linphone_upnp_context_send_add_port_binding(lupnp, port_mapping);
+ linphone_upnp_context_send_add_port_binding(lupnp, port_mapping, FALSE);
}
}
*/
UpnpContext* linphone_upnp_context_new(LinphoneCore *lc) {
- LCSipTransports transport;
UpnpContext *lupnp = (UpnpContext *)ms_new0(UpnpContext,1);
- const char *ip_address;
ms_mutex_init(&lupnp->mutex, NULL);
ms_cond_init(&lupnp->empty_cond, NULL);
+ lupnp->last_ready_check = 0;
+ lupnp->last_ready_state = LinphoneUpnpStateIdle;
+
lupnp->lc = lc;
lupnp->pending_bindings = NULL;
lupnp->adding_configs = NULL;
lupnp->state = LinphoneUpnpStateIdle;
ms_message("uPnP IGD: New %p for core %p", lupnp, lc);
- linphone_core_get_sip_transports(lc, &transport);
- if(transport.udp_port != 0) {
- lupnp->sip_udp = linphone_upnp_port_binding_new();
- lupnp->sip_udp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
- lupnp->sip_udp->local_port = transport.udp_port;
- lupnp->sip_udp->external_port = transport.udp_port;
- } else {
- lupnp->sip_udp = NULL;
- }
- if(transport.tcp_port != 0) {
- lupnp->sip_tcp = linphone_upnp_port_binding_new();
- lupnp->sip_tcp->protocol = UPNP_IGD_IP_PROTOCOL_TCP;
- lupnp->sip_tcp->local_port = transport.tcp_port;
- lupnp->sip_tcp->external_port = transport.tcp_port;
- } else {
- lupnp->sip_tcp = NULL;
- }
- if(transport.tls_port != 0) {
- lupnp->sip_tls = linphone_upnp_port_binding_new();
- lupnp->sip_tls->protocol = UPNP_IGD_IP_PROTOCOL_TCP;
- lupnp->sip_tls->local_port = transport.tls_port;
- lupnp->sip_tls->external_port = transport.tls_port;
- } else {
- lupnp->sip_tls = NULL;
- }
+ // Init ports
+ lupnp->sip_udp = NULL;
+ lupnp->sip_tcp = NULL;
+ lupnp->sip_tls = NULL;
linphone_core_add_iterate_hook(lc, linphone_core_upnp_hook, lupnp);
return NULL;
}
- ip_address = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt);
- if(lupnp->sip_udp != NULL) {
- strncpy(lupnp->sip_udp->local_addr, ip_address, sizeof(lupnp->sip_udp->local_addr));
- }
- if(lupnp->sip_tcp != NULL) {
- strncpy(lupnp->sip_tcp->local_addr, ip_address, sizeof(lupnp->sip_tcp->local_addr));
- }
- if(lupnp->sip_tls != NULL) {
- strncpy(lupnp->sip_tls->local_addr, ip_address, sizeof(lupnp->sip_tls->local_addr));
- }
-
lupnp->state = LinphoneUpnpStatePending;
upnp_igd_start(lupnp->upnp_igd_ctxt);
}
void linphone_upnp_context_destroy(UpnpContext *lupnp) {
- /*
- * Not need, all hooks are removed before
- * linphone_core_remove_iterate_hook(lc, linphone_core_upnp_hook, lc);
- */
+ linphone_core_remove_iterate_hook(lupnp->lc, linphone_core_upnp_hook, lupnp);
ms_mutex_lock(&lupnp->mutex);
/* Send port binding removes */
if(lupnp->sip_udp != NULL) {
- linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_udp);
+ linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_udp, TRUE);
}
if(lupnp->sip_tcp != NULL) {
- linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tcp);
+ linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tcp, TRUE);
}
if(lupnp->sip_tls != NULL) {
- linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tls);
+ linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tls, TRUE);
}
/* Wait all pending bindings are done */
ms_message("uPnP IGD: Wait all pending port bindings ...");
ms_cond_wait(&lupnp->empty_cond, &lupnp->mutex);
}
- ms_mutex_unlock(&lupnp->mutex);
if(lupnp->upnp_igd_ctxt != NULL) {
upnp_igd_destroy(lupnp->upnp_igd_ctxt);
+ lupnp->upnp_igd_ctxt = NULL;
}
- /* Run one time the hook for configuration update */
- linphone_core_upnp_hook(lupnp);
+ /* Run one more time configuration update */
+ linphone_upnp_update_config(lupnp);
/* Release port bindings */
if(lupnp->sip_udp != NULL) {
lupnp->removing_configs = ms_list_free(lupnp->removing_configs);
ms_list_for_each(lupnp->pending_bindings,(void (*)(void*))linphone_upnp_port_binding_release);
lupnp->pending_bindings = ms_list_free(lupnp->pending_bindings);
+
+ ms_mutex_unlock(&lupnp->mutex);
ms_mutex_destroy(&lupnp->mutex);
ms_cond_destroy(&lupnp->empty_cond);
ms_free(lupnp);
}
-LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *ctx) {
- return ctx->state;
+LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *lupnp) {
+ LinphoneUpnpState state;
+ ms_mutex_lock(&lupnp->mutex);
+ state = lupnp->state;
+ ms_mutex_unlock(&lupnp->mutex);
+ return state;
+}
+
+bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) {
+ bool_t ready = TRUE;
+
+ // 1 Check global uPnP state
+ ready = (lupnp->state == LinphoneUpnpStateOk);
+
+ // 2 Check external ip address
+ if(ready) {
+ if (upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt) == NULL) {
+ ready = FALSE;
+ }
+ }
+
+ // 3 Check sip ports bindings
+ if(ready) {
+ if(lupnp->sip_udp != NULL) {
+ if(lupnp->sip_udp->state != LinphoneUpnpStateOk) {
+ ready = FALSE;
+ }
+ } else if(lupnp->sip_tcp != NULL) {
+ if(lupnp->sip_tcp->state != LinphoneUpnpStateOk) {
+ ready = FALSE;
+ }
+ } else if(lupnp->sip_tls != NULL) {
+ if(lupnp->sip_tls->state != LinphoneUpnpStateOk) {
+ ready = FALSE;
+ }
+ } else {
+ ready = FALSE;
+ }
+ }
+
+ return ready;
+}
+
+bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) {
+ bool_t ready;
+ ms_mutex_lock(&lupnp->mutex);
+ ready = _linphone_upnp_context_is_ready_for_register(lupnp);
+ ms_mutex_unlock(&lupnp->mutex);
+ return ready;
+}
+
+int linphone_upnp_context_get_external_port(UpnpContext *lupnp) {
+ int port = -1;
+ ms_mutex_lock(&lupnp->mutex);
+
+ if(lupnp->sip_udp != NULL) {
+ if(lupnp->sip_udp->state == LinphoneUpnpStateOk) {
+ port = lupnp->sip_udp->external_port;
+ }
+ } else if(lupnp->sip_tcp != NULL) {
+ if(lupnp->sip_tcp->state == LinphoneUpnpStateOk) {
+ port = lupnp->sip_tcp->external_port;
+ }
+ } else if(lupnp->sip_tls != NULL) {
+ if(lupnp->sip_tls->state == LinphoneUpnpStateOk) {
+ port = lupnp->sip_tls->external_port;
+ }
+ }
+
+ ms_mutex_unlock(&lupnp->mutex);
+ return port;
}
-const char* linphone_upnp_context_get_external_ipaddress(UpnpContext *ctx) {
- return upnp_igd_get_external_ipaddress(ctx->upnp_igd_ctxt);
+const char* linphone_upnp_context_get_external_ipaddress(UpnpContext *lupnp) {
+ const char* addr = NULL;
+ ms_mutex_lock(&lupnp->mutex);
+ addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt);
+ ms_mutex_unlock(&lupnp->mutex);
+ return addr;
}
-int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port) {
+int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry) {
upnp_igd_port_mapping mapping;
char description[128];
int ret;
return 0;
}
}
+
+ // No retry if specified
+ if(port->retry != 0 && !retry) {
+ return -1;
+ }
if(port->retry >= UPNP_ADD_MAX_RETRY) {
ret = -1;
return ret;
}
-int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port) {
+int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry) {
upnp_igd_port_mapping mapping;
int ret;
return 0;
}
}
+
+ // No retry if specified
+ if(port->retry != 0 && !retry) {
+ return 1;
+ }
if(port->retry >= UPNP_REMOVE_MAX_RETRY) {
ret = -1;
LinphoneCore *lc = call->core;
UpnpContext *lupnp = lc->upnp;
int ret = -1;
- const char *local_addr, *external_addr;
if(lupnp == NULL) {
return ret;
}
ms_mutex_lock(&lupnp->mutex);
+
// Don't handle when the call
if(lupnp->state == LinphoneUpnpStateOk && call->upnp_session != NULL) {
ret = 0;
- local_addr = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt);
- external_addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt);
/*
* Audio part
*/
- strncpy(call->upnp_session->audio->rtp->local_addr, local_addr, LINPHONE_IPADDR_SIZE);
- strncpy(call->upnp_session->audio->rtp->external_addr, external_addr, LINPHONE_IPADDR_SIZE);
- call->upnp_session->audio->rtp->local_port = call->audio_port;
- if(call->upnp_session->audio->rtp->external_port == -1) {
- call->upnp_session->audio->rtp->external_port = call->audio_port;
- }
- strncpy(call->upnp_session->audio->rtcp->local_addr, local_addr, LINPHONE_IPADDR_SIZE);
- strncpy(call->upnp_session->audio->rtcp->external_addr, external_addr, LINPHONE_IPADDR_SIZE);
- call->upnp_session->audio->rtcp->local_port = call->audio_port+1;
- if(call->upnp_session->audio->rtcp->external_port == -1) {
- call->upnp_session->audio->rtcp->external_port = call->audio_port+1;
- }
- if(audio) {
- // Add audio port binding
- linphone_upnp_context_send_add_port_binding(lupnp, call->upnp_session->audio->rtp);
- linphone_upnp_context_send_add_port_binding(lupnp, call->upnp_session->audio->rtcp);
- } else {
- // Remove audio port binding
- linphone_upnp_context_send_remove_port_binding(lupnp, call->upnp_session->audio->rtp);
- linphone_upnp_context_send_remove_port_binding(lupnp, call->upnp_session->audio->rtcp);
- }
+ linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp,
+ UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->audio_port:0, UPNP_CALL_RETRY_DELAY);
+ linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp,
+ UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->audio_port+1:0, UPNP_CALL_RETRY_DELAY);
+
/*
* Video part
*/
- strncpy(call->upnp_session->video->rtp->local_addr, local_addr, LINPHONE_IPADDR_SIZE);
- strncpy(call->upnp_session->video->rtp->external_addr, external_addr, LINPHONE_IPADDR_SIZE);
- call->upnp_session->video->rtp->local_port = call->video_port;
- if(call->upnp_session->video->rtp->external_port == -1) {
- call->upnp_session->video->rtp->external_port = call->video_port;
- }
- strncpy(call->upnp_session->video->rtcp->local_addr, local_addr, LINPHONE_IPADDR_SIZE);
- strncpy(call->upnp_session->video->rtcp->external_addr, external_addr, LINPHONE_IPADDR_SIZE);
- call->upnp_session->video->rtcp->local_port = call->video_port+1;
- if(call->upnp_session->video->rtcp->external_port == -1) {
- call->upnp_session->video->rtcp->external_port = call->video_port+1;
- }
- if(video) {
- // Add video port binding
- linphone_upnp_context_send_add_port_binding(lupnp, call->upnp_session->video->rtp);
- linphone_upnp_context_send_add_port_binding(lupnp, call->upnp_session->video->rtcp);
- } else {
- // Remove video port binding
- linphone_upnp_context_send_remove_port_binding(lupnp, call->upnp_session->video->rtp);
- linphone_upnp_context_send_remove_port_binding(lupnp, call->upnp_session->video->rtcp);
- }
+ linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp,
+ UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->video_port:0, UPNP_CALL_RETRY_DELAY);
+
+ linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp,
+ UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->video_port+1:0, UPNP_CALL_RETRY_DELAY);
}
ms_mutex_unlock(&lupnp->mutex);
}
+
int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md) {
bool_t audio = FALSE;
bool_t video = FALSE;
call->stats[LINPHONE_CALL_STATS_VIDEO].upnp_state = call->upnp_session->video->state;
}
+void linphone_upnp_update_stream_state(UpnpStream *stream) {
+ if((stream->rtp == NULL || stream->rtp->state == LinphoneUpnpStateOk || stream->rtp->state == LinphoneUpnpStateIdle) &&
+ (stream->rtcp == NULL || stream->rtcp->state == LinphoneUpnpStateOk || stream->rtcp->state == LinphoneUpnpStateIdle)) {
+ stream->state = LinphoneUpnpStateOk;
+ } else if((stream->rtp != NULL &&
+ (stream->rtp->state == LinphoneUpnpStateAdding || stream->rtp->state == LinphoneUpnpStateRemoving)) ||
+ (stream->rtcp != NULL &&
+ (stream->rtcp->state == LinphoneUpnpStateAdding || stream->rtcp->state == LinphoneUpnpStateRemoving))) {
+ stream->state = LinphoneUpnpStatePending;
+ } else if((stream->rtp != NULL && stream->rtp->state == LinphoneUpnpStateKo) ||
+ (stream->rtcp != NULL && stream->rtcp->state == LinphoneUpnpStateKo)) {
+ stream->state = LinphoneUpnpStateKo;
+ } else {
+ ms_error("Invalid stream %p state", stream);
+ }
+}
+
int linphone_upnp_call_process(LinphoneCall *call) {
LinphoneCore *lc = call->core;
UpnpContext *lupnp = lc->upnp;
/*
* Update Audio state
*/
- if((call->upnp_session->audio->rtp->state == LinphoneUpnpStateOk || call->upnp_session->audio->rtp->state == LinphoneUpnpStateIdle) &&
- (call->upnp_session->audio->rtcp->state == LinphoneUpnpStateOk || call->upnp_session->audio->rtcp->state == LinphoneUpnpStateIdle)) {
- call->upnp_session->audio->state = LinphoneUpnpStateOk;
- } else if(call->upnp_session->audio->rtp->state == LinphoneUpnpStateAdding ||
- call->upnp_session->audio->rtp->state == LinphoneUpnpStateRemoving ||
- call->upnp_session->audio->rtcp->state == LinphoneUpnpStateAdding ||
- call->upnp_session->audio->rtcp->state == LinphoneUpnpStateRemoving) {
- call->upnp_session->audio->state = LinphoneUpnpStatePending;
- } else if(call->upnp_session->audio->rtcp->state == LinphoneUpnpStateKo ||
- call->upnp_session->audio->rtp->state == LinphoneUpnpStateKo) {
- call->upnp_session->audio->state = LinphoneUpnpStateKo;
- } else {
- call->upnp_session->audio->state = LinphoneUpnpStateIdle;
- }
+ linphone_upnp_update_stream_state(call->upnp_session->audio);
/*
* Update Video state
*/
- if((call->upnp_session->video->rtp->state == LinphoneUpnpStateOk || call->upnp_session->video->rtp->state == LinphoneUpnpStateIdle) &&
- (call->upnp_session->video->rtcp->state == LinphoneUpnpStateOk || call->upnp_session->video->rtcp->state == LinphoneUpnpStateIdle)) {
- call->upnp_session->video->state = LinphoneUpnpStateOk;
- } else if(call->upnp_session->video->rtp->state == LinphoneUpnpStateAdding ||
- call->upnp_session->video->rtp->state == LinphoneUpnpStateRemoving ||
- call->upnp_session->video->rtcp->state == LinphoneUpnpStateAdding ||
- call->upnp_session->video->rtcp->state == LinphoneUpnpStateRemoving) {
- call->upnp_session->video->state = LinphoneUpnpStatePending;
- } else if(call->upnp_session->video->rtcp->state == LinphoneUpnpStateKo ||
- call->upnp_session->video->rtp->state == LinphoneUpnpStateKo) {
- call->upnp_session->video->state = LinphoneUpnpStateKo;
- } else {
- call->upnp_session->video->state = LinphoneUpnpStateIdle;
- }
+ linphone_upnp_update_stream_state(call->upnp_session->video);
+ /*
+ * Update stat
+ */
+ linphone_core_update_upnp_state_in_call_stats(call);
+
/*
* Update session state
*/
call->upnp_session->state = LinphoneUpnpStateIdle;
}
newState = call->upnp_session->state;
-
- /* When change is done proceed update */
- if(oldState != LinphoneUpnpStateOk && oldState != LinphoneUpnpStateKo &&
- (call->upnp_session->state == LinphoneUpnpStateOk || call->upnp_session->state == LinphoneUpnpStateKo)) {
- if(call->upnp_session->state == LinphoneUpnpStateOk)
- ms_message("uPnP IGD: uPnP for Call %p is ok", call);
- else
- ms_message("uPnP IGD: uPnP for Call %p is ko", call);
-
- switch (call->state) {
- case LinphoneCallUpdating:
- linphone_core_start_update_call(lc, call);
- break;
- case LinphoneCallUpdatedByRemote:
- linphone_core_start_accept_call_update(lc, call);
- break;
- case LinphoneCallOutgoingInit:
- linphone_core_proceed_with_invite_if_ready(lc, call, NULL);
- break;
- case LinphoneCallIdle:
- linphone_core_notify_incoming_call(lc, call);
- break;
- default:
- break;
- }
- }
}
ms_mutex_unlock(&lupnp->mutex);
-
- /*
- * Update uPnP call stats
- */
- if(oldState != newState) {
- linphone_core_update_upnp_state_in_call_stats(call);
+
+ /* When change is done proceed update */
+ if(oldState != LinphoneUpnpStateOk && oldState != LinphoneUpnpStateKo &&
+ (newState == LinphoneUpnpStateOk || newState == LinphoneUpnpStateKo)) {
+ if(call->upnp_session->state == LinphoneUpnpStateOk)
+ ms_message("uPnP IGD: uPnP for Call %p is ok", call);
+ else
+ ms_message("uPnP IGD: uPnP for Call %p is ko", call);
+
+ switch (call->state) {
+ case LinphoneCallUpdating:
+ linphone_core_start_update_call(lc, call);
+ break;
+ case LinphoneCallUpdatedByRemote:
+ linphone_core_start_accept_call_update(lc, call);
+ break;
+ case LinphoneCallOutgoingInit:
+ linphone_core_proceed_with_invite_if_ready(lc, call, NULL);
+ break;
+ case LinphoneCallIdle:
+ linphone_core_notify_incoming_call(lc, call);
+ break;
+ default:
+ break;
+ }
}
return ret;
ms_message("uPnP IGD: Refresh mappings");
- /* Remove context port bindings */
if(lupnp->sip_udp != NULL) {
global_list = ms_list_append(global_list, lupnp->sip_udp);
}
global_list = ms_list_append(global_list, lupnp->sip_tls);
}
- /* Remove call port bindings */
list = lupnp->lc->calls;
while(list != NULL) {
call = (LinphoneCall *)list->data;
if(call->upnp_session != NULL) {
- global_list = ms_list_append(global_list, call->upnp_session->audio->rtp);
- global_list = ms_list_append(global_list, call->upnp_session->audio->rtcp);
- global_list = ms_list_append(global_list, call->upnp_session->video->rtp);
- global_list = ms_list_append(global_list, call->upnp_session->video->rtcp);
+ if(call->upnp_session->audio->rtp != NULL) {
+ global_list = ms_list_append(global_list, call->upnp_session->audio->rtp);
+ }
+ if(call->upnp_session->audio->rtcp != NULL) {
+ global_list = ms_list_append(global_list, call->upnp_session->audio->rtcp);
+ }
+ if(call->upnp_session->video->rtp != NULL) {
+ global_list = ms_list_append(global_list, call->upnp_session->video->rtp);
+ }
+ if(call->upnp_session->video->rtcp != NULL) {
+ global_list = ms_list_append(global_list, call->upnp_session->video->rtcp);
+ }
}
list = list->next;
}
- // Remove port binding configurations
list = linphone_upnp_config_list_port_bindings(lupnp->lc->config);
for(item = list;item != NULL; item = item->next) {
port_mapping = (UpnpPortBinding *)item->data;
port_mapping2 = linphone_upnp_port_binding_equivalent_in_list(global_list, port_mapping);
if(port_mapping2 == NULL) {
- linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping);
+ linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, TRUE);
} else if(port_mapping2->state == LinphoneUpnpStateIdle){
/* Force to remove */
port_mapping2->state = LinphoneUpnpStateOk;
list = global_list;
while(list != NULL) {
port_mapping = (UpnpPortBinding *)list->data;
- linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping);
- linphone_upnp_context_send_add_port_binding(lupnp, port_mapping);
+ linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, TRUE);
+ linphone_upnp_context_send_add_port_binding(lupnp, port_mapping, TRUE);
list = list->next;
}
global_list = ms_list_free(global_list);
}
-bool_t linphone_core_upnp_hook(void *data) {
+void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay) {
+ const char *local_addr, *external_addr;
+ time_t now = time(NULL);
+ if(port != 0) {
+ if(*port_mapping != NULL) {
+ if(port != (*port_mapping)->local_port) {
+ linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE);
+ *port_mapping = NULL;
+ }
+ }
+ if(*port_mapping == NULL) {
+ *port_mapping = linphone_upnp_port_binding_new_or_collect(lupnp->pending_bindings, protocol, port, port);
+ }
+
+ // Get addresses
+ local_addr = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt);
+ external_addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt);
+
+ // Force binding update on local address change
+ if(local_addr != NULL) {
+ if(strncmp((*port_mapping)->local_addr, local_addr, sizeof((*port_mapping)->local_addr))) {
+ linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE);
+ strncpy((*port_mapping)->local_addr, local_addr, sizeof((*port_mapping)->local_addr));
+ }
+ }
+ if(external_addr != NULL) {
+ strncpy((*port_mapping)->external_addr, external_addr, sizeof((*port_mapping)->external_addr));
+ }
+
+ // Add (if not already done) the binding
+ if(now - (*port_mapping)->last_update >= retry_delay) {
+ (*port_mapping)->last_update = now;
+ linphone_upnp_context_send_add_port_binding(lupnp, *port_mapping, FALSE);
+ }
+ } else {
+ if(*port_mapping != NULL) {
+ linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE);
+ *port_mapping = NULL;
+ }
+ }
+}
+
+void linphone_upnp_update_config(UpnpContext* lupnp) {
char key[64];
- MSList *item;
+ const MSList *item;
UpnpPortBinding *port_mapping;
- UpnpContext *lupnp = (UpnpContext *)data;
- ms_mutex_lock(&lupnp->mutex);
-
+
/* Add configs */
for(item = lupnp->adding_configs;item!=NULL;item=item->next) {
port_mapping = (UpnpPortBinding *)item->data;
}
ms_list_for_each(lupnp->removing_configs,(void (*)(void*))linphone_upnp_port_binding_release);
lupnp->removing_configs = ms_list_free(lupnp->removing_configs);
+}
+
+bool_t linphone_core_upnp_hook(void *data) {
+ LCSipTransports transport;
+ LinphoneUpnpState ready_state;
+ const MSList *item;
+ time_t now = time(NULL);
+ UpnpContext *lupnp = (UpnpContext *)data;
+
+ ms_mutex_lock(&lupnp->mutex);
+
+ /* Update ports */
+ if(lupnp->state == LinphoneUpnpStateOk) {
+ linphone_core_get_sip_transports(lupnp->lc, &transport);
+ linphone_upnp_update_port_binding(lupnp, &lupnp->sip_udp, UPNP_IGD_IP_PROTOCOL_UDP, transport.udp_port, UPNP_CORE_RETRY_DELAY);
+ linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tcp, UPNP_IGD_IP_PROTOCOL_TCP, transport.tcp_port, UPNP_CORE_RETRY_DELAY);
+ linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tls, UPNP_IGD_IP_PROTOCOL_TCP, transport.tls_port, UPNP_CORE_RETRY_DELAY);
+ }
+
+ /* Refresh registers if we are ready */
+ if(now - lupnp->last_ready_check >= UPNP_CORE_READY_CHECK) {
+ lupnp->last_ready_check = now;
+ ready_state = (_linphone_upnp_context_is_ready_for_register(lupnp))? LinphoneUpnpStateOk: LinphoneUpnpStateKo;
+ if(ready_state != lupnp->last_ready_state) {
+ for(item=linphone_core_get_proxy_config_list(lupnp->lc);item!=NULL;item=item->next) {
+ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)item->data;
+ if (linphone_proxy_config_register_enabled(cfg)) {
+ if (ready_state != LinphoneUpnpStateOk) {
+ // Only reset ithe registration if we require that upnp should be ok
+ if(lupnp->lc->sip_conf.register_only_when_upnp_is_ok) {
+ linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone, "Registration impossible (uPnP not ready)");
+ }
+ } else {
+ cfg->commit=TRUE;
+ }
+ }
+ }
+ lupnp->last_ready_state = ready_state;
+ }
+ }
+
+ linphone_upnp_update_config(lupnp);
ms_mutex_unlock(&lupnp->mutex);
return TRUE;
upnpStream = session->video;
}
if(upnpStream != NULL) {
- if(upnpStream->rtp->state == LinphoneUpnpStateOk) {
+ if(upnpStream->rtp != NULL && upnpStream->rtp->state == LinphoneUpnpStateOk) {
strncpy(stream->rtp_addr, upnpStream->rtp->external_addr, LINPHONE_IPADDR_SIZE);
stream->rtp_port = upnpStream->rtp->external_port;
}
- if(upnpStream->rtcp->state == LinphoneUpnpStateOk) {
+ if(upnpStream->rtcp != NULL && upnpStream->rtcp->state == LinphoneUpnpStateOk) {
strncpy(stream->rtcp_addr, upnpStream->rtcp->external_addr, LINPHONE_IPADDR_SIZE);
stream->rtcp_port = upnpStream->rtcp->external_port;
}
port = ms_new0(UpnpPortBinding,1);
ms_mutex_init(&port->mutex, NULL);
port->state = LinphoneUpnpStateIdle;
+ port->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
port->local_addr[0] = '\0';
port->local_port = -1;
port->external_addr[0] = '\0';
port->to_remove = FALSE;
port->to_add = FALSE;
port->ref = 1;
+ port->last_update = 0;
return port;
}
+UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_protocol protocol, int local_port, int external_port) {
+ UpnpPortBinding *port_binding = linphone_upnp_port_binding_new();
+ port_binding->protocol = protocol;
+ port_binding->local_port = local_port;
+ port_binding->external_port = external_port;
+ return port_binding;
+}
+
+UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(MSList *list, upnp_igd_ip_protocol protocol, int local_port, int external_port) {
+ UpnpPortBinding *tmp_binding;
+ UpnpPortBinding *end_binding;
+ end_binding = linphone_upnp_port_binding_new_with_parameters(protocol, local_port, external_port);
+ tmp_binding = linphone_upnp_port_binding_equivalent_in_list(list, end_binding);
+ if(tmp_binding != NULL) {
+ linphone_upnp_port_binding_release(end_binding);
+ end_binding = tmp_binding;
+ }
+ return end_binding;
+}
+
UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port) {
UpnpPortBinding *new_port = NULL;
new_port = ms_new0(UpnpPortBinding,1);
UpnpStream* linphone_upnp_stream_new() {
UpnpStream *stream = ms_new0(UpnpStream,1);
stream->state = LinphoneUpnpStateIdle;
- stream->rtp = linphone_upnp_port_binding_new();
- stream->rtp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
- stream->rtcp = linphone_upnp_port_binding_new();
- stream->rtcp->protocol = UPNP_IGD_IP_PROTOCOL_UDP;
+ stream->rtp = NULL;
+ stream->rtcp = NULL;
return stream;
}
void linphone_upnp_stream_destroy(UpnpStream* stream) {
- linphone_upnp_port_binding_release(stream->rtp);
- stream->rtp = NULL;
- linphone_upnp_port_binding_release(stream->rtcp);
- stream->rtcp = NULL;
+ if(stream->rtp != NULL) {
+ linphone_upnp_port_binding_release(stream->rtp);
+ stream->rtp = NULL;
+ }
+ if(stream->rtcp != NULL) {
+ linphone_upnp_port_binding_release(stream->rtcp);
+ stream->rtcp = NULL;
+ }
ms_free(stream);
}
if(lc->upnp != NULL) {
/* Remove bindings */
- linphone_upnp_context_send_remove_port_binding(lc->upnp, session->audio->rtp);
- linphone_upnp_context_send_remove_port_binding(lc->upnp, session->audio->rtcp);
- linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtp);
- linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtcp);
+ if(session->audio->rtp != NULL) {
+ linphone_upnp_context_send_remove_port_binding(lc->upnp, session->audio->rtp, TRUE);
+ }
+ if(session->audio->rtcp != NULL) {
+ linphone_upnp_context_send_remove_port_binding(lc->upnp, session->audio->rtcp, TRUE);
+ }
+ if(session->video->rtp != NULL) {
+ linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtp, TRUE);
+ }
+ if(session->video->rtcp != NULL) {
+ linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtcp, TRUE);
+ }
}
linphone_upnp_stream_destroy(session->audio);
return session->state;
}
+
/*
* uPnP Config
*/
void linphone_upnp_context_destroy(UpnpContext *ctx);
LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *ctx);
const char *linphone_upnp_context_get_external_ipaddress(UpnpContext *ctx);
+int linphone_upnp_context_get_external_port(UpnpContext *ctx);
+bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *ctx);
void linphone_core_update_upnp_state_in_call_stats(LinphoneCall *call);
#endif //LINPHONE_UPNP_H
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="call_statistics">
+ <property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Call statistics</property>
<property name="type_hint">dialog</property>
- <signal name="response" handler="linphone_gtk_call_statistics_closed"/>
+ <signal name="response" handler="linphone_gtk_call_statistics_closed" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
- <property name="n_rows">6</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">7</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="audio_codec_label">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Audio codec</property>
</object>
<packing>
<child>
<object class="GtkLabel" id="video_codec_label">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Video codec</property>
</object>
<packing>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Audio IP bandwidth usage</property>
</object>
<packing>
<child>
<object class="GtkLabel" id="audio_codec">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<child>
<object class="GtkLabel" id="video_codec">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<child>
<object class="GtkLabel" id="audio_bandwidth_usage">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Audio Media connectivity</property>
</object>
<packing>
<child>
<object class="GtkLabel" id="audio_media_connectivity">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Video IP bandwidth usage</property>
</object>
<packing>
<child>
<object class="GtkLabel" id="video_bandwidth_usage">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">Video Media connectivity</property>
</object>
<packing>
<child>
<object class="GtkLabel" id="video_media_connectivity">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="bottom_attach">6</property>
</packing>
</child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">Round trip time</property>
+ </object>
+ <packing>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="round_trip_time">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ </packing>
+ </child>
</object>
</child>
</object>
<child type="label">
<object class="GtkLabel" id="call_statistics_label">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes"><b>Call statistics and information</b></property>
<property name="use_markup">True</property>
</object>
<property name="position">1</property>
</packing>
</child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <object class="GtkButton" id="button1">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
</object>
</child>
<action-widgets>
#define PADDING_PIXELS 4
+/*
+ * conferencee_box = a vbox where participants are added or removed
+ * conf_frame = the conference tab
+ */
+
static GtkWidget *create_conference_label(void){
GtkWidget *box=gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box),gtk_image_new_from_stock(GTK_STOCK_ADD,GTK_ICON_SIZE_MENU),FALSE,FALSE,0);
linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_core_get_conference_local_input_volume, linphone_gtk_get_core());
}
-static GtkWidget *get_conference_tab(GtkWidget *mw){
- GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conference_tab");
- GtkWidget *conf_frame=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conf_frame");
- if(conf_frame!=NULL){
- if (box==NULL){
- GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
- box=gtk_vbox_new(FALSE,0);
- GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame");
- gtk_box_set_homogeneous(GTK_BOX(box),TRUE);
- init_local_participant(participant);
- gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS);
- gtk_widget_show(box);
- g_object_set_data(G_OBJECT(mw),"conference_tab",box);
- gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS);
- }
- }
+static GtkWidget *get_conferencee_box(GtkWidget *mw){
+ GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conferencee_box");
return box;
}
static GtkWidget *find_conferencee_from_call(LinphoneCall *call){
GtkWidget *mw=linphone_gtk_get_main_window();
- get_conference_tab(mw);
- GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
- GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
+ GtkWidget *conferencee_box=get_conferencee_box(mw);
GList *elem;
GtkWidget *ret=NULL;
+
+ if (conferencee_box==NULL) return NULL;
+
if (call!=NULL){
- GList *l=gtk_container_get_children(GTK_CONTAINER(conf_box));
+ GList *l=gtk_container_get_children(GTK_CONTAINER(conferencee_box));
for(elem=l;elem!=NULL;elem=elem->next){
GtkWidget *frame=(GtkWidget*)elem->data;
if (call==g_object_get_data(G_OBJECT(frame),"call")){
return ret;
}
-void linphone_gtk_set_in_conference(LinphoneCall *call){
+static GtkWidget * create_conference_panel(void){
GtkWidget *mw=linphone_gtk_get_main_window();
+ GtkWidget *conf_frame=linphone_gtk_create_widget("main","conf_frame");
+ GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
+ GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf");
+ GtkWidget *image=create_pixmap("stopcall-small.png");
+ GtkWidget *box;
GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
+
+ gtk_button_set_image(GTK_BUTTON(button_conf),image);
+ g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL);
+ g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame);
+
+ box=gtk_vbox_new(FALSE,0);
+ GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame");
+ gtk_widget_show(participant);
+ gtk_box_set_homogeneous(GTK_BOX(box),TRUE);
+ init_local_participant(participant);
+ gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS);
+ gtk_widget_show(box);
+ g_object_set_data(G_OBJECT(mw),"conferencee_box",box);
+ gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS);
+
+ gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame,
+ create_conference_label());
+ return conf_frame;
+}
+
+void linphone_gtk_set_in_conference(LinphoneCall *call){
+ GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
- g_object_set_data(G_OBJECT(mw),"is_conf",GINT_TO_POINTER(TRUE));
+ GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
+
if(conf_frame==NULL){
- conf_frame=linphone_gtk_create_widget("main","conf_frame");
- GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf");
- GtkWidget *image=create_pixmap("stopcall-small.png");
- gtk_button_set_image(GTK_BUTTON(button_conf),image);
- g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL);
- g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame);
- gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame,
- create_conference_label());
+ conf_frame=create_conference_panel();
}
- GtkWidget *participant=find_conferencee_from_call(call);
- GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
+ GtkWidget *participant=find_conferencee_from_call(call);
+
if (participant==NULL){
- const LinphoneAddress *addr=linphone_call_get_remote_address(call);
- participant=linphone_gtk_create_widget("main","callee_frame");
+ /*create and add it */
+ GtkWidget *conferencee_box=get_conferencee_box(mw);
GtkWidget *sound_meter;
+ const LinphoneAddress *addr=linphone_call_get_remote_address(call);
gchar *markup;
+
+ participant=linphone_gtk_create_widget("main","callee_frame");
+ gtk_widget_show(participant);
if (linphone_address_get_display_name(addr)!=NULL){
markup=g_strdup_printf("<b>%s</b>",linphone_address_get_display_name(addr));
}else{
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),markup);
g_free(markup);
sound_meter=linphone_gtk_get_widget(participant,"sound_indicator");
- linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call);
- gtk_box_pack_start(GTK_BOX(conf_box),participant,FALSE,FALSE,PADDING_PIXELS);
+ linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call);
+ gtk_box_pack_start(GTK_BOX(conferencee_box),participant,FALSE,FALSE,PADDING_PIXELS);
g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref);
gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch),
- gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame));
+ gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame));
}
}
}
void linphone_gtk_unset_from_conference(LinphoneCall *call){
- GtkWidget *mw=linphone_gtk_get_main_window();
- GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
- GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
- GtkWidget *frame;
- if (conf_box==NULL) return; /*conference tab already destroyed*/
- frame=find_conferencee_from_call(call);
- GList *children;
+ GtkWidget *frame=find_conferencee_from_call(call);
+
if (frame){
+ GtkWidget *mw=linphone_gtk_get_main_window();
+ GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
+ GtkWidget *conferencee_box=g_object_get_data(G_OBJECT(mw),"conferencee_box");
+ GList *children;
+
+ g_message("Removing a participant from conference");
gtk_widget_destroy(frame);
+ children=gtk_container_get_children(GTK_CONTAINER(conferencee_box));
+ if (g_list_length(children)==1){ /* only local participant */
+ /*the conference is terminated */
+ g_message("The conference is terminated");
+ g_object_set_data(G_OBJECT(mw),"conferencee_box",NULL);
+ gtk_widget_destroy(conf_frame);
+ g_object_set_data(G_OBJECT(mw),"conf_frame",NULL);
+ }
+ g_list_free(children);
}
- children=gtk_container_get_children(GTK_CONTAINER(conf_box));
- if (g_list_length(children)==2){
- /*the conference is terminated */
- gtk_widget_destroy(conf_box);
- g_object_set_data(G_OBJECT(mw),"conference_tab",NULL);
- }
- gtk_widget_destroy(conf_frame);
- g_list_free(children);
- g_object_set_data(G_OBJECT(mw),"is_conf",GINT_TO_POINTER(FALSE));
- g_object_set_data(G_OBJECT(mw),"conf_frame",NULL);
}
+
+
if (page!=NULL){
LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(page),"call");
if (call==NULL){
- if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(main_window),"is_conf"))){
+ GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(main_window),"conf_frame");
+ if (conf_frame==page){
if (is_conf)
*is_conf=TRUE;
return NULL;
}
void update_tab_header(LinphoneCall *call,gboolean pause){
- GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call);
- GtkWidget *main_window=linphone_gtk_get_main_window();
- GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch"));
- gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index"));
- GtkWidget *new_label=gtk_hbox_new (FALSE,0);
- GtkWidget *i=NULL;
- if(pause){
-i=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_SMALL_TOOLBAR);
- } else {
- i=create_pixmap ("startcall-small.png");
- }
+ GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call);
+ GtkWidget *main_window=linphone_gtk_get_main_window();
+ GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch"));
+ gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index"));
+ GtkWidget *new_label=gtk_hbox_new (FALSE,0);
+ GtkWidget *i=NULL;
GtkWidget *l;
- gchar *text=g_strdup_printf(_("Call #%i"),call_index);
+ gchar *text;
+
+ if(pause){
+ i=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_SMALL_TOOLBAR);
+ } else {
+ i=create_pixmap ("startcall-small.png");
+ }
+
+ text=g_strdup_printf(_("Call #%i"),call_index);
l=gtk_label_new (text);
gtk_box_pack_start (GTK_BOX(new_label),i,FALSE,FALSE,0);
gtk_box_pack_end(GTK_BOX(new_label),l,TRUE,TRUE,0);
- gtk_notebook_set_tab_label(notebook,w,new_label);
- gtk_widget_show_all(new_label);
+ gtk_notebook_set_tab_label(notebook,w,new_label);
+ gtk_widget_show_all(new_label);
}
static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const char *image_name, gboolean is_stock){
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_transfer_call,other_call);
}
}
- gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,
- gtk_get_current_event_time());
+ gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
gtk_widget_show(menu);
}
gtk_widget_set_sensitive(button,FALSE);
g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame",NULL);
linphone_core_add_all_to_conference(linphone_gtk_get_core());
- //linphone_core_add_to_conference(linphone_gtk_get_core(),(LinphoneCall*)call_ref);
}
GtkWidget *acodec_ui=linphone_gtk_get_widget(callstats,"audio_codec");
GtkWidget *vcodec_ui=linphone_gtk_get_widget(callstats,"video_codec");
if (acodec){
-
char tmp[64]={0};
snprintf(tmp,sizeof(tmp)-1,"%s/%i/%i",acodec->mime_type,acodec->clock_rate,acodec->channels);
gtk_label_set_label(GTK_LABEL(acodec_ui),tmp);
static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){
const LinphoneCallStats *as=linphone_call_get_audio_stats(call);
const LinphoneCallStats *vs=linphone_call_get_video_stats(call);
- const char *audio_media_connectivity = _("Direct");
- const char *video_media_connectivity = _("Direct");
+ const char *audio_media_connectivity = _("Direct or through server");
+ const char *video_media_connectivity = _("Direct or through server");
+ gboolean has_video=linphone_call_params_video_enabled(linphone_call_get_current_params(call));
gchar *tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
as->download_bandwidth,as->upload_bandwidth);
+
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp);
g_free(tmp);
- tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
- vs->download_bandwidth,vs->upload_bandwidth);
+ if (has_video)
+ tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),vs->download_bandwidth,vs->upload_bandwidth);
+ else tmp=NULL;
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp);
- g_free(tmp);
+ if (tmp) g_free(tmp);
if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) {
audio_media_connectivity = upnp_state_to_string(as->upnp_state);
} else if(as->ice_state != LinphoneIceStateNotActivated) {
audio_media_connectivity = ice_state_to_string(as->ice_state);
}
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity);
- if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) {
- video_media_connectivity = upnp_state_to_string(vs->upnp_state);
- } else if(vs->ice_state != LinphoneIceStateNotActivated) {
- video_media_connectivity = ice_state_to_string(vs->ice_state);
- }
+
+ if (has_video){
+ if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) {
+ video_media_connectivity = upnp_state_to_string(vs->upnp_state);
+ } else if(vs->ice_state != LinphoneIceStateNotActivated) {
+ video_media_connectivity = ice_state_to_string(vs->ice_state);
+ }
+ }else video_media_connectivity=NULL;
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity);
+
+ if (as->round_trip_delay>0){
+ tmp=g_strdup_printf(_("%.3f seconds"),as->round_trip_delay);
+ gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp);
+ g_free(tmp);
+ }
}
static gboolean refresh_call_stats(GtkWidget *callstats){
if (in_conf){
linphone_gtk_set_in_conference(call);
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),FALSE);
+ }else{
+ linphone_gtk_unset_from_conference(call); /*in case it was previously*/
+ gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),TRUE);
}
gtk_widget_show_all(linphone_gtk_get_widget(callview,"buttons_panel"));
if (!in_conf) gtk_widget_show_all(linphone_gtk_get_widget(callview,"record_hbox"));
void linphone_gtk_record_call_toggled(GtkWidget *button){
gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
- LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
- GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call);
- const LinphoneCallParams *params=linphone_call_get_current_params(call);
- const char *filepath=linphone_call_params_get_record_file(params);
- gchar *message=g_strdup_printf(_("<small><i>Recording into %s %s</i></small>"),filepath,active ? "" : _("(Paused)"));
+ gboolean is_conf=FALSE;
+ const char *filepath;
+ gchar *message;
+ LinphoneCore *lc=linphone_gtk_get_core();
+ LinphoneCall *call=linphone_gtk_get_currently_displayed_call(&is_conf);
+ GtkWidget *callview;
+ GtkWidget *label;
+ if (call){
+ callview=(GtkWidget*)linphone_call_get_user_pointer (call);
+ const LinphoneCallParams *params=linphone_call_get_current_params(call);
+ filepath=linphone_call_params_get_record_file(params);
+ label=linphone_gtk_get_widget(callview,"record_status");
+ }else if (is_conf){
+ GtkWidget *mw=linphone_gtk_get_main_window();
+ callview=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
+ label=linphone_gtk_get_widget(callview,"conf_record_status");
+ filepath=(const char*)g_object_get_data(G_OBJECT(mw),"conf_record_path");
+ if (filepath==NULL){
+ filepath=linphone_gtk_get_record_path(NULL,TRUE);
+ g_object_set_data_full(G_OBJECT(mw),"conf_record_path",(char*)filepath,g_free);
+ }
+ }else{
+ g_warning("linphone_gtk_record_call_toggled(): bug.");
+ return;
+ }
+ message=g_strdup_printf(_("<small><i>Recording into\n%s %s</i></small>"),filepath,active ? "" : _("(Paused)"));
if (active){
- linphone_call_start_recording(call);
+ if (call)
+ linphone_call_start_recording(call);
+ else
+ linphone_core_start_conference_recording(lc,filepath);
}else {
- linphone_call_stop_recording(call);
+ if (call)
+ linphone_call_stop_recording(call);
+ else
+ linphone_core_stop_conference_recording(lc);
+
}
- gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callview,"record_status")),message);
+ gtk_label_set_markup(GTK_LABEL(label),message);
g_free(message);
}
void linphone_gtk_monitor_usb(void);
void linphone_gtk_unmonitor_usb(void);
+gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference);
+
}
}
-gchar *linphone_gtk_get_call_record_path(LinphoneAddress *address){
+gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference){
const char *dir=g_get_user_special_dir(G_USER_DIRECTORY_MUSIC);
- const char *id=linphone_address_get_username(address);
+ const char *id="unknown";
char filename[256]={0};
- if (id==NULL) id=linphone_address_get_domain(address);
- snprintf(filename,sizeof(filename)-1,"%s-%lu-%s-record.wav",
- linphone_gtk_get_ui_config("title","Linphone"),
- (unsigned long)time(NULL),id);
+ char date[64]={0};
+ time_t curtime=time(NULL);
+ struct tm loctime;
+
+#ifdef WIN32
+ loctime=*localtime(&curtime);
+#else
+ localtime_r(&curtime,&loctime);
+#endif
+ snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min);
+
+ if (address){
+ id=linphone_address_get_username(address);
+ if (id==NULL) id=linphone_address_get_domain(address);
+ }
+ if (is_conference){
+ snprintf(filename,sizeof(filename)-1,"%s-conference-%s.wav",
+ linphone_gtk_get_ui_config("title","Linphone"),
+ date);
+ }else{
+ snprintf(filename,sizeof(filename)-1,"%s-call-%s-%s.wav",
+ linphone_gtk_get_ui_config("title","Linphone"),
+ date,
+ id);
+ }
return g_build_filename(dir,filename,NULL);
}
if (addr!=NULL){
LinphoneCallParams *params=linphone_core_create_default_call_parameters(lc);
- gchar *record_file=linphone_gtk_get_call_record_path(addr);
+ gchar *record_file=linphone_gtk_get_record_path(addr,FALSE);
linphone_call_params_set_record_file(params,record_file);
linphone_core_invite_address_with_params(lc,addr,params);
completion_add_text(GTK_ENTRY(uri_bar),entered);
return FALSE;
}
+
+static void accept_incoming_call(LinphoneCall *call){
+ LinphoneCore *lc=linphone_gtk_get_core();
+ LinphoneCallParams *params=linphone_core_create_default_call_parameters(lc);
+ gchar *record_file=linphone_gtk_get_record_path(linphone_call_get_remote_address(call),FALSE);
+ linphone_call_params_set_record_file(params,record_file);
+ linphone_core_accept_call_with_params(lc,call,params);
+ linphone_call_params_destroy(params);
+}
+
static gboolean linphone_gtk_auto_answer(LinphoneCall *call){
- if (linphone_call_get_state(call)==LinphoneCallIncomingReceived){
- linphone_core_accept_call (linphone_gtk_get_core(),call);
+ LinphoneCallState state=linphone_call_get_state(call);
+ if (state==LinphoneCallIncomingReceived || state==LinphoneCallIncomingEarlyMedia){
+ accept_incoming_call(call);
linphone_call_unref(call);
}
return FALSE;
}
void linphone_gtk_start_call(GtkWidget *w){
- LinphoneCore *lc=linphone_gtk_get_core();
- LinphoneCall *call;
+ LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
/*change into in-call mode, then do the work later as it might block a bit */
GtkWidget *mw=gtk_widget_get_toplevel(w);
GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
+ LinphoneCallState state= call ? linphone_call_get_state(call) : LinphoneCallIdle;
- call=linphone_gtk_get_currently_displayed_call(NULL);
- if (call!=NULL && linphone_call_get_state(call)==LinphoneCallIncomingReceived){
- linphone_core_accept_call(lc,call);
+ if (state == LinphoneCallIncomingReceived || state == LinphoneCallIncomingEarlyMedia){
+ accept_incoming_call(call);
}else{
/*immediately disable the button and delay a bit the execution the linphone_core_invite()
so that we don't freeze the button. linphone_core_invite() might block for some hundreds of milliseconds*/
void linphone_gtk_answer_clicked(GtkWidget *button){
LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
if (call){
- linphone_core_accept_call(linphone_gtk_get_core(),call);
+ accept_incoming_call(call);
linphone_gtk_show_main_window(); /* useful when the button is clicked on a notification */
}
}
<object class="GtkVBox" id="conf_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
<child>
<object class="GtkHButtonBox" id="button_conf">
<property name="visible">True</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="conf_record_hbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToggleButton" id="conf_record_button">
+ <property name="label">gtk-media-record</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ <signal name="toggled" handler="linphone_gtk_record_call_toggled" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="conf_record_status">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">char</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
</object>
</child>
</object>
}
g_signal_connect(G_OBJECT(combo),"changed",(GCallback)linphone_gtk_media_encryption_changed,NULL);
}
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory")),linphone_core_is_media_encryption_mandatory(lc));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory")),
+ linphone_core_is_media_encryption_mandatory(lc));
g_object_unref(G_OBJECT(model));
}
if (pb==NULL) {
pb=linphone_gtk_create_window("parameters");
g_object_set_data(G_OBJECT(mw),"parameters",pb);
- ms_error("linphone_gtk_show_paramters: create");
}else {
gtk_widget_show(pb);
- ms_error("linphone_gtk_show_parameters: show");
return;
}
codec_list=linphone_gtk_get_widget(pb,"codec_list");
linphone_core_ipv6_enabled(lc));
linphone_core_get_sip_transports(lc,&tr);
- if (tr.tcp_port > 0) {
- gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
+ if (tr.tcp_port > 0) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.tcp_port);
- }
- else if (tr.tls_port > 0) {
- gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
+ }
+ else if (tr.tls_port > 0) {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.tls_port);
- }
- else {
- gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0);
- gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
+ }
+ else {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0);
+ gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.udp_port);
- }
+ }
linphone_core_get_audio_port_range(lc, &min_port, &max_port);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")), min_port);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_upnp")),TRUE);
break;
}
+ if(!linphone_core_upnp_available(lc)) {
+ gtk_widget_hide(linphone_gtk_get_widget(pb,"use_upnp"));
+ }
+
mtu=linphone_core_get_mtu(lc);
if (mtu<=0){
gtk_widget_set_sensitive(linphone_gtk_get_widget(pb,"mtu"),FALSE);
* @param aCall to be terminated
*/
public void terminateCall(LinphoneCall aCall);
+ /**
+ * Declines an incoming call, providing a reason for declining it.
+ */
+ public void declineCall(LinphoneCall aCall, Reason reason);
/**
* Returns The LinphoneCall the current call if one is in call
*
**/
void startEchoCalibration(Object data) throws LinphoneCoreException;
+ /**
+ * Returns true if echo calibration is recommended.
+ * If the device has a builtin echo canceller or calibration value is already known, it will return false.
+ */
+ boolean needsEchoCalibration();
+
void enableIpv6(boolean enable);
/**
* @deprecated
*/
void adjustSoftwareVolume(int i);
+ /**
+ * Pause a call.
+ **/
boolean pauseCall(LinphoneCall call);
+ /**
+ * Resume a call.
+ **/
boolean resumeCall(LinphoneCall call);
boolean pauseAllCalls();
void setZrtpSecretsCache(String file);
void enableEchoLimiter(boolean val);
+ /**
+ * Indicates whether the local user is part of the conference.
+ **/
boolean isInConference();
+ /**
+ * Connect the local user to the conference.
+ **/
boolean enterConference();
+ /**
+ * Disconnect the local user from the conference.
+ **/
void leaveConference();
+ /**
+ * Add an established call to the conference. The LinphoneCore is able to manage one client based conference.
+ **/
void addToConference(LinphoneCall call);
- void addAllToConference();
+ /**
+ * Remove an established call from the conference.
+ **/
void removeFromConference(LinphoneCall call);
-
+ void addAllToConference();
+
+ /**
+ * Terminate the conference, all users are disconnected.
+ **/
void terminateConference();
int getConferenceSize();
+
+ /**
+ * Request recording of the conference into a supplied file path.
+ * The format is wav.
+ **/
+ void startConferenceRecording(String path);
+ /**
+ * Stop recording of the conference.
+ **/
+ void stopConferenceRecording();
+
void terminateAllCalls();
+ /**
+ * Returns all calls.
+ **/
LinphoneCall[] getCalls();
int getCallsNb();
--- /dev/null
+package org.linphone.core;
+
+import java.util.Vector;
+
+public class Reason {
+ static private Vector<Reason> values = new Vector<Reason>();
+ /**
+ * None (no failure)
+ */
+ static public Reason None = new Reason(0,"None");
+ /**
+ * No response
+ */
+ static public Reason NoResponse = new Reason(1,"NoResponse");
+ /**
+ * Bad credentials
+ */
+ static public Reason BadCredentials = new Reason(2,"BadCredentials");
+ /**
+ * Call declined
+ */
+ static public Reason Declined = new Reason(3,"Declined");
+ /**
+ * Not found
+ */
+ static public Reason NotFound = new Reason(4,"NotFound");
+ /**
+ * Call not answered (in time).
+ */
+ static public Reason NotAnswered = new Reason(5,"NotAnswered");
+ /**
+ * Call not answered (in time).
+ */
+ static public Reason Busy = new Reason(6,"Busy");
+
+ protected final int mValue;
+ private final String mStringValue;
+
+
+ private Reason(int value,String stringValue) {
+ mValue = value;
+ values.addElement(this);
+ mStringValue=stringValue;
+ }
+ public static Reason fromInt(int value) {
+ for (int i=0; i<values.size();i++) {
+ Reason state = (Reason) values.elementAt(i);
+ if (state.mValue == value) return state;
+ }
+ throw new RuntimeException("Reason not found ["+value+"]");
+ }
+
+ public String toString() {
+ return mStringValue;
+ }
+}
setVideoPolicy(nativePtr, autoInitiate, autoAccept);
}
private native void setStaticPicture(long nativePtr, String path);
- public void setStaticPicture(String path) {
+ public synchronized void setStaticPicture(String path) {
setStaticPicture(nativePtr, path);
}
private native void setUserAgent(long nativePtr, String name, String version);
@Override
- public void setUserAgent(String name, String version) {
+ public synchronized void setUserAgent(String name, String version) {
setUserAgent(nativePtr,name,version);
}
private native void setCpuCountNative(int count);
- public void setCpuCount(int count)
+ public synchronized void setCpuCount(int count)
{
setCpuCountNative(count);
}
- public int getMissedCallsCount() {
+ public synchronized int getMissedCallsCount() {
return getMissedCallsCount(nativePtr);
}
- public void removeCallLog(LinphoneCallLog log) {
+ public synchronized void removeCallLog(LinphoneCallLog log) {
removeCallLog(nativePtr, ((LinphoneCallLogImpl) log).getNativePtr());
}
- public void resetMissedCallsCount() {
+ public synchronized void resetMissedCallsCount() {
resetMissedCallsCount(nativePtr);
}
}
private native void refreshRegisters(long nativePtr);
- public void refreshRegisters() {
+ public synchronized void refreshRegisters() {
refreshRegisters(nativePtr);
}
}
@Override
- public PayloadType findPayloadType(String mime, int clockRate) {
+ public synchronized PayloadType findPayloadType(String mime, int clockRate) {
return findPayloadType(mime, clockRate, 1);
}
private native void removeFriend(long ptr, long lf);
@Override
- public void removeFriend(LinphoneFriend lf) {
+ public synchronized void removeFriend(LinphoneFriend lf) {
removeFriend(nativePtr, lf.getNativePtr());
}
private native long getFriendByAddress(long ptr, String sipUri);
@Override
- public LinphoneFriend findFriendByAddress(String sipUri) {
+ public synchronized LinphoneFriend findFriendByAddress(String sipUri) {
long ptr = getFriendByAddress(nativePtr, sipUri);
if (ptr == 0) {
return null;
return new LinphoneFriendImpl(ptr);
}
- public void setAudioPort(int port) {
+ public synchronized void setAudioPort(int port) {
setAudioPort(nativePtr, port);
}
- public void setVideoPort(int port) {
+ public synchronized void setVideoPort(int port) {
setVideoPort(nativePtr, port);
}
- public void setAudioPortRange(int minPort, int maxPort) {
+ public synchronized void setAudioPortRange(int minPort, int maxPort) {
setAudioPortRange(nativePtr, minPort, maxPort);
}
- public void setVideoPortRange(int minPort, int maxPort) {
+ public synchronized void setVideoPortRange(int minPort, int maxPort) {
setVideoPortRange(nativePtr, minPort, maxPort);
}
- public void setIncomingTimeout(int timeout) {
+ public synchronized void setIncomingTimeout(int timeout) {
setIncomingTimeout(nativePtr, timeout);
}
- public void setInCallTimeout(int timeout)
+ public synchronized void setInCallTimeout(int timeout)
{
setInCallTimeout(nativePtr, timeout);
}
private native void setMicrophoneGain(long ptr, float gain);
- public void setMicrophoneGain(float gain) {
+ public synchronized void setMicrophoneGain(float gain) {
setMicrophoneGain(nativePtr, gain);
}
- public void setPrimaryContact(String displayName, String username) {
+ public synchronized void setPrimaryContact(String displayName, String username) {
setPrimaryContact(nativePtr, displayName, username);
}
private native void setUseSipInfoForDtmfs(long ptr, boolean use);
- public void setUseSipInfoForDtmfs(boolean use) {
+ public synchronized void setUseSipInfoForDtmfs(boolean use) {
setUseSipInfoForDtmfs(nativePtr, use);
}
private native void setUseRfc2833ForDtmfs(long ptr, boolean use);
- public void setUseRfc2833ForDtmfs(boolean use) {
+ public synchronized void setUseRfc2833ForDtmfs(boolean use) {
setUseRfc2833ForDtmfs(nativePtr, use);
}
private native long getConfig(long ptr);
- public LpConfig getConfig() {
+ public synchronized LpConfig getConfig() {
long configPtr=getConfig(nativePtr);
return new LpConfigImpl(configPtr);
}
+ private native boolean needsEchoCalibration(long ptr);
+ @Override
+ public synchronized boolean needsEchoCalibration() {
+ return needsEchoCalibration(nativePtr);
+ }
+ private native void declineCall(long coreptr, long callptr, int reason);
+ @Override
+ public synchronized void declineCall(LinphoneCall aCall, Reason reason) {
+ declineCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr,reason.mValue);
+ }
private native boolean upnpAvailable(long ptr);
public boolean upnpAvailable() {
public String getUpnpExternalIpaddress() {
return getUpnpExternalIpaddress(nativePtr);
}
+ private native int startConferenceRecording(long nativePtr, String path);
+ @Override
+ public void startConferenceRecording(String path) {
+ startConferenceRecording(nativePtr,path);
+ }
+
+ private native int stopConferenceRecording(long nativePtr);
+ @Override
+ public void stopConferenceRecording() {
+ stopConferenceRecording(nativePtr);
+ }
}
+++ /dev/null
-<?xml version = '1.0'?>
-<kdevelop>
- <general>
- <author>Simon Morlat</author>
- <email>simon.morlat@linphone.org</email>
- <version>[3.1.2]</version>
- <projectmanagement>KDevCustomProject</projectmanagement>
- <primarylanguage>C</primarylanguage>
- <ignoreparts/>
- <projectname>linphone</projectname>
- <projectdirectory>.</projectdirectory>
- <absoluteprojectpath>false</absoluteprojectpath>
- <description/>
- <defaultencoding/>
- </general>
- <kdevcustomproject>
- <run>
- <directoryradio>executable</directoryradio>
- <mainprogram>gtk-glade/linphone</mainprogram>
- <programargs/>
- <globaldebugarguments/>
- <globalcwd/>
- <useglobalprogram>false</useglobalprogram>
- <terminal>false</terminal>
- <autocompile>false</autocompile>
- <autoinstall>false</autoinstall>
- <autokdesu>false</autokdesu>
- <envvars/>
- </run>
- <filetypes>
- <filetype>*.java</filetype>
- <filetype>*.h</filetype>
- <filetype>*.H</filetype>
- <filetype>*.hh</filetype>
- <filetype>*.hxx</filetype>
- <filetype>*.hpp</filetype>
- <filetype>*.c</filetype>
- <filetype>*.C</filetype>
- <filetype>*.cc</filetype>
- <filetype>*.cpp</filetype>
- <filetype>*.c++</filetype>
- <filetype>*.cxx</filetype>
- </filetypes>
- <blacklist>
- <path>config.h</path>
- <path>exosip</path>
- <path>exosip/eXosip2.h</path>
- <path>exosip/eXosip.c</path>
- <path>exosip/eXosip_cfg.h</path>
- <path>exosip/eXosip.h</path>
- <path>exosip/eXutils.c</path>
- <path>exosip/jauth.c</path>
- <path>exosip/jcallback.c</path>
- <path>exosip/jcall.c</path>
- <path>exosip/jdialog.c</path>
- <path>exosip/jevents.c</path>
- <path>exosip/jfreinds.c</path>
- <path>exosip/jidentity.c</path>
- <path>exosip/jnotify.c</path>
- <path>exosip/jpipe.c</path>
- <path>exosip/jpipe.h</path>
- <path>exosip/jpublish.c</path>
- <path>exosip/jreg.c</path>
- <path>exosip/jrequest.c</path>
- <path>exosip/jresponse.c</path>
- <path>exosip/jsubscribe.c</path>
- <path>exosip/jsubscribers.c</path>
- <path>exosip/misc.c</path>
- <path>exosip/sdp_offans.c</path>
- <path>exosip/udp.c</path>
- <path>gnome</path>
- <path>gnome/addressbook.c</path>
- <path>gnome/addressbook.h</path>
- <path>gnome/applet.c</path>
- <path>gnome/callbacks.c</path>
- <path>gnome/callbacks.h</path>
- <path>gnome/friends.c</path>
- <path>gnome/friends.h</path>
- <path>gnome/gui_utils.c</path>
- <path>gnome/gui_utils.h</path>
- <path>gnome/interface.c</path>
- <path>gnome/interface.h</path>
- <path>gnome/linphone.c</path>
- <path>gnome/linphone.h</path>
- <path>gnome/main.c</path>
- <path>gnome/presence.c</path>
- <path>gnome/presence.h</path>
- <path>gnome/propertybox.c</path>
- <path>gnome/propertybox.h</path>
- <path>gnome/support.c</path>
- <path>gnome/support.h</path>
- <path>gsmlib</path>
- <path>gsmlib/code.c</path>
- <path>gsmlib/config.h</path>
- <path>gsmlib/debug.c</path>
- <path>gsmlib/decode.c</path>
- <path>gsmlib/gsmadd.c</path>
- <path>gsmlib/gsm_create.c</path>
- <path>gsmlib/gsm_decode.c</path>
- <path>gsmlib/gsm_destroy.c</path>
- <path>gsmlib/gsm_encode.c</path>
- <path>gsmlib/gsm_explode.c</path>
- <path>gsmlib/gsm.h</path>
- <path>gsmlib/gsm_implode.c</path>
- <path>gsmlib/gsm_option.c</path>
- <path>gsmlib/gsm_print.c</path>
- <path>gsmlib/gsm_wrapper.c</path>
- <path>gsmlib/gsm_wrapper.h</path>
- <path>gsmlib/long_term.c</path>
- <path>gsmlib/lpc.c</path>
- <path>gsmlib/preprocess.c</path>
- <path>gsmlib/private.h</path>
- <path>gsmlib/proto.h</path>
- <path>gsmlib/rpe.c</path>
- <path>gsmlib/short_term.c</path>
- <path>gsmlib/table.c</path>
- <path>gsmlib/toast.h</path>
- <path>gsmlib/unproto.h</path>
- <path>gtk</path>
- <path>gtk/addressbook.c</path>
- <path>gtk/addressbook.h</path>
- <path>gtk/applet.c</path>
- <path>gtk/callbacks.c</path>
- <path>gtk/callbacks.h</path>
- <path>gtk/friends.c</path>
- <path>gtk/friends.h</path>
- <path>gtk/gui_utils.c</path>
- <path>gtk/gui_utils.h</path>
- <path>gtk/interface.c</path>
- <path>gtk/interface.h</path>
- <path>gtk/linphone.c</path>
- <path>gtk/linphone.h</path>
- <path>gtk/main.c</path>
- <path>gtk/presence.c</path>
- <path>gtk/presence.h</path>
- <path>gtk/propertybox.c</path>
- <path>gtk/propertybox.h</path>
- <path>gtk/support.c</path>
- <path>gtk/support.h</path>
- <path>intl</path>
- <path>intl/bindtextdom.c</path>
- <path>intl/cat-compat.c</path>
- <path>intl/dcgettext.c</path>
- <path>intl/dgettext.c</path>
- <path>intl/explodename.c</path>
- <path>intl/finddomain.c</path>
- <path>intl/gettext.c</path>
- <path>intl/gettext.h</path>
- <path>intl/gettextP.h</path>
- <path>intl/hash-string.h</path>
- <path>intl/intl-compat.c</path>
- <path>intl/l10nflist.c</path>
- <path>intl/libgettext.h</path>
- <path>intl/loadinfo.h</path>
- <path>intl/loadmsgcat.c</path>
- <path>intl/localealias.c</path>
- <path>intl/textdomain.c</path>
- <path>lpc10-1.5</path>
- <path>lpc10-1.5/analys.c</path>
- <path>lpc10-1.5/bitio.c</path>
- <path>lpc10-1.5/bsynz.c</path>
- <path>lpc10-1.5/chanwr.c</path>
- <path>lpc10-1.5/dcbias.c</path>
- <path>lpc10-1.5/decode.c</path>
- <path>lpc10-1.5/deemp.c</path>
- <path>lpc10-1.5/difmag.c</path>
- <path>lpc10-1.5/dyptrk.c</path>
- <path>lpc10-1.5/encode.c</path>
- <path>lpc10-1.5/energy.c</path>
- <path>lpc10-1.5/f2c.h</path>
- <path>lpc10-1.5/f2clib.c</path>
- <path>lpc10-1.5/ham84.c</path>
- <path>lpc10-1.5/hp100.c</path>
- <path>lpc10-1.5/invert.c</path>
- <path>lpc10-1.5/irc2pc.c</path>
- <path>lpc10-1.5/ivfilt.c</path>
- <path>lpc10-1.5/lpc10.h</path>
- <path>lpc10-1.5/lpc10_wrapper.c</path>
- <path>lpc10-1.5/lpc10_wrapper.h</path>
- <path>lpc10-1.5/lpcdec.c</path>
- <path>lpc10-1.5/lpcenc.c</path>
- <path>lpc10-1.5/lpcini.c</path>
- <path>lpc10-1.5/lpfilt.c</path>
- <path>lpc10-1.5/median.c</path>
- <path>lpc10-1.5/mload.c</path>
- <path>lpc10-1.5/onset.c</path>
- <path>lpc10-1.5/pitsyn.c</path>
- <path>lpc10-1.5/placea.c</path>
- <path>lpc10-1.5/placev.c</path>
- <path>lpc10-1.5/preemp.c</path>
- <path>lpc10-1.5/prepro.c</path>
- <path>lpc10-1.5/random.c</path>
- <path>lpc10-1.5/rcchk.c</path>
- <path>lpc10-1.5/synths.c</path>
- <path>lpc10-1.5/tbdm.c</path>
- <path>lpc10-1.5/voicin.c</path>
- <path>lpc10-1.5/vparms.c</path>
- <path>media_api</path>
- <path>media_api/apitest.c</path>
- <path>media_api/apitest.h</path>
- <path>media_api/basiccall.c</path>
- <path>media_api/basiccall.h</path>
- <path>media_api/callmember.c</path>
- <path>media_api/callmember.h</path>
- <path>media_api/common.h</path>
- <path>media_api/media_api.c</path>
- <path>media_api/media_api.h</path>
- <path>media_api/mediaflow.c</path>
- <path>media_api/mediaflow.h</path>
- <path>mediastreamer</path>
- <path>mediastreamer/affine.c</path>
- <path>mediastreamer/affine.h</path>
- <path>mediastreamer/alsacard.c</path>
- <path>mediastreamer/alsacard.h</path>
- <path>mediastreamer/audiostream.c</path>
- <path>mediastreamer/g711common.h</path>
- <path>mediastreamer/hpuxsndcard.c</path>
- <path>mediastreamer/jackcard.c</path>
- <path>mediastreamer/jackcard.h</path>
- <path>mediastreamer/mediastream.c</path>
- <path>mediastreamer/mediastream.h</path>
- <path>mediastreamer/msAlawdec.c</path>
- <path>mediastreamer/msAlawdec.h</path>
- <path>mediastreamer/msAlawenc.c</path>
- <path>mediastreamer/msAlawenc.h</path>
- <path>mediastreamer/msavdecoder.c</path>
- <path>mediastreamer/msavdecoder.h</path>
- <path>mediastreamer/msavencoder.c</path>
- <path>mediastreamer/msavencoder.h</path>
- <path>mediastreamer/msbuffer.c</path>
- <path>mediastreamer/msbuffer.h</path>
- <path>mediastreamer/ms.c</path>
- <path>mediastreamer/mscodec.c</path>
- <path>mediastreamer/mscodec.h</path>
- <path>mediastreamer/mscopy.c</path>
- <path>mediastreamer/mscopy.h</path>
- <path>mediastreamer/msfdispatcher.c</path>
- <path>mediastreamer/msfdispatcher.h</path>
- <path>mediastreamer/msfifo.c</path>
- <path>mediastreamer/msfifo.h</path>
- <path>mediastreamer/msfilter.c</path>
- <path>mediastreamer/msfilter.h</path>
- <path>mediastreamer/msGSMdecoder.c</path>
- <path>mediastreamer/msGSMdecoder.h</path>
- <path>mediastreamer/msGSMencoder.c</path>
- <path>mediastreamer/msGSMencoder.h</path>
- <path>mediastreamer/ms.h</path>
- <path>mediastreamer/msLPC10decoder.c</path>
- <path>mediastreamer/msLPC10decoder.h</path>
- <path>mediastreamer/msLPC10encoder.c</path>
- <path>mediastreamer/msLPC10encoder.h</path>
- <path>mediastreamer/msMUlawdec.c</path>
- <path>mediastreamer/msMUlawdec.h</path>
- <path>mediastreamer/msMUlawenc.c</path>
- <path>mediastreamer/msMUlawenc.h</path>
- <path>mediastreamer/msnosync.c</path>
- <path>mediastreamer/msnosync.h</path>
- <path>mediastreamer/msossread.c</path>
- <path>mediastreamer/msossread.h</path>
- <path>mediastreamer/msosswrite.c</path>
- <path>mediastreamer/msosswrite.h</path>
- <path>mediastreamer/msqdispatcher.c</path>
- <path>mediastreamer/msqdispatcher.h</path>
- <path>mediastreamer/msqueue.c</path>
- <path>mediastreamer/msqueue.h</path>
- <path>mediastreamer/msread.c</path>
- <path>mediastreamer/msread.h</path>
- <path>mediastreamer/msringplayer.c</path>
- <path>mediastreamer/msringplayer.h</path>
- <path>mediastreamer/msrtprecv.c</path>
- <path>mediastreamer/msrtprecv.h</path>
- <path>mediastreamer/msrtpsend.c</path>
- <path>mediastreamer/msrtpsend.h</path>
- <path>mediastreamer/mssdlout.c</path>
- <path>mediastreamer/mssdlout.h</path>
- <path>mediastreamer/mssmpeg.c</path>
- <path>mediastreamer/mssmpeg.h</path>
- <path>mediastreamer/mssoundread.c</path>
- <path>mediastreamer/mssoundread.h</path>
- <path>mediastreamer/mssoundwrite.c</path>
- <path>mediastreamer/mssoundwrite.h</path>
- <path>mediastreamer/msspeexdec.c</path>
- <path>mediastreamer/msspeexdec.h</path>
- <path>mediastreamer/msspeexenc.c</path>
- <path>mediastreamer/msspeexenc.h</path>
- <path>mediastreamer/mssync.c</path>
- <path>mediastreamer/mssync.h</path>
- <path>mediastreamer/mstcpclient.c</path>
- <path>mediastreamer/mstcpclient.h</path>
- <path>mediastreamer/mstcpserv.c</path>
- <path>mediastreamer/mstcpserv.h</path>
- <path>mediastreamer/mstimer.c</path>
- <path>mediastreamer/mstimer.h</path>
- <path>mediastreamer/mstruespeechdecoder.c</path>
- <path>mediastreamer/mstruespeechdecoder.h</path>
- <path>mediastreamer/mstruespeechencoder.c</path>
- <path>mediastreamer/mstruespeechencoder.h</path>
- <path>mediastreamer/msutils.h</path>
- <path>mediastreamer/msv4l.c</path>
- <path>mediastreamer/msv4l.h</path>
- <path>mediastreamer/msvideooutput.c</path>
- <path>mediastreamer/msvideooutput.h</path>
- <path>mediastreamer/msvideosource.c</path>
- <path>mediastreamer/msvideosource.h</path>
- <path>mediastreamer/mswrite.c</path>
- <path>mediastreamer/mswrite.h</path>
- <path>mediastreamer/msxine.c</path>
- <path>mediastreamer/msxine.h</path>
- <path>mediastreamer/osscard.c</path>
- <path>mediastreamer/osscard.h</path>
- <path>mediastreamer/rfc2429.h</path>
- <path>mediastreamer/ring_test.c</path>
- <path>mediastreamer/sndcard.c</path>
- <path>mediastreamer/sndcard.h</path>
- <path>mediastreamer/test_alaw.c</path>
- <path>mediastreamer/test.c</path>
- <path>mediastreamer/test_gsm.c</path>
- <path>mediastreamer/test_lpc10.c</path>
- <path>mediastreamer/test_mulaw.c</path>
- <path>mediastreamer/test_rtprecv.c</path>
- <path>mediastreamer/test_smpeg.c</path>
- <path>mediastreamer/test_speex.c</path>
- <path>mediastreamer/test_truespeech.c</path>
- <path>mediastreamer/test_v4l.c</path>
- <path>mediastreamer/test_videostream.c</path>
- <path>mediastreamer/test_xine.c</path>
- <path>mediastreamer/videoclient.c</path>
- <path>mediastreamer/videoserver.c</path>
- <path>mediastreamer/videostream.c</path>
- <path>mediastreamer/waveheader.h</path>
- <path>po</path>
- <path>po/cat-id-tbl.c</path>
- <path>win32acm</path>
- <path>win32acm/afl.c</path>
- <path>win32acm/com.h</path>
- <path>win32acm/config.h</path>
- <path>win32acm/cpudetect.c</path>
- <path>win32acm/cpudetect.h</path>
- <path>win32acm/cputable.h</path>
- <path>win32acm/driver.c</path>
- <path>win32acm/driver.h</path>
- <path>win32acm/elfdll.c</path>
- <path>win32acm/ext.c</path>
- <path>win32acm/ext.h</path>
- <path>win32acm/ldt_keeper.c</path>
- <path>win32acm/ldt_keeper.h</path>
- <path>win32acm/loader.h</path>
- <path>win32acm/module.c</path>
- <path>win32acm/mp_msg.c</path>
- <path>win32acm/mp_msg.h</path>
- <path>win32acm/pe_image.c</path>
- <path>win32acm/pe_resource.c</path>
- <path>win32acm/registry.c</path>
- <path>win32acm/registry.h</path>
- <path>win32acm/resource.c</path>
- <path>win32acm/test_truespeech.c</path>
- <path>win32acm/win32.c</path>
- <path>win32acm/win32codec.c</path>
- <path>win32acm/win32codec.h</path>
- <path>win32acm/win32.h</path>
- <path>win32acm/wine</path>
- <path>win32acm/wine/basetsd.h</path>
- <path>win32acm/wine/debugtools.h</path>
- <path>win32acm/wine/driver.h</path>
- <path>win32acm/wine/elfdll.h</path>
- <path>win32acm/wine/heap.h</path>
- <path>win32acm/wine/ldt.h</path>
- <path>win32acm/wine/mmreg.h</path>
- <path>win32acm/wine/module.h</path>
- <path>win32acm/wine/msacmdrv.h</path>
- <path>win32acm/wine/msacm.h</path>
- <path>win32acm/wine/ntdef.h</path>
- <path>win32acm/wine/pe_image.h</path>
- <path>win32acm/wine/poppack.h</path>
- <path>win32acm/wine/pshpack1.h</path>
- <path>win32acm/wine/pshpack2.h</path>
- <path>win32acm/wine/pshpack4.h</path>
- <path>win32acm/wine/pshpack8.h</path>
- <path>win32acm/wine/vfw.h</path>
- <path>win32acm/wine/winbase.h</path>
- <path>win32acm/wine/windef.h</path>
- <path>win32acm/wine/windows.h</path>
- <path>win32acm/wine/winerror.h</path>
- <path>win32acm/wine/winestring.h</path>
- <path>win32acm/wine/winnt.h</path>
- <path>win32acm/wine/winreg.h</path>
- <path>win32acm/wine/winuser.h</path>
- <path>win32acm/wineacm.h</path>
- <path>win32acm/wrapper.h</path>
- <path>builddate.h</path>
- </blacklist>
- <build>
- <buildtool>make</buildtool>
- <builddir/>
- </build>
- <other>
- <prio>0</prio>
- <otherbin/>
- <defaulttarget/>
- <otheroptions/>
- <selectedenvironment>default</selectedenvironment>
- <environments>
- <default/>
- </environments>
- </other>
- <make>
- <abortonerror>true</abortonerror>
- <numberofjobs>0</numberofjobs>
- <prio>0</prio>
- <dontact>false</dontact>
- <makebin/>
- <defaulttarget/>
- <makeoptions/>
- <selectedenvironment>default</selectedenvironment>
- <environments>
- <default/>
- </environments>
- </make>
- </kdevcustomproject>
- <kdevdebugger>
- <general>
- <dbgshell/>
- <gdbpath/>
- <configGdbScript/>
- <runShellScript/>
- <runGdbScript/>
- <breakonloadinglibs>true</breakonloadinglibs>
- <separatetty>false</separatetty>
- <floatingtoolbar>false</floatingtoolbar>
- <raiseGDBOnStart>false</raiseGDBOnStart>
- </general>
- <display>
- <staticmembers>false</staticmembers>
- <demanglenames>true</demanglenames>
- <outputradix>10</outputradix>
- </display>
- </kdevdebugger>
- <kdevdoctreeview>
- <ignoretocs>
- <toc>ada</toc>
- <toc>ada_bugs_gcc</toc>
- <toc>bash</toc>
- <toc>bash_bugs</toc>
- <toc>clanlib</toc>
- <toc>fortran_bugs_gcc</toc>
- <toc>gnome1</toc>
- <toc>gnustep</toc>
- <toc>gtk</toc>
- <toc>gtk_bugs</toc>
- <toc>haskell</toc>
- <toc>haskell_bugs_ghc</toc>
- <toc>java_bugs_gcc</toc>
- <toc>java_bugs_sun</toc>
- <toc>kde2book</toc>
- <toc>libstdc++</toc>
- <toc>opengl</toc>
- <toc>pascal_bugs_fp</toc>
- <toc>php</toc>
- <toc>php_bugs</toc>
- <toc>perl</toc>
- <toc>perl_bugs</toc>
- <toc>python</toc>
- <toc>python_bugs</toc>
- <toc>qt-kdev3</toc>
- <toc>ruby</toc>
- <toc>ruby_bugs</toc>
- <toc>sdl</toc>
- <toc>stl</toc>
- <toc>sw</toc>
- <toc>w3c-dom-level2-html</toc>
- <toc>w3c-svg</toc>
- <toc>w3c-uaag10</toc>
- <toc>wxwidgets_bugs</toc>
- </ignoretocs>
- <ignoreqt_xml>
- <toc>Guide to the Qt Translation Tools</toc>
- <toc>Qt Assistant Manual</toc>
- <toc>Qt Designer Manual</toc>
- <toc>Qt Reference Documentation</toc>
- <toc>qmake User Guide</toc>
- </ignoreqt_xml>
- <ignoredoxygen>
- <toc>KDE Libraries (Doxygen)</toc>
- </ignoredoxygen>
- </kdevdoctreeview>
- <kdevfilecreate>
- <filetypes/>
- <useglobaltypes>
- <type ext="c" />
- <type ext="h" />
- </useglobaltypes>
- </kdevfilecreate>
- <kdevcppsupport>
- <qt>
- <used>false</used>
- <version>3</version>
- <includestyle>3</includestyle>
- <root></root>
- <designerintegration>EmbeddedKDevDesigner</designerintegration>
- <qmake></qmake>
- <designer></designer>
- <designerpluginpaths/>
- </qt>
- <references/>
- <codecompletion>
- <automaticCodeCompletion>false</automaticCodeCompletion>
- <automaticArgumentsHint>true</automaticArgumentsHint>
- <automaticHeaderCompletion>true</automaticHeaderCompletion>
- <codeCompletionDelay>250</codeCompletionDelay>
- <argumentsHintDelay>400</argumentsHintDelay>
- <headerCompletionDelay>250</headerCompletionDelay>
- <showOnlyAccessibleItems>false</showOnlyAccessibleItems>
- <completionBoxItemOrder>0</completionBoxItemOrder>
- <howEvaluationContextMenu>true</howEvaluationContextMenu>
- <showCommentWithArgumentHint>true</showCommentWithArgumentHint>
- <statusBarTypeEvaluation>false</statusBarTypeEvaluation>
- <namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
- <processPrimaryTypes>true</processPrimaryTypes>
- <processFunctionArguments>false</processFunctionArguments>
- <preProcessAllHeaders>false</preProcessAllHeaders>
- <parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
- <resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
- <alwaysParseInBackground>true</alwaysParseInBackground>
- <usePermanentCaching>true</usePermanentCaching>
- <alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
- <includePaths>.;</includePaths>
- </codecompletion>
- <creategettersetter>
- <prefixGet/>
- <prefixSet>set</prefixSet>
- <prefixVariable>m_,_</prefixVariable>
- <parameterName>theValue</parameterName>
- <inlineGet>true</inlineGet>
- <inlineSet>true</inlineSet>
- </creategettersetter>
- <splitheadersource>
- <enabled>false</enabled>
- <synchronize>true</synchronize>
- <orientation>Vertical</orientation>
- </splitheadersource>
- </kdevcppsupport>
- <kdevfileview>
- <groups>
- <hidenonprojectfiles>false</hidenonprojectfiles>
- <hidenonlocation>false</hidenonlocation>
- </groups>
- <tree>
- <hidepatterns>*.o,*.lo,CVS</hidepatterns>
- <hidenonprojectfiles>false</hidenonprojectfiles>
- </tree>
- </kdevfileview>
- <cppsupportpart>
- <filetemplates>
- <interfacesuffix>.h</interfacesuffix>
- <implementationsuffix>.cpp</implementationsuffix>
- </filetemplates>
- </cppsupportpart>
-</kdevelop>
-Subproject commit 44992c096673ace578ba5248db7019ba1e0d78d5
+Subproject commit 4ed2e518cf79c62fe8df7f23ce99e0fbfe2e799d