/*
linphone
-Copyright (C) 2010 Belledonne Communications SARL
+Copyright (C) 2010 Belledonne Communications SARL
(simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
LinphoneAddress *addr=linphone_address_new(me);
const char *username=linphone_address_get_username (addr);
SalMediaDescription *md=sal_media_description_new();
-
+
md->session_id=session_id;
md->session_ver=session_ver;
md->nstreams=1;
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,username,sizeof(md->username));
md->bandwidth=linphone_core_get_download_bandwidth(lc);
-
+
/*set audio capabilities */
strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr));
md->streams[0].port=call->audio_port;
pt=payload_type_clone(rtp_profile_get_payload_from_mime(&av_profile,"telephone-event"));
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
-
+
if (call->params.has_video){
md->nstreams++;
if (port_offset==-1) return;
call->audio_port=linphone_core_get_audio_port(call->core)+port_offset;
call->video_port=linphone_core_get_video_port(call->core)+port_offset;
-
+
}
static void discover_mtu(LinphoneCore *lc, const char *remote){
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
ms_free(from_str);
}
-
+
linphone_address_clean(from);
linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
linphone_call_init_common(call, from, to);
static void linphone_call_set_terminated(LinphoneCall *call){
LinphoneCore *lc=call->core;
-
+
linphone_core_update_allocated_audio_bandwidth(lc);
call->owns_call_log=FALSE;
linphone_call_log_completed(call);
-
-
+
+
if (call == lc->current_call){
ms_message("Resetting the current call");
lc->current_call=NULL;
if (linphone_core_del_call(lc,call) != 0){
ms_error("Could not remove the call from the list !!!");
}
-
+
if (ms_list_size(lc->calls)==0)
linphone_core_notify_all_friends(lc,lc->presence_mode);
-
+
}
const char *linphone_call_state_to_string(LinphoneCallState cs){
if (cstate == LinphoneCallConnected) {
call->log->status=LinphoneCallSuccess;
}
-
+
if (lc->vtable.call_state_changed)
lc->vtable.call_state_changed(lc,call,cstate,message);
if (cstate==LinphoneCallReleased){
* executed yet.
* Pending transfers are executed when this call is being paused or closed,
* locally or by remote endpoint.
- * If the call is already paused while receiving the transfer request, the
+ * If the call is already paused while receiving the transfer request, the
* transfer immediately occurs.
**/
bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){
LinphoneCore *lc=call->core;
SalMediaDescription *md=call->localdesc;
AudioStream *audiostream;
-
+
call->audiostream=audiostream=audio_stream_new(md->streams[0].port,linphone_core_ipv6_enabled(lc));
if (linphone_core_echo_limiter_enabled(lc)){
const char *type=lp_config_get_string(lc->config,"sound","el_type","mic");
int enabled=lp_config_get_int(lc->config,"sound","noisegate",0);
audio_stream_enable_noise_gate(audiostream,enabled);
}
-
+
if (lc->a_rtp)
rtp_session_set_transports(audiostream->session,lc->a_rtp,lc->a_rtcp);
float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05);
float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0);
int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0);
-
+
if (!call->audio_muted)
audio_stream_set_mic_gain(st,mic_gain);
- else
+ else
audio_stream_set_mic_gain(st,0);
recv_gain = lc->sound_conf.soft_play_lev;
LinphoneCore *lc=call->core;
int up_ptime=0;
*used_pt=-1;
-
+
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
PayloadType *pt=(PayloadType*)elem->data;
int number;
-
+
if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) {
if (desc->type==SalAudio){
linphone_core_update_allocated_audio_bandwidth_in_call(call,pt);
remote_bw=get_video_bandwidth(remote_bw,call->audio_bw);
}
}
-
- if (desc->type==SalAudio){
+
+ if (desc->type==SalAudio){
bw=get_min_bandwidth(call->audio_bw,remote_bw);
}else bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw);
if (bw>0) pt->normal_bitrate=bw*1000;
SalProtoRtpAvp,SalVideo);
#endif
bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
-
+
if(call->audiostream == NULL)
{
ms_fatal("start_media_stream() called without prior init !");
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalAudio);
if (stream && stream->dir!=SalStreamInactive && stream->port!=0){
- MSSndCard *playcard=lc->sound_conf.lsd_card ?
+ MSSndCard *playcard=lc->sound_conf.lsd_card ?
lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard;
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
const char *playfile=lc->play_file;
}
#ifdef VIDEO_ENABLED
{
-
+
used_pt=-1;
/* shutdown preview */
if (lc->previewstream!=NULL) {
bool_t is_inactive=FALSE;
call->current_params.has_video=TRUE;
-
+
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
video_stream_enable_self_view(call->videostream,lc->video_conf.selfview);
if (lc->video_window_id!=0)
if (lc->preview_window_id!=0)
video_stream_set_native_preview_window_id (call->videostream,lc->preview_window_id);
video_stream_use_preview_video_window (call->videostream,lc->use_preview_window);
-
+
if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
cam=get_nowebcam_device();
dir=VideoStreamSendOnly;
}
if (!is_inactive){
video_stream_set_direction (call->videostream, dir);
+ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation);
+ video_stream_set_device_rotation(call->videostream, lc->device_rotation);
video_stream_start(call->videostream,
call->video_profile, addr, vstream->port,
vstream->port+1,
call->all_muted=all_inputs_muted;
call->playing_ringbacktone=send_ringbacktone;
call->up_bw=linphone_core_get_upload_bandwidth(lc);
-
+
if (ortp_zrtp_available()) {
OrtpZrtpParams params;
params.zid=get_hexa_zrtp_identifier(lc);
call->videostream=NULL;
}
ms_event_queue_skip(call->core->msevq);
-
+
#endif
if (call->audio_profile){
rtp_profile_clear_all(call->audio_profile);
/**
* @addtogroup call_misc
* @{
-**/
+**/
/**
* Returns the measured sound volume played locally (received from remote)
- * It is expressed in dbm0.
+ * It is expressed in dbm0.
**/
float linphone_call_get_play_volume(LinphoneCall *call){
AudioStream *st=call->audiostream;
float vol=0;
ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol);
return vol;
-
+
}
return LINPHONE_VOLUME_DB_LOWEST;
}
/**
* Returns the measured sound volume recorded locally (sent to remote)
- * It is expressed in dbm0.
+ * It is expressed in dbm0.
**/
float linphone_call_get_record_volume(LinphoneCall *call){
AudioStream *st=call->audiostream;
float vol=0;
ms_filter_call_method(st->volrecv,MS_VOLUME_GET,&vol);
return vol;
-
+
}
return LINPHONE_VOLUME_DB_LOWEST;
}
* 1-2 = very poor quality <br>
* 0-1 = can't be worse, mostly unusable <br>
*
- * @returns The function returns -1 if no quality measurement is available, for example if no
+ * @returns The function returns -1 if no quality measurement is available, for example if no
* active audio stream exist. Otherwise it returns the quality rating.
**/
float linphone_call_get_current_quality(LinphoneCall *call){
{
snprintf(temp,sizeof(temp),"Remote end %s seems to have disconnected, the call is going to be closed.",from);
free(from);
- }
+ }
else
{
snprintf(temp,sizeof(temp),"Remote end seems to have disconnected, the call is going to be closed.");
void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){
int disconnect_timeout = linphone_core_get_nortp_timeout(call->core);
bool_t disconnected=FALSE;
-
+
if (call->state==LinphoneCallStreamsRunning && one_second_elapsed){
RtpSession *as=NULL,*vs=NULL;
float audio_load=0, video_load=0;
void linphone_call_log_completed(LinphoneCall *call){
LinphoneCore *lc=call->core;
-
+
call->log->duration=time(NULL)-call->start_time;
-
+
if (call->log->status==LinphoneCallMissed){
char *info;
lc->missed_calls++;
}
call_logs_write_to_config_file(lc);
}
-
-
return 0;
}
-
+
/*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)
LpConfig *cfg=lc->config;
if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return;
-
+
for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){
LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
snprintf(logsection,sizeof(logsection),"call_log_%i",i);
if (tmp) cl->refkey=ms_strdup(tmp);
cl->quality=lp_config_get_float(cfg,logsection,"quality",-1);
lc->call_logs=ms_list_append(lc->call_logs,cl);
- }else break;
+ }else break;
}
}
/**
* Returns a human readable string describing the call.
- *
+ *
* @note: the returned char* must be freed by the application (use ms_free()).
**/
char * linphone_call_log_to_str(LinphoneCallLog *cl){
/**
* Returns RTP statistics computed locally regarding the call.
- *
+ *
**/
const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){
return &cl->local_stats;
* @ingroup misc
*
* @param file a C FILE* where to fprintf logs. If null stdout is used.
- *
+ *
**/
void linphone_core_enable_logs(FILE *file){
if (file==NULL) file=stdout;
*
* @param logfunc The address of a OrtpLogFunc callback whose protoype is
* typedef void (*OrtpLogFunc)(OrtpLogLevel lev, const char *fmt, va_list args);
- *
+ *
**/
void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){
ortp_set_log_level_mask(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL);
lc->sound_conf.latency=0;
#if !defined(TARGET_OS_IPHONE) && !defined(ANDROID)
tmp=TRUE;
-#else
+#else
tmp=FALSE;
#endif
tmp=lp_config_get_int(lc->config,"sound","echocancellation",tmp);
break;
}
}
-
+
/*for tuning or test*/
lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0);
lc->sip_conf.register_only_when_network_is_up=
nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
linphone_core_set_nortp_timeout(lc,nortp_timeout);
rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE);
- linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_no_xmit_on_audio_mute);
+ linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_no_xmit_on_audio_mute);
}
static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, const char *recv_fmtp){
if (pt){
if (mtype==SalVideo && pt->type!=PAYLOAD_VIDEO)
pt=NULL;
- else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED
+ else if (mtype==SalAudio && (pt->type!=PAYLOAD_AUDIO_PACKETIZED
&& pt->type!=PAYLOAD_AUDIO_CONTINUOUS)){
pt=NULL;
}
lc->max_call_logs=lp_config_get_int(config,"misc","history_max_size",15);
}
-static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path,
+static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path,
const char *factory_config_path, void * userdata)
{
memset (lc, 0, sizeof (LinphoneCore));
lc->data=userdata;
lc->ringstream_autorelease=TRUE;
-
+
memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
lc->sal=sal_init();
sal_set_user_pointer(lc->sal,lc);
sal_set_callbacks(lc->sal,&linphone_sal_callbacks);
-
+
sip_setup_register_all();
sound_config_read(lc);
net_config_read(lc);
/**
* Instanciates a LinphoneCore object.
* @ingroup initializing
- *
+ *
* The LinphoneCore object is the primary handle for doing all phone actions.
* It should be unique within your application.
* @param vtable a LinphoneCoreVTable structure holding your application callbacks
* The config file is used to store all settings, call logs, friends, proxies... so that all these settings
* become persistent over the life of the LinphoneCore object.
* It is allowed to set a NULL config file. In that case LinphoneCore will not store any settings.
- * @param factory_config_path a path to a read-only config file that can be used to
+ * @param factory_config_path a path to a read-only config file that can be used to
* to store hard-coded preference such as proxy settings or internal preferences.
* The settings in this factory file always override the one in the normal config file.
* It is OPTIONAL, use NULL if unneeded.
* @param userdata an opaque user pointer that can be retrieved at any time (for example in
* callbacks) using linphone_core_get_user_data().
- *
+ *
**/
LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
const char *config_path, const char *factory_config_path, void * userdata)
**/
const char *linphone_core_get_primary_contact(LinphoneCore *lc){
char *identity;
-
+
if (lc->sip_conf.guess_hostname){
if (lc->sip_conf.guessed_contact==NULL || lc->sip_conf.loopback_only){
update_primary_contact(lc);
/**
* Sets the no-rtp timeout value in seconds.
- *
+ *
* @ingroup media_parameters
* See linphone_core_get_nortp_timeout() for details.
**/
* @ingroup network_parameters
**/
int linphone_core_set_sip_transports(LinphoneCore *lc, const LCSipTransports * tr){
-
+
if (transports_unchanged(tr,&lc->sip_conf.transports))
return 0;
memcpy(&lc->sip_conf.transports,tr,sizeof(*tr));
-
+
if (lc->sal==NULL) return 0;
return apply_transports(lc);
}
lc_callback_obj_invoke(&lc->preview_finished_cb,lc);
}
- if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0
+ if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0
&& (curtime-lc->dmfs_playing_start_time)>5){
ring_stop(lc->ringstream);
lc->ringstream=NULL;
* configuration, eventually escape the '+' by 00.
* - if no domain part is supplied, append the domain name of the default proxy
* - if no sip: is present, prepend it
- *
+ *
* The result is a syntaxically correct SIP address.
**/
LinphoneProxyConfig *proxy=lc->default_proxy;;
char *tmpurl;
LinphoneAddress *uri;
-
+
if (is_enum(url,&enum_domain)){
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Looking for telephone number destination..."));
return uri;
}
}
-
+
if (proxy!=NULL){
/* append the proxy domain suffix */
const char *identity=linphone_proxy_config_get_identity(proxy);
return ms_strdup(fixed_contact);
}
}
-
+
ctt=linphone_core_get_primary_contact_parsed(lc);
-
+
if (ctt!=NULL){
char *ret;
/*otherwise use supllied localip*/
char *contact;
char *real_url,*barmsg;
char *from;
-
+
/*try to be best-effort in giving real local or routable contact address */
contact=get_fixed_contact(lc,call,dest_proxy);
if (contact){
sal_op_set_contact(call->op, contact);
ms_free(contact);
}
-
+
//TODO : should probably not be done here
linphone_call_init_media_streams(call);
- if (!lc->sip_conf.sdp_200_ack){
+ if (!lc->sip_conf.sdp_200_ack){
call->media_pending=TRUE;
sal_call_set_local_media_description(call->op,call->localdesc);
}
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,barmsg);
ms_free(barmsg);
-
+
if (err<0){
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Could not call"));
* @ingroup call_control
* @param lc the LinphoneCore object
* @param addr the destination of the call (sip address).
- *
+ *
* The LinphoneAddress can be constructed directly using linphone_address_new(), or
* created by linphone_core_interpret_url().
* The application doesn't own a reference to the returned LinphoneCall object.
* @param lc the LinphoneCore object
* @param addr the destination of the call (sip address).
@param params call parameters
- *
+ *
* The LinphoneAddress can be constructed directly using linphone_address_new(), or
* created by linphone_core_interpret_url().
* The application doesn't own a reference to the returned LinphoneCall object.
char *real_url=NULL;
LinphoneProxyConfig *dest_proxy=NULL;
LinphoneCall *call;
-
+
if (linphone_core_in_call(lc)){
if (lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("Sorry, you have to pause or stop the current call first !"));
}
linphone_core_get_default_proxy(lc,&proxy);
route=linphone_core_get_route(lc);
-
+
real_url=linphone_address_as_string(addr);
dest_proxy=linphone_core_lookup_known_proxy(lc,addr);
call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),params);
sal_op_set_route(call->op,route);
-
+
if(linphone_core_add_call(lc,call)!= 0)
{
ms_warning("we had a problem in adding the call into the invite ... weird");
sal_op_set_user_pointer(call->ping_op,call);
call->start_time=time(NULL);
}
-
+
if (real_url!=NULL) ms_free(real_url);
return call;
}
* this method.
* @param lc the LinphoneCore object
* @param call the LinphoneCall object representing the call to be answered.
- *
+ *
**/
int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
{
const char *contact=NULL;
SalOp *replaced;
SalMediaDescription *new_md;
-
+
if (call==NULL){
//if just one call is present answer the only one ...
if(linphone_core_get_calls_nb (lc) != 1)
/*call already accepted*/
return -1;
}
-
+
/* check if this call is supposed to replace an already running one*/
replaced=sal_call_get_replaces(call->op);
if (replaced){
ms_warning("Cannot accept this call, there is already one running.");
return -1;
}
-
+
/*can accept a new call only if others are on hold */
{
MSList *elem;
ms_message("ring stopped");
lc->ringstream=NULL;
}
-
+
linphone_core_get_default_proxy(lc,&cfg);
dest_proxy=cfg;
dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
if (call->audiostream==NULL)
linphone_call_init_media_streams(call);
-
+
sal_call_accept(call->op);
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Connected."));
if (new_md){
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
}else call->media_pending=TRUE;
-
+
ms_message("call answered.");
return 0;
}
}
sal_call_terminate(call->op);
terminate_call(lc,call);
-
+
linphone_call_set_state(call,LinphoneCallEnd,"Call terminated");
return 0;
}
{
char temp[255]={0};
LinphoneCall *call = the_call;
-
+
if(call->state!=LinphoneCallPaused ){
ms_warning("we cannot resume a call that has not been established and paused before");
return -1;
}
linphone_call_set_state (call,LinphoneCallResuming,"Resuming");
snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call));
- if (lc->vtable.display_status)
+ if (lc->vtable.display_status)
lc->vtable.display_status(lc,temp);
return 0;
}
* Set the incoming call timeout in seconds.
*
* @ingroup call_control
- * If an incoming call isn't answered for this timeout period, it is
+ * If an incoming call isn't answered for this timeout period, it is
* automatically declined.
**/
void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds){
LinphoneOnlineStatus presence_mode)
{
if (minutes_away>0) lc->minutes_away=minutes_away;
-
+
if (lc->alt_contact!=NULL) {
ms_free(lc->alt_contact);
lc->alt_contact=NULL;
}
if (call->audiostream!=NULL){
audio_stream_set_mic_gain(call->audiostream,
- (val==TRUE) ? 0 : lp_config_get_float(lc->config,"sound","mic_gain",1));
+ (val==TRUE) ? 0 : lp_config_get_float(lc->config,"sound","mic_gain",1));
if ( linphone_core_get_rtp_no_xmit_on_audio_mute(lc) ){
audio_stream_mute_rtp(call->audiostream,val);
}
}
// returns rtp transmission status for an active stream
-// if audio is muted and config parameter rtp_no_xmit_on_audio_mute
+// if audio is muted and config parameter rtp_no_xmit_on_audio_mute
// was set on then rtp transmission is also muted
bool_t linphone_core_is_rtp_muted(LinphoneCore *lc){
LinphoneCall *call=linphone_core_get_current_call(lc);
ipstring, sizeof(ipstring), NULL, 0, NI_NUMERICHOST);
if (error) {
return lc->net_conf.nat_address;
- }
-
+ }
+
if (lc->net_conf.nat_address_ip!=NULL){
ms_free(lc->net_conf.nat_address_ip);
}
VideoStream *vs = NULL;
vs=get_active_video_stream(lc);
-
+
/* If we have a video stream (either preview, either from call), we
have a source and it is using the static picture filter, then
force the filter to use that picture. */
force the filter to use that picture. */
if (vs && vs->source) {
if (ms_filter_get_id(vs->source) == MS_STATIC_IMAGE_ID) {
-
+
float fps;
-
+
ms_filter_call_method(vs->source, MS_FILTER_GET_FPS,(void *)&fps);
return fps;
}
* If not set the core will create its own window.
**/
void linphone_core_set_native_preview_window_id(LinphoneCore *lc, unsigned long id){
-#ifdef VIDEO_ENABLED
lc->preview_window_id=id;
+#ifdef VIDEO_ENABLED
LinphoneCall *call=linphone_core_get_current_call(lc);
if (call!=NULL && call->videostream){
video_stream_set_native_preview_window_id(call->videostream,id);
lc->use_preview_window=yesno;
}
+/**
+ * Tells the core the device current orientation. This can be used by capture filters
+ * on mobile devices to select between portrait/landscape mode and to produce properly
+ * orientated images. The exact meaning of the value in rotation if left to each device
+ * specific implementations.
+ *
+**/
+void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) {
+ms_message("%s : rotation=%d\n", __FUNCTION__, rotation);
+ lc->device_rotation = rotation;
+#ifdef VIDEO_ENABLED
+ LinphoneCall *call=linphone_core_get_current_call(lc);
+ if (call!=NULL && call->videostream){
+ video_stream_set_device_rotation(call->videostream,rotation);
+ }
+#endif
+}
+
static MSVideoSizeDef supported_resolutions[]={
#ifdef ENABLE_HD
{ {MS_VIDEO_SIZE_1080P_W,MS_VIDEO_SIZE_1080P_H} , "1080p" },
/**
* Sets a wav file to be played when putting somebody on hold,
* or when files are used instead of soundcards (see linphone_core_use_files()).
- *
+ *
* The file must be a 16 bit linear wav file.
**/
void linphone_core_set_play_file(LinphoneCore *lc, const char *file){
/**
* Sets a wav file where incoming stream is to be recorded,
* when files are used instead of soundcards (see linphone_core_use_files()).
- *
+ *
* The file must be a 16 bit linear wav file.
**/
void linphone_core_set_record_file(LinphoneCore *lc, const char *file){
*
* @returns 0 or -1 if no call is running.
**/
-
+
int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote){
LinphoneCall *call=linphone_core_get_current_call (lc);
if (call!=NULL){
ms_free(lc->net_conf.nat_address_ip);
}
lp_config_set_int(lc->config,"net","firewall_policy",config->firewall_policy);
- lp_config_set_int(lc->config,"net","mtu",config->mtu);
+ lp_config_set_int(lc->config,"net","mtu",config->mtu);
}
lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL));
-
+
for(elem=config->proxies,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data);
linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
ms_list_free(config->proxies);
config->proxies=NULL;
-
+
linphone_proxy_config_write_to_config_file(lc->config,NULL,i); /*mark the end */
for(elem=lc->auth_info,i=0;elem!=NULL;elem=ms_list_next(elem),i++){
ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy);
ms_list_free(lc->auth_info);
lc->auth_info=NULL;
-
+
sal_uninit(lc->sal);
lc->sal=NULL;
ms_free(lc->sip_conf.guessed_contact);
if (config->contact)
ms_free(config->contact);
-
+
}
void rtp_config_uninit(LinphoneCore *lc)
}
sprintf(key,"audio_codec_%i",index);
lp_config_clean_section (lc->config,key);
-
+
index=0;
for(node=config->video_codecs;node!=NULL;node=ms_list_next(node)){
pt=(PayloadType*)(node->data);
}
sprintf(key,"video_codec_%i",index);
lp_config_clean_section (lc->config,key);
-
+
ms_list_free(lc->codecs_conf.audio_codecs);
ms_list_free(lc->codecs_conf.video_codecs);
}
* Returns the LpConfig object used to manage the storage (config) file.
*
* @ingroup misc
- * The application can use the LpConfig object to insert its own private
+ * The application can use the LpConfig object to insert its own private
* sections and pairs of key=value in the configuration file.
- *
+ *
**/
LpConfig *linphone_core_get_config(LinphoneCore *lc){
return lc->config;
{
MSList *it;
MSList *the_calls = lc->calls;
-
+
it=ms_list_find(the_calls,call);
- if (it)
+ if (it)
{
the_calls = ms_list_remove_link(the_calls,it);
}
bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) {
return sal_get_keepalive_period(lc->sal) > 0;
}
-
+
void linphone_core_start_dtmf_stream(LinphoneCore* lc) {
get_dtmf_gen(lc); /*make sure ring stream is started*/
lc->ringstream_autorelease=FALSE; /*disable autorelease mode*/
* The LinphoneAddress has methods to extract and manipulate all parts of the address.
* When some part of the address (for example the username) is empty, the accessor methods
* return NULL.
- *
+ *
* @ingroup linphone_address
* @var LinphoneAddress
*/
* Enum representing the status of a call
* @ingroup call_logs
**/
-typedef enum _LinphoneCallStatus {
+typedef enum _LinphoneCallStatus {
LinphoneCallSuccess, /**< The call was sucessful*/
LinphoneCallAborted, /**< The call was aborted */
LinphoneCallMissed, /**< The call was missed (unanswered)*/
* Structure representing a call log.
*
* @ingroup call_logs
- *
+ *
**/
typedef struct _LinphoneCallLog{
LinphoneCallDir dir; /**< The direction of the call*/
/**
* The LinphoneCallParams is an object containing various call related parameters.
- * It can be used to retrieve parameters from a currently running call or modify the call's characteristics
+ * It can be used to retrieve parameters from a currently running call or modify the call's characteristics
* dynamically.
**/
struct _LinphoneCallParams;
* different SIP domains.
*
* Once created and filled, a LinphoneAuthInfo must be added to the LinphoneCore in
- * order to become known and used automatically when needed.
+ * order to become known and used automatically when needed.
* Use linphone_core_add_auth_info() for that purpose.
*
* The LinphoneCore object can take the initiative to request authentication information
* when needed to the application through the auth_info_requested callback of the
* LinphoneCoreVTable structure.
*
- * The application can respond to this information request later using
- * linphone_core_add_auth_info(). This will unblock all pending authentication
+ * The application can respond to this information request later using
+ * linphone_core_add_auth_info(). This will unblock all pending authentication
* transactions and retry them with authentication headers.
*
**/
int linphone_core_set_relay_addr(LinphoneCore *lc, const char *addr);
/* sound functions */
-/* returns a null terminated static array of string describing the sound devices */
+/* returns a null terminated static array of string describing the sound devices */
const char** linphone_core_get_sound_devices(LinphoneCore *lc);
bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *device);
bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *device);
bool_t linphone_core_self_view_enabled(const LinphoneCore *lc);
-/* returns a null terminated static array of string describing the webcams */
+/* returns a null terminated static array of string describing the webcams */
const char** linphone_core_get_video_devices(const LinphoneCore *lc);
int linphone_core_set_video_device(LinphoneCore *lc, const char *id);
const char *linphone_core_get_video_device(const LinphoneCore *lc);
void linphone_core_set_native_preview_window_id(LinphoneCore *lc, unsigned long id);
void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno);
+void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation);
/*play/record support: use files instead of soundcard*/
void linphone_core_use_files(LinphoneCore *lc, bool_t yesno);
* force registration refresh to be initiated upon next iterate
* @ingroup proxies
*/
-void linphone_core_refresh_registers(LinphoneCore* lc);
+void linphone_core_refresh_registers(LinphoneCore* lc);
void linphone_call_send_vfu_request(LinphoneCall *call);
#include "linphonecore_utils.h"
#include <ortp/zrtp.h>
+extern "C" {
+#include "mediastreamer2/mediastream.h"
+}
#include "mediastreamer2/msjava.h"
-
+#include "private.h"
#include <cpu-features.h>
#ifdef ANDROID
linphone_core_set_native_video_window_id((LinphoneCore*)lc,(unsigned long)obj);
}
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPreviewWindowId(JNIEnv* env
+ ,jobject thiz
+ ,jlong lc
+ ,jobject obj) {
+ linphone_core_set_native_preview_window_id((LinphoneCore*)lc,(unsigned long)obj);
+}
+
+extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDeviceRotation(JNIEnv* env
+ ,jobject thiz
+ ,jlong lc
+ ,jint rotation) {
+ linphone_core_set_device_rotation((LinphoneCore*)lc,rotation);
+}
+
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFirewallPolicy(JNIEnv *env, jobject thiz, jlong lc, int enum_value){
linphone_core_set_firewall_policy((LinphoneCore*)lc,(LinphoneFirewallPolicy)enum_value);
linphone_call_enable_camera((LinphoneCall *)lc, (bool_t) b);
}
+extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_cameraEnabled(JNIEnv *env, jobject thiz, jlong lc){
+ linphone_call_camera_enabled((LinphoneCall *)lc);
+}
+
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_inviteAddressWithParams(JNIEnv *env, jobject thiz, jlong lc, jlong addr, jlong params){
return (jlong) linphone_core_invite_address_with_params((LinphoneCore *)lc, (const LinphoneAddress *)addr, (const LinphoneCallParams *)params);
}
extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getDuration(JNIEnv* env,jobject thiz,jlong ptr) {
linphone_call_get_duration((LinphoneCall *) ptr);
}
-
+
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getSignalingTransportPort(JNIEnv* env,jobject thiz,jlong ptr, jint code) {
LCSipTransports tr;
linphone_core_get_sip_transports((LinphoneCore *) ptr, &tr);
tr.udp_port = udp;
tr.tcp_port = tcp;
tr.tls_port = tls;
-
+
linphone_core_set_sip_transports(lc, &tr); // tr will be copied
}
}
}
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_setVideoDevice(JNIEnv *env,jobject thiz,jlong pCore,jint id) {
+ LinphoneCore* lc = (LinphoneCore *) pCore;
+ const char** devices = linphone_core_get_video_devices(lc);
+ if (devices == NULL) {
+ ms_error("No existing video devices\n");
+ return -1;
+ }
+ int i;
+ for(i=0; i<=id; i++) {
+ if (devices[i] == NULL)
+ break;
+ ms_message("Existing device %d : %s\n", i, devices[i]);
+ if (i==id) {
+ return linphone_core_set_video_device(lc, devices[i]);
+ }
+ }
+ return -1;
+}
+
+extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getVideoDevice(JNIEnv *env,jobject thiz,jlong pCore) {
+ LinphoneCore* lc = (LinphoneCore *) pCore;
+ const char** devices = linphone_core_get_video_devices(lc);
+ if (devices == NULL) {
+ ms_error("No existing video devices\n");
+ return -1;
+ }
+ const char* cam = linphone_core_get_video_device(lc);
+ if (cam == NULL) {
+ ms_error("No current video device\n");
+ } else {
+ int i=0;
+ while(devices[i] != NULL) {
+ if (strcmp(devices[i], cam) == 0)
+ return i;
+ i++;
+ }
+ }
+ ms_warning("Returning default (0) device\n");
+ return 0;
+}
+
extern "C" jstring Java_org_linphone_core_LinphoneCallImpl_getAuthenticationToken(JNIEnv* env,jobject thiz,jlong ptr) {
LinphoneCall *call = (LinphoneCall *) ptr;
const char* token = linphone_call_get_authentication_token(call);
msandroid_hack_speaker_state(speakerOn);
// End Galaxy S hack functions
}
-
void lsd_player_set_gain(LsdPlayer *p, float gain){
MSAudioMixerCtl gainctl;
gainctl.pin=p->mixer_pin;
- gainctl.gain=gain;
+ gainctl.param.gain=gain;
ms_filter_call_method(p->lsd->mixer,MS_AUDIO_MIXER_SET_INPUT_GAIN,&gainctl);
}
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-
+
#ifndef _PRIVATE_H
#define _PRIVATE_H
#endif
#include "mediastreamer2/mediastream.h"
-#ifndef LIBLINPHONE_VERSION
+#ifndef LIBLINPHONE_VERSION
#define LIBLINPHONE_VERSION LINPHONE_VERSION
#endif
-#ifndef PACKAGE_SOUND_DIR
+#ifndef PACKAGE_SOUND_DIR
#define PACKAGE_SOUND_DIR "."
#endif
LinphoneReason error;
};
-struct _LinphoneAuthInfo
+struct _LinphoneAuthInfo
{
char *username;
char *realm;
bool_t subscribe_active;
bool_t inc_subscribe_pending;
bool_t commit;
-};
+};
typedef struct sip_config
int audio_jitt_comp; /*jitter compensation*/
int video_jitt_comp; /*jitter compensation*/
int nortp_timeout;
- bool_t rtp_no_xmit_on_audio_mute;
+ bool_t rtp_no_xmit_on_audio_mute;
/* stop rtp xmit when audio muted */
}rtp_config_t;
bool_t auto_net_state_mon;
bool_t network_reachable;
bool_t use_preview_window;
+ int device_rotation;
bool_t ringstream_autorelease;
char* zrtp_secrets_cache;
};
linphone_gtk_update_call_buttons (call);
}
+static void update_registration_status(LinphoneProxyConfig *cfg, LinphoneRegistrationState rs){
+ GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
+ GtkTreeModel *model=gtk_combo_box_get_model(box);
+ GtkTreeIter iter;
+ gboolean found=FALSE;
+ const char *stock_id=NULL;
+
+ if (gtk_tree_model_get_iter_first(model,&iter)){
+ gpointer p;
+ do{
+ gtk_tree_model_get(model,&iter,2,&p,-1);
+ if (p==cfg) {
+ found=TRUE;
+ break;
+ }
+ }while(gtk_tree_model_iter_next(model,&iter));
+ }
+ if (!found) {
+ g_warning("Could not find proxy config in combo box of identities.");
+ return;
+ }
+ switch (rs){
+ case LinphoneRegistrationOk:
+ stock_id=GTK_STOCK_YES;
+ break;
+ case LinphoneRegistrationProgress:
+ stock_id=GTK_STOCK_REFRESH;
+ break;
+ case LinphoneRegistrationCleared:
+ stock_id=NULL;
+ break;
+ case LinphoneRegistrationFailed:
+ stock_id=GTK_STOCK_DIALOG_WARNING;
+ break;
+ default:
+ break;
+ }
+ gtk_list_store_set(GTK_LIST_STORE(model),&iter,1,stock_id,-1);
+}
+
static void linphone_gtk_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg,
LinphoneRegistrationState rs, const char *msg){
switch (rs){
default:
break;
}
+ update_registration_status(cfg,rs);
}
g_object_weak_ref(G_OBJECT(icon),(GWeakNotify)gtk_widget_destroy,menu);
}
+static void init_identity_combo(GtkComboBox *box){
+ GtkListStore *store;
+ GtkCellRenderer *r1,*r2;
+ store=gtk_list_store_new(3,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_POINTER);
+ gtk_cell_layout_clear(GTK_CELL_LAYOUT(box));
+ gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(box),(r1=gtk_cell_renderer_text_new()),TRUE);
+ gtk_cell_layout_pack_end(GTK_CELL_LAYOUT(box),(r2=gtk_cell_renderer_pixbuf_new()),FALSE);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(box),r1,"text",0);
+ gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(box),r2,"stock-id",1);
+ g_object_set(G_OBJECT(r1),"ellipsize",PANGO_ELLIPSIZE_END,NULL);
+ gtk_combo_box_set_model(box,GTK_TREE_MODEL(store));
+}
+
void linphone_gtk_load_identities(void){
const MSList *elem;
GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities"));
LinphoneProxyConfig *def=NULL;
int def_index=0,i;
GtkListStore *store;
+ GtkTreeIter iter;
store=GTK_LIST_STORE(gtk_combo_box_get_model(box));
+ if (gtk_tree_model_get_n_columns(GTK_TREE_MODEL(store))==1){
+ /* model is empty, this is the first time we go here */
+ init_identity_combo(box);
+ store=GTK_LIST_STORE(gtk_combo_box_get_model(box));
+ }
gtk_list_store_clear(store);
-
linphone_core_get_default_proxy(linphone_gtk_get_core(),&def);
def_identity=g_strdup_printf(_("%s (Default)"),linphone_core_get_primary_contact(linphone_gtk_get_core()));
- gtk_combo_box_append_text(box,def_identity);
+ gtk_list_store_append(store,&iter);
+ gtk_list_store_set(store,&iter,0,def_identity,1,NULL,2,NULL,-1);
g_free(def_identity);
for(i=1,elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core());
elem!=NULL;
elem=ms_list_next(elem),i++){
LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data;
- gtk_combo_box_append_text(box,linphone_proxy_config_get_identity(cfg));
+ gtk_list_store_append(store,&iter);
+ gtk_list_store_set(store,&iter,0,linphone_proxy_config_get_identity(cfg),1,
+ linphone_proxy_config_is_registered(cfg) ? GTK_STOCK_YES : NULL,
+ 2,cfg,-1);
if (cfg==def) {
def_index=i;
}
*/
package org.linphone.core;
-import java.util.Vector;
/**
* Object representing a Call. calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or passed to the application by listener {@link LinphoneCoreListener#callState(LinphoneCore, LinphoneCall, State, String)}
* Linphone call states
*
*/
- static class State {
- @SuppressWarnings("unchecked")
- static private Vector values = new Vector();
- private final int mValue;
- private final String mStringValue;
+ enum State {
/**
* Idle
*/
- public final static State Idle = new State(0,"Idle");
+ Idle(0, "Idle"),
/**
* Incoming call received.
*/
- public final static State IncomingReceived = new State(1,"IncomingReceived");
+ IncomingReceived(1, "IncomingReceived"),
/**
- * Outgoing call initialiazed.
+ * Outgoing call initialized.
*/
- public final static State OutgoingInit = new State(2,"OutgoingInit");
+ OutgoingInit(2, "OutgoingInit"),
/**
* Outgoing call in progress.
*/
- public final static State OutgoingProgress = new State(3,"OutgoingProgress");
+ OutgoingProgress(3, "OutgoingProgress"),
/**
* Outgoing call ringing.
*/
- public final static State OutgoingRinging = new State(4,"OutgoingRinging");
+ OutgoingRinging(4, "OutgoingRinging"),
/**
* Outgoing call early media
*/
- public final static State OutgoingEarlyMedia = new State(5,"OutgoingEarlyMedia");
+ OutgoingEarlyMedia(5, "OutgoingEarlyMedia"),
/**
* Connected
*/
- public final static State Connected = new State(6,"Connected");
+ Connected(6, "Connected"),
/**
* Streams running
*/
- public final static State StreamsRunning = new State(7,"StreamsRunning");
+ StreamsRunning(7, "StreamsRunning"),
/**
- * Paussing
+ * Pausing
*/
- public final static State Pausing = new State(8,"Pausing");
+ Pausing(8, "Pausing"),
/**
* Paused
*/
- public final static State Paused = new State(9,"Paused");
+ Paused(9, "Paused"),
/**
* Resuming
*/
- public final static State Resuming = new State(10,"Resuming");
+ Resuming(10, "Resuming"),
/**
* Refered
*/
- public final static State Refered = new State(11,"Refered");
+ Refered(11,"Refered"),
/**
* Error
*/
- public final static State Error = new State(12,"Error");
+ Error(12,"Error"),
/**
* Call end
*/
- public final static State CallEnd = new State(13,"CallEnd");
-
+ CallEnd(13,"CallEnd"),
/**
* Paused by remote
*/
- public final static State PausedByRemote = new State(14,"PausedByRemote");
-
+ PausedByRemote(14,"PausedByRemote"),
/**
* The call's parameters are updated, used for example when video is asked by remote
*/
- public static final State CallUpdatedByRemote = new State(15, "CallUpdatedByRemote");
-
+ CallUpdatedByRemote(15, "CallUpdatedByRemote"),
/**
* We are proposing early media to an incoming call
*/
- public static final State CallIncomingEarlyMedia = new State(16,"CallIncomingEarlyMedia");
-
+ CallIncomingEarlyMedia(16,"CallIncomingEarlyMedia"),
/**
* The remote accepted the call update initiated by us
*/
- public static final State CallUpdated = new State(17, "CallUpdated");
-
+ CallUpdated(17, "CallUpdated"),
/**
* The call object is now released.
*/
- public static final State CallReleased = new State(18,"CallReleased");
+ CallReleased(18,"CallReleased");
- @SuppressWarnings("unchecked")
- private State(int value,String stringValue) {
- mValue = value;
- values.addElement(this);
- mStringValue=stringValue;
+
+ private final int mValue;
+ private final String mStringValue;
+ private State(int v, String desc) {
+ this.mValue = v;
+ this.mStringValue = desc;
}
+
public static State fromInt(int value) {
-
- for (int i=0; i<values.size();i++) {
- State state = (State) values.elementAt(i);
- if (state.mValue == value) return state;
+ State[] allStates = State.values();
+ for (int i=0; i<allStates.length;i++) {
+ if (allStates[i].mValue == value)
+ return allStates[i];
}
throw new RuntimeException("state not found ["+value+"]");
}
LinphoneCallParams getCurrentParamsCopy();
void enableCamera(boolean enabled);
+ boolean cameraEnabled();
+
/**
* Enables or disable echo cancellation.
* @param enable
void setVideoWindow(Object w);
void setPreviewWindow(Object w);
+ void setDeviceRotation(int rotation);
+
+ void setVideoDevice(int id);
+ int getVideoDevice();
+
/**
* Enables video globally.
*
-Subproject commit 021c5cd8cca603c6e905ec6688a4deefa995358c
+Subproject commit 5ee91bbafef99fea6e56a31714af4eceaf0d6553