3 * \brief event handling
5 * Copyright (C) 2004-2008 Ushodaya Enterprises Limited
6 * \author Charles Yates <charles.yates@pandora.be>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "mlt_properties.h"
29 #include "mlt_events.h"
31 /** Memory leak checks. */
33 #undef _MLT_EVENT_CHECKS_
35 #ifdef _MLT_EVENT_CHECKS_
36 static int events_created = 0;
37 static int events_destroyed = 0;
40 /** \brief Events class
44 struct mlt_events_struct
50 typedef struct mlt_events_struct *mlt_events;
52 /** \brief Event class
56 struct mlt_event_struct
61 mlt_listener listener;
65 /** Increment the reference count on this event.
68 void mlt_event_inc_ref( mlt_event this )
74 /** Increment the block count on this event.
77 void mlt_event_block( mlt_event this )
79 if ( this != NULL && this->owner != NULL )
83 /** Decrement the block count on this event.
86 void mlt_event_unblock( mlt_event this )
88 if ( this != NULL && this->owner != NULL )
95 void mlt_event_close( mlt_event this )
99 if ( -- this->ref_count == 1 )
101 if ( this->ref_count <= 0 )
103 #ifdef _MLT_EVENT_CHECKS_
105 fprintf( stderr, "Events created %d, destroyed %d\n", events_created, events_destroyed );
112 /* Forward declaration to private functions.
115 static mlt_events mlt_events_fetch( mlt_properties );
116 static void mlt_events_store( mlt_properties, mlt_events );
117 static void mlt_events_close( mlt_events );
119 /** Initialise the events structure.
122 void mlt_events_init( mlt_properties this )
124 mlt_events events = mlt_events_fetch( this );
125 if ( events == NULL )
127 events = malloc( sizeof( struct mlt_events_struct ) );
128 events->list = mlt_properties_new( );
129 mlt_events_store( this, events );
133 /** Register an event and transmitter.
136 int mlt_events_register( mlt_properties this, char *id, mlt_transmitter transmitter )
139 mlt_events events = mlt_events_fetch( this );
140 if ( events != NULL )
142 mlt_properties list = events->list;
144 error = mlt_properties_set_data( list, id, transmitter, 0, NULL, NULL );
145 sprintf( temp, "list:%s", id );
146 if ( mlt_properties_get_data( list, temp, NULL ) == NULL )
147 mlt_properties_set_data( list, temp, mlt_properties_new( ), 0, ( mlt_destructor )mlt_properties_close, NULL );
155 void mlt_events_fire( mlt_properties this, char *id, ... )
157 mlt_events events = mlt_events_fetch( this );
158 if ( events != NULL )
163 mlt_properties list = events->list;
164 mlt_properties listeners = NULL;
166 mlt_transmitter transmitter = mlt_properties_get_data( list, id, NULL );
167 sprintf( temp, "list:%s", id );
168 listeners = mlt_properties_get_data( list, temp, NULL );
170 va_start( alist, id );
172 args[ i ] = va_arg( alist, void * );
173 while( args[ i ++ ] != NULL );
176 if ( listeners != NULL )
178 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
180 mlt_event event = mlt_properties_get_data_at( listeners, i, NULL );
181 if ( event != NULL && event->owner != NULL && event->block_count == 0 )
183 if ( transmitter != NULL )
184 transmitter( event->listener, event->owner, event->service, args );
186 event->listener( event->owner, event->service );
193 /** Register a listener.
196 mlt_event mlt_events_listen( mlt_properties this, void *service, char *id, mlt_listener listener )
198 mlt_event event = NULL;
199 mlt_events events = mlt_events_fetch( this );
200 if ( events != NULL )
202 mlt_properties list = events->list;
203 mlt_properties listeners = NULL;
205 sprintf( temp, "list:%s", id );
206 listeners = mlt_properties_get_data( list, temp, NULL );
207 if ( listeners != NULL )
211 for ( i = 0; event == NULL && i < mlt_properties_count( listeners ); i ++ )
213 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
214 if ( entry != NULL && entry->owner != NULL )
216 if ( entry->service == service && entry->listener == listener )
219 else if ( ( entry == NULL || entry->owner == NULL ) && first_null == -1 )
227 event = malloc( sizeof( struct mlt_event_struct ) );
230 #ifdef _MLT_EVENT_CHECKS_
233 sprintf( temp, "%d", first_null == -1 ? mlt_properties_count( listeners ) : first_null );
234 event->owner = events;
235 event->ref_count = 0;
236 event->block_count = 0;
237 event->listener = listener;
238 event->service = service;
239 mlt_properties_set_data( listeners, temp, event, 0, ( mlt_destructor )mlt_event_close, NULL );
240 mlt_event_inc_ref( event );
249 /** Block all events for a given service.
252 void mlt_events_block( mlt_properties this, void *service )
254 mlt_events events = mlt_events_fetch( this );
255 if ( events != NULL )
258 mlt_properties list = events->list;
259 for ( j = 0; j < mlt_properties_count( list ); j ++ )
261 char *temp = mlt_properties_get_name( list, j );
262 if ( !strncmp( temp, "list:", 5 ) )
264 mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
265 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
267 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
268 if ( entry != NULL && entry->service == service )
269 mlt_event_block( entry );
276 /** Unblock all events for a given service.
279 void mlt_events_unblock( mlt_properties this, void *service )
281 mlt_events events = mlt_events_fetch( this );
282 if ( events != NULL )
285 mlt_properties list = events->list;
286 for ( j = 0; j < mlt_properties_count( list ); j ++ )
288 char *temp = mlt_properties_get_name( list, j );
289 if ( !strncmp( temp, "list:", 5 ) )
291 mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
292 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
294 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
295 if ( entry != NULL && entry->service == service )
296 mlt_event_unblock( entry );
303 /** Disconnect all events for a given service.
306 void mlt_events_disconnect( mlt_properties this, void *service )
308 mlt_events events = mlt_events_fetch( this );
309 if ( events != NULL )
312 mlt_properties list = events->list;
313 for ( j = 0; j < mlt_properties_count( list ); j ++ )
315 char *temp = mlt_properties_get_name( list, j );
316 if ( !strncmp( temp, "list:", 5 ) )
318 mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
319 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
321 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
322 char *name = mlt_properties_get_name( listeners, i );
323 if ( entry != NULL && entry->service == service )
324 mlt_properties_set_data( listeners, name, NULL, 0, NULL, NULL );
331 /** \brief private to mlt_events_struct, used by mlt_events_wait_for() */
337 pthread_mutex_t mutex;
341 static void mlt_events_listen_for( mlt_properties this, condition_pair *pair )
343 pthread_mutex_lock( &pair->mutex );
344 if ( pair->done == 0 )
346 pthread_cond_signal( &pair->cond );
347 pthread_mutex_unlock( &pair->mutex );
351 mlt_event mlt_events_setup_wait_for( mlt_properties this, char *id )
353 condition_pair *pair = malloc( sizeof( condition_pair ) );
355 pthread_cond_init( &pair->cond, NULL );
356 pthread_mutex_init( &pair->mutex, NULL );
357 pthread_mutex_lock( &pair->mutex );
358 return mlt_events_listen( this, pair, id, ( mlt_listener )mlt_events_listen_for );
361 void mlt_events_wait_for( mlt_properties this, mlt_event event )
365 condition_pair *pair = event->service;
366 pthread_cond_wait( &pair->cond, &pair->mutex );
370 void mlt_events_close_wait_for( mlt_properties this, mlt_event event )
374 condition_pair *pair = event->service;
377 pthread_mutex_unlock( &pair->mutex );
378 pthread_mutex_destroy( &pair->mutex );
379 pthread_cond_destroy( &pair->cond );
383 /** Fetch the events object.
386 static mlt_events mlt_events_fetch( mlt_properties this )
388 mlt_events events = NULL;
390 events = mlt_properties_get_data( this, "_events", NULL );
394 /** Store the events object.
397 static void mlt_events_store( mlt_properties this, mlt_events events )
399 if ( this != NULL && events != NULL )
400 mlt_properties_set_data( this, "_events", events, 0, ( mlt_destructor )mlt_events_close, NULL );
403 /** Close the events object.
406 static void mlt_events_close( mlt_events events )
408 if ( events != NULL )
410 mlt_properties_close( events->list );