00001 #include <gtask/gtask-event-dispatcher.h>
00002 #include <gtask/gtask-packet.h>
00003
00004 #include <gtask/gtask-internals.h>
00005
00006 typedef struct _WatchInfo {
00007 guint watch_id;
00008 GType watch_type;
00009 GTaskEventFunc func;
00010 gpointer data;
00011 } WatchInfo;
00012
00013 static gpointer parent_class;
00014
00015 static void
00016 gtask_event_dispatcher_class_init( GTaskEventDispatcherClass *klass );
00017
00018 static void
00019 gtask_event_dispatcher_init( GTaskEventDispatcher *dispatcher, gpointer g_class );
00020
00021 static void
00022 gtask_event_dispatcher_dispose( GObject *obj );
00023
00024 static void
00025 gtask_event_dispatcher_finalize( GObject *obj );
00026
00027 GType gtask_event_dispatcher_get_type( void ) {
00028 static GType type = 0;
00029
00030 if( type == 0 ) {
00031 static const GTypeInfo info = {
00032 sizeof( GTaskEventDispatcherClass ),
00033 NULL,
00034 NULL,
00035 (GClassInitFunc) gtask_event_dispatcher_class_init,
00036 NULL,
00037 NULL,
00038 sizeof( GTaskEventDispatcher ),
00039 0,
00040 (GInstanceInitFunc) gtask_event_dispatcher_init
00041 };
00042
00043 type = g_type_register_static( G_TYPE_OBJECT,
00044 "GTaskEventDispatcher",
00045 &info,
00046 0 );
00047 }
00048
00049 return type;
00050 }
00051
00052 static void
00053 gtask_event_dispatcher_class_init( GTaskEventDispatcherClass *klass ) {
00054 GObjectClass *gobject_class = G_OBJECT_CLASS( klass );
00055
00056 parent_class = g_type_class_peek_parent( klass );
00057
00058 gobject_class->dispose = gtask_event_dispatcher_dispose;
00059 gobject_class->finalize = gtask_event_dispatcher_finalize;
00060 }
00061
00062 static void
00063 gtask_event_dispatcher_init( GTaskEventDispatcher *dispatcher,
00064 gpointer g_class )
00065 {
00066 GTaskEventDispatcherPrivate *private = g_new0( GTaskEventDispatcherPrivate, 1 );
00067
00068 private->dispose_has_run = FALSE;
00069 private->watches = g_array_new( FALSE, TRUE, sizeof( WatchInfo ) );
00070 private->next_watch_id = 1;
00071
00072 dispatcher->private = private;
00073 }
00074
00075 static void
00076 gtask_event_dispatcher_dispose( GObject *obj ) {
00077 GTaskEventDispatcher *dispatcher = GTASK_EVENT_DISPATCHER( obj );
00078 GTaskEventDispatcherPrivate *private = dispatcher->private;
00079
00080 if( private->dispose_has_run )
00081 return;
00082
00083 g_object_unref( private->parser );
00084
00085 private->dispose_has_run = TRUE;
00086
00087 if( G_OBJECT_CLASS( parent_class )->dispose )
00088 G_OBJECT_CLASS( parent_class )->dispose( obj );
00089 }
00090
00091 static void
00092 gtask_event_dispatcher_finalize( GObject *obj ) {
00093 GTaskEventDispatcher *dispatcher = GTASK_EVENT_DISPATCHER( obj );
00094 GTaskEventDispatcherPrivate *private = dispatcher->private;
00095
00096 g_array_free( private->watches, TRUE );
00097 g_free( private );
00098
00099 if( G_OBJECT_CLASS( parent_class )->finalize )
00100 G_OBJECT_CLASS( parent_class )->finalize( obj );
00101 }
00102
00120 GTaskEventDispatcher *
00121 gtask_event_dispatcher_new_with_parser( GTaskStreamParser *parser ) {
00122 GTaskEventDispatcher *dispatcher;
00123
00124 g_return_val_if_fail( GTASK_IS_STREAM_PARSER( parser ), NULL );
00125
00126 dispatcher = g_object_new( GTASK_EVENT_DISPATCHER_TYPE, NULL );
00127
00128 g_object_ref( parser );
00129
00130 dispatcher->private->parser = parser;
00131
00132 return dispatcher;
00133 }
00134
00152 guint
00153 gtask_event_dispatcher_add_watch( GTaskEventDispatcher *dispatch,
00154 GType watch_type,
00155 GTaskEventFunc func,
00156 gpointer user_data )
00157 {
00158 WatchInfo info;
00159
00160 g_return_val_if_fail( GTASK_IS_EVENT_DISPATCHER( dispatch ), 0 );
00161
00162 g_debug( "IN: gtask_event_dispatcher_add_watch" );
00163
00164 info.watch_id = dispatch->private->next_watch_id++;
00165 info.watch_type = watch_type;
00166 info.func = func;
00167 info.data = user_data;
00168
00169 g_array_append_val( dispatch->private->watches, info );
00170
00171 g_debug( "LEAVING: gtask_event_dispatcher_add_watch" );
00172 return info.watch_id;
00173 }
00174
00181 void
00182 gtask_event_dispatcher_remove_watch( GTaskEventDispatcher *dispatch,
00183 guint watch_id )
00184 {
00185 GTaskEventDispatcherPrivate *private;
00186 guint i;
00187
00188 g_return_if_fail( GTASK_IS_EVENT_DISPATCHER( dispatch ) );
00189 g_return_if_fail( watch_id > 0 );
00190
00191 g_debug( "IN: gtask_event_dispatcher_remove_watch" );
00192
00193 private = dispatch->private;
00194
00195 for( i = 0; i < private->watches->len; i++ ) {
00196 WatchInfo info = g_array_index( private->watches, WatchInfo, i );
00197
00198 if( info.watch_id == watch_id )
00199 g_array_remove_index( private->watches, i-- );
00200 else if( info.watch_id > watch_id )
00201 return;
00202 }
00203
00204 g_debug( "LEAVING: gtask_event_dispatcher_remove_watch" );
00205 }
00206
00217 GTaskStreamParser *
00218 gtask_event_dispatcher_get_stream_parser( GTaskEventDispatcher *dispatch ) {
00219 g_return_val_if_fail( GTASK_IS_EVENT_DISPATCHER( dispatch ), NULL );
00220
00221 return dispatch->private->parser;
00222 }
00223
00224
00236 gboolean
00237 gtask_event_dispatcher_private_parse_callback( GIOChannel *chann,
00238 GIOCondition cond,
00239 gpointer data )
00240 {
00241 GTaskEventDispatcher *dispatcher;
00242 GTaskStreamParser *parser;
00243 GIOStatus status;
00244 GObject *packet;
00245 GArray *remove;
00246 gchar buff[1025];
00247 guint num;
00248 guint i;
00249
00250 g_debug( "IN: gtask_event_dispatcher_private_parse_callback()" );
00251
00252 g_return_val_if_fail( cond == G_IO_IN, TRUE );
00253 g_return_val_if_fail( GTASK_IS_EVENT_DISPATCHER( data ), FALSE );
00254
00255 dispatcher = GTASK_EVENT_DISPATCHER( data );
00256 remove = g_array_new( FALSE, FALSE, sizeof( guint ) );
00257
00258 parser = gtask_event_dispatcher_get_stream_parser( dispatcher );
00259
00260 status = g_io_channel_read_chars( chann, buff, 1024, &num, NULL );
00261
00262 buff[num] = '\0';
00263
00264 switch( status ) {
00265 case G_IO_STATUS_EOF:
00267 return FALSE;
00268 case G_IO_STATUS_ERROR:
00269 g_message( "status == G_IO_STATUS_ERROR" );
00271 return FALSE;
00272 case G_IO_STATUS_AGAIN:
00273 return TRUE;
00274 default:
00275 break;
00276 }
00277
00278 if( !gtask_stream_parser_push_data( parser, buff, num ) ) {
00279 g_warning( "parsing error on stream" );
00280 return FALSE;
00281 }
00282
00283 if( !gtask_stream_parser_has_packets( parser ) ) {
00284 g_warning( "no new packets created" );
00285 return TRUE;
00286 }
00287
00288 g_debug( "new packets are in the queue" );
00289 while( ( packet = gtask_stream_parser_get_next_packet( parser ) ) != NULL )
00290 {
00291 GType type = G_OBJECT_TYPE( packet );
00292 GArray *watches = dispatcher->private->watches;
00293 guint len = watches->len;
00294
00295 g_debug( "EventDispatcher: packet_type: %s", G_OBJECT_TYPE_NAME( packet ) );
00296
00297 for( i = 0; i < len; i++ ) {
00298 WatchInfo info = g_array_index( watches, WatchInfo, i );
00299
00300 if( g_type_is_a( type, info.watch_type ) ) {
00301 g_warning( "dispatching to watch candidate: %p", packet );
00302
00303 if( !info.func( dispatcher, (GObject *) packet, info.data ) ) {
00304 g_array_append_val( remove, i );
00305 }
00306
00307 g_warning( "done dispatching to watch candidate: %p", packet );
00308 }
00309 }
00310
00311 g_warning( "unref'ing packet: %p %s", packet, G_OBJECT_TYPE_NAME( packet ) );
00312 if( !G_IS_OBJECT( packet ) ) {
00313 g_warning( "WTF?! it's not an object?" );
00314 } else {
00315 g_warning( "Back in the real world glib thinks this is an object" );
00316 }
00317 g_object_unref( packet );
00318 g_warning( "done unref'ing packet" );
00319 }
00320 g_warning( "no more packets" );
00321
00322 for( i = 0; i < remove->len; i++ ) {
00323 gtask_event_dispatcher_remove_watch( dispatcher,
00324 g_array_index( remove, guint, i ) );
00325 }
00326
00327 g_warning( "done removing people" );
00328
00329 g_array_free( remove, TRUE );
00330
00331 g_debug( "LEAVING: gtask_event_dispatcher_private_parse_callback()" );
00332
00333 return TRUE;
00334 }