--- linphone-1.6.0/coreapi/Makefile.am 2006-08-09 15:01:57.000000000 +0200 +++ linphone-1.6.0-yea/coreapi/Makefile.am 2007-01-28 18:45:12.000000000 +0100 @@ -26,7 +26,8 @@ liblinphone_la_SOURCES=\ friend.c \ authentication.c \ lpconfig.c lpconfig.h \ - chat.c + chat.c \ + general_state.c liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) --- linphone-1.6.0/coreapi/authentication.c 2006-08-09 15:01:57.000000000 +0200 +++ linphone-1.6.0-yea/coreapi/authentication.c 2007-01-28 18:45:12.000000000 +0100 @@ -246,12 +246,16 @@ void linphone_register_authentication_re ms_return_if_fail(resp!=NULL); cfg=linphone_core_get_proxy_config_from_rid(lc,ev->rid); ms_return_if_fail(cfg!=NULL); + if (cfg->auth_pending) + gstate_new_state(lc, GSTATE_REG_FAILED, "Authentication required"); if (linphone_process_authentication(lc,resp,cfg,cfg->auth_pending)){ /* we have the information, so retry the register */ eXosip_lock(); eXosip_register(ev->rid,-1); eXosip_unlock(); } + else + gstate_new_state(lc, GSTATE_REG_FAILED, "Authentication required"); cfg->auth_pending=TRUE; } --- linphone-1.6.0/coreapi/exevents.c 2006-12-28 14:42:51.000000000 +0100 +++ linphone-1.6.0-yea/coreapi/exevents.c 2007-01-28 18:45:12.000000000 +0100 @@ -56,6 +56,7 @@ int linphone_call_accepted(LinphoneCore sdp_context_read_answer(lc->call->sdpctx,sdpbody); lc->vtable.show(lc); lc->vtable.display_status(lc,_("Connected.")); + gstate_new_state(lc, GSTATE_CALL_OUT_CONNECTED, NULL); lc->call->state=LCStateAVRunning; if (lc->ringstream!=NULL){ ring_stop(lc->ringstream); @@ -86,6 +87,7 @@ int linphone_call_terminated(LinphoneCor linphone_core_stop_media_streams(lc); lc->vtable.show(lc); lc->vtable.display_status(lc,_("Call terminated.")); + gstate_new_state(lc, GSTATE_CALL_END, NULL); if (lc->vtable.bye_recv!=NULL) lc->vtable.bye_recv(lc,ev->remote_uri); if (lc->call!=NULL){ @@ -103,6 +105,7 @@ int linphone_call_released(LinphoneCore linphone_call_destroy(lc->call); lc->call=NULL; lc->vtable.display_status(lc,_("Could not reach destination.")); + gstate_new_state(lc, GSTATE_CALL_ERROR, NULL); } return 0; } @@ -180,8 +183,11 @@ int linphone_call_failure(LinphoneCore * lc->ringstream=NULL; } linphone_core_stop_media_streams(lc); - if (lc->call!=NULL) linphone_call_destroy(lc->call); - lc->call=NULL; + if (lc->call!=NULL) { + linphone_call_destroy(lc->call); + gstate_new_state(lc, GSTATE_CALL_ERROR, NULL); + lc->call=NULL; + } return 0; } @@ -320,10 +326,15 @@ int linphone_inc_new_call(LinphoneCore * barmesg=ortp_strdup_printf("%s %s",tmp,_("is contacting you.")); lc->vtable.show(lc); lc->vtable.display_status(lc,barmesg); + gstate_new_state(lc, GSTATE_CALL_IN_INVITE, tmp); lc->vtable.inv_recv(lc,tmp); ms_free(barmesg); osip_free(tmp); } + else + { + gstate_new_state(lc, GSTATE_CALL_IN_INVITE, NULL); + } } break; default: @@ -677,6 +688,7 @@ void linphone_registration_faillure(Linp if (strlen(ev->reason_phrase)==0) msg=ortp_strdup_printf(_("Registration on %s failed (timeout)."),ev->req_uri); else msg=ev->reason_phrase; lc->vtable.display_status(lc,msg); + gstate_new_state(lc, GSTATE_REG_FAILED, msg); if ( msg != ev->reason_phrase ) ms_free(msg); } @@ -691,6 +703,7 @@ void linphone_registration_success(Linph ms_return_if_fail(cfg!=NULL); cfg->auth_pending=FALSE; cfg->registered=TRUE; + gstate_new_state(lc, GSTATE_REG_OK, NULL); } void linphone_core_process_event(LinphoneCore *lc,eXosip_event_t *ev) --- linphone-1.6.0/coreapi/general_state.c 1970-01-01 01:00:00.000000000 +0100 +++ linphone-1.6.0-yea/coreapi/general_state.c 2007-01-28 18:45:12.000000000 +0100 @@ -0,0 +1,101 @@ +/**************************************************************************** + * + * File: general_state.c + * + * Copyright (C) 2006, 2007 Thomas Reitmayr + * + **************************************************************************** + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + ****************************************************************************/ + + +#include "linphonecore.h" + + +static gstate_t _gstates[GSTATE_GROUP_CALL+1]; + +#if 0 +static const char *_gstates_text[] = { + "GSTATE_POWER_OFF", /* 0 */ + "GSTATE_POWER_STARTUP", /* 1 */ + "GSTATE_POWER_ON", /* 2 */ + "GSTATE_POWER_SHUTDOWN", /* 3 */ + NULL, NULL, NULL, NULL, NULL, NULL, + + "GSTATE_REG_NONE", /* 10 */ + "GSTATE_REG_OK", /* 11 */ + "GSTATE_REG_FAILED", /* 12 */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + "GSTATE_CALL_IDLE", /* 20 */ + "GSTATE_CALL_OUT_INVITE", /* 21 */ + "GSTATE_CALL_OUT_CONNECTED", /* 22 */ + "GSTATE_CALL_IN_INVITE", /* 23 */ + "GSTATE_CALL_IN_CONNECTED", /* 24 */ + "GSTATE_CALL_END", /* 25 */ + "GSTATE_CALL_ERROR" /* 26 */ +}; +#endif + +/* set the initial states */ +void gstate_initialize(void) { + _gstates[GSTATE_GROUP_POWER] = GSTATE_POWER_OFF; + _gstates[GSTATE_GROUP_REG] = GSTATE_REG_NONE; + _gstates[GSTATE_GROUP_CALL] = GSTATE_CALL_IDLE; +} + + +/* retrieve the current state of the specified state group */ +gstate_t gstate_get_state(gstate_group_t group) { + return _gstates[group]; +} + + +void gstate_new_state(struct _LinphoneCore *lc, + gstate_t new_state, + const char *message) { + LinphoneGeneralState states_arg; + + /* determine the affected group */ + if (new_state < GSTATE_REG_NONE) + states_arg.group = GSTATE_GROUP_POWER; + else if (new_state < GSTATE_CALL_IDLE) + states_arg.group = GSTATE_GROUP_REG; + else + states_arg.group = GSTATE_GROUP_CALL; + + /* store the new state while remembering the old one */ + states_arg.new_state = new_state; + states_arg.old_state = _gstates[states_arg.group]; + _gstates[states_arg.group] = new_state; + states_arg.message = message; + + /*printf("gstate_new_state: %s\t-> %s\t(%s)\n", + _gstates_text[states_arg.old_state], + _gstates_text[states_arg.new_state], + message);*/ + + /* call the virtual method */ + if (lc->vtable.general_state) + lc->vtable.general_state(lc, &states_arg); + + /* immediately proceed to idle state */ + if (new_state == GSTATE_CALL_END || + new_state == GSTATE_CALL_ERROR) + gstate_new_state(lc, GSTATE_CALL_IDLE, NULL); +} + --- linphone-1.6.0/coreapi/linphonecore.c 2007-01-21 21:33:39.000000000 +0100 +++ linphone-1.6.0-yea/coreapi/linphonecore.c 2007-01-28 18:45:12.000000000 +0100 @@ -528,6 +528,14 @@ const char * linphone_core_get_version(v void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vtable, const char *config_path, void * userdata) { + memset (lc, 0, sizeof (LinphoneCore)); + lc->data=userdata; + + memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable)); + + gstate_initialize(); + gstate_new_state(lc, GSTATE_POWER_STARTUP, NULL); + ortp_init(); rtp_profile_set_payload(&av_profile,115,&payload_type_lpc1015); rtp_profile_set_payload(&av_profile,110,&payload_type_speex_nb); @@ -542,11 +550,6 @@ linphone_core_init (LinphoneCore * lc, c ms_init(); - memset (lc, 0, sizeof (LinphoneCore)); - lc->data=userdata; - - memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable)); - lc->config=lp_config_new(config_path); @@ -568,6 +571,7 @@ linphone_core_init (LinphoneCore * lc, c ui_config_read(lc); ms_mutex_init(&lc->lock,NULL); lc->vtable.display_status(lc,_("Ready")); + gstate_new_state(lc, GSTATE_POWER_ON, NULL); } LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable, @@ -1013,9 +1017,11 @@ int linphone_core_invite(LinphoneCore *l lc->vtable.display_warning(lc,_("Sorry, having multiple simultaneous calls is not supported yet !")); } + gstate_new_state(lc, GSTATE_CALL_OUT_INVITE, url); linphone_core_get_default_proxy(lc,&proxy); if (!linphone_core_interpret_url(lc,url,&real_url,&real_parsed_url)){ /* bad url */ + gstate_new_state(lc, GSTATE_CALL_ERROR, NULL); return -1; } barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); @@ -1059,6 +1065,8 @@ int linphone_core_invite(LinphoneCore *l if (real_url!=NULL) ms_free(real_url); if (real_parsed_url!=NULL) osip_to_free(real_parsed_url); if (parsed_url2!=NULL) osip_from_free(parsed_url2); + if (err<0) + gstate_new_state(lc, GSTATE_CALL_ERROR, NULL); return (err<0) ? -1 : 0; } @@ -1284,6 +1292,7 @@ int linphone_core_accept_call(LinphoneCo eXosip_answer_call_with_body(lc->call->did,200,"application/sdp",sdpmesg); eXosip_unlock(); lc->vtable.display_status(lc,_("Connected.")); + gstate_new_state(lc, GSTATE_CALL_IN_CONNECTED, NULL); linphone_core_start_media_streams(lc, lc->call); return 0; @@ -1308,6 +1317,7 @@ int linphone_core_terminate_call(Linphon } linphone_core_stop_media_streams(lc); lc->vtable.display_status(lc,_("Call ended") ); + gstate_new_state(lc, GSTATE_CALL_END, NULL); linphone_call_destroy(call); return 0; } @@ -1859,6 +1869,7 @@ LpConfig *linphone_core_get_config(Linph void linphone_core_uninit(LinphoneCore *lc) { + gstate_new_state(lc, GSTATE_POWER_SHUTDOWN, NULL); #ifdef VIDEO_ENABLED if (lc->previewstream!=NULL){ video_preview_stop(lc->previewstream); @@ -1880,6 +1891,7 @@ void linphone_core_uninit(LinphoneCore * ortp_exit(); eXosip_quit(); exosip_running=FALSE; + gstate_new_state(lc, GSTATE_POWER_OFF, NULL); } void linphone_core_destroy(LinphoneCore *lc){ --- linphone-1.6.0/coreapi/linphonecore.h 2006-11-29 14:50:48.000000000 +0100 +++ linphone-1.6.0-yea/coreapi/linphonecore.h 2007-01-28 18:45:12.000000000 +0100 @@ -301,6 +301,50 @@ void linphone_chat_room_destroy(Linphone void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud); void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr); +/* describes the different groups of states */ +typedef enum _gstate_group { + GSTATE_GROUP_POWER, + GSTATE_GROUP_REG, + GSTATE_GROUP_CALL +} gstate_group_t; + +typedef enum _gstate { + /* states for GSTATE_GROUP_POWER */ + GSTATE_POWER_OFF = 0, /* initial state */ + GSTATE_POWER_STARTUP, + GSTATE_POWER_ON, + GSTATE_POWER_SHUTDOWN, + /* states for GSTATE_GROUP_REG */ + GSTATE_REG_NONE = 10, /* initial state */ + GSTATE_REG_OK, + GSTATE_REG_FAILED, + /* states for GSTATE_GROUP_CALL */ + GSTATE_CALL_IDLE = 20, /* initial state */ + GSTATE_CALL_OUT_INVITE, + GSTATE_CALL_OUT_CONNECTED, + GSTATE_CALL_IN_INVITE, + GSTATE_CALL_IN_CONNECTED, + GSTATE_CALL_END, + GSTATE_CALL_ERROR +} gstate_t; + +struct _LinphoneGeneralState { + gstate_t old_state; + gstate_t new_state; + gstate_group_t group; + const char *message; +}; +typedef struct _LinphoneGeneralState LinphoneGeneralState; + +/* retrieve the current state of the specified state group */ +gstate_t gstate_get_state(gstate_group_t group); + +/* private: set the initial states */ +void gstate_initialize(void); + +/* private: set a new state */ +void gstate_new_state(struct _LinphoneCore *lc, gstate_t new_state, const char *message); + typedef void (*ShowInterfaceCb)(struct _LinphoneCore *lc); typedef void (*InviteReceivedCb)(struct _LinphoneCore *lc, const char *from); typedef void (*ByeReceivedCb)(struct _LinphoneCore *lc, const char *from); @@ -314,6 +358,7 @@ typedef void (*NewUnknownSubscriberCb)(s typedef void (*AuthInfoRequested)(struct _LinphoneCore *lc, const char *realm, const char *username); typedef void (*CallLogUpdated)(struct _LinphoneCore *lc, struct _LinphoneCallLog *newcl); typedef void (*TextMessageReceived)(struct _LinphoneCore *lc, LinphoneChatRoom *room, const char *from, const char *message); +typedef void (*GeneralStateChange)(struct _LinphoneCore *lc, LinphoneGeneralState *gstate); typedef struct _LinphoneVTable { @@ -334,6 +379,7 @@ typedef struct _LinphoneVTable DisplayQuestionCb display_question; CallLogUpdated call_log_updated; TextMessageReceived text_received; + GeneralStateChange general_state; } LinphoneCoreVTable; typedef struct _LCCallbackObj --- linphone-1.6.0/exosip/jcallback.c 2006-08-09 15:01:57.000000000 +0200 +++ linphone-1.6.0-yea/exosip/jcallback.c 2007-01-28 18:45:12.000000000 +0100 @@ -1874,7 +1874,7 @@ eXosip_set_callbacks(osip_t *osip) osip_set_kill_transaction_callback(osip ,OSIP_ICT_KILL_TRANSACTION, &cb_ict_kill_transaction); - osip_set_kill_transaction_callback(osip ,OSIP_NIST_KILL_TRANSACTION, + osip_set_kill_transaction_callback(osip ,OSIP_IST_KILL_TRANSACTION, &cb_ist_kill_transaction); osip_set_kill_transaction_callback(osip ,OSIP_NICT_KILL_TRANSACTION, &cb_nict_kill_transaction); --- linphone-1.6.0/exosip/udp.c 2006-08-25 15:32:39.000000000 +0200 +++ linphone-1.6.0-yea/exosip/udp.c 2007-01-28 18:45:12.000000000 +0100 @@ -783,6 +783,8 @@ static void eXosip_process_new_options(o return ; } + osip_list_add(eXosip.j_transactions, transaction, 0); + evt_answer = osip_new_outgoing_sipmessage(answer); evt_answer->transactionid = transaction->transactionid; --- linphone-1.6.0/console/linphonec.c 2007-01-10 15:11:24.000000000 +0100 +++ linphone-1.6.0-yea/console/linphonec.c 2007-01-28 18:46:46.000000000 +0100 @@ -131,7 +131,8 @@ LinphoneCoreVTable linphonec_vtable = { display_warning:linphonec_display_warning, display_url:linphonec_display_url, display_question:stub, - text_received:linphonec_text_received + text_received:linphonec_text_received, + general_state:NULL }; /***************************************************************************