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