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
);