vtables.c 11.3 KB
Newer Older
Simon Morlat's avatar
Simon Morlat committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
/*
linphone
Copyright (C) 2000  Simon MORLAT (simon.morlat@linphone.org)
Copyright (C) 2010  Belledonne Communications SARL

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

#include "private.h"


LinphoneCoreVTable *linphone_core_v_table_new() {
	return ms_new0(LinphoneCoreVTable,1);
}

void linphone_core_v_table_set_user_data(LinphoneCoreVTable *table, void *data) {
	table->user_data = data;
}

void* linphone_core_v_table_get_user_data(LinphoneCoreVTable *table) {
	return table->user_data;
}

void linphone_core_v_table_destroy(LinphoneCoreVTable* table) {
	ms_free(table);
}

LinphoneCoreVTable *linphone_core_get_current_vtable(LinphoneCore *lc) {
	return lc->current_vtable;
}

static void cleanup_dead_vtable_refs(LinphoneCore *lc){
	MSList *it,*next_it;
	for(it=lc->vtable_refs; it!=NULL; ){
		VTableReference *ref=(VTableReference*)it->data;
		next_it=it->next;
		if (ref->valid==0){
			ref->valid=0;
			lc->vtable_refs=ms_list_remove_link(lc->vtable_refs, it);
			ms_free(ref);
		}
		it=next_it;
	}
}

58
#define NOTIFY_IF_EXIST(function_name, ...) \
Simon Morlat's avatar
Simon Morlat committed
59 60
	MSList* iterator; \
	VTableReference *ref; \
61 62 63
	bool_t has_cb = FALSE; \
	for (iterator=lc->vtable_refs; iterator!=NULL; iterator=iterator->next)\
		if ((ref=(VTableReference*)iterator->data)->valid && (lc->current_vtable=ref->vtable)->function_name) {\
64
			lc->current_vtable->function_name(__VA_ARGS__);\
65 66 67
			has_cb = TRUE;\
		}\
	if (has_cb) ms_message("Linphone core [%p] notifying [%s]",lc,#function_name)
Simon Morlat's avatar
Simon Morlat committed
68

69
#define NOTIFY_IF_EXIST_INTERNAL(function_name, internal_val, ...) \
70 71 72 73
	MSList* iterator; \
	VTableReference *ref; \
	bool_t has_cb = FALSE; \
	for (iterator=lc->vtable_refs; iterator!=NULL; iterator=iterator->next)\
74
		if ((ref=(VTableReference*)iterator->data)->valid && (lc->current_vtable=ref->vtable)->function_name && (ref->internal == internal_val)) {\
75 76 77 78 79
			lc->current_vtable->function_name(__VA_ARGS__);\
			has_cb = TRUE;\
		}\
	if (has_cb) ms_message("Linphone core [%p] notifying [%s]",lc,#function_name)

Simon Morlat's avatar
Simon Morlat committed
80
void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) {
81
	NOTIFY_IF_EXIST(global_state_changed,lc,gstate,message);
Simon Morlat's avatar
Simon Morlat committed
82 83 84 85
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message){
86
	NOTIFY_IF_EXIST(call_state_changed, lc,call,cstate,message);
Simon Morlat's avatar
Simon Morlat committed
87 88 89 90
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) {
91
	NOTIFY_IF_EXIST(call_encryption_changed, lc,call,on,authentication_token);
Simon Morlat's avatar
Simon Morlat committed
92 93 94 95
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
96
	NOTIFY_IF_EXIST(registration_state_changed, lc,cfg,cstate,message);
Simon Morlat's avatar
Simon Morlat committed
97 98
	cleanup_dead_vtable_refs(lc);
}
jehan's avatar
jehan committed
99
#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
100
#pragma GCC diagnostic push
jehan's avatar
jehan committed
101
#endif
102
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Simon Morlat's avatar
Simon Morlat committed
103
void linphone_core_notify_show_interface(LinphoneCore *lc){
104
	NOTIFY_IF_EXIST(show, lc);
Simon Morlat's avatar
Simon Morlat committed
105 106 107 108
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_display_status(LinphoneCore *lc, const char *message) {
109
	NOTIFY_IF_EXIST(display_status, lc,message);
Simon Morlat's avatar
Simon Morlat committed
110 111 112 113
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_display_message(LinphoneCore *lc, const char *message){
114
	NOTIFY_IF_EXIST(display_message, lc,message);
Simon Morlat's avatar
Simon Morlat committed
115 116 117 118
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message){
119
	NOTIFY_IF_EXIST(display_warning, lc,message);
Simon Morlat's avatar
Simon Morlat committed
120 121 122 123
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url){
124
	NOTIFY_IF_EXIST(display_url, lc,message,url);
Simon Morlat's avatar
Simon Morlat committed
125 126
	cleanup_dead_vtable_refs(lc);
}
jehan's avatar
jehan committed
127
#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
128
#pragma GCC diagnostic pop
jehan's avatar
jehan committed
129
#endif
Simon Morlat's avatar
Simon Morlat committed
130
void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf){
131
	NOTIFY_IF_EXIST(notify_presence_received, lc,lf);
Simon Morlat's avatar
Simon Morlat committed
132 133 134 135
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url){
136
	NOTIFY_IF_EXIST(new_subscription_requested, lc,lf,url);
Simon Morlat's avatar
Simon Morlat committed
137 138 139 140
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){
141
	NOTIFY_IF_EXIST(auth_info_requested, lc,realm,username,domain);
Simon Morlat's avatar
Simon Morlat committed
142 143 144 145
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl){
146
	NOTIFY_IF_EXIST(call_log_updated, lc,newcl);
Simon Morlat's avatar
Simon Morlat committed
147 148
	cleanup_dead_vtable_refs(lc);
}
jehan's avatar
jehan committed
149
#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
150
#pragma GCC diagnostic push
jehan's avatar
jehan committed
151
#endif
152
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Simon Morlat's avatar
Simon Morlat committed
153 154

void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){
155
	NOTIFY_IF_EXIST(text_received, lc,room,from,message);
Simon Morlat's avatar
Simon Morlat committed
156 157
	cleanup_dead_vtable_refs(lc);
}
jehan's avatar
jehan committed
158
#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
159
#pragma GCC diagnostic pop
jehan's avatar
jehan committed
160
#endif
Simon Morlat's avatar
Simon Morlat committed
161 162

void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message){
163
	NOTIFY_IF_EXIST(message_received, lc,room,message);
Simon Morlat's avatar
Simon Morlat committed
164 165
	cleanup_dead_vtable_refs(lc);
}
jehan's avatar
jehan committed
166
#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
167
#pragma GCC diagnostic push
jehan's avatar
jehan committed
168
#endif
169
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
Simon Morlat's avatar
Simon Morlat committed
170
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) {
171
	NOTIFY_IF_EXIST(file_transfer_recv, lc,message,content,buff,size);
Simon Morlat's avatar
Simon Morlat committed
172 173 174 175
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message,  const LinphoneContent* content, char* buff, size_t* size) {
176
	NOTIFY_IF_EXIST(file_transfer_send, lc,message,content,buff,size);
Simon Morlat's avatar
Simon Morlat committed
177 178 179 180
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) {
181
	NOTIFY_IF_EXIST(file_transfer_progress_indication, lc,message,content,offset,total);
Simon Morlat's avatar
Simon Morlat committed
182 183
	cleanup_dead_vtable_refs(lc);
}
jehan's avatar
jehan committed
184
#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4)
185
#pragma GCC diagnostic pop
jehan's avatar
jehan committed
186
#endif
Simon Morlat's avatar
Simon Morlat committed
187
void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) {
188
	NOTIFY_IF_EXIST(is_composing_received, lc,room);
Simon Morlat's avatar
Simon Morlat committed
189 190 191 192
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf) {
193
	NOTIFY_IF_EXIST(dtmf_received, lc,call,dtmf);
Simon Morlat's avatar
Simon Morlat committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207
	cleanup_dead_vtable_refs(lc);
}

bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc) {
	MSList* iterator;
	for (iterator=lc->vtable_refs; iterator!=NULL; iterator=iterator->next){
		VTableReference *ref=(VTableReference*)iterator->data;
		if (ref->valid && ref->vtable->dtmf_received)
			return TRUE;
	}
	return FALSE;
}

void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to) {
208
	NOTIFY_IF_EXIST(refer_received, lc,refer_to);
Simon Morlat's avatar
Simon Morlat committed
209 210 211 212
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf) {
213
	NOTIFY_IF_EXIST(buddy_info_updated, lc,lf);
Simon Morlat's avatar
Simon Morlat committed
214 215 216 217
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) {
218
	NOTIFY_IF_EXIST(transfer_state_changed, lc,transfered,new_call_state);
Simon Morlat's avatar
Simon Morlat committed
219 220 221 222
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats) {
223
	NOTIFY_IF_EXIST(call_stats_updated, lc,call,stats);
Simon Morlat's avatar
Simon Morlat committed
224 225 226 227
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg) {
228
	NOTIFY_IF_EXIST(info_received, lc,call,msg);
Simon Morlat's avatar
Simon Morlat committed
229 230 231 232
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) {
233
	NOTIFY_IF_EXIST(configuring_status, lc,status,message);
Simon Morlat's avatar
Simon Morlat committed
234 235 236 237
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) {
238
	NOTIFY_IF_EXIST(network_reachable, lc,reachable);
Simon Morlat's avatar
Simon Morlat committed
239 240 241 242
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) {
243
	NOTIFY_IF_EXIST_INTERNAL(notify_received, linphone_event_is_internal(lev), lc, lev, notified_event, body);
Simon Morlat's avatar
Simon Morlat committed
244 245 246 247
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) {
248
	NOTIFY_IF_EXIST_INTERNAL(subscription_state_changed,linphone_event_is_internal(lev), lc,lev,state);
Simon Morlat's avatar
Simon Morlat committed
249 250 251 252
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) {
253
	NOTIFY_IF_EXIST(publish_state_changed, lc,lev,state);
Simon Morlat's avatar
Simon Morlat committed
254 255 256 257
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info) {
258
	NOTIFY_IF_EXIST(log_collection_upload_state_changed, lc, state, info);
Simon Morlat's avatar
Simon Morlat committed
259 260 261 262
	cleanup_dead_vtable_refs(lc);
}

void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t offset, size_t total) {
263
	NOTIFY_IF_EXIST(log_collection_upload_progress_indication, lc, offset, total);
Simon Morlat's avatar
Simon Morlat committed
264 265 266
	cleanup_dead_vtable_refs(lc);
}

267
static VTableReference * v_table_reference_new(LinphoneCoreVTable *vtable, bool_t autorelease, bool_t internal){
Simon Morlat's avatar
Simon Morlat committed
268 269 270
	VTableReference *ref=ms_new0(VTableReference,1);
	ref->valid=1;
	ref->autorelease=autorelease;
271
	ref->internal = internal;
Simon Morlat's avatar
Simon Morlat committed
272 273 274 275 276 277 278 279 280
	ref->vtable=vtable;
	return ref;
}

void v_table_reference_destroy(VTableReference *ref){
	if (ref->autorelease) linphone_core_v_table_destroy(ref->vtable);
	ms_free(ref);
}

281
void _linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable, bool_t autorelease, bool_t internal) {
Simon Morlat's avatar
Simon Morlat committed
282
	ms_message("Vtable [%p] registered on core [%p]",lc,vtable);
283
	lc->vtable_refs=ms_list_append(lc->vtable_refs,v_table_reference_new(vtable, autorelease, internal));
Simon Morlat's avatar
Simon Morlat committed
284 285 286
}

void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable){
287
	_linphone_core_add_listener(lc, vtable, FALSE, FALSE);
Simon Morlat's avatar
Simon Morlat committed
288 289 290 291 292 293 294 295 296 297 298
}

void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable) {
	MSList *it;
	ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable);
	for(it=lc->vtable_refs; it!=NULL; it=it->next){
		VTableReference *ref=(VTableReference*)it->data;
		if (ref->vtable==vtable)
			ref->valid=0;
	}
}