diff --git a/console/commands.c b/console/commands.c index 6f527831e..5fca480a6 100644 --- a/console/commands.c +++ b/console/commands.c @@ -287,10 +287,10 @@ static LPC_COMMAND advanced_commands[] = { "'codec list' : list audio codecs\n" "'codec enable ' : enable available audio codec\n" "'codec disable ' : disable audio codec" }, - { "vcodec", lpc_cmd_vcodec, "Video codec configuration", - "'vcodec list' : list video codecs\n" - "'vcodec enable ' : enable available video codec\n" - "'vcodec disable ' : disable video codec" }, + { "vcodec", lpc_cmd_vcodec, "Video codec configuration", + "'vcodec list' : list video codecs\n" + "'vcodec enable ' : enable available video codec\n" + "'vcodec disable ' : disable video codec" }, { "ec", lpc_cmd_echocancellation, "Echo cancellation", "'ec on [] [] []' : turn EC on with given delay, tail length and framesize\n" "'ec off' : turn echo cancellation (EC) off\n" diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c index b6ed5b77e..505ee95e3 100644 --- a/coreapi/bellesip_sal/sal_address_impl.c +++ b/coreapi/bellesip_sal/sal_address_impl.c @@ -208,6 +208,11 @@ void sal_address_set_uri_params(SalAddress *addr, const char *params){ belle_sip_parameters_set(parameters,params); } +bool_t sal_address_has_uri_param(SalAddress *addr, const char *name){ + belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr))); + return belle_sip_parameters_has_parameter(parameters, name); +} + void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value){ belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr)),header_name, header_value); } diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 265b237b8..8ff4fa08e 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -464,13 +464,13 @@ static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) { sal_auth_info_delete(auth_info); } -Sal * sal_init(){ +Sal * sal_init(MSFactory *factory){ belle_sip_listener_callbacks_t listener_callbacks; Sal * sal=ms_new0(Sal,1); /*belle_sip_object_enable_marshal_check(TRUE);*/ sal->auto_contacts=TRUE; - + sal->factory = factory; /*first create the stack, which initializes the belle-sip object's pool for this thread*/ belle_sip_set_log_handler(_belle_sip_log); sal->stack = belle_sip_stack_new(NULL); diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 9837e8078..d492d91e5 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -25,6 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "belle-sip/belle-sdp.h" struct Sal{ + MSFactory *factory; SalCallbacks callbacks; MSList *pending_auths;/*MSList of SalOp */ belle_sip_stack_t* stack; diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 482413d6d..7ff099f72 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -57,13 +57,13 @@ static void sdp_process(SalOp *h){ h->result=sal_media_description_new(); if (h->sdp_offering){ - offer_answer_initiate_outgoing(h->base.local_media,h->base.remote_media,h->result); + offer_answer_initiate_outgoing(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result); }else{ int i; if (h->sdp_answer){ belle_sip_object_unref(h->sdp_answer); } - offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); + offer_answer_initiate_incoming(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); /*for backward compatibility purpose*/ if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) { set_addr_to_0000(h->result->addr); diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c index 75f87a2d9..0c93ff2fa 100644 --- a/coreapi/bellesip_sal/sal_op_events.c +++ b/coreapi/bellesip_sal/sal_op_events.c @@ -236,15 +236,6 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event return -1; } -int sal_subscribe_refresh(SalOp *op) { - if (op->refresher) { - belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher)); - return 0; - } - ms_warning("sal_refresh_subscribe(): no refresher"); - return -1; -} - int sal_unsubscribe(SalOp *op){ if (op->refresher){ const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 88d6cf0f9..3fabb55ca 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -789,3 +789,11 @@ bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *op) { bool_t sal_op_is_forked_of(const SalOp *op1, const SalOp *op2){ return op1->base.call_id && op2->base.call_id && strcmp(op1->base.call_id, op2->base.call_id) == 0; } +int sal_op_refresh(SalOp *op) { + if (op->refresher) { + belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher)); + return 0; + } + ms_warning("sal_refresh on op [%p] of type [%s] no refresher",op,sal_op_type_to_string(op->type)); + return -1; +} diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c index a1dc85204..d5c16ff66 100644 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ b/coreapi/bellesip_sal/sal_op_publish.c @@ -25,17 +25,17 @@ static void publish_refresher_listener (belle_sip_refresher_t* refresher ,const char* reason_phrase) { SalOp* op = (SalOp*)user_pointer; const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); belle_sip_response_t *response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(last_publish_trans)); - /*belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));*/ ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",sal_op_get_proxy(op)); - if (status_code==412){ - /*resubmit the request after removing the SIP-If-Match*/ - belle_sip_message_remove_header((belle_sip_message_t*)last_publish,"SIP-If-Match"); - belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES); - }else if (status_code==0){ + if (status_code==0){ op->base.root->callbacks.on_expire(op); }else if (status_code>=200){ + belle_sip_header_t *sip_etag; + const char *sip_etag_string = NULL; + if ((sip_etag = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response), "SIP-ETag"))) { + sip_etag_string = belle_sip_header_get_unparsed_value(sip_etag); + } + sal_op_set_entity_tag(op, sip_etag_string); sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL); sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); op->base.root->callbacks.on_publish_response(op); @@ -60,42 +60,6 @@ void sal_op_publish_fill_cbs(SalOp *op) { op->type=SalOpPublish; } -/* - * Sending a publish with 0 expires removes the event state and such request shall not contain a body. - * See RFC3903, section 4.5 - */ - -/*presence publish */ -int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence){ - belle_sip_request_t *req=NULL; - if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - - op->type=SalOpPublish; - req=sal_op_build_request(op,"PUBLISH"); - - if( req == NULL ){ - return -1; - } - - if (sal_op_get_contact_address(op)){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event","presence")); - sal_add_presence_info(op,BELLE_SIP_MESSAGE(req),presence); - return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); - } else { - /*update presence status*/ - const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); - sal_add_presence_info(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? presence : NULL); - return belle_sip_refresher_refresh(op->refresher,expires); - } -} - int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ belle_sip_request_t *req=NULL; if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { @@ -109,7 +73,11 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna if( req == NULL ){ return -1; } - + + if (sal_op_get_entity_tag(op)) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("SIP-If-Match", sal_op_get_entity_tag(op))); + } + if (sal_op_get_contact_address(op)){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); } @@ -131,3 +99,14 @@ int sal_publish(SalOp *op, const char *from, const char *to, const char *eventna return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); } } + +int sal_op_unpublish(SalOp *op){ + if (op->refresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); + belle_sip_refresher_refresh(op->refresher,0); + return 0; + } + return -1; +} diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 26e207d79..b884bf224 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -405,7 +405,7 @@ static void start_remote_ring(LinphoneCore *lc, LinphoneCall *call) { if (call->audiostream) audio_stream_unprepare_sound(call->audiostream); if( lc->sound_conf.remote_ring ){ - lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); + lc->ringstream=ring_start(lc->factory, lc->sound_conf.remote_ring,2000,ringcard); } } } @@ -1038,10 +1038,11 @@ static void register_failure(SalOp *op){ } else { linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details); } - if (cfg->publish_op){ + if (cfg->long_term_event){ /*prevent publish to be sent now until registration gets successful*/ - sal_op_release(cfg->publish_op); - cfg->publish_op=NULL; + linphone_event_terminate(cfg->long_term_event); + linphone_event_unref(cfg->long_term_event); + cfg->long_term_event=NULL; cfg->send_publish=cfg->publish; } } @@ -1137,7 +1138,13 @@ static void parse_presence_requested(SalOp *op, const char *content_type, const } static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) { - linphone_notify_convert_presence_to_xml(op, presence, contact, content); + /*for backward compatibility because still used by notify. No loguer used for publish*/ + + if(linphone_presence_model_get_presentity((LinphonePresenceModel*)presence) == NULL) { + LinphoneAddress * presentity = linphone_address_new(contact); + linphone_presence_model_set_presentity((LinphonePresenceModel*)presence, presentity); + } + *content = linphone_presence_model_to_xml((LinphonePresenceModel*)presence); } static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg){ @@ -1303,7 +1310,7 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ }else if (status==SalSubscribePending){ linphone_event_set_state(lev,LinphoneSubscriptionPending); }else{ - if (lev->subscription_state==LinphoneSubscriptionActive && ei->reason==SalReasonIOError){ + if (lev->subscription_state==LinphoneSubscriptionActive && (ei->reason==SalReasonIOError || ei->reason == SalReasonNoMatch)){ linphone_event_set_state(lev,LinphoneSubscriptionOutgoingProgress); } else linphone_event_set_state(lev,LinphoneSubscriptionError); diff --git a/coreapi/conference.cc b/coreapi/conference.cc index 57bc27c1e..fee935b82 100644 --- a/coreapi/conference.cc +++ b/coreapi/conference.cc @@ -32,31 +32,39 @@ namespace Linphone { -class Participant { -public: - Participant(LinphoneCall *call); - Participant(const Participant &src); - ~Participant(); - bool operator==(const Participant &src) const; - const LinphoneAddress *getUri() const {return m_uri;} - LinphoneCall *getCall() const {return m_call;} - void setCall(LinphoneCall *call) {m_call = call;} - -private: - LinphoneAddress *m_uri; - LinphoneCall *m_call; -}; - class Conference { public: + class Participant { + public: + Participant(LinphoneCall *call); + Participant(const Participant &src); + ~Participant(); + bool operator==(const Participant &src) const; + const LinphoneAddress *getUri() const {return m_uri;} + LinphoneCall *getCall() const {return m_call;} + void setCall(LinphoneCall *call) {m_call = call;} + + private: + LinphoneAddress *m_uri; + LinphoneCall *m_call; + }; + class Params { public: Params(const LinphoneCore *core = NULL); void enableVideo(bool enable) {m_enableVideo = enable;} bool videoRequested() const {return m_enableVideo;} + void setStateChangedCallback(LinphoneConferenceStateChangedCb cb, void *user_data) { + m_state_changed_cb=cb; + m_user_data=user_data; + } private: bool m_enableVideo; + LinphoneConferenceStateChangedCb m_state_changed_cb; + void *m_user_data; + + friend class Conference; }; Conference(LinphoneCore *core, const Params *params = NULL); @@ -88,14 +96,19 @@ public: virtual void onCallStreamStopping(LinphoneCall *call) {}; virtual void onCallTerminating(LinphoneCall *call) {}; + LinphoneConferenceState getState() const {return m_state;} + static const char *stateToString(LinphoneConferenceState state); + protected: const Participant *findParticipant(const LinphoneAddress* uri) const; + void setState(LinphoneConferenceState state); LinphoneCore *m_core; AudioStream *m_localParticipantStream; bool m_isMuted; std::list m_participants; Params m_currentParams; + LinphoneConferenceState m_state; }; class LocalConference: public Conference { @@ -153,12 +166,9 @@ public: virtual int stopRecording() {return 0;} private: - enum State { - NotConnectedToFocus, - ConnectingToFocus, - ConnectedToFocus, - }; - static const char *stateToString(State state); + bool focusIsReady() const; + bool transferToFocus(LinphoneCall *call); + void reset(); void onFocusCallSateChanged(LinphoneCallState state); void onPendingCallStateChanged(LinphoneCall *call, LinphoneCallState state); @@ -170,10 +180,10 @@ private: const char *m_focusAddr; char *m_focusContact; LinphoneCall *m_focusCall; - State m_state; LinphoneCoreVTable *m_vtable; MSList *m_pendingCalls; MSList *m_transferingCalls; + bool m_isTerminating; }; }; @@ -183,22 +193,22 @@ using namespace Linphone; using namespace std; -Participant::Participant(LinphoneCall *call) { +Conference::Participant::Participant(LinphoneCall *call) { m_uri = linphone_address_clone(linphone_call_get_remote_address(call)); m_call = linphone_call_ref(call); } -Participant::Participant(const Participant &src) { +Conference::Participant::Participant(const Participant &src) { m_uri = linphone_address_clone(src.m_uri); m_call = src.m_call ? linphone_call_ref(src.m_call) : NULL; } -Participant::~Participant() { +Conference::Participant::~Participant() { linphone_address_unref(m_uri); if(m_call) linphone_call_unref(m_call); } -bool Participant::operator==(const Participant &src) const { +bool Conference::Participant::operator==(const Participant &src) const { return linphone_address_equal(m_uri, src.m_uri); } @@ -216,7 +226,9 @@ Conference::Params::Params(const LinphoneCore *core): m_enableVideo(false) { Conference::Conference(LinphoneCore *core, const Conference::Params *params): m_core(core), m_localParticipantStream(NULL), - m_isMuted(false) { + m_isMuted(false), + m_currentParams(), + m_state(LinphoneConferenceStopped) { if(params) m_currentParams = *params; } @@ -275,7 +287,19 @@ float Conference::getInputVolume() const { return LINPHONE_VOLUME_DB_LOWEST; } -const Participant *Conference::findParticipant(const LinphoneAddress *uri) const { +const char *Conference::stateToString(LinphoneConferenceState state) { + switch(state) { + case LinphoneConferenceStopped: return "Stopped"; + case LinphoneConferenceStarting: return "Starting"; + case LinphoneConferenceReady: return "Ready"; + case LinphoneConferenceStartingFailed: return "Startig failed"; + default: return "Invalid state"; + } +} + + + +const Conference::Participant *Conference::findParticipant(const LinphoneAddress *uri) const { list::const_iterator it = m_participants.begin(); while(it!=m_participants.end()) { if(linphone_address_equal(uri, it->getUri())) break; @@ -285,6 +309,17 @@ const Participant *Conference::findParticipant(const LinphoneAddress *uri) const else return &*it; } +void Conference::setState(LinphoneConferenceState state) { + if(m_state != state) { + ms_message("Switching conference [%p] into state '%s'", this, stateToString(state)); + m_state = state; + if(m_currentParams.m_state_changed_cb) { + m_currentParams.m_state_changed_cb((LinphoneConference *)this, state, m_currentParams.m_user_data); + } + } +} + + LocalConference::LocalConference(LinphoneCore *core, const Conference::Params *params): @@ -294,9 +329,11 @@ LocalConference::LocalConference(LinphoneCore *core, const Conference::Params *p m_recordEndpoint(NULL), m_localDummyProfile(NULL), m_terminated(FALSE) { + MSAudioConferenceParams ms_conf_params; ms_conf_params.samplerate = lp_config_get_int(m_core->config, "sound","conference_rate",16000); - m_conf=ms_audio_conference_new(&ms_conf_params); + m_conf=ms_audio_conference_new(&ms_conf_params, core->factory); + m_state=LinphoneConferenceReady; } LocalConference::~LocalConference() { @@ -315,7 +352,7 @@ RtpProfile *LocalConference::sMakeDummyProfile(int samplerate){ void LocalConference::addLocalEndpoint() { /*create a dummy audiostream in order to extract the local part of it */ /* network address and ports have no meaning and are not used here. */ - AudioStream *st=audio_stream_new(65000,65001,FALSE); + AudioStream *st=audio_stream_new(m_core->factory, 65000,65001,FALSE); MSSndCard *playcard=m_core->sound_conf.lsd_card ? m_core->sound_conf.lsd_card : m_core->sound_conf.play_sndcard; MSSndCard *captcard=m_core->sound_conf.capt_sndcard; @@ -527,7 +564,7 @@ int LocalConference::startRecording(const char *path) { return -1; } if (m_recordEndpoint==NULL){ - m_recordEndpoint=ms_audio_endpoint_new_recorder(); + m_recordEndpoint=ms_audio_endpoint_new_recorder(m_core->factory); ms_audio_conference_add_member(m_conf,m_recordEndpoint); } ms_audio_recorder_endpoint_start(m_recordEndpoint,path); @@ -585,10 +622,10 @@ RemoteConference::RemoteConference(LinphoneCore *core, const Conference::Params m_focusAddr(NULL), m_focusContact(NULL), m_focusCall(NULL), - m_state(NotConnectedToFocus), m_vtable(NULL), m_pendingCalls(NULL), - m_transferingCalls(NULL) { + m_transferingCalls(NULL), + m_isTerminating(false) { m_focusAddr = lp_config_get_string(m_core->config, "misc", "conference_focus_addr", ""); m_vtable = linphone_core_v_table_new(); m_vtable->call_state_changed = callStateChangedCb; @@ -598,7 +635,7 @@ RemoteConference::RemoteConference(LinphoneCore *core, const Conference::Params } RemoteConference::~RemoteConference() { - if(m_state == ConnectedToFocus) terminate(); + terminate(); linphone_core_remove_listener(m_core, m_vtable); linphone_core_v_table_destroy(m_vtable); } @@ -608,34 +645,38 @@ int RemoteConference::addParticipant(LinphoneCall *call) { LinphoneCallParams *params; switch(m_state) { - case NotConnectedToFocus: + case LinphoneConferenceStopped: + case LinphoneConferenceStartingFailed: Conference::addParticipant(call); ms_message("Calling the conference focus (%s)", m_focusAddr); addr = linphone_address_new(m_focusAddr); if(addr) { params = linphone_core_create_call_params(m_core, NULL); linphone_call_params_enable_video(params, m_currentParams.videoRequested()); - m_focusCall = linphone_call_ref(linphone_core_invite_address_with_params(m_core, addr, params)); + m_focusCall = linphone_core_invite_address_with_params(m_core, addr, params); m_focusCall->conf_ref = (LinphoneConference *)this; m_localParticipantStream = m_focusCall->audiostream; m_pendingCalls = ms_list_append(m_pendingCalls, call); - m_state = ConnectingToFocus; LinphoneCallLog *callLog = linphone_call_get_call_log(m_focusCall); callLog->was_conference = TRUE; linphone_address_unref(addr); linphone_call_params_unref(params); + setState(LinphoneConferenceStarting); return 0; } else return -1; - case ConnectingToFocus: + case LinphoneConferenceStarting: Conference::addParticipant(call); - m_pendingCalls = ms_list_append(m_pendingCalls, call); + if(focusIsReady()) { + transferToFocus(call); + } else { + m_pendingCalls = ms_list_append(m_pendingCalls, call); + } return 0; - case ConnectedToFocus: + case LinphoneConferenceReady: Conference::addParticipant(call); - m_transferingCalls = ms_list_append(m_transferingCalls, call); - linphone_core_transfer_call(m_core, call, m_focusContact); + transferToFocus(call); return 0; default: @@ -649,15 +690,21 @@ int RemoteConference::removeParticipant(const LinphoneAddress *uri) { int res; switch(m_state) { - case ConnectedToFocus: + case LinphoneConferenceReady: tmp = linphone_address_as_string_uri_only(uri); refer_to = ms_strdup_printf("%s;method=BYE", tmp); res = sal_call_refer(m_focusCall->op, refer_to); ms_free(tmp); ms_free(refer_to); - if(res == 0) return Conference::removeParticipant(uri); - else return -1; + if(res == 0) { + return Conference::removeParticipant(uri); + } else { + char *tmp = linphone_address_as_string(uri); + ms_error("Conference: could not remove participant '%s': REFER with BYE has failed", tmp); + ms_free(tmp); + return -1; + } default: ms_error("Cannot remove %s from conference: Bad conference state (%s)", linphone_address_as_string(uri), stateToString(m_state)); @@ -666,20 +713,27 @@ int RemoteConference::removeParticipant(const LinphoneAddress *uri) { } int RemoteConference::terminate() { + m_isTerminating = true; switch(m_state) { - case ConnectingToFocus: - case ConnectedToFocus: + case LinphoneConferenceReady: + case LinphoneConferenceStarting: linphone_core_terminate_call(m_core, m_focusCall); + reset(); + Conference::terminate(); + m_isTerminating = false; + setState(LinphoneConferenceStopped); break; + default: + m_isTerminating = false; break; } - Conference::terminate(); + return 0; } int RemoteConference::enter() { - if(m_state != ConnectedToFocus) { + if(m_state != LinphoneConferenceReady) { ms_error("Could not enter in the conference: bad conference state (%s)", stateToString(m_state)); return -1; } @@ -697,7 +751,7 @@ int RemoteConference::enter() { } int RemoteConference::leave() { - if(m_state != ConnectedToFocus) { + if(m_state != LinphoneConferenceReady) { ms_error("Could not leave the conference: bad conference state (%s)", stateToString(m_state)); return -1; } @@ -715,26 +769,45 @@ int RemoteConference::leave() { } bool RemoteConference::isIn() const { - if(m_state != ConnectedToFocus) return false; + if(m_state != LinphoneConferenceReady) return false; LinphoneCallState callState = linphone_call_get_state(m_focusCall); return callState == LinphoneCallStreamsRunning; } -const char *RemoteConference::stateToString(RemoteConference::State state) { - switch(state) { - case NotConnectedToFocus: return "NotConnectedToFocus"; - case ConnectingToFocus: return "ConnectingToFocus"; - case ConnectedToFocus: return "ConnectedToFocus"; - default: return "Unknown"; +bool RemoteConference::focusIsReady() const { + LinphoneCallState focusState; + if(m_focusCall == NULL) return false; + focusState = linphone_call_get_state(m_focusCall); + return focusState == LinphoneCallStreamsRunning || focusState == LinphoneCallPaused; +} + +bool RemoteConference::transferToFocus(LinphoneCall *call) { + if(linphone_core_transfer_call(m_core, call, m_focusContact) == 0) { + m_transferingCalls = ms_list_append(m_transferingCalls, call); + return true; + } else { + ms_error("Conference: could not transfer call [%p] to %s", call, m_focusContact); + return false; } } +void RemoteConference::reset() { + m_localParticipantStream = NULL; + m_focusAddr = NULL; + if(m_focusContact) { + ms_free(m_focusContact); + m_focusContact = NULL; + } + m_focusCall = NULL; + m_pendingCalls = ms_list_free(m_pendingCalls); + m_transferingCalls = ms_list_free(m_transferingCalls); +} + void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) { MSList *it; switch (state) { case LinphoneCallConnected: - m_state = ConnectedToFocus; m_focusContact = ms_strdup(linphone_call_get_remote_contact(m_focusCall)); it = m_pendingCalls; while (it) { @@ -744,27 +817,21 @@ void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) { MSList *current_elem = it; it = it->next; m_pendingCalls = ms_list_remove_link(m_pendingCalls, current_elem); - m_transferingCalls = ms_list_append(m_transferingCalls, pendingCall); - linphone_core_transfer_call(m_core, pendingCall, m_focusContact); + transferToFocus(pendingCall); } else { it = it->next; } } + setState(LinphoneConferenceReady); break; case LinphoneCallError: + reset(); + setState(LinphoneConferenceStartingFailed); + break; + case LinphoneCallEnd: - m_state = NotConnectedToFocus; - linphone_call_unref(m_focusCall); - m_focusCall = NULL; - m_localParticipantStream = NULL; - if(m_focusContact) { - ms_free(m_focusContact); - m_focusContact = NULL; - } - m_pendingCalls = ms_list_free(m_pendingCalls); - m_transferingCalls = ms_list_free(m_transferingCalls); - Conference::terminate(); + if(!m_isTerminating) terminate(); break; default: break; @@ -775,7 +842,7 @@ void RemoteConference::onPendingCallStateChanged(LinphoneCall *call, LinphoneCal switch(state) { case LinphoneCallStreamsRunning: case LinphoneCallPaused: - if(m_state == ConnectedToFocus) { + if(m_state == LinphoneConferenceReady) { m_pendingCalls = ms_list_remove(m_pendingCalls, call); m_transferingCalls = ms_list_append(m_transferingCalls, call); linphone_core_transfer_call(m_core, call, m_focusContact); @@ -825,6 +892,10 @@ void RemoteConference::transferStateChanged(LinphoneCore *lc, LinphoneCall *tran +const char *linphone_conference_state_to_string(LinphoneConferenceState state) { + return Conference::stateToString(state); +} + LinphoneConferenceParams *linphone_conference_params_new(const LinphoneCore *core) { return (LinphoneConferenceParams *)new Conference::Params(core); } @@ -845,6 +916,10 @@ bool_t linphone_conference_params_video_requested(const LinphoneConferenceParams return ((Conference::Params *)params)->videoRequested(); } +void linphone_conference_params_set_state_changed_callback(LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data) { + ((Conference::Params *)params)->setStateChangedCallback(cb, user_data); +} + LinphoneConference *linphone_local_conference_new(LinphoneCore *core) { @@ -867,6 +942,10 @@ void linphone_conference_free(LinphoneConference *obj) { delete (Conference *)obj; } +LinphoneConferenceState linphone_conference_get_state(const LinphoneConference *obj) { + return ((Conference *)obj)->getState(); +} + int linphone_conference_add_participant(LinphoneConference *obj, LinphoneCall *call) { return ((Conference *)obj)->addParticipant(call); } @@ -916,9 +995,9 @@ int linphone_conference_get_size(const LinphoneConference *obj) { } MSList *linphone_conference_get_participants(const LinphoneConference *obj) { - const list &participants = ((Conference *)obj)->getParticipants(); + const list &participants = ((Conference *)obj)->getParticipants(); MSList *participants_list = NULL; - for(list::const_iterator it=participants.begin();it!=participants.end();it++) { + for(list::const_iterator it=participants.begin();it!=participants.end();it++) { LinphoneAddress *uri = linphone_address_clone(it->getUri()); participants_list = ms_list_append(participants_list, uri); } diff --git a/coreapi/conference.h b/coreapi/conference.h index a043a8a33..cc9762bf1 100644 --- a/coreapi/conference.h +++ b/coreapi/conference.h @@ -37,11 +37,18 @@ extern "C" { * @{ */ +/** + * LinphoneConference class + */ +typedef struct _LinphoneConference LinphoneConference; /** * Parameters for initialization of conferences */ typedef struct _LinphoneCorferenceParams LinphoneConferenceParams; + + + /** * Create a #LinphoneConferenceParams with default parameters set. * @param core #LinphoneCore to use to find out the default parameters. Can be NULL. @@ -73,10 +80,7 @@ LINPHONE_PUBLIC bool_t linphone_conference_params_video_requested(const Linphone -/** - * LinphoneConference class - */ -typedef struct _LinphoneConference LinphoneConference; + /** * Remove a participant from a conference diff --git a/coreapi/conference_private.h b/coreapi/conference_private.h index 3147cfd9a..bc203f794 100644 --- a/coreapi/conference_private.h +++ b/coreapi/conference_private.h @@ -37,11 +37,48 @@ typedef enum { LinphoneConferenceClassRemote } LinphoneConferenceClass; +/** + * List of states used by #LinphoneConference + */ +typedef enum { + LinphoneConferenceStopped, /*< Initial state */ + LinphoneConferenceStarting, /*< A participant has been added but the conference is not running yet */ + LinphoneConferenceReady, /*< The conference is running */ + LinphoneConferenceStartingFailed /*< A participant has been added but the initialization of the conference has failed */ +} LinphoneConferenceState; +/** + * Type of the funtion to pass as callback to linphone_conference_params_set_state_changed_callback() + * @param conference The conference instance which the state has changed + * @param new_state The new state of the conferenece + * @param user_data Pointer pass to user_data while linphone_conference_params_set_state_changed_callback() was being called + */ +typedef void (*LinphoneConferenceStateChangedCb)(LinphoneConference *conference, LinphoneConferenceState new_state, void *user_data); + + +/** + * A function to converte a #LinphoneConferenceState into a string + */ +const char *linphone_conference_state_to_string(LinphoneConferenceState state); + + +/** + * Set a callback which will be called when the state of the conferenec is switching + * @param params A #LinphoneConferenceParams object + * @param cb The callback to call + * @param user_data Pointer to pass to the user_data parameter of #LinphoneConferenceStateChangedCb + */ +void linphone_conference_params_set_state_changed_callback(LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data); + + LinphoneConference *linphone_local_conference_new(LinphoneCore *core); LinphoneConference *linphone_local_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params); LinphoneConference *linphone_remote_conference_new(LinphoneCore *core); LinphoneConference *linphone_remote_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params); void linphone_conference_free(LinphoneConference *obj); +/** + * Get the state of a conference + */ +LinphoneConferenceState linphone_conference_get_state(const LinphoneConference *obj); int linphone_conference_add_participant(LinphoneConference *obj, LinphoneCall *call); int linphone_conference_remove_participant_with_call(LinphoneConference *obj, LinphoneCall *call); diff --git a/coreapi/ec-calibrator.c b/coreapi/ec-calibrator.c index bdf3a9180..8ff0cbc8a 100644 --- a/coreapi/ec-calibrator.c +++ b/coreapi/ec-calibrator.c @@ -41,25 +41,25 @@ static void ecc_init_filters(EcCalibrator *ecc){ ms_filter_call_method(ecc->sndread,MS_FILTER_GET_SAMPLE_RATE,&rate); ms_filter_call_method(ecc->sndread,MS_FILTER_SET_NCHANNELS,&ecc_channels); ms_filter_call_method(ecc->sndread,MS_FILTER_GET_NCHANNELS,&channels); - ecc->read_resampler=ms_filter_new(MS_RESAMPLE_ID); + ecc->read_resampler=ms_factory_create_filter(ecc->factory, MS_RESAMPLE_ID); ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_SAMPLE_RATE,&rate); ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&ecc->rate); ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_NCHANNELS,&ecc_channels); ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_NCHANNELS,&channels); - ecc->det=ms_filter_new(MS_TONE_DETECTOR_ID); + ecc->det=ms_factory_create_filter(ecc->factory, MS_TONE_DETECTOR_ID); ms_filter_call_method(ecc->det,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate); - ecc->rec=ms_filter_new(MS_VOID_SINK_ID); + ecc->rec=ms_factory_create_filter(ecc->factory, MS_VOID_SINK_ID); ms_filter_link(ecc->sndread,0,ecc->read_resampler,0); ms_filter_link(ecc->read_resampler,0,ecc->det,0); ms_filter_link(ecc->det,0,ecc->rec,0); - ecc->play=ms_filter_new(MS_VOID_SOURCE_ID); - ecc->gen=ms_filter_new(MS_DTMF_GEN_ID); + ecc->play=ms_factory_create_filter(ecc->factory, MS_VOID_SOURCE_ID); + ecc->gen=ms_factory_create_filter(ecc->factory, MS_DTMF_GEN_ID); ms_filter_call_method(ecc->gen,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate); - ecc->write_resampler=ms_filter_new(MS_RESAMPLE_ID); + ecc->write_resampler=ms_factory_create_filter(ecc->factory, MS_RESAMPLE_ID); ecc->sndwrite=ms_snd_card_create_writer(ecc->play_card); ms_filter_call_method(ecc->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate); @@ -281,7 +281,7 @@ static void * ecc_thread(void *p){ return NULL; } -EcCalibrator * ec_calibrator_new(MSSndCard *play_card, MSSndCard *capt_card, unsigned int rate, LinphoneEcCalibrationCallback cb, +EcCalibrator * ec_calibrator_new(MSFactory *factory, MSSndCard *play_card, MSSndCard *capt_card, unsigned int rate, LinphoneEcCalibrationCallback cb, LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data){ EcCalibrator *ecc=ms_new0(EcCalibrator,1); @@ -292,6 +292,7 @@ EcCalibrator * ec_calibrator_new(MSSndCard *play_card, MSSndCard *capt_card, uns ecc->audio_uninit_cb=audio_uninit_cb; ecc->capt_card=capt_card; ecc->play_card=play_card; + ecc->factory=factory; return ecc; } @@ -317,7 +318,7 @@ int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibration return -1; } rate = lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000); - lc->ecc=ec_calibrator_new(lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,rate,cb,audio_init_cb,audio_uninit_cb,cb_data); + lc->ecc=ec_calibrator_new(lc->factory, lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,rate,cb,audio_init_cb,audio_uninit_cb,cb_data); lc->ecc->play_cool_tones = lp_config_get_int(lc->config, "sound", "ec_calibrator_cool_tones", 0); ec_calibrator_start(lc->ecc); return 0; diff --git a/coreapi/event.c b/coreapi/event.c index 2d6c8f270..07e373b73 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -201,7 +201,7 @@ int linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *b } int linphone_event_refresh_subscribe(LinphoneEvent *lev) { - return sal_subscribe_refresh(lev->op); + return sal_op_refresh(lev->op); } int linphone_event_accept_subscription(LinphoneEvent *lev){ @@ -291,6 +291,16 @@ int linphone_event_update_publish(LinphoneEvent* lev, const LinphoneContent* bod return linphone_event_send_publish(lev,body); } +int linphone_event_refresh_publish(LinphoneEvent *lev) { + return sal_op_refresh(lev->op); +} +void linphone_event_pause_publish(LinphoneEvent *lev) { + if (lev->op) sal_op_stop_refreshing(lev->op); +} +void linphone_event_unpublish(LinphoneEvent *lev) { + lev->terminating = TRUE; /* needed to get clear event*/ + if (lev->op) sal_op_unpublish(lev->op); +} void linphone_event_set_user_data(LinphoneEvent *ev, void *up){ ev->userdata=up; } @@ -320,7 +330,7 @@ void linphone_event_terminate(LinphoneEvent *lev){ if (lev->publish_state!=LinphonePublishNone){ if (lev->publish_state==LinphonePublishOk && lev->expires!=-1){ sal_publish(lev->op,NULL,NULL,NULL,0,NULL); - }else sal_op_stop_refreshing(lev->op); + }else sal_op_unpublish(lev->op); linphone_event_set_publish_state(lev,LinphonePublishCleared); return; } diff --git a/coreapi/event.h b/coreapi/event.h index 5200beb66..b9033f8c7 100644 --- a/coreapi/event.h +++ b/coreapi/event.h @@ -208,6 +208,21 @@ LINPHONE_PUBLIC int linphone_event_send_publish(LinphoneEvent *lev, const Linpho **/ LINPHONE_PUBLIC int linphone_event_update_publish(LinphoneEvent *lev, const LinphoneContent *body); +/** + * Refresh an outgoing publish keeping the same body. + * @param lev LinphoneEvent object. + * @return 0 if successful, -1 otherwise. + */ +LINPHONE_PUBLIC int linphone_event_refresh_publish(LinphoneEvent *lev); + +/** + * Prevent an event from refreshing its publish. + * This is useful to let registrations to expire naturally (or) when the application wants to keep control on when + * refreshes are sent. + * The refreshing operations can be resumed with linphone_proxy_config_refresh_register(). + * @param[in] cfg #LinphoneEvent object. + **/ +LINPHONE_PUBLIC void linphone_event_pause_publish(LinphoneEvent *lev); /** * Return reason code (in case of error state reached). diff --git a/coreapi/friend.c b/coreapi/friend.c index d0a162081..0fbac0951 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -547,13 +547,25 @@ void linphone_friend_done(LinphoneFriend *fr) { } } +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic push +#endif +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" LinphoneFriend * linphone_core_create_friend(LinphoneCore *lc) { - return linphone_friend_new(); + LinphoneFriend * lf = linphone_friend_new(); + lf->lc = lc; + return lf; } LinphoneFriend * linphone_core_create_friend_with_address(LinphoneCore *lc, const char *address) { - return linphone_friend_new_with_address(address); + LinphoneFriend * lf = linphone_friend_new_with_address(address); + if (lf) + lf->lc = lc; + return lf; } +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic pop +#endif void linphone_core_add_friend(LinphoneCore *lc, LinphoneFriend *lf) { if (linphone_friend_list_add_friend(linphone_core_get_default_friend_list(lc), lf) != LinphoneFriendListOK) return; diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index f7501e2c4..e2d56c447 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -723,7 +723,7 @@ void linphone_friend_list_subscription_state_changed(LinphoneCore *lc, LinphoneE , lev , list); - if (state == LinphoneSubscriptionOutgoingProgress) { + if (state == LinphoneSubscriptionOutgoingProgress && linphone_event_get_reason(lev) == LinphoneReasonNoMatch) { ms_message("Resseting version count for friend list [%p]",list); list->expected_notification_version = 0; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 59af9315e..ba55fd1c2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -48,9 +48,9 @@ static void _linphone_call_set_next_video_frame_decoded_trigger(LinphoneCall *ca void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index); -MSWebCam *get_nowebcam_device(){ +MSWebCam *get_nowebcam_device(MSFactory* f){ #ifdef VIDEO_ENABLED - return ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),"StaticImage: Static picture"); + return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(f),"StaticImage: Static picture"); #else return NULL; #endif @@ -982,9 +982,9 @@ static void discover_mtu(LinphoneCore *lc, const char *remote){ /*attempt to discover mtu*/ mtu=ms_discover_mtu(remote); if (mtu>0){ - ms_set_mtu(mtu); + ms_factory_set_mtu(lc->factory, mtu); ms_message("Discovered mtu is %i, RTP payload max size is %i", - mtu, ms_get_payload_max_size()); + mtu, ms_factory_get_payload_max_size(lc->factory)); } } } @@ -2340,7 +2340,7 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ if (remotedesc) stream_desc = sal_media_description_find_best_stream(remotedesc, SalAudio); - call->audiostream=audiostream=audio_stream_new2(linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index), + call->audiostream=audiostream=audio_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index), multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_audio_stream_index].rtp_port, multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_audio_stream_index].rtcp_port); if (multicast_role == SalMulticastReceiver) @@ -2353,7 +2353,8 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ setup_dtls_params(call, &audiostream->ms); media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[call->main_audio_stream_index]); }else{ - call->audiostream=audio_stream_new_with_sessions(&call->sessions[call->main_audio_stream_index]); + call->audiostream=audio_stream_new_with_sessions(lc->factory, &call->sessions[call->main_audio_stream_index]); + } audiostream=call->audiostream; if (call->media_ports[call->main_audio_stream_index].rtp_port==-1){ @@ -2439,7 +2440,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){ if (remotedesc) stream_desc = sal_media_description_find_best_stream(remotedesc, SalVideo); - call->videostream=video_stream_new2(linphone_call_get_bind_ip_for_stream(call,call->main_video_stream_index), + call->videostream=video_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_video_stream_index), multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_video_stream_index].rtp_port, multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_video_stream_index].rtcp_port); if (multicast_role == SalMulticastReceiver) @@ -2452,7 +2453,7 @@ void linphone_call_init_video_stream(LinphoneCall *call){ setup_dtls_params(call, &call->videostream->ms); media_stream_reclaim_sessions(&call->videostream->ms, &call->sessions[call->main_video_stream_index]); }else{ - call->videostream=video_stream_new_with_sessions(&call->sessions[call->main_video_stream_index]); + call->videostream=video_stream_new_with_sessions(lc->factory, &call->sessions[call->main_video_stream_index]); } if (call->media_ports[call->main_video_stream_index].rtp_port==-1){ @@ -2505,7 +2506,7 @@ void linphone_call_init_text_stream(LinphoneCall *call){ if (call->op) remotedesc = sal_call_get_remote_media_description(call->op); if (remotedesc) stream_desc = sal_media_description_find_best_stream(remotedesc, SalText); - call->textstream = textstream = text_stream_new2(linphone_call_get_bind_ip_for_stream(call,call->main_text_stream_index), + call->textstream = textstream = text_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_text_stream_index), multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_text_stream_index].rtp_port, multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_text_stream_index].rtcp_port); if (multicast_role == SalMulticastReceiver) @@ -2517,7 +2518,7 @@ void linphone_call_init_text_stream(LinphoneCall *call){ setup_dtls_params(call, &textstream->ms); media_stream_reclaim_sessions(&textstream->ms, &call->sessions[call->main_text_stream_index]); } else { - call->textstream = text_stream_new_with_sessions(&call->sessions[call->main_text_stream_index]); + call->textstream = text_stream_new_with_sessions(lc->factory, &call->sessions[call->main_text_stream_index]); } textstream = call->textstream; if (call->media_ports[call->main_text_stream_index].rtp_port == -1) { @@ -2942,7 +2943,7 @@ static RtpSession * create_audio_rtp_io_session(LinphoneCall *call) { if (pt != NULL) { call->rtp_io_audio_profile = rtp_profile_new("RTP IO audio profile"); rtp_profile_set_payload(call->rtp_io_audio_profile, ptnum, payload_type_clone(pt)); - rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1); + rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1, ms_factory_get_mtu(lc->factory)); rtp_session_set_profile(rtp_session, call->rtp_io_audio_profile); rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1); rtp_session_enable_rtcp(rtp_session, FALSE); @@ -3143,7 +3144,7 @@ static RtpSession * create_video_rtp_io_session(LinphoneCall *call) { if (pt != NULL) { call->rtp_io_video_profile = rtp_profile_new("RTP IO video profile"); rtp_profile_set_payload(call->rtp_io_video_profile, ptnum, payload_type_clone(pt)); - rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1); + rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1, ms_factory_get_mtu(lc->factory)); rtp_session_set_profile(rtp_session, call->rtp_io_video_profile); rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1); rtp_session_enable_rtcp(rtp_session, FALSE); @@ -4772,7 +4773,7 @@ MSWebCam *linphone_call_get_video_device(const LinphoneCall *call) { LinphoneCallState state = linphone_call_get_state(call); bool_t paused = (state == LinphoneCallPausing) || (state == LinphoneCallPaused); if (paused || call->all_muted || (call->camera_enabled == FALSE)) - return get_nowebcam_device(); + return get_nowebcam_device(call->core->factory); else return call->core->video_conf.device; } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 93791eafe..191e72e78 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -33,6 +33,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include "mediastreamer2/mediastream.h" +#include "mediastreamer2/msfactory.h" #include "mediastreamer2/mseventqueue.h" #include "mediastreamer2/msvolume.h" #include "mediastreamer2/msequalizer.h" @@ -778,7 +779,7 @@ static void build_sound_devices_table(LinphoneCore *lc){ const char **old; int ndev; int i; - const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get()); + const MSList *elem=ms_snd_card_manager_get_list(ms_factory_get_snd_card_manager(lc->factory)); ndev=ms_list_size(elem); devices=ms_malloc((ndev+1)*sizeof(const char *)); for (i=0;elem!=NULL;elem=elem->next,i++){ @@ -823,13 +824,13 @@ static void sound_config_read(LinphoneCore *lc) char s=*i; *i='\0'; card=ms_alsa_card_new_custom(d+l,d+l); - ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card); + ms_snd_card_manager_add_card(ms_factory_get_snd_card_manager(lc->factory),card); *i=s; l=i-d+1; } if(d[l]!='\0') { card=ms_alsa_card_new_custom(d+l,d+l); - ms_snd_card_manager_add_card(ms_snd_card_manager_get(),card); + ms_snd_card_manager_add_card(ms_factory_get_snd_card_manager(lc->factory),card); } free(d); } @@ -1157,7 +1158,8 @@ static bool_t linphone_core_codec_supported(LinphoneCore *lc, SalStreamType type } else if (type == SalText) { return TRUE; } - return ms_filter_codec_supported(mime); + //ms_filter_codec_supported(mime) + return ms_factory_codec_supported (lc->factory, mime ); } @@ -1293,7 +1295,7 @@ static void build_video_devices_table(LinphoneCore *lc){ if (lc->video_conf.cams) ms_free(lc->video_conf.cams); /* retrieve all video devices */ - elem=ms_web_cam_manager_get_list(ms_web_cam_manager_get()); + elem=ms_web_cam_manager_get_list(ms_factory_get_web_cam_manager(lc->factory)); ndev=ms_list_size(elem); devices=ms_malloc((ndev+1)*sizeof(const char *)); for (i=0;elem!=NULL;elem=elem->next,i++){ @@ -1526,7 +1528,7 @@ static void misc_config_read(LinphoneCore *lc) { } static void linphone_core_start(LinphoneCore * lc) { - sip_setup_register_all(); + sip_setup_register_all(lc->factory); sound_config_read(lc); net_config_read(lc); rtp_config_read(lc); @@ -1587,7 +1589,8 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){ /*default enabled audio codecs, in order of preference*/ #if defined(__arm__) || defined(_M_ARM) /*hack for opus, that needs to be disabed by default on ARM single processor, otherwise there is no cpu left for video processing*/ - if (ms_get_cpu_count()==1) opus_enabled=FALSE; + //if (ms_get_cpu_count()==1) opus_enabled=FALSE; + if (ms_factory_get_cpu_count(lc->factory)==1) opus_enabled=FALSE; #endif linphone_core_register_payload_type(lc,&payload_type_opus,"useinbandfec=1",opus_enabled); linphone_core_register_payload_type(lc,&payload_type_silk_wb,NULL,TRUE); @@ -1686,16 +1689,15 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up"); ortp_init(); linphone_core_activate_log_serialization_if_needed(); - - ms_init(); - + + lc->factory = ms_factory_new_with_voip(); linphone_core_register_default_codecs(lc); linphone_core_register_offer_answer_providers(lc); /* Get the mediastreamer2 event queue */ /* This allows to run event's callback in linphone_core_iterate() */ - lc->msevq=ms_factory_create_event_queue(ms_factory_get_fallback()); - - lc->sal=sal_init(); + lc->msevq=ms_factory_create_event_queue(lc->factory); + + lc->sal=sal_init(lc->factory); sal_set_http_proxy_host(lc->sal, linphone_core_get_http_proxy_host(lc)); sal_set_http_proxy_port(lc->sal, linphone_core_get_http_proxy_port(lc)); @@ -3324,7 +3326,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ if (lc->ringstream && lc->dmfs_playing_start_time!=0){ linphone_core_stop_dtmf_stream(lc); } - linphone_ringtoneplayer_start(lc->ringtoneplayer, ringcard, lc->sound_conf.local_ring, 2000); + linphone_ringtoneplayer_start(lc->factory, lc->ringtoneplayer, ringcard, lc->sound_conf.local_ring, 2000); }else{ /* else play a tone within the context of the current call */ call->ringing_beep=TRUE; @@ -4499,10 +4501,10 @@ void linphone_core_set_rec_level(LinphoneCore *lc, int level) if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_CAPTURE,level); } -static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){ +static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap, MSFactory *f){ MSSndCard *sndcard=NULL; if (devid!=NULL){ - sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid); + sndcard=ms_snd_card_manager_get_card(ms_factory_get_snd_card_manager(f),devid); if (sndcard!=NULL && (ms_snd_card_get_capabilities(sndcard) & cap)==0 ){ ms_warning("%s card does not have the %s capability, ignoring.", @@ -4513,15 +4515,15 @@ static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){ } if (sndcard==NULL) { if ((cap & MS_SND_CARD_CAP_CAPTURE) && (cap & MS_SND_CARD_CAP_PLAYBACK)){ - sndcard=ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()); + sndcard=ms_snd_card_manager_get_default_card(ms_factory_get_snd_card_manager(f)); }else if (cap & MS_SND_CARD_CAP_CAPTURE){ - sndcard=ms_snd_card_manager_get_default_capture_card(ms_snd_card_manager_get()); + sndcard=ms_snd_card_manager_get_default_capture_card(ms_factory_get_snd_card_manager(f)); } else if (cap & MS_SND_CARD_CAP_PLAYBACK){ - sndcard=ms_snd_card_manager_get_default_playback_card(ms_snd_card_manager_get()); + sndcard=ms_snd_card_manager_get_default_playback_card(ms_factory_get_snd_card_manager(f)); } if (sndcard==NULL){/*looks like a bug! take the first one !*/ - const MSList *elem=ms_snd_card_manager_get_list(ms_snd_card_manager_get()); + const MSList *elem=ms_snd_card_manager_get_list(ms_factory_get_snd_card_manager(f)); if (elem) sndcard=(MSSndCard*)elem->data; } } @@ -4538,7 +4540,7 @@ static MSSndCard *get_card_from_string_id(const char *devid, unsigned int cap){ **/ bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *devid){ MSSndCard *sndcard; - sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid); + sndcard=ms_snd_card_manager_get_card(ms_factory_get_snd_card_manager(lc->factory),devid); if (sndcard!=NULL && (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_CAPTURE)) return TRUE; return FALSE; } @@ -4552,7 +4554,7 @@ bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, const char *devi **/ bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *devid){ MSSndCard *sndcard; - sndcard=ms_snd_card_manager_get_card(ms_snd_card_manager_get(),devid); + sndcard=ms_snd_card_manager_get_card(ms_factory_get_snd_card_manager(lc->factory),devid); if (sndcard!=NULL && (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_PLAYBACK)) return TRUE; return FALSE; } @@ -4565,7 +4567,7 @@ bool_t linphone_core_sound_device_can_playback(LinphoneCore *lc, const char *dev * @param devid the device name as returned by linphone_core_get_sound_devices() **/ int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){ - MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK); + MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK, lc->factory); lc->sound_conf.ring_sndcard=card; if (card && linphone_core_ready(lc)) lp_config_set_string(lc->config,"sound","ringer_dev_id",ms_snd_card_get_string_id(card)); @@ -4580,7 +4582,7 @@ int linphone_core_set_ringer_device(LinphoneCore *lc, const char * devid){ * @param devid the device name as returned by linphone_core_get_sound_devices() **/ int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){ - MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK); + MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_PLAYBACK, lc->factory); lc->sound_conf.play_sndcard=card; if (card && linphone_core_ready(lc)) lp_config_set_string(lc->config,"sound","playback_dev_id",ms_snd_card_get_string_id(card)); @@ -4595,7 +4597,7 @@ int linphone_core_set_playback_device(LinphoneCore *lc, const char * devid){ * @param devid the device name as returned by linphone_core_get_sound_devices() **/ int linphone_core_set_capture_device(LinphoneCore *lc, const char * devid){ - MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_CAPTURE); + MSSndCard *card=get_card_from_string_id(devid,MS_SND_CARD_CAP_CAPTURE, lc->factory); lc->sound_conf.capt_sndcard=card; if (card && linphone_core_ready(lc)) lp_config_set_string(lc->config,"sound","capture_dev_id",ms_snd_card_get_string_id(card)); @@ -4678,7 +4680,7 @@ void linphone_core_reload_sound_devices(LinphoneCore *lc){ if (capture != NULL) { capture_copy = ms_strdup(capture); } - ms_snd_card_manager_reload(ms_snd_card_manager_get()); + ms_snd_card_manager_reload(ms_factory_get_snd_card_manager(lc->factory)); build_sound_devices_table(lc); if (ringer_copy != NULL) { linphone_core_set_ringer_device(lc, ringer_copy); @@ -4700,7 +4702,7 @@ void linphone_core_reload_video_devices(LinphoneCore *lc){ if (devid != NULL) { devid_copy = ms_strdup(devid); } - ms_web_cam_manager_reload(ms_web_cam_manager_get()); + ms_web_cam_manager_reload(ms_factory_get_web_cam_manager(lc->factory)); build_video_devices_table(lc); if (devid_copy != NULL) { linphone_core_set_video_device(lc, devid_copy); @@ -4826,13 +4828,16 @@ int linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCb } lc_callback_obj_init(&lc->preview_finished_cb,end_of_ringtone,userdata); lc->preview_finished=0; - err = linphone_ringtoneplayer_start_with_cb(lc->ringtoneplayer, ringcard, ring, -1, notify_end_of_ringtone,(void *)lc); + err = linphone_ringtoneplayer_start_with_cb(lc->factory, lc->ringtoneplayer, ringcard, ring, -1, notify_end_of_ringtone,(void *)lc); if (err) { lc->preview_finished=1; } return err; } +MSFactory *linphone_core_get_ms_factory(LinphoneCore *lc){ + return lc->factory; +} /** * Sets the path to a wav file used for ringing back. * @@ -5268,7 +5273,7 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ if (lc->previewstream==NULL){ const char *display_filter=linphone_core_get_video_display_filter(lc); MSVideoSize vsize=lc->video_conf.preview_vsize.width!=0 ? lc->video_conf.preview_vsize : lc->video_conf.vsize; - lc->previewstream=video_preview_new(); + lc->previewstream=video_preview_new(lc->factory); video_preview_set_size(lc->previewstream,vsize); if (display_filter) video_preview_set_display_filter_name(lc->previewstream,display_filter); @@ -5276,6 +5281,7 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ video_preview_set_native_window_id(lc->previewstream,lc->preview_window_id); video_preview_set_fps(lc->previewstream,linphone_core_get_preferred_framerate(lc)); video_preview_start(lc->previewstream,lc->video_conf.device); + lc->previewstream->ms.factory = lc->factory; } }else{ if (lc->previewstream!=NULL){ @@ -5447,13 +5453,13 @@ int linphone_core_set_video_device(LinphoneCore *lc, const char *id){ MSWebCam *olddev=lc->video_conf.device; const char *vd; if (id!=NULL){ - lc->video_conf.device=ms_web_cam_manager_get_cam(ms_web_cam_manager_get(),id); + lc->video_conf.device=ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(lc->factory),id); if (lc->video_conf.device==NULL){ ms_warning("Could not find video device %s",id); } } if (lc->video_conf.device==NULL) - lc->video_conf.device=ms_web_cam_manager_get_default_cam(ms_web_cam_manager_get()); + lc->video_conf.device=ms_web_cam_manager_get_default_cam(ms_factory_get_web_cam_manager(lc->factory)); if (olddev!=NULL && olddev!=lc->video_conf.device){ toggle_video_preview(lc,FALSE);/*restart the video local preview*/ } @@ -5962,7 +5968,7 @@ static MSFilter *get_audio_resource(LinphoneCore *lc, LinphoneAudioResourceType if (ringcard == NULL) return NULL; - ringstream=lc->ringstream=ring_start(NULL,0,ringcard); + ringstream=lc->ringstream=ring_start(lc->factory, NULL,0,ringcard); ms_filter_call_method(lc->ringstream->gendtmf,MS_DTMF_GEN_SET_DEFAULT_AMPLITUDE,&); lc->dmfs_playing_start_time = ms_get_cur_time_ms()/1000; }else{ @@ -6126,9 +6132,9 @@ void linphone_core_set_mtu(LinphoneCore *lc, int mtu){ ms_error("MTU too small !"); mtu=500; } - ms_set_mtu(mtu); - ms_message("MTU is supposed to be %i, rtp payload max size will be %i",mtu, ms_get_payload_max_size()); - }else ms_set_mtu(0);//use mediastreamer2 default value + ms_factory_set_mtu(lc->factory, mtu); + ms_message("MTU is supposed to be %i, rtp payload max size will be %i",mtu, ms_factory_get_payload_max_size(lc->factory)); + }else ms_factory_set_mtu(lc->factory, 0);//use mediastreamer2 default value } void linphone_core_set_waiting_callback(LinphoneCore *lc, LinphoneCoreWaitingCallback cb, void *user_context){ @@ -6224,6 +6230,7 @@ void sip_config_uninit(LinphoneCore *lc) if (lc->sip_network_reachable) { for(elem=config->proxies;elem!=NULL;elem=ms_list_next(elem)){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data); + _linphone_proxy_config_unpublish(cfg); /* to unpublish without changing the stored flag enable_publish */ _linphone_proxy_config_unregister(cfg); /* to unregister without changing the stored flag enable_register */ } @@ -6491,10 +6498,12 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_message_storage_close(lc); linphone_core_call_log_storage_close(lc); linphone_core_friends_storage_close(lc); - ms_exit(); + linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); linphone_core_deactivate_log_serialization_if_needed(); ms_list_free_with_data(lc->vtable_refs,(void (*)(void *))v_table_reference_destroy); + + ms_factory_destroy(lc->factory); } static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable, time_t curtime){ @@ -7510,18 +7519,30 @@ LinphoneRingtonePlayer *linphone_core_get_ringtoneplayer(LinphoneCore *lc) { return lc->ringtoneplayer; } +static void linphone_core_conference_state_changed(LinphoneConference *conf, LinphoneConferenceState cstate, void *user_data) { + LinphoneCore *lc = (LinphoneCore *)user_data; + if(cstate == LinphoneConferenceStartingFailed || cstate == LinphoneConferenceStopped) { + linphone_conference_free(lc->conf_ctx); + lc->conf_ctx = NULL; + } +} + LinphoneConference *linphone_core_create_conference_with_params(LinphoneCore *lc, const LinphoneConferenceParams *params) { const char *conf_method_name; if(lc->conf_ctx == NULL) { + LinphoneConferenceParams *params2 = linphone_conference_params_clone(params); + linphone_conference_params_set_state_changed_callback(params2, linphone_core_conference_state_changed, lc); conf_method_name = lp_config_get_string(lc->config, "misc", "conference_type", "local"); if(strcasecmp(conf_method_name, "local") == 0) { - lc->conf_ctx = linphone_local_conference_new_with_params(lc, params); + lc->conf_ctx = linphone_local_conference_new_with_params(lc, params2); } else if(strcasecmp(conf_method_name, "remote") == 0) { - lc->conf_ctx = linphone_remote_conference_new_with_params(lc, params); + lc->conf_ctx = linphone_remote_conference_new_with_params(lc, params2); } else { ms_error("'%s' is not a valid conference method", conf_method_name); + linphone_conference_params_free(params2); return NULL; } + linphone_conference_params_free(params2); } else { ms_error("Could not create a conference: a conference instance already exists"); return NULL; @@ -7531,7 +7552,12 @@ LinphoneConference *linphone_core_create_conference_with_params(LinphoneCore *lc int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call) { LinphoneConference *conference = linphone_core_get_conference(lc); - if(conference == NULL) conference = linphone_core_create_conference_with_params(lc, NULL); + if(conference == NULL) { + LinphoneConferenceParams *params = linphone_conference_params_new(lc); + linphone_conference_params_set_state_changed_callback(params, linphone_core_conference_state_changed, lc); + conference = linphone_core_create_conference_with_params(lc, params); + linphone_conference_params_free(params); + } if(conference) return linphone_conference_add_participant(lc->conf_ctx, call); else return -1; } @@ -7557,7 +7583,10 @@ int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call) { } int linphone_core_terminate_conference(LinphoneCore *lc) { - if(lc->conf_ctx == NULL) return -1; + if(lc->conf_ctx == NULL) { + ms_error("Could not terminate conference: no conference context"); + return -1; + } linphone_conference_terminate(lc->conf_ctx); linphone_conference_free(lc->conf_ctx); lc->conf_ctx = NULL; diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index a0f069657..b962c1ab8 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -38,15 +38,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define LINPHONE_HOSTNAME_SIZE 128 #ifndef LINPHONE_PUBLIC - #define LINPHONE_PUBLIC MS2_PUBLIC +#define LINPHONE_PUBLIC MS2_PUBLIC #endif #ifndef LINPHONE_DEPRECATED -#if defined(_MSC_VER) - #define LINPHONE_DEPRECATED __declspec(deprecated) -#else - #define LINPHONE_DEPRECATED __attribute__ ((deprecated)) -#endif +#define LINPHONE_DEPRECATED MS2_DEPRECATED #endif @@ -3259,6 +3255,10 @@ LINPHONE_PUBLIC void linphone_core_set_ring_during_incoming_early_media(Linphone LINPHONE_PUBLIC bool_t linphone_core_get_ring_during_incoming_early_media(const LinphoneCore *lc); LINPHONE_PUBLIC int linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCbFunc func,void * userdata); +/** + * Returns the MSFactory (mediastreamer2 factory) used by the LinphoneCore to control mediastreamer2 library. +**/ +LINPHONE_PUBLIC MSFactory* linphone_core_get_ms_factory(LinphoneCore* lc); LINPHONE_PUBLIC int linphone_core_play_local(LinphoneCore *lc, const char *audiofile); LINPHONE_PUBLIC void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bool_t val); LINPHONE_PUBLIC bool_t linphone_core_echo_cancellation_enabled(LinphoneCore *lc); diff --git a/coreapi/linphonecore_utils.h b/coreapi/linphonecore_utils.h index 04069e504..9350a179d 100644 --- a/coreapi/linphonecore_utils.h +++ b/coreapi/linphonecore_utils.h @@ -44,7 +44,7 @@ bool_t lsd_player_loop_enabled(const LsdPlayer *p); void lsd_player_set_gain(LsdPlayer *p, float gain); LinphoneSoundDaemon *lsd_player_get_daemon(const LsdPlayer *p); -LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate, int nchannels); +LinphoneSoundDaemon * linphone_sound_daemon_new(MSFactory* factory, const char *cardname, int rate, int nchannels); LsdPlayer * linphone_sound_daemon_get_player(LinphoneSoundDaemon *lsd); void linphone_sound_daemon_release_player(LinphoneSoundDaemon *lsd, LsdPlayer *lsdplayer); void linphone_sound_daemon_stop_all_players(LinphoneSoundDaemon *obj); diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 6345945b3..c33ef6478 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -119,15 +119,17 @@ typedef struct _LinphoneFriend LinphoneFriend; /** * Contructor * @return a new empty #LinphoneFriend + * @deprecated use #linphone_core_create_friend instead */ -LINPHONE_PUBLIC LinphoneFriend * linphone_friend_new(void); +LINPHONE_PUBLIC MS2_DEPRECATED LinphoneFriend * linphone_friend_new(void); /*fix me me replace MS2_DEPRECATED by LINPHONE_DEPRECATED*/ /** * Contructor same as linphone_friend_new() + linphone_friend_set_address() * @param addr a buddy address, must be a sip uri like sip:joe@sip.linphone.org * @return a new #LinphoneFriend with \link linphone_friend_get_address() address initialized \endlink + * @deprecated use #linphone_core_create_friend_with_address instead */ -LINPHONE_PUBLIC LinphoneFriend *linphone_friend_new_with_address(const char *addr); +LINPHONE_PUBLIC MS2_DEPRECATED LinphoneFriend *linphone_friend_new_with_address(const char *addr); /*fix me me replace MS2_DEPRECATED by LINPHONE_DEPRECATED*/ /** * Contructor same as linphone_friend_new() + linphone_friend_set_address() diff --git a/coreapi/linphonepresence.h b/coreapi/linphonepresence.h index c0168cb8b..a4a451ad6 100644 --- a/coreapi/linphonepresence.h +++ b/coreapi/linphonepresence.h @@ -261,6 +261,21 @@ LINPHONE_PUBLIC char * linphone_presence_model_get_contact(const LinphonePresenc */ LINPHONE_PUBLIC int linphone_presence_model_set_contact(LinphonePresenceModel *model, const char *contact); +/** + * Sets the presentity of a presence model. + * @param[in] model The #LinphonePresenceModel object for which to set the contact. + * @param[in] presentity The presentity address to set (presentity is copied). + * @return 0 if successful, a value < 0 in case of error. + */ +LINPHONE_PUBLIC int linphone_presence_model_set_presentity(LinphonePresenceModel *model, const LinphoneAddress *presentity); +/** + * Gets the presentity of a presence model. + * @param[in] model The #LinphonePresenceModel object to get the contact from. + * @return A pointer to a const LinphoneAddress, or NULL if no contact is found. + * + */ +LINPHONE_PUBLIC const LinphoneAddress * linphone_presence_model_get_presentity(const LinphonePresenceModel *model); + /** * Gets the first activity of a presence model (there is usually only one). * @param[in] model The #LinphonePresenceModel object to get the activity from. diff --git a/coreapi/localplayer.c b/coreapi/localplayer.c index eb53eb640..a741a0a9b 100644 --- a/coreapi/localplayer.c +++ b/coreapi/localplayer.c @@ -36,7 +36,7 @@ LinphonePlayer *linphone_core_create_local_player(LinphoneCore *lc, MSSndCard *s LinphonePlayer *obj = ms_new0(LinphonePlayer, 1); if(snd_card == NULL) snd_card = lc->sound_conf.ring_sndcard; if(video_out == NULL) video_out = linphone_core_get_video_display_filter(lc); - obj->impl = ms_media_player_new(snd_card, video_out, window_id); + obj->impl = ms_media_player_new(lc->factory, snd_card, video_out, window_id); obj->open = _local_player_open; obj->start = _local_player_start; obj->pause = _local_player_pause; diff --git a/coreapi/lsd.c b/coreapi/lsd.c index 6aa803a06..dd28511a5 100644 --- a/coreapi/lsd.c +++ b/coreapi/lsd.c @@ -61,7 +61,7 @@ struct _LinphoneSoundDaemon { static MSFilter *create_writer(MSSndCard *c){ LinphoneSoundDaemon *lsd=(LinphoneSoundDaemon*)c->data; - MSFilter *itcsink=ms_filter_new(MS_ITC_SINK_ID); + MSFilter *itcsink=ms_factory_create_filter(ms_snd_card_get_factory(c), MS_ITC_SINK_ID); ms_filter_call_method(itcsink,MS_ITC_SINK_CONNECT,lsd->branches[0].player); return itcsink; } @@ -114,11 +114,11 @@ int lsd_player_stop(LsdPlayer *p){ return 0; } -static void lsd_player_init(LsdPlayer *p, MSConnectionPoint mixer, MSFilterId playerid, LinphoneSoundDaemon *lsd){ +static void lsd_player_init(MSFactory* factory, LsdPlayer *p, MSConnectionPoint mixer, MSFilterId playerid, LinphoneSoundDaemon *lsd){ MSConnectionHelper h; - p->player=ms_filter_new(playerid); - p->rateconv=ms_filter_new(MS_RESAMPLE_ID); - p->chanadapter=ms_filter_new(MS_CHANNEL_ADAPTER_ID); + p->player=ms_factory_create_filter(factory, playerid); + p->rateconv=ms_factory_create_filter(factory,MS_RESAMPLE_ID); + p->chanadapter=ms_factory_create_filter(factory,MS_CHANNEL_ADAPTER_ID); ms_connection_helper_start(&h); ms_connection_helper_link(&h,p->player,-1,0); @@ -219,16 +219,15 @@ void lsd_player_set_gain(LsdPlayer *p, float gain){ ms_filter_call_method(p->lsd->mixer,MS_AUDIO_MIXER_SET_INPUT_GAIN,&gainctl); } -LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate, int nchannels){ +LinphoneSoundDaemon * linphone_sound_daemon_new(MSFactory* factory, const char *cardname, int rate, int nchannels){ int i; MSConnectionPoint mp; LinphoneSoundDaemon *lsd; - MSSndCard *card=ms_snd_card_manager_get_card( - ms_snd_card_manager_get(), + MSSndCard *card=ms_snd_card_manager_get_card(ms_factory_get_snd_card_manager(factory), cardname); if (card==NULL){ card=ms_snd_card_manager_get_default_playback_card ( - ms_snd_card_manager_get()); + ms_factory_get_snd_card_manager(factory)); if (card==NULL){ ms_error("linphone_sound_daemon_new(): No playback soundcard available"); return NULL; @@ -237,7 +236,7 @@ LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate, lsd=ms_new0(LinphoneSoundDaemon,1); lsd->soundout=ms_snd_card_create_writer(card); - lsd->mixer=ms_filter_new(MS_AUDIO_MIXER_ID); + lsd->mixer=ms_factory_create_filter(ms_snd_card_get_factory(card),MS_AUDIO_MIXER_ID); lsd->out_rate=rate; lsd->out_nchans=nchannels; ms_filter_call_method(lsd->soundout,MS_FILTER_SET_SAMPLE_RATE,&lsd->out_rate); @@ -248,11 +247,11 @@ LinphoneSoundDaemon * linphone_sound_daemon_new(const char *cardname, int rate, mp.filter=lsd->mixer; mp.pin=0; - lsd_player_init(&lsd->branches[0],mp,MS_ITC_SOURCE_ID,lsd); + lsd_player_init(factory, &lsd->branches[0],mp,MS_ITC_SOURCE_ID,lsd); ms_filter_add_notify_callback(lsd->branches[0].player,(MSFilterNotifyFunc)lsd_player_configure,&lsd->branches[0],FALSE); for(i=1;ibranches[i],mp,MS_FILE_PLAYER_ID,lsd); + lsd_player_init(factory,&lsd->branches[i],mp,MS_FILE_PLAYER_ID,lsd); } ms_filter_link(lsd->mixer,0,lsd->soundout,0); lsd->ticker=ms_ticker_new(); diff --git a/coreapi/misc.c b/coreapi/misc.c index 9f5fece93..996d3d867 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -94,8 +94,9 @@ void linphone_core_set_payload_type_number(LinphoneCore *lc, PayloadType *pt, in } const char *linphone_core_get_payload_type_description(LinphoneCore *lc, PayloadType *pt){ - if (ms_filter_codec_supported(pt->mime_type)){ - MSFilterDesc *desc=ms_filter_get_encoder(pt->mime_type); + //if (ms_filter_codec_supported(pt->mime_type)){ + if (ms_factory_codec_supported(lc->factory, pt->mime_type)){ + MSFilterDesc *desc=ms_factory_get_encoder(lc->factory, pt->mime_type); #ifdef ENABLE_NLS return dgettext("mediastreamer",desc->text); #else @@ -260,7 +261,7 @@ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, const Payloa && linphone_core_echo_cancellation_enabled(lc) && (pt->clock_rate!=16000 && pt->clock_rate!=8000) && strcasecmp(pt->mime_type,"opus")!=0 - && ms_filter_lookup_by_name("MSWebRTCAEC")!=NULL){ + && ms_factory_lookup_filter_by_name(lc->factory, "MSWebRTCAEC")!=NULL){ ms_warning("Payload type %s/%i cannot be used because software echo cancellation is required but is unable to operate at this rate.", pt->mime_type,pt->clock_rate); ret=FALSE; @@ -1831,7 +1832,7 @@ const char ** linphone_core_get_supported_file_formats(LinphoneCore *core){ if (core->supported_formats==NULL){ core->supported_formats=ms_malloc0(3*sizeof(char*)); core->supported_formats[0]=wav; - if (ms_factory_lookup_filter_by_id(ms_factory_get_fallback(),MS_MKV_RECORDER_ID)){ + if (ms_factory_lookup_filter_by_id(core->factory,MS_MKV_RECORDER_ID)){ core->supported_formats[1]=mkv; } } diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index bc115001a..7bed10b92 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -145,7 +145,7 @@ static PayloadType * generic_match(const MSList *local_payloads, const PayloadTy void linphone_core_register_offer_answer_providers(LinphoneCore *lc){ - MSFactory *factory = ms_factory_get_fallback(); + MSFactory *factory = lc->factory; ms_factory_register_offer_answer_provider(factory, &red_offer_answer_provider); ms_factory_register_offer_answer_provider(factory, &g729a_offer_answer_provider); ms_factory_register_offer_answer_provider(factory, &opus_offer_answer_provider); @@ -154,10 +154,10 @@ void linphone_core_register_offer_answer_providers(LinphoneCore *lc){ /* * Returns a PayloadType from the local list that matches a PayloadType offered or answered in the remote list */ -static PayloadType * find_payload_type_best_match(const MSList *local_payloads, const PayloadType *refpt, +static PayloadType * find_payload_type_best_match(MSFactory *factory, const MSList *local_payloads, const PayloadType *refpt, const MSList *remote_payloads, bool_t reading_response){ PayloadType *ret = NULL; - MSOfferAnswerContext *ctx = ms_factory_create_offer_answer_context(ms_factory_get_fallback(), refpt->mime_type); + MSOfferAnswerContext *ctx = ms_factory_create_offer_answer_context(factory, refpt->mime_type); if (ctx){ ms_message("Doing offer/answer processing with specific provider for codec [%s]", refpt->mime_type); ret = ms_offer_answer_context_match_payload(ctx, local_payloads, refpt, remote_payloads, reading_response); @@ -168,7 +168,7 @@ static PayloadType * find_payload_type_best_match(const MSList *local_payloads, } -static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t reading_response, bool_t one_matching_codec){ +static MSList *match_payloads(MSFactory *factory, const MSList *local, const MSList *remote, bool_t reading_response, bool_t one_matching_codec){ const MSList *e2,*e1; MSList *res=NULL; PayloadType *matched; @@ -176,7 +176,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t for(e2=remote;e2!=NULL;e2=e2->next){ PayloadType *p2=(PayloadType*)e2->data; - matched=find_payload_type_best_match(local, p2, remote, reading_response); + matched=find_payload_type_best_match(factory, local, p2, remote, reading_response); if (matched){ int local_number=payload_type_get_number(matched); int remote_number=payload_type_get_number(p2); @@ -321,11 +321,11 @@ static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offere return res; } -static void initiate_outgoing(const SalStreamDescription *local_offer, +static void initiate_outgoing(MSFactory* factory, const SalStreamDescription *local_offer, const SalStreamDescription *remote_answer, SalStreamDescription *result){ if (remote_answer->rtp_port!=0) - result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE); + result->payloads=match_payloads(factory, local_offer->payloads,remote_answer->payloads,TRUE,FALSE); else { ms_message("Local stream description [%p] rejected by peer",local_offer); result->rtp_port=0; @@ -438,10 +438,10 @@ static void initiate_outgoing(const SalStreamDescription *local_offer, } -static void initiate_incoming(const SalStreamDescription *local_cap, +static void initiate_incoming(MSFactory *factory, const SalStreamDescription *local_cap, const SalStreamDescription *remote_offer, SalStreamDescription *result, bool_t one_matching_codec){ - result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec); + result->payloads=match_payloads(factory, local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec); result->proto=remote_offer->proto; result->type=local_cap->type; result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir); @@ -513,7 +513,7 @@ static void initiate_incoming(const SalStreamDescription *local_cap, * Returns a media description to run the streams with, based on a local offer * and the returned response (remote). **/ -int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, +int offer_answer_initiate_outgoing(MSFactory *factory, const SalMediaDescription *local_offer, const SalMediaDescription *remote_answer, SalMediaDescription *result){ int i; @@ -524,7 +524,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, ls=&local_offer->streams[i]; rs=&remote_answer->streams[i]; if (rs && ls->proto == rs->proto && rs->type == ls->type) { - initiate_outgoing(ls,rs,&result->streams[i]); + initiate_outgoing(factory, ls,rs,&result->streams[i]); memcpy(&result->streams[i].rtcp_xr, &ls->rtcp_xr, sizeof(result->streams[i].rtcp_xr)); if ((ls->rtcp_xr.enabled == TRUE) && (rs->rtcp_xr.enabled == FALSE)) { result->streams[i].rtcp_xr.enabled = FALSE; @@ -552,7 +552,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, * and the received offer. * The returned media description is an answer and should be sent to the offerer. **/ -int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities, +int offer_answer_initiate_incoming(MSFactory *factory, const SalMediaDescription *local_capabilities, const SalMediaDescription *remote_offer, SalMediaDescription *result, bool_t one_matching_codec){ int i; @@ -562,7 +562,7 @@ int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities rs = &remote_offer->streams[i]; ls = &local_capabilities->streams[i]; if (ls && rs->type == ls->type && rs->proto == ls->proto){ - initiate_incoming(ls,rs,&result->streams[i],one_matching_codec); + initiate_incoming(factory, ls,rs,&result->streams[i],one_matching_codec); // Handle global RTCP FB attributes result->streams[i].rtcp_fb.generic_nack_enabled = rs->rtcp_fb.generic_nack_enabled; result->streams[i].rtcp_fb.tmmbr_enabled = rs->rtcp_fb.tmmbr_enabled; diff --git a/coreapi/offeranswer.h b/coreapi/offeranswer.h index 0c8ebd7b1..009e82fcb 100644 --- a/coreapi/offeranswer.h +++ b/coreapi/offeranswer.h @@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Returns a media description to run the streams with, based on a local offer * and the returned response (remote). **/ -int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, +int offer_answer_initiate_outgoing(MSFactory *factory, const SalMediaDescription *local_offer, const SalMediaDescription *remote_answer, SalMediaDescription *result); @@ -39,7 +39,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer, * and the received offer. * The returned media description is an answer and should be sent to the offerer. **/ -int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities, +int offer_answer_initiate_incoming(MSFactory* factory, const SalMediaDescription *local_capabilities, const SalMediaDescription *remote_offer, SalMediaDescription *result, bool_t one_matching_codec); diff --git a/coreapi/presence.c b/coreapi/presence.c index 4e98ab028..c19a508bd 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -67,6 +67,7 @@ struct _LinphonePresencePerson { * This model is not complete. For example, it does not handle devices. */ struct _LinphonePresenceModel { + LinphoneAddress *presentity; /* "The model seeks to describe the presentity, identified by a presentity URI.*/ void *user_data; int refcnt; MSList *services; /**< A list of _LinphonePresenceService structures. Also named tuples in the RFC. */ @@ -246,7 +247,8 @@ static void presence_model_find_open_basic_status(LinphonePresenceService *servi static void presence_model_delete(LinphonePresenceModel *model) { if (model == NULL) return; - + if (model->presentity) + linphone_address_unref(model->presentity); ms_list_for_each(model->services, (MSIterateFunc)linphone_presence_service_unref); ms_list_free(model->services); ms_list_for_each(model->persons, (MSIterateFunc)linphone_presence_person_unref); @@ -671,7 +673,22 @@ int linphone_presence_model_clear_persons(LinphonePresenceModel *model) { return 0; } +int linphone_presence_model_set_presentity(LinphonePresenceModel *model, const LinphoneAddress *presentity) { + + if (model->presentity) { + linphone_address_unref(model->presentity); + model->presentity = NULL; + } + if (presentity) { + model->presentity=linphone_address_clone(presentity); + linphone_address_clean(model->presentity); + } + return 0; +} +const LinphoneAddress * linphone_presence_model_get_presentity(const LinphonePresenceModel *model) { + return model->presentity; +} /***************************************************************************** * PRESENCE SERVICE FUNCTIONS TO GET ACCESS TO ALL FUNCTIONALITIES * @@ -1772,24 +1789,28 @@ static void write_xml_presence_person_obj(LinphonePresencePerson *person, struct if (err < 0) *st->err = err; } -void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content) { - LinphonePresenceModel *model; - xmlBufferPtr buf; - xmlTextWriterPtr writer; +char *linphone_presence_model_to_xml(LinphonePresenceModel *model) { + xmlBufferPtr buf = NULL; + xmlTextWriterPtr writer = NULL; int err; - - if ((contact == NULL) || (content == NULL)) return; - - model = (LinphonePresenceModel *)presence; + char *contact = NULL; + char * content = NULL; + + if (model->presentity) { + contact = linphone_address_as_string_uri_only(model->presentity); + } else { + ms_error("Cannot convert presence model [%p] to xml because no presentity set", model); + goto end; + } buf = xmlBufferCreate(); if (buf == NULL) { ms_error("Error creating the XML buffer"); - return; + goto end; } writer = xmlNewTextWriterMemory(buf, 0); if (writer == NULL) { ms_error("Error creating the XML writer"); - return; + goto end; } xmlTextWriterSetIndent(writer,1); @@ -1815,7 +1836,7 @@ void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presen } else { struct _presence_service_obj_st st={0}; st.writer = writer; - st.contact = contact; + st.contact = contact; /*default value*/ st.err = &err; ms_list_for_each2(model->services, (MSIterate2Func)write_xml_presence_service_obj, &st); } @@ -1842,10 +1863,14 @@ void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presen } if (err > 0) { /* xmlTextWriterEndDocument returns the size of the content. */ - *content = ms_strdup((char *)buf->content); + content = ms_strdup((char *)buf->content); } - xmlFreeTextWriter(writer); - xmlBufferFree(buf); + +end: + if (contact) ms_free(contact); + if (writer) xmlFreeTextWriter(writer); + if (buf) xmlBufferFree(buf); + return content; } void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model){ diff --git a/coreapi/private.h b/coreapi/private.h index f79683b56..b82db1e4a 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -399,6 +399,8 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig *obj); void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc); void _linphone_proxy_config_release(LinphoneProxyConfig *cfg); +void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj); + /* * returns service route as defined in as defined by rfc3608, might be a list instead of just one. * Can be NULL @@ -605,7 +607,6 @@ struct _LinphoneProxyConfig int auth_failures; char *dial_prefix; LinphoneRegistrationState state; - SalOp *publish_op; LinphoneAVPFMode avpf_mode; bool_t commit; @@ -625,6 +626,8 @@ struct _LinphoneProxyConfig LinphoneAddress *saved_identity; /*---*/ LinphoneAddress *pending_contact; /*use to store previous contact in case of network failure*/ + LinphoneEvent *long_term_event; + unsigned long long previous_publish_config_hash[2]; }; @@ -890,6 +893,7 @@ void linphone_task_list_free(LinphoneTaskList *t); struct _LinphoneCore { + MSFactory* factory; MSList* vtable_refs; Sal *sal; LinphoneGlobalState state; @@ -1048,6 +1052,7 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, cons void _linphone_core_configure_resolver(void); struct _EcCalibrator{ + MSFactory *factory; ms_thread_t thread; MSSndCard *play_card,*capt_card; MSFilter *sndread,*det,*rec; @@ -1138,6 +1143,7 @@ SalReason linphone_reason_to_sal(LinphoneReason reason); LinphoneReason linphone_reason_from_sal(SalReason reason); LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); +void linphone_event_unpublish(LinphoneEvent *lev); /** * Useful for out of dialog notify * */ @@ -1496,7 +1502,7 @@ void _linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable, b #ifdef VIDEO_ENABLED LINPHONE_PUBLIC MSWebCam *linphone_call_get_video_device(const LinphoneCall *call); -MSWebCam *get_nowebcam_device(void); +MSWebCam *get_nowebcam_device(MSFactory *f); #endif bool_t linphone_core_lime_for_file_sharing_enabled(const LinphoneCore *lc); @@ -1504,6 +1510,8 @@ BELLE_SIP_DECLARE_VPTR(LinphoneTunnelConfig); int linphone_core_get_default_proxy_config_index(LinphoneCore *lc); +char *linphone_presence_model_to_xml(LinphonePresenceModel *model) ; + #ifdef __cplusplus } #endif diff --git a/coreapi/proxy.c b/coreapi/proxy.c index 01c8ddcb7..90c5def90 100644 --- a/coreapi/proxy.c +++ b/coreapi/proxy.c @@ -130,6 +130,50 @@ LinphoneProxyConfig *linphone_proxy_config_new() { return linphone_core_create_proxy_config(NULL); } +static char * append_linphone_address(LinphoneAddress *addr,char *out) { + char *res = out; + if (addr) { + char *tmp; + tmp = linphone_address_as_string(addr); + res = ms_strcat_printf(out, "%s",tmp); + ms_free(tmp); + } + return res; +}; +static char * append_string(const char * string,char *out) { + char *res = out; + if (string) { + res = ms_strcat_printf(out, "%s",string); + } + return res; +} +/* + * return true if computed value has changed + */ +bool_t linphone_proxy_config_compute_publish_params_hash(LinphoneProxyConfig * cfg) { + char * source = NULL; + char hash[33]; + char saved; + unsigned long long previous_hash[2]; + previous_hash[0] = cfg->previous_publish_config_hash[0]; + previous_hash[1] = cfg->previous_publish_config_hash[1]; + + source = ms_strcat_printf(source, "%i",cfg->privacy); + source=append_linphone_address(cfg->identity_address, source); + source=append_string(cfg->reg_proxy,source); + source=append_string(cfg->reg_route,source); + source=append_string(cfg->realm,source); + source = ms_strcat_printf(source, "%i",cfg->publish_expires); + source = ms_strcat_printf(source, "%i",cfg->publish); + belle_sip_auth_helper_compute_ha1(source, "dummy", "dummy", hash); + ms_free(source); + saved = hash[16]; + hash[16] = '\0'; + cfg->previous_publish_config_hash[0] = strtoull(hash, (char **)NULL, 16); + hash[16] = saved; + cfg->previous_publish_config_hash[1] = strtoull(&hash[16], (char **)NULL, 16); + return previous_hash[0] != cfg->previous_publish_config_hash[0] || previous_hash[1] != cfg->previous_publish_config_hash[1]; +} static void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg); BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneProxyConfig); @@ -152,9 +196,9 @@ void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){ sal_op_release(cfg->op); cfg->op=NULL; } - if (cfg->publish_op){ - sal_op_release(cfg->publish_op); - cfg->publish_op=NULL; + if (cfg->long_term_event){ + linphone_event_unref(cfg->long_term_event); + cfg->long_term_event=NULL; } } @@ -320,15 +364,13 @@ void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg){ } void linphone_proxy_config_edit(LinphoneProxyConfig *cfg){ - if (cfg->publish && cfg->publish_op){ - /*unpublish*/ - sal_publish_presence(cfg->publish_op,NULL,NULL,0,(SalPresenceModel *)NULL); - sal_op_release(cfg->publish_op); - cfg->publish_op=NULL; - } /*store current config related to server location*/ linphone_proxy_config_store_server_config(cfg); - + linphone_proxy_config_compute_publish_params_hash(cfg); + + if (cfg->publish && cfg->long_term_event){ + linphone_event_pause_publish(cfg->long_term_event); + } /*stop refresher in any case*/ linphone_proxy_config_pause_register(cfg); } @@ -351,9 +393,10 @@ void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){ cfg->pending_contact=contact_addr; } - if (cfg->publish_op){ - sal_op_release(cfg->publish_op); - cfg->publish_op=NULL; + if (cfg->long_term_event){ /*might probably do better*/ + linphone_event_terminate(cfg->long_term_event); + linphone_event_unref(cfg->long_term_event); + cfg->long_term_event=NULL; } if (cfg->op){ sal_op_release(cfg->op); @@ -1001,6 +1044,26 @@ int linphone_proxy_config_done(LinphoneProxyConfig *cfg) sal_op_unref(cfg->op); /*but we keep refresher to handle authentication if needed*/ cfg->op=NULL; } + if (cfg->long_term_event) { + if (res == LinphoneProxyConfigAddressDifferent) { + _linphone_proxy_config_unpublish(cfg); + } + + } + } + if (linphone_proxy_config_compute_publish_params_hash(cfg)) { + ms_message("Publish params have changed on proxy config [%p]",cfg); + if (cfg->long_term_event) { + if (!cfg->publish) { + /*publish is terminated*/ + linphone_event_terminate(cfg->long_term_event); + } + linphone_event_unref(cfg->long_term_event); + cfg->long_term_event = NULL; + } + if (cfg->publish) cfg->send_publish=TRUE; + } else { + ms_message("Publish params have not changed on proxy config [%p]",cfg); } cfg->commit=TRUE; linphone_proxy_config_write_all_to_config_file(cfg->lc); @@ -1021,28 +1084,46 @@ void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){ int err=0; - + if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){ - if (proxy->publish_op==NULL){ - const LinphoneAddress *to=linphone_proxy_config_get_identity_address(proxy); - proxy->publish_op=sal_op_new(proxy->lc->sal); - - linphone_configure_op(proxy->lc, proxy->publish_op, - to, NULL, FALSE); - - if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){ - sal_op_set_contact_address(proxy->publish_op,linphone_proxy_config_get_identity_address(proxy)); - } + LinphoneContent *content; + char *presence_body; + if (proxy->long_term_event==NULL){ + proxy->long_term_event = linphone_core_create_publish(proxy->lc + , linphone_proxy_config_get_identity_address(proxy) + , "presence" + , linphone_proxy_config_get_publish_expires(proxy)); } - err=sal_publish_presence(proxy->publish_op - ,NULL - ,NULL - ,linphone_proxy_config_get_publish_expires(proxy) - ,(SalPresenceModel *)presence); + proxy->long_term_event->internal = TRUE; + + if (linphone_presence_model_get_presentity(presence) == NULL) { + ms_message("No presentity set for model [%p], using identity from proxy config [%p]", presence, proxy); + linphone_presence_model_set_presentity(presence,linphone_proxy_config_get_identity_address(proxy)); + } + + if (!(presence_body = linphone_presence_model_to_xml(presence))) { + ms_error("Cannot publish presence model [%p] for proxy config [%p] because of xml serilization error",presence,proxy); + return -1; + } + + content = linphone_content_new(); + linphone_content_set_buffer(content,presence_body,strlen(presence_body)); + linphone_content_set_type(content, "application"); + linphone_content_set_subtype(content,"pidf+xml"); + err = linphone_event_send_publish(proxy->long_term_event, content); + linphone_content_unref(content); }else proxy->send_publish=TRUE; /*otherwise do not send publish if registration is in progress, this will be done later*/ return err; } +void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj) { + if (obj->long_term_event + && (linphone_event_get_publish_state(obj->long_term_event) == LinphonePublishOk || + (linphone_event_get_publish_state(obj->long_term_event) == LinphonePublishProgress && obj->publish_expires != 0))) { + linphone_event_unpublish(obj->long_term_event); + } +} + const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg){ return cfg->reg_route; } @@ -1376,7 +1457,6 @@ void linphone_proxy_config_update(LinphoneProxyConfig *cfg){ if (can_register(cfg)){ linphone_proxy_config_register(cfg); cfg->commit=FALSE; - if (cfg->publish) cfg->send_publish=TRUE; } } if (cfg->send_publish && (cfg->state==LinphoneRegistrationOk || cfg->state==LinphoneRegistrationCleared)){ diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 5f01ab99b..ea4ba3f6e 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -271,8 +271,7 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, int ret = 0; LinphoneEvent *lev; LinphoneAddress *request_uri; - char * domain; - const char* route; + const char* collector_uri; /*if we are on a low bandwidth network, do not send reports to not overload it*/ if (linphone_call_params_low_bandwidth_enabled(linphone_call_get_current_params(call))){ @@ -353,14 +352,21 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, } - route = linphone_proxy_config_get_quality_reporting_collector(call->dest_proxy); - domain = ms_strdup_printf("sip:%s", linphone_proxy_config_get_domain(call->dest_proxy)); - request_uri = linphone_address_new(route ? route : domain); - ms_free(domain); + collector_uri = linphone_proxy_config_get_quality_reporting_collector(call->dest_proxy); + if (!collector_uri){ + collector_uri = ms_strdup_printf("sip:%s", linphone_proxy_config_get_domain(call->dest_proxy)); + } + request_uri = linphone_address_new(collector_uri); lev=linphone_core_create_publish(call->core, request_uri, "vq-rtcpxr", expires); - if (route) { - ms_message("Publishing report with custom route %s", route); - sal_op_set_route(lev->op, route); + /* Special exception for quality report PUBLISH: if the collector_uri has any transport related parameters + * (port, transport, maddr), then it is sent directly. + * Otherwise it is routed as any LinphoneEvent publish, following proxy config policy. + **/ + if (sal_address_has_uri_param((SalAddress*)request_uri, "transport") || + sal_address_has_uri_param((SalAddress*)request_uri, "maddr") || + linphone_address_get_port(request_uri) != 0) { + ms_message("Publishing report with custom route %s", collector_uri); + sal_op_set_route(lev->op, collector_uri); } if (linphone_event_send_publish(lev, content) != 0){ diff --git a/coreapi/ringtoneplayer.c b/coreapi/ringtoneplayer.c index c1841aae7..1e1e64fd6 100644 --- a/coreapi/ringtoneplayer.c +++ b/coreapi/ringtoneplayer.c @@ -19,9 +19,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "private.h" +#include -int linphone_ringtoneplayer_start(LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms) { - return linphone_ringtoneplayer_start_with_cb(rp, card, ringtone, loop_pause_ms, NULL, NULL); +int linphone_ringtoneplayer_start(MSFactory *factory, LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms) { + return linphone_ringtoneplayer_start_with_cb(factory, rp, card, ringtone, loop_pause_ms, NULL, NULL); } #ifdef __ios @@ -36,7 +37,7 @@ void linphone_ringtoneplayer_destroy(LinphoneRingtonePlayer* rp) { linphone_ringtoneplayer_ios_destroy(rp); } -int linphone_ringtoneplayer_start_with_cb(LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms, LinphoneRingtonePlayerFunc end_of_ringtone, void * user_data) { +int linphone_ringtoneplayer_start_with_cb(MSFactory* f, LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms, LinphoneRingtonePlayerFunc end_of_ringtone, void * user_data) { if (linphone_ringtoneplayer_is_started(rp)) { ms_message("the local ringtone is already started"); return 2; @@ -83,7 +84,7 @@ static void notify_end_of_ringtone(void *ud, MSFilter *f, unsigned int event, vo } } -int linphone_ringtoneplayer_start_with_cb(LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms, LinphoneRingtonePlayerFunc end_of_ringtone, void * user_data) { +int linphone_ringtoneplayer_start_with_cb(MSFactory *factory, LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms, LinphoneRingtonePlayerFunc end_of_ringtone, void * user_data) { if (linphone_ringtoneplayer_is_started(rp)) { ms_message("the local ringtone is already started"); return 2; @@ -92,7 +93,7 @@ int linphone_ringtoneplayer_start_with_cb(LinphoneRingtonePlayer* rp, MSSndCard* ms_message("Starting local ringtone..."); rp->end_of_ringtone = end_of_ringtone; rp->end_of_ringtone_ud = user_data; - rp->ringstream=ring_start_with_cb(ringtone,loop_pause_ms,card,notify_end_of_ringtone,rp); + rp->ringstream=ring_start_with_cb(factory, ringtone,loop_pause_ms,card,notify_end_of_ringtone,rp); return rp->ringstream != NULL ? 0 : 1; } return 3; diff --git a/coreapi/ringtoneplayer.h b/coreapi/ringtoneplayer.h index 21afc7109..b632b1f55 100644 --- a/coreapi/ringtoneplayer.h +++ b/coreapi/ringtoneplayer.h @@ -24,7 +24,7 @@ typedef void (*LinphoneRingtonePlayerFunc)(LinphoneRingtonePlayer* rp, void* use LINPHONE_PUBLIC LinphoneRingtonePlayer* linphone_ringtoneplayer_new(void); LINPHONE_PUBLIC void linphone_ringtoneplayer_destroy(LinphoneRingtonePlayer* rp); -LINPHONE_PUBLIC int linphone_ringtoneplayer_start(LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms); +LINPHONE_PUBLIC int linphone_ringtoneplayer_start(MSFactory *factory, LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms); /** * Start a ringtone player * @param rp LinphoneRingtonePlayer object @@ -33,7 +33,8 @@ LINPHONE_PUBLIC int linphone_ringtoneplayer_start(LinphoneRingtonePlayer* rp, MS * @param loop_pause_ms pause interval in milliseconds to be observed between end of play and resuming at start. A value of -1 disables loop mode * @return 0 if the player successfully started, positive error code otherwise */ -LINPHONE_PUBLIC int linphone_ringtoneplayer_start_with_cb(LinphoneRingtonePlayer* rp, MSSndCard* card, const char* ringtone, int loop_pause_ms, LinphoneRingtonePlayerFunc end_of_ringtone, void * user_data); +LINPHONE_PUBLIC int linphone_ringtoneplayer_start_with_cb(MSFactory *factory, LinphoneRingtonePlayer* rp, MSSndCard* card, + const char* ringtone, int loop_pause_ms, LinphoneRingtonePlayerFunc end_of_ringtone, void * user_data); LINPHONE_PUBLIC bool_t linphone_ringtoneplayer_is_started(LinphoneRingtonePlayer* rp); LINPHONE_PUBLIC int linphone_ringtoneplayer_stop(LinphoneRingtonePlayer* rp); diff --git a/coreapi/sal.c b/coreapi/sal.c index 701d68b90..97d45f612 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -570,13 +570,6 @@ const SalAddress *sal_op_get_to_address(const SalOp *op){ return ((SalOpBase*)op)->to_address; } -const char *sal_op_get_route(const SalOp *op){ -#ifdef BELLE_SIP -ms_fatal("sal_op_get_route not supported, use sal_op_get_route_addresses instead"); -#endif - return ((SalOpBase*)op)->route; -} - const char *sal_op_get_remote_ua(const SalOp *op){ return ((SalOpBase*)op)->remote_ua; } @@ -696,6 +689,11 @@ void __sal_op_free(SalOp *op){ sal_custom_header_free(b->recv_custom_headers); if (b->sent_custom_headers) sal_custom_header_free(b->sent_custom_headers); + + if (b->entity_tag != NULL){ + ms_free(b->entity_tag); + b->entity_tag = NULL; + } ms_free(op); } @@ -1007,3 +1005,17 @@ char* sal_op_get_public_uri(SalOp *op) { } return NULL; } +const char *sal_op_get_entity_tag(const SalOp* op) { + SalOpBase* op_base = (SalOpBase*)op; + return op_base->entity_tag; +} +void sal_op_set_entity_tag(SalOp *op, const char* entity_tag) { + SalOpBase* op_base = (SalOpBase*)op; + if (op_base->entity_tag != NULL){ + ms_free(op_base->entity_tag); + } + if (entity_tag) + op_base->entity_tag = ms_strdup(entity_tag); + else + op_base->entity_tag = NULL; +} diff --git a/coreapi/sipsetup.c b/coreapi/sipsetup.c index 29ffd46fc..8a5aea58c 100644 --- a/coreapi/sipsetup.c +++ b/coreapi/sipsetup.c @@ -35,9 +35,10 @@ void sip_setup_register(SipSetup *ss){ registered_sip_setups=ms_list_append(registered_sip_setups,ss); } -void sip_setup_register_all(void){ +void sip_setup_register_all(MSFactory *factory){ SipSetup **p=all_sip_setups; - ms_load_plugins(LINPHONE_PLUGINS_DIR); + ms_factory_load_plugins(factory, LINPHONE_PLUGINS_DIR); + //ms_load_plugins(LINPHONE_PLUGINS_DIR); while(*p!=NULL){ sip_setup_register(*p); p++; diff --git a/coreapi/sipsetup.h b/coreapi/sipsetup.h index 63d71d5f1..dd1c48dc7 100644 --- a/coreapi/sipsetup.h +++ b/coreapi/sipsetup.h @@ -132,7 +132,7 @@ void buddy_lookup_request_set_max_results(BuddyLookupRequest *req, int ncount); void sip_setup_register(SipSetup *ss); -void sip_setup_register_all(void); +void sip_setup_register_all(MSFactory* factory); SipSetup *sip_setup_lookup(const char *type_name); void sip_setup_unregister_all(void); LINPHONE_PUBLIC unsigned int sip_setup_get_capabilities(SipSetup *s); diff --git a/coreapi/vtables.c b/coreapi/vtables.c index 848507991..e31962f5a 100644 --- a/coreapi/vtables.c +++ b/coreapi/vtables.c @@ -250,7 +250,7 @@ void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneE } void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) { - NOTIFY_IF_EXIST(publish_state_changed, lc,lev,state); + NOTIFY_IF_EXIST_INTERNAL(publish_state_changed, linphone_event_is_internal(lev), lc, lev, state); cleanup_dead_vtable_refs(lc); } diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c index b10a2c93a..e3166b4a4 100644 --- a/gtk/audio_assistant.c +++ b/gtk/audio_assistant.c @@ -211,14 +211,15 @@ static gboolean linphone_gtk_stop_record(gpointer data){ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ LinphoneCore *lc = linphone_gtk_get_core(); + MSFactory *factory = linphone_core_get_ms_factory(lc); AudioStream *stream = NULL; - MSSndCardManager *manager = ms_snd_card_manager_get(); + MSSndCardManager *manager = ms_factory_get_snd_card_manager(factory); gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); gint timeout_id; if(active){ gchar *path = get_record_file(); - stream=audio_stream_new(8888, 8889, FALSE); + stream=audio_stream_new(factory, 8888, 8889, FALSE); if(stream != NULL){ audio_stream_start_full(stream,&av_profile,"127.0.0.1",8888,"127.0.0.1",8889,0,0,NULL, path,NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); @@ -255,13 +256,14 @@ static void endoffile_cb(void *ud, MSFilter *f, unsigned int ev,void * arg){ void linphone_gtk_start_play_record_sound(GtkWidget *w,gpointer data){ LinphoneCore *lc = linphone_gtk_get_core(); + MSFactory *factory = linphone_core_get_ms_factory(lc); gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); AudioStream *stream = NULL; - MSSndCardManager *manager = ms_snd_card_manager_get(); + MSSndCardManager *manager = ms_factory_get_snd_card_manager(factory); if(active){ gchar *path = g_object_get_data(G_OBJECT(audio_assistant),"path"); - stream=audio_stream_new(8888, 8889, FALSE); + stream=audio_stream_new(factory, 8888, 8889, FALSE); if(path != NULL){ audio_stream_start_full(stream,&av_profile,"127.0.0.1",8888,"127.0.0.1",8889,0,0,path, NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),NULL,FALSE); @@ -446,14 +448,15 @@ static GtkWidget *create_end_page(void){ static void prepare(GtkAssistant *w){ AudioStream *audio_stream = NULL; LinphoneCore *lc=linphone_gtk_get_core(); + MSFactory *factory = linphone_core_get_ms_factory(lc); int page = gtk_assistant_get_current_page(w); GtkWidget *mic_audiolevel = get_widget_from_assistant("mic_audiolevel"); GtkWidget *label_audiolevel = get_widget_from_assistant("label_audiolevel"); //Speaker page if(page == 1){ - MSSndCardManager *manager = ms_snd_card_manager_get(); - audio_stream = audio_stream_start_with_sndcards(&av_profile,9898,"127.0.0.1",19898,0,0,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); + MSSndCardManager *manager = ms_factory_get_snd_card_manager(factory); + audio_stream = audio_stream_start_with_sndcards(factory, &av_profile,9898,"127.0.0.1",19898,0,0,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); if (mic_audiolevel != NULL && audio_stream != NULL){ g_object_set_data(G_OBJECT(audio_assistant),"stream",audio_stream); linphone_gtk_init_audio_meter(mic_audiolevel,(get_volume_t)audio_stream_get_record_volume,audio_stream); diff --git a/gtk/calllogs.c b/gtk/calllogs.c index 713ed6e96..58fb4e6e5 100644 --- a/gtk/calllogs.c +++ b/gtk/calllogs.c @@ -301,7 +301,7 @@ void linphone_gtk_call_log_update(GtkWidget *w){ time_t start_date_time=linphone_call_log_get_start_date(cl); const gchar *call_status_icon_name; -#if GLIB_CHECK_VERSION(2,26,0) +#if GLIB_CHECK_VERSION(2,30,0) // The g_date_time_format function exists since 2.26.0 but the '%c' format is only supported since 2.30.0 if (start_date_time){ GDateTime *dt=g_date_time_new_from_unix_local(start_date_time); start_date=g_date_time_format(dt,"%c"); @@ -309,6 +309,9 @@ void linphone_gtk_call_log_update(GtkWidget *w){ } #else start_date=g_strdup(ctime(&start_date_time)); + if (start_date[strlen(start_date) - 1] == '\n') { + start_date[strlen(start_date) - 1] = '\0'; + } #endif lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),addr); if(lf != NULL){ diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 974542075..b826029c8 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -1417,8 +1417,9 @@ void linphone_gtk_fill_webcams(GtkWidget *pb){ void linphone_gtk_fill_video_renderers(GtkWidget *pb){ #ifdef VIDEO_ENABLED /* video_stream_get_default_video_renderer requires video enabled */ LinphoneCore *lc=linphone_gtk_get_core(); + MSFactory *factory = linphone_core_get_ms_factory(lc); GtkWidget *combo=linphone_gtk_get_widget(pb,"renderers"); - MSList *l=ms_filter_lookup_by_interface(MSFilterVideoDisplayInterface); + MSList *l=ms_factory_lookup_filter_by_interface(factory, MSFilterVideoDisplayInterface); MSList *elem; int i; int active=-1; diff --git a/gtk/videowindow.c b/gtk/videowindow.c index d8296aaa5..86c84ac5a 100644 --- a/gtk/videowindow.c +++ b/gtk/videowindow.c @@ -61,8 +61,10 @@ static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint datalen--; } if (player){ + const char* filepath = (strstr(path,"file://")==path) ? path+strlen("file://") : path; if (linphone_player_open(player,filepath,on_end_of_play,NULL)==0){ + linphone_player_start(player); }else{ GtkWidget *warn=gtk_message_dialog_new(GTK_WINDOW(widget),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, diff --git a/include/sal/sal.h b/include/sal/sal.h index 699fe8351..d95ad6ae4 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -126,13 +126,14 @@ void sal_address_set_transport_name(SalAddress* addr,const char* transport); void sal_address_set_method_param(SalAddress *addr, const char *method); void sal_address_set_params(SalAddress *addr, const char *params); void sal_address_set_uri_params(SalAddress *addr, const char *params); +bool_t sal_address_has_uri_param(SalAddress *addr, const char *name); bool_t sal_address_is_ipv6(const SalAddress *addr); bool_t sal_address_is_sip(const SalAddress *addr); void sal_address_set_password(SalAddress *addr, const char *passwd); const char *sal_address_get_password(const SalAddress *addr); void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value); -LINPHONE_PUBLIC Sal * sal_init(void); +LINPHONE_PUBLIC Sal * sal_init(MSFactory *factory); LINPHONE_PUBLIC void sal_uninit(Sal* sal); void sal_set_user_pointer(Sal *sal, void *user_data); void *sal_get_user_pointer(const Sal *sal); @@ -353,6 +354,7 @@ typedef struct SalOpBase{ SalAddress* service_route; /*as defined by rfc3608, might be a list*/ SalCustomHeader *sent_custom_headers; SalCustomHeader *recv_custom_headers; + char* entity_tag; /*as defined by rfc3903 (I.E publih)*/ } SalOpBase; @@ -641,6 +643,8 @@ void sal_op_set_to(SalOp *op, const char *to); void sal_op_set_to_address(SalOp *op, const SalAddress *to); SalOp *sal_op_ref(SalOp* h); void sal_op_stop_refreshing(SalOp *op); +int sal_op_refresh(SalOp *op); + void sal_op_release(SalOp *h); /*same as release, but does not stop refresher if any*/ void* sal_op_unref(SalOp* op); @@ -654,7 +658,6 @@ const SalAddress *sal_op_get_from_address(const SalOp *op); const char *sal_op_get_to(const SalOp *op); const SalAddress *sal_op_get_to_address(const SalOp *op); const SalAddress *sal_op_get_contact_address(const SalOp *op); -const char *sal_op_get_route(const SalOp *op); const MSList* sal_op_get_route_addresses(const SalOp *op); const char *sal_op_get_proxy(const SalOp *op); /*raw contact header value with header params*/ @@ -684,6 +687,10 @@ const SalErrorInfo *sal_op_get_error_info(const SalOp *op); void sal_error_info_reset(SalErrorInfo *ei); void sal_error_info_set(SalErrorInfo *ei, SalReason reason, int code, const char *status_string, const char *warning); +/*entity tag used for publish (see RFC 3903)*/ +const char *sal_op_get_entity_tag(const SalOp* op); +void sal_op_set_entity_tag(SalOp *op, const char* entity_tag); + /*Call API*/ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc); int sal_call(SalOp *h, const char *from, const char *to); @@ -740,8 +747,9 @@ int sal_notify_presence(SalOp *op, SalPresenceModel *presence); int sal_notify_presence_close(SalOp *op); /*presence publish */ -int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence); - +//int sal_publish_presence(SalOp *op, const char *from, const char *to, int expires, SalPresenceModel *presence); +SalBodyHandler *sal_presence_model_create_body_handler(SalPresenceModel *presence); + /*ping: main purpose is to obtain its own contact address behind firewalls*/ int sal_ping(SalOp *op, const char *from, const char *to); @@ -754,11 +762,11 @@ int sal_subscribe(SalOp *op, const char *from, const char *to, const char *event int sal_unsubscribe(SalOp *op); int sal_subscribe_accept(SalOp *op); int sal_subscribe_decline(SalOp *op, SalReason reason); -int sal_subscribe_refresh(SalOp *op); int sal_notify(SalOp *op, const SalBodyHandler *body); int sal_notify_close(SalOp *op); int sal_publish(SalOp *op, const char *from, const char *to, const char*event_name, int expires, const SalBodyHandler *body); - +int sal_op_unpublish(SalOp *op); + /*privacy, must be in sync with LinphonePrivacyMask*/ typedef enum _SalPrivacy { SalPrivacyNone=0x0, diff --git a/linphone.spec.in b/linphone.spec.in index fa5541a0a..a92ec864e 100644 --- a/linphone.spec.in +++ b/linphone.spec.in @@ -100,6 +100,7 @@ rm -rf $RPM_BUILD_ROOT %{_bindir}/lpc2xml_test %{_bindir}/xml2lpc_test %{_bindir}/lp-gen-wrappers +%{_bindir}/lp-sendmsg %{_includedir}/linphone %{_libdir}/*.a %{_libdir}/*.la diff --git a/mediastreamer2 b/mediastreamer2 index 7053d54e7..dd5ad1b73 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 7053d54e7e3375944ee54671b82c3b5f63eac072 +Subproject commit dd5ad1b738989bc6964f889e17f275eea85e11c0 diff --git a/oRTP b/oRTP index 83bf0a09c..1d533c749 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 83bf0a09cc2127086e15817d16793320c9fb9af0 +Subproject commit 1d533c7490475b26a29f3fce300ac7004ab74a88 diff --git a/tester/call_tester.c b/tester/call_tester.c index 8eb458f93..c1a267e36 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -547,14 +547,14 @@ static void call_outbound_with_multiple_proxy(void) { // set first LPC to unreacheable proxy addr linphone_proxy_config_edit(lpc); - linphone_proxy_config_set_server_addr(lpc,"12.13.14.15:5223;transport=udp"); - linphone_proxy_config_set_route(lpc, "12.13.14.15:5223;transport=udp;lr"); + linphone_proxy_config_set_server_addr(lpc,"sip:linphone.org:9016;transport=udp"); + linphone_proxy_config_set_route(lpc, "sip:linphone.org:9016;transport=udp;lr"); linphone_proxy_config_done(lpc); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 1, 2000)); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneRegistrationOk, 1, 10000)); BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationProgress, 2, 200)); - BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 1, 2000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 1, 10000)); // calling marie should go through the second proxy config BC_ASSERT_TRUE(call(marie, pauline)); @@ -667,7 +667,7 @@ static void call_with_specified_codec_bitrate(void) { int max_bw=50; #ifdef __arm__ - if (ms_get_cpu_count() <2) { /*2 opus codec channel + resampler is too much for a single core*/ + if (ms_factory_get_cpu_count(marie->lc->factory) <2) { /*2 opus codec channel + resampler is too much for a single core*/ #ifndef ANDROID codec = "speex"; rate = 8000; @@ -2343,20 +2343,20 @@ static void video_call_using_policy_AVPF_implicit_caller_and_callee(void) { linphone_core_manager_destroy(callee); linphone_core_manager_destroy(caller); } -static void video_call_base_avpf(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy,LinphoneMediaEncryption mode, bool_t callee_video_enabled, bool_t caller_video_enabled) { - linphone_core_set_avpf_mode(pauline->lc,LinphoneAVPFEnabled); - linphone_core_set_avpf_mode(marie->lc,LinphoneAVPFEnabled); - video_call_base_3(pauline,marie,using_policy,mode,callee_video_enabled,caller_video_enabled); - end_call(pauline, marie); +static void video_call_base_avpf(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bool_t using_policy,LinphoneMediaEncryption mode, bool_t callee_video_enabled, bool_t caller_video_enabled) { + linphone_core_set_avpf_mode(caller->lc,LinphoneAVPFEnabled); + linphone_core_set_avpf_mode(callee->lc,LinphoneAVPFEnabled); + video_call_base_3(caller,callee,using_policy,mode,callee_video_enabled,caller_video_enabled); + end_call(caller, callee); } static void video_call_avpf(void) { - LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_rc"); - LinphoneCoreManager* marie = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "marie_rc" : "marie_tcp_rc"); + LinphoneCoreManager* callee = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* caller = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - video_call_base_avpf(pauline,marie,FALSE,LinphoneMediaEncryptionNone,TRUE,TRUE); - linphone_core_manager_destroy(pauline); - linphone_core_manager_destroy(marie); + video_call_base_avpf(caller,callee,FALSE,LinphoneMediaEncryptionNone,TRUE,TRUE); + linphone_core_manager_destroy(callee); + linphone_core_manager_destroy(caller); } @@ -2984,7 +2984,8 @@ static void call_with_mkv_file_player(void) { BC_ASSERT_PTR_NOT_NULL(player); if (player){ int res = linphone_player_open(player,hellomkv,on_eof,marie); - if(!ms_filter_codec_supported("opus")) { + //if(!ms_filter_codec_supported("opus")) { + if(!ms_factory_codec_supported(marie->lc->factory, "opus") && !ms_factory_codec_supported(pauline->lc->factory, "opus")){ BC_ASSERT_EQUAL(res, -1, int, "%d"); end_call(marie, pauline); goto end; @@ -5710,7 +5711,8 @@ static void call_logs_sqlite_storage(void) { MSList *logs = NULL; LinphoneCallLog *call_log = NULL; LinphoneAddress *laure = NULL; - time_t start_time = time(NULL); + time_t user_data_time = time(NULL); + time_t start_time = 0; unlink(logs_db); linphone_core_set_call_logs_database_path(marie->lc, logs_db); @@ -5719,7 +5721,8 @@ static void call_logs_sqlite_storage(void) { BC_ASSERT_TRUE(call(marie, pauline)); wait_for_until(marie->lc, pauline->lc, NULL, 5, 500); call_log = linphone_call_get_call_log(linphone_core_get_current_call(marie->lc)); - linphone_call_log_set_user_data(call_log, &start_time); + start_time = linphone_call_log_get_start_date(call_log); + linphone_call_log_set_user_data(call_log, &user_data_time); linphone_call_log_set_ref_key(call_log, "ref_key"); end_call(marie, pauline); BC_ASSERT_TRUE(linphone_core_get_call_history_size(marie->lc) == 1); @@ -5752,7 +5755,7 @@ static void call_logs_sqlite_storage(void) { if (ref_key) { BC_ASSERT_STRING_EQUAL(ref_key, "ref_key"); } - BC_ASSERT_PTR_EQUAL(linphone_call_log_get_user_data(call_log), &start_time); + BC_ASSERT_PTR_EQUAL(linphone_call_log_get_user_data(call_log), &user_data_time); call_id = linphone_call_log_get_call_id(call_log); BC_ASSERT_PTR_NOT_NULL(call_id); @@ -5762,7 +5765,8 @@ static void call_logs_sqlite_storage(void) { linphone_call_log_get_remote_address(call_log), linphone_proxy_config_get_identity_address(linphone_core_get_default_proxy_config(pauline->lc)))); BC_ASSERT_PTR_NOT_NULL(linphone_call_log_get_remote_stats(call_log)); - BC_ASSERT_GREATER(linphone_call_log_get_start_date(call_log), start_time, int, "%d"); + BC_ASSERT_PTR_NOT_NULL(linphone_call_log_get_start_date(call_log)); + BC_ASSERT_EQUAL(linphone_call_log_get_start_date(call_log), start_time, int, "%d"); BC_ASSERT_EQUAL(linphone_call_log_get_status(call_log), LinphoneCallSuccess, int, "%d"); } diff --git a/tester/dtmf_tester.c b/tester/dtmf_tester.c index 616002aae..abfeef7cb 100644 --- a/tester/dtmf_tester.c +++ b/tester/dtmf_tester.c @@ -36,7 +36,9 @@ void send_dtmf_base(LinphoneCoreManager **pmarie, LinphoneCoreManager **ppauline LinphoneCall *marie_call = NULL; if (use_opus) { - if (!ms_filter_codec_supported("opus")) { + //if (!ms_filter_codec_supported("opus")) { + if(!ms_factory_codec_supported(marie->lc->factory, "opus") && !ms_factory_codec_supported(pauline->lc->factory, "opus")){ + ms_warning("Opus not supported, skipping test."); return; } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index c852b7c68..37dd5543b 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -259,6 +259,7 @@ typedef struct _LinphoneConferenceServer { LinphoneCoreManager base; LinphoneCall *first_call; LinphoneCoreVTable *vtable; + LinphoneRegistrationState reg_state; } LinphoneConferenceServer; typedef struct _LinphoneCallTestParams { @@ -362,7 +363,7 @@ void liblinphone_tester_uninit(void); int liblinphone_tester_set_log_file(const char *filename); bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, LinphoneIceState state); -LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file); +LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file, bool_t do_registration); void linphone_conference_server_destroy(LinphoneConferenceServer *conf_srv); extern const char *liblinphone_tester_mire_id; diff --git a/tester/liblinphone_tester_windows.cpp b/tester/liblinphone_tester_windows.cpp index 015af02d2..1748e712b 100644 --- a/tester/liblinphone_tester_windows.cpp +++ b/tester/liblinphone_tester_windows.cpp @@ -108,7 +108,7 @@ bool NativeTester::run(Platform::String^ suiteName, Platform::String^ caseName, linphone_core_set_log_level_mask(ORTP_FATAL); } linphone_core_set_log_handler(libLinphoneNativeOutputTraceHandler); - return bc_tester_run_tests(wssuitename == all ? 0 : csuitename, wscasename == all ? 0 : ccasename) != 0; + return bc_tester_run_tests(wssuitename == all ? 0 : csuitename, wscasename == all ? 0 : ccasename, NULL) != 0; } void NativeTester::runAllToXml() diff --git a/tester/multi_call_tester.c b/tester/multi_call_tester.c index 58474c041..a7f00e855 100644 --- a/tester/multi_call_tester.c +++ b/tester/multi_call_tester.c @@ -188,6 +188,7 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag LinphoneConference *conference; const MSList* calls; bool_t is_remote_conf; + bool_t focus_is_up = (focus && ((LinphoneConferenceServer *)focus)->reg_state == LinphoneRegistrationOk); MSList* lcs=ms_list_append(NULL,marie->lc); lcs=ms_list_append(lcs,pauline->lc); lcs=ms_list_append(lcs,laure->lc); @@ -213,9 +214,21 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag if(!is_remote_conf) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallUpdating,initial_marie_stat.number_of_LinphoneCallUpdating+1,5000)); } else { - BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,initial_marie_stat.number_of_LinphoneCallStreamsRunning+1,5000)); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallConnected,initial_marie_stat.number_of_LinphoneTransferCallConnected+1,5000)); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,initial_marie_stat.number_of_LinphoneCallEnd+1,5000)); + if(focus_is_up) { + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,initial_marie_stat.number_of_LinphoneCallStreamsRunning+1,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallConnected,initial_marie_stat.number_of_LinphoneTransferCallConnected+1,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,initial_marie_stat.number_of_LinphoneCallEnd+1,5000)); + } else { + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallError, initial_marie_stat.number_of_LinphoneCallError+1, 5000)); + BC_ASSERT_PTR_NULL(linphone_core_get_conference(marie->lc)); + BC_ASSERT_EQUAL(linphone_core_terminate_conference(marie->lc), -1, int, "%d"); + linphone_core_terminate_call(marie->lc, marie_call_pauline); + linphone_core_terminate_call(marie->lc, marie_call_laure); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallEnd, initial_marie_stat.number_of_LinphoneCallEnd+2, 10000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEnd, initial_pauline_stat.number_of_LinphoneCallEnd+1, 5000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneCallEnd, initial_laure_stat.number_of_LinphoneCallEnd+1, 5000)); + goto end; + } } linphone_core_add_to_conference(marie->lc,marie_call_pauline); @@ -267,11 +280,11 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag } linphone_core_terminate_conference(marie->lc); - BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,is_remote_conf?2:1,10000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,is_remote_conf?3:1,10000)); BC_ASSERT_TRUE(wait_for_list(lcs,&laure->stat.number_of_LinphoneCallEnd,is_remote_conf?2:1,10000)); - + +end: ms_list_free(lcs); } @@ -766,7 +779,38 @@ void simple_remote_conference(void) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); LinphoneCoreManager *laure = linphone_core_manager_new("laure_rc"); - LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc"); + LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc", TRUE); + LpConfig *marie_config = linphone_core_get_config(marie->lc); + LinphoneProxyConfig *focus_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)focus)->lc); + LinphoneProxyConfig *laure_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)laure)->lc); + const char *laure_proxy_uri = linphone_proxy_config_get_server_addr(laure_proxy_config); + const char *focus_uri = linphone_proxy_config_get_identity(focus_proxy_config); + int laure_n_register = laure->stat.number_of_LinphoneRegistrationOk; + MSList *lcs = NULL; + + lp_config_set_string(marie_config, "misc", "conference_type", "remote"); + lp_config_set_string(marie_config, "misc", "conference_focus_addr", focus_uri); + + linphone_proxy_config_edit(laure_proxy_config); + linphone_proxy_config_set_route(laure_proxy_config, laure_proxy_uri); + linphone_proxy_config_done(laure_proxy_config); + lcs = ms_list_append(lcs, laure->lc); + BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphoneRegistrationOk, laure_n_register+1, 5000)); + ms_list_free(lcs); + + simple_conference_base(marie, pauline, laure, (LinphoneCoreManager *)focus); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + linphone_conference_server_destroy(focus); +} + +void simple_remote_conference_shut_down_focus(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCoreManager *laure = linphone_core_manager_new("laure_rc"); + LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc", FALSE); LpConfig *marie_config = linphone_core_get_config(marie->lc); LinphoneProxyConfig *focus_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)focus)->lc); LinphoneProxyConfig *laure_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)laure)->lc); @@ -797,7 +841,7 @@ void eject_from_3_participants_remote_conference(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc"); - LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc"); + LinphoneConferenceServer *focus = linphone_conference_server_new("conference_focus_rc", TRUE); LpConfig *marie_config = linphone_core_get_config(marie->lc); LinphoneProxyConfig *focus_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)focus)->lc); LinphoneProxyConfig *laure_proxy_config = linphone_core_get_default_proxy_config(((LinphoneCoreManager *)laure)->lc); @@ -840,7 +884,8 @@ test_t multi_call_tests[] = { TEST_NO_TAG("Unattended call transfer with error", unattended_call_transfer_with_error), TEST_NO_TAG("Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call), TEST_NO_TAG("Simple remote conference", simple_remote_conference), - TEST_NO_TAG("Eject from 3 participants in remote conference", eject_from_3_participants_remote_conference) + TEST_NO_TAG("Simple remote conference with shut down focus", simple_remote_conference_shut_down_focus), + TEST_NO_TAG("Eject from 3 participants in remote conference", eject_from_3_participants_remote_conference), }; test_suite_t multi_call_test_suite = {"Multi call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/player_tester.c b/tester/player_tester.c index 3354c5fa2..7625329ed 100644 --- a/tester/player_tester.c +++ b/tester/player_tester.c @@ -44,10 +44,12 @@ static void play_file(const char *filename, bool_t supported_format, const char BC_ASSERT_PTR_NOT_NULL(lc_manager); if(lc_manager == NULL) return; - audio_codec_supported = (audio_mime && ms_factory_get_decoder(ms_factory_get_fallback(), audio_mime)); - video_codec_supported = (video_mime && ms_factory_get_decoder(ms_factory_get_fallback(), video_mime)); + audio_codec_supported = (audio_mime && ms_factory_get_decoder(linphone_core_get_ms_factory((void *)lc_manager->lc), audio_mime)); + video_codec_supported = (video_mime && ms_factory_get_decoder(linphone_core_get_ms_factory((void *)lc_manager->lc), video_mime)); - player = linphone_core_create_local_player(lc_manager->lc, ms_snd_card_manager_get_default_card(ms_snd_card_manager_get()), video_stream_get_default_video_renderer(), 0); + player = linphone_core_create_local_player(lc_manager->lc, + ms_snd_card_manager_get_default_card(ms_factory_get_snd_card_manager(linphone_core_get_ms_factory((void *)lc_manager->lc))), + video_stream_get_default_video_renderer(), 0); BC_ASSERT_PTR_NOT_NULL(player); if(player == NULL) goto fail; diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 13c603156..6d53c5dd9 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -130,7 +130,10 @@ static void simple_publish_with_expire(int expires) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneProxyConfig* proxy; LinphonePresenceModel* presence; - + LinphoneCoreVTable *vtable = linphone_core_v_table_new(); + vtable->publish_state_changed = linphone_publish_state_changed; + _linphone_core_add_listener(marie->lc, vtable, TRUE, TRUE ); + proxy = linphone_core_get_default_proxy_config(marie->lc); linphone_proxy_config_edit(proxy); if (expires >0) { @@ -138,11 +141,44 @@ static void simple_publish_with_expire(int expires) { } linphone_proxy_config_enable_publish(proxy,TRUE); linphone_proxy_config_done(proxy); - wait_core(marie->lc); + + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,1)); + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,1)); + presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,NULL); linphone_core_set_presence_model(marie->lc,presence); - wait_core(marie->lc); + + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,2)); + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,2)); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_done(proxy); + /*make sure no publish is sent*/ + BC_ASSERT_FALSE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3,expires*1000/2)); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_enable_publish(proxy,FALSE); + linphone_proxy_config_done(proxy); + + /*BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3));*/ + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishCleared,1)); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_enable_publish(proxy,TRUE); + linphone_proxy_config_done(proxy); + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,3)); + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,3)); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_set_publish_expires(proxy, linphone_proxy_config_get_publish_expires(proxy)+1); + linphone_proxy_config_done(proxy); + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishProgress,4)); + BC_ASSERT_TRUE(wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphonePublishOk,4)); + linphone_core_manager_destroy(marie); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,2,int,"%i"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,4,int,"%i"); + } static void simple_publish(void) { @@ -150,7 +186,7 @@ static void simple_publish(void) { } static void publish_with_expires(void) { - simple_publish_with_expire(1); + simple_publish_with_expire(2); } static bool_t subscribe_to_callee_presence(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr) { @@ -490,7 +526,7 @@ static void test_subscribe_notify_publish(void) { LpConfig *pauline_lp; char* lf_identity; LinphoneFriend *lf; - + linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); pauline_lp = linphone_core_get_config(pauline->lc); @@ -502,7 +538,7 @@ static void test_subscribe_notify_publish(void) { linphone_core_add_friend(pauline->lc,lf); /*wait for subscribe acknowledgment*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,1,2000); + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,1,2000)); BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d"); /*enable publish*/ @@ -515,18 +551,18 @@ static void test_subscribe_notify_publish(void) { linphone_proxy_config_done(proxy); /*wait for marie status*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,2,2000); + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,2,2000)); BC_ASSERT_EQUAL(LinphoneStatusOnline,linphone_friend_get_status(lf), int, "%d"); presence =linphone_presence_model_new_with_activity(LinphonePresenceActivityBusy,NULL); linphone_core_set_presence_model(marie->lc,presence); /*wait for new status*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,3,2000); + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,3,2000)); BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*wait for refresh*/ - wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,4,5000); + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_NotifyPresenceReceived,4,5000)); BC_ASSERT_EQUAL(LinphoneStatusBusy,linphone_friend_get_status(lf), int, "%d"); /*linphone_core_remove_friend(pauline->lc,lf);*/ @@ -535,10 +571,24 @@ static void test_subscribe_notify_publish(void) { BC_ASSERT_EQUAL(LinphonePresenceActivityOffline,linphone_friend_get_status(lf), int, "%d"); */ - /*Expect a notify at publication expiration*/ - wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyPresenceReceived,6,5000); + /*Expect a notify at publication expiration because marie is no longuer scheduled*/ + BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_NotifyPresenceReceived,6,5000)); BC_ASSERT_EQUAL(LinphoneStatusOffline,linphone_friend_get_status(lf), int, "%d"); + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphonePresenceActivityBusy,4,5000));/*re- schedule marie to clean up things*/ + + /*simulate a rapid presence change to make sure only first and last are transmited*/ + linphone_core_set_presence_model(marie->lc,linphone_presence_model_new_with_activity(LinphonePresenceActivityAway,NULL)); + linphone_core_set_presence_model(marie->lc,linphone_presence_model_new_with_activity(LinphonePresenceActivityBreakfast,NULL)); + linphone_core_set_presence_model(marie->lc,linphone_presence_model_new_with_activity(LinphonePresenceActivityAppointment,NULL)); + + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphonePresenceActivityAppointment,1,5000)); + + BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePresenceActivityAway, 1, int,"%i"); + BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePresenceActivityBreakfast, 0, int,"%i"); + BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePresenceActivityAppointment, 1, int,"%i"); + + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -731,6 +781,7 @@ static void test_presence_list(void) { lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); + ms_message("Disabling publish"); enable_publish(laure, FALSE); enable_publish(marie, FALSE); enable_publish(pauline, FALSE); @@ -826,7 +877,7 @@ static void test_presence_list_subscription_expire_for_unknown(void) { linphone_core_manager_destroy(laure); } -static void test_presence_list_subscribe_dialog_expire(void) { +static void test_presence_list_subscribe_with_error(bool_t io_error) { LinphoneCoreManager *laure = linphone_core_manager_new("laure_tcp_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); const char *rls_uri = "sip:rls@sip.example.org"; @@ -835,7 +886,7 @@ static void test_presence_list_subscribe_dialog_expire(void) { const char *pauline_identity; MSList* lcs = NULL; int dummy = 0; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 3); + lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); pauline_identity = get_identity(pauline); @@ -860,7 +911,7 @@ static void test_presence_list_subscribe_dialog_expire(void) { wait_for_list(lcs, &dummy, 1, 2000); /* Wait a little bit for the subscribe to happen */ enable_publish(pauline, TRUE); - wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 2000); + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 1, 6000)); BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); BC_ASSERT_GREATER(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); @@ -872,21 +923,26 @@ static void test_presence_list_subscribe_dialog_expire(void) { BC_ASSERT_EQUAL(lf->presence_received, FALSE, int, "%d"); BC_ASSERT_EQUAL(lf->subscribe_active, TRUE, int, "%d"); - BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_NotifyPresenceReceived, 2, 5000)); - ms_message("Simulating in/out packets losses"); - sal_set_send_error(laure->lc->sal,1500); /*make sure no refresh is sent, trash the message without generating error*/ - sal_set_recv_error(laure->lc->sal, 1500); /*make sure server notify to close the dialog is also ignored*/ - - wait_for_list(lcs, &dummy, 1, 3000); /* Wait a little bit for the subscribe to happen */ - + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 2, 6000)); + if (io_error) { + ms_message("Simulating socket error"); + sal_set_recv_error(laure->lc->sal, -1); + wait_for_list(lcs, &dummy, 1, 500); /* just time for socket to be closed */ + } else { + ms_message("Simulating in/out packets losses"); + sal_set_send_error(laure->lc->sal,1500); /*make sure no refresh is sent, trash the message without generating error*/ + sal_set_recv_error(laure->lc->sal, 1500); /*make sure server notify to close the dialog is also ignored*/ + wait_for_list(lcs, &dummy, 1, 5000); /* Wait a little bit for the subscribe to happen */ + } /*restart normal behavior*/ sal_set_send_error(laure->lc->sal,0); sal_set_recv_error(laure->lc->sal, 1); + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 3, 6000)); /* give time for subscription to recover to avoid to receive 491 Request pending*/ linphone_core_set_presence_model(pauline->lc, linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityAway, NULL)); - BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_NotifyPresenceReceived, 3, 5000)); + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 1, 6000)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); @@ -894,7 +950,13 @@ static void test_presence_list_subscribe_dialog_expire(void) { linphone_core_manager_destroy(pauline); } +static void test_presence_list_subscribe_dialog_expire(void) { + test_presence_list_subscribe_with_error(FALSE); +} +static void test_presence_list_subscribe_io_error(void) { + test_presence_list_subscribe_with_error(TRUE); +} test_t presence_tests[] = { TEST_NO_TAG("Simple Subscribe", simple_subscribe), @@ -911,7 +973,8 @@ test_t presence_tests[] = { TEST_NO_TAG("Forked subscribe with late publish", test_forked_subscribe_notify_publish), TEST_NO_TAG("Presence list", test_presence_list), TEST_NO_TAG("Presence list, subscription expiration for unknown contact",test_presence_list_subscription_expire_for_unknown), - TEST_NO_TAG("Presence list, silent subscription expiration", test_presence_list_subscribe_dialog_expire) + TEST_NO_TAG("Presence list, silent subscription expiration", test_presence_list_subscribe_dialog_expire), + TEST_NO_TAG("Presence list, io error",test_presence_list_subscribe_io_error) }; test_suite_t presence_test_suite = {"Presence", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/register_tester.c b/tester/register_tester.c index a8fa71a82..4c062af9e 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -235,7 +235,7 @@ static void change_expires(void){ LinphoneProxyConfig* proxy_config; register_with_refresh_base(lcm->lc,FALSE,NULL,NULL); - linphone_core_get_default_proxy(lcm->lc,&proxy_config); + proxy_config = linphone_core_get_default_proxy_config(lcm->lc); linphone_proxy_config_edit(proxy_config); reset_counters(counters); /*clear stats*/ diff --git a/tester/tester.c b/tester/tester.c index 4b23f3f79..430d30d4d 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -248,7 +248,7 @@ LinphoneCoreManager *get_manager(LinphoneCore *lc){ } bool_t transport_supported(LinphoneTransportType transport) { - Sal *sal = sal_init(); + Sal *sal = sal_init(NULL); bool_t supported = sal_transport_available(sal,(SalTransport)transport); if (!supported) ms_message("TLS transport not supported, falling back to TCP if possible otherwise skipping test."); sal_uninit(sal); @@ -296,13 +296,13 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file) { { MSWebCam *cam; - cam = ms_web_cam_manager_get_cam(ms_web_cam_manager_get(), "Mire: Mire (synthetic moving picture)"); + cam = ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(mgr->lc->factory), "Mire: Mire (synthetic moving picture)"); if (cam == NULL) { MSWebCamDesc *desc = ms_mire_webcam_desc_get(); if (desc){ cam=ms_web_cam_new(desc); - ms_web_cam_manager_add_cam(ms_web_cam_manager_get(), cam); + ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(mgr->lc->factory), cam); } } } @@ -668,7 +668,7 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph return video_enabled ? (realtime_text_enabled ? text_success && audio_success && video_success : audio_success && video_success) : realtime_text_enabled ? text_success && audio_success : audio_success; } -void linphone_conference_server_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) { +static void linphone_conference_server_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) { LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); LinphoneConferenceServer *conf_srv = (LinphoneConferenceServer *)vtable->user_data; @@ -697,7 +697,7 @@ void linphone_conference_server_call_state_changed(LinphoneCore *lc, LinphoneCal } } -void linphone_conference_server_refer_received(LinphoneCore *core, const char *refer_to) { +static void linphone_conference_server_refer_received(LinphoneCore *core, const char *refer_to) { char method[20]; LinphoneAddress *refer_to_addr = linphone_address_new(refer_to); char *uri; @@ -715,17 +715,30 @@ void linphone_conference_server_refer_received(LinphoneCore *core, const char *r linphone_address_destroy(refer_to_addr); } -LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file) { +static void linphone_conference_server_registration_state_changed(LinphoneCore *core, + LinphoneProxyConfig *cfg, + LinphoneRegistrationState cstate, + const char *message) { + LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(core); + LinphoneConferenceServer *m = (LinphoneConferenceServer *)linphone_core_v_table_get_user_data(vtable); + if(cfg == linphone_core_get_default_proxy_config(core)) { + m->reg_state = cstate; + } +} + +LinphoneConferenceServer* linphone_conference_server_new(const char *rc_file, bool_t do_registration) { LinphoneConferenceServer *conf_srv = (LinphoneConferenceServer *)ms_new0(LinphoneConferenceServer, 1); LinphoneCoreManager *lm = (LinphoneCoreManager *)conf_srv; conf_srv->vtable = linphone_core_v_table_new(); conf_srv->vtable->call_state_changed = linphone_conference_server_call_state_changed; conf_srv->vtable->refer_received = linphone_conference_server_refer_received; + conf_srv->vtable->registration_state_changed = linphone_conference_server_registration_state_changed; conf_srv->vtable->user_data = conf_srv; + conf_srv->reg_state = LinphoneRegistrationNone; linphone_core_manager_init(lm, rc_file); linphone_core_add_listener(lm->lc, conf_srv->vtable); - linphone_core_manager_start(lm, TRUE); + linphone_core_manager_start(lm, do_registration); return conf_srv; } diff --git a/tools/auto_answer.c b/tools/auto_answer.c index 8cedc9bc0..133b88d84 100644 --- a/tools/auto_answer.c +++ b/tools/auto_answer.c @@ -164,7 +164,7 @@ int main(int argc, char *argv[]){ { MSWebCamDesc *desc = ms_mire_webcam_desc_get(); if (desc){ - ms_web_cam_manager_add_cam(ms_web_cam_manager_get(),ms_web_cam_new(desc)); + ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(linphone_core_get_ms_factory(lc)),ms_web_cam_new(desc)); linphone_core_set_video_device(lc,"Mire: Mire (synthetic moving picture)"); } } diff --git a/tools/test_lsd.c b/tools/test_lsd.c index ed38fedde..9c308cb04 100644 --- a/tools/test_lsd.c +++ b/tools/test_lsd.c @@ -51,7 +51,7 @@ int main(int argc, char *argv[]) { linphone_core_enable_logs(stdout); lc = linphone_core_new(&vtable, NULL, NULL, NULL); - lsd = linphone_sound_daemon_new(NULL, 44100, 1); + lsd = linphone_sound_daemon_new(linphone_core_get_ms_factory(lc), NULL, 44100, 1); linphone_core_use_sound_daemon(lc, lsd);