2 * mlt_events.h -- event handling
3 * Copyright (C) 2004-2005 Ushodaya Enterprises Limited
4 * Author: Charles Yates <charles.yates@pandora.be>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include "mlt_properties.h"
27 #include "mlt_events.h"
29 /** Memory leak checks.
32 //#define _MLT_EVENT_CHECKS_
34 #ifdef _MLT_EVENT_CHECKS_
35 static int events_created = 0;
36 static int events_destroyed = 0;
39 struct mlt_events_struct
45 typedef struct mlt_events_struct *mlt_events;
47 struct mlt_event_struct
52 mlt_listener listener;
56 /** Increment the reference count on this event.
59 void mlt_event_inc_ref( mlt_event this )
65 /** Increment the block count on this event.
68 void mlt_event_block( mlt_event this )
70 if ( this != NULL && this->owner != NULL )
74 /** Decrement the block count on this event.
77 void mlt_event_unblock( mlt_event this )
79 if ( this != NULL && this->owner != NULL )
86 void mlt_event_close( mlt_event this )
90 if ( -- this->ref_count == 1 )
92 if ( this->ref_count <= 0 )
94 #ifdef _MLT_EVENT_CHECKS_
96 fprintf( stderr, "Events created %d, destroyed %d\n", events_created, events_destroyed );
103 /** Forward declaration to private functions.
106 static mlt_events mlt_events_fetch( mlt_properties );
107 static void mlt_events_store( mlt_properties, mlt_events );
108 static void mlt_events_close( mlt_events );
110 /** Initialise the events structure.
113 void mlt_events_init( mlt_properties this )
115 mlt_events events = mlt_events_fetch( this );
116 if ( events == NULL )
118 events = malloc( sizeof( struct mlt_events_struct ) );
119 events->list = mlt_properties_new( );
120 mlt_events_store( this, events );
124 /** Register an event and transmitter.
127 int mlt_events_register( mlt_properties this, char *id, mlt_transmitter transmitter )
130 mlt_events events = mlt_events_fetch( this );
131 if ( events != NULL )
133 mlt_properties list = events->list;
135 error = mlt_properties_set_data( list, id, transmitter, 0, NULL, NULL );
136 sprintf( temp, "list:%s", id );
137 if ( mlt_properties_get_data( list, temp, NULL ) == NULL )
138 mlt_properties_set_data( list, temp, mlt_properties_new( ), 0, ( mlt_destructor )mlt_properties_close, NULL );
146 void mlt_events_fire( mlt_properties this, char *id, ... )
148 mlt_events events = mlt_events_fetch( this );
149 if ( events != NULL )
154 mlt_properties list = events->list;
155 mlt_properties listeners = NULL;
157 mlt_transmitter transmitter = mlt_properties_get_data( list, id, NULL );
158 sprintf( temp, "list:%s", id );
159 listeners = mlt_properties_get_data( list, temp, NULL );
161 va_start( alist, id );
163 args[ i ] = va_arg( alist, void * );
164 while( args[ i ++ ] != NULL );
167 if ( listeners != NULL )
169 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
171 mlt_event event = mlt_properties_get_data_at( listeners, i, NULL );
172 if ( event != NULL && event->owner != NULL && event->block_count == 0 )
174 if ( transmitter != NULL )
175 transmitter( event->listener, event->owner, event->service, args );
177 event->listener( event->owner, event->service );
184 /** Register a listener.
187 mlt_event mlt_events_listen( mlt_properties this, void *service, char *id, mlt_listener listener )
189 mlt_event event = NULL;
190 mlt_events events = mlt_events_fetch( this );
191 if ( events != NULL )
193 mlt_properties list = events->list;
194 mlt_properties listeners = NULL;
196 sprintf( temp, "list:%s", id );
197 listeners = mlt_properties_get_data( list, temp, NULL );
198 if ( listeners != NULL )
202 for ( i = 0; event == NULL && i < mlt_properties_count( listeners ); i ++ )
204 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
205 if ( entry != NULL && entry->owner != NULL )
207 if ( entry->service == service && entry->listener == listener )
210 else if ( ( entry == NULL || entry->owner == NULL ) && first_null == -1 )
218 event = malloc( sizeof( struct mlt_event_struct ) );
221 #ifdef _MLT_EVENT_CHECKS_
224 sprintf( temp, "%d", first_null == -1 ? mlt_properties_count( listeners ) : first_null );
225 event->owner = events;
226 event->ref_count = 0;
227 event->block_count = 0;
228 event->listener = listener;
229 event->service = service;
230 mlt_properties_set_data( listeners, temp, event, 0, ( mlt_destructor )mlt_event_close, NULL );
235 mlt_event_inc_ref( event );
241 /** Block all events for a given service.
244 void mlt_events_block( mlt_properties this, void *service )
246 mlt_events events = mlt_events_fetch( this );
247 if ( events != NULL )
250 mlt_properties list = events->list;
251 for ( j = 0; j < mlt_properties_count( list ); j ++ )
253 char *temp = mlt_properties_get_name( list, j );
254 if ( !strncmp( temp, "list:", 5 ) )
256 mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
257 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
259 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
260 if ( entry != NULL && entry->service == service )
261 mlt_event_block( entry );
268 /** Unblock all events for a given service.
271 void mlt_events_unblock( mlt_properties this, void *service )
273 mlt_events events = mlt_events_fetch( this );
274 if ( events != NULL )
277 mlt_properties list = events->list;
278 for ( j = 0; j < mlt_properties_count( list ); j ++ )
280 char *temp = mlt_properties_get_name( list, j );
281 if ( !strncmp( temp, "list:", 5 ) )
283 mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
284 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
286 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
287 if ( entry != NULL && entry->service == service )
288 mlt_event_unblock( entry );
295 /** Disconnect all events for a given service.
298 void mlt_events_disconnect( mlt_properties this, void *service )
300 mlt_events events = mlt_events_fetch( this );
301 if ( events != NULL )
304 mlt_properties list = events->list;
305 for ( j = 0; j < mlt_properties_count( list ); j ++ )
307 char *temp = mlt_properties_get_name( list, j );
308 if ( !strncmp( temp, "list:", 5 ) )
310 mlt_properties listeners = mlt_properties_get_data( list, temp, NULL );
311 for ( i = 0; i < mlt_properties_count( listeners ); i ++ )
313 mlt_event entry = mlt_properties_get_data_at( listeners, i, NULL );
314 char *name = mlt_properties_get_name( listeners, i );
315 if ( entry != NULL && entry->service == service )
316 mlt_properties_set_data( listeners, name, NULL, 0, NULL, NULL );
327 pthread_mutex_t mutex;
331 static void mlt_events_listen_for( mlt_properties this, condition_pair *pair )
333 pthread_mutex_lock( &pair->mutex );
334 if ( pair->done == 0 )
336 pthread_cond_signal( &pair->cond );
337 pthread_mutex_unlock( &pair->mutex );
341 mlt_event mlt_events_setup_wait_for( mlt_properties this, char *id )
343 condition_pair *pair = malloc( sizeof( condition_pair ) );
345 pthread_cond_init( &pair->cond, NULL );
346 pthread_mutex_init( &pair->mutex, NULL );
347 pthread_mutex_lock( &pair->mutex );
348 return mlt_events_listen( this, pair, id, ( mlt_listener )mlt_events_listen_for );
351 void mlt_events_wait_for( mlt_properties this, mlt_event event )
355 condition_pair *pair = event->service;
356 pthread_cond_wait( &pair->cond, &pair->mutex );
360 void mlt_events_close_wait_for( mlt_properties this, mlt_event event )
364 condition_pair *pair = event->service;
367 pthread_mutex_unlock( &pair->mutex );
368 pthread_mutex_destroy( &pair->mutex );
369 pthread_cond_destroy( &pair->cond );
373 /** Fetch the events object.
376 static mlt_events mlt_events_fetch( mlt_properties this )
378 mlt_events events = NULL;
380 events = mlt_properties_get_data( this, "_events", NULL );
384 /** Store the events object.
387 static void mlt_events_store( mlt_properties this, mlt_events events )
389 if ( this != NULL && events != NULL )
390 mlt_properties_set_data( this, "_events", events, 0, ( mlt_destructor )mlt_events_close, NULL );
393 /** Close the events object.
396 static void mlt_events_close( mlt_events events )
398 if ( events != NULL )
400 mlt_properties_close( events->list );