From: Pierre d'Herbemont Date: Mon, 13 Aug 2007 19:08:15 +0000 (+0000) Subject: misc/events.c: Add a new way to send receive events. (ripped of from libvlc). It... X-Git-Tag: 0.9.0-test0~6558 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=a945f9dee63b95e378a464bb3eeff84a0c28b469;p=vlc misc/events.c: Add a new way to send receive events. (ripped of from libvlc). It will allow input_item to send events. --- diff --git a/include/vlc_events.h b/include/vlc_events.h new file mode 100644 index 0000000000..e117b2ba60 --- /dev/null +++ b/include/vlc_events.h @@ -0,0 +1,172 @@ +/***************************************************************************** + * events.h: events definitions + * Interface used to send events. + ***************************************************************************** + * Copyright (C) 2007 the VideoLAN team + * $Id$ + * + * Authors: Pierre d'Herbemont + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#ifndef VLC_EVENTS_H +# define VLC_EVENTS_H + +#include + +/** + * \file + * This file is the interface definition for events + * (implementation in src/misc/events.c) + */ + +/***************************************************************************** + * Documentation + *****************************************************************************/ +/* + **** Background + * + * This implements a way to send and receive event for an object (which can be + * a simple C struct or less). + * + * This is in direct concurrency with the Variable based Callback + * (see src/misc/variables.c). + * + * It has the following advantages over Variable based Callback: + * - No need to implement the whole VLC_COMMON_MEMBERS in the object, + * thus it reduce it size. This is especially true for input_item_t which + * doesn't have VLC_COMMON_MEMBERS. This is the first reason of existence of + * this implementation. + * - Libvlc can easily be based upon that. + * - Existing event are clearly declared (in include/vlc_events.h) + * + * + **** Example usage + * + * (vlc_cool_object_t doesn't need to have the VLC_COMMON_MEMBERS.) + * + * struct vlc_cool_object_t + * { + * ... + * vlc_event_manager_t p_event_manager; + * ... + * } + * + * vlc_my_cool_object_new() + * { + * ... + * vlc_event_manager_Create( &p_self->p_event_manager, p_this ); + * vlc_event_manager_register_event_type(p_self->p_event_manager, + * vlc_MyCoolObjectDidSomething, p_e) + * ... + * } + * + * vlc_my_cool_object_release() + * { + * ... + * vlc_event_manager_release( p_self->p_event_manager ); + * ... + * } + * + * vlc_my_cool_object_do_something() + * { + * ... + * vlc_event_t event; + * event.type = vlc_MyCoolObjectDidSomething; + * event.u.my_cool_object_did_something.what_it_did = kSomething; + * vlc_event_send( p_self->p_event_manager, &event ); + * } + * */ + + /***************************************************************************** + * Event Type + *****************************************************************************/ + +/* Private structure defined in misc/events.c */ +struct vlc_event_listeners_group_t; + +/* Event manager type */ +typedef struct vlc_event_manager_t +{ + void * p_obj; + DECL_ARRAY(struct vlc_event_listeners_group_t *) listeners_groups; +} vlc_event_manager_t; + +/* List of event */ +typedef enum vlc_event_type_t { + vlc_InputItemMetaChanged +} vlc_event_type_t; + +/* Event definition */ +typedef struct vlc_event_t +{ + vlc_event_type_t type; + void * p_obj; /* Sender object, automatically filled by event_Send() */ + union event_type_specific + { + struct + { + int meta; /* One of the meta identified in include/vlc_meta.h */ + } input_item_meta_changed; + } u; +} vlc_event_t; + +/* Event callback type */ +typedef void ( *vlc_event_callback_t )( const vlc_event_t *, void * ); + + /***************************************************************************** + * Event manager + *****************************************************************************/ + +/* + * p_obj points to the object that owns the event manager, and from + * which events are sent + */ +int event_manager_Create( vlc_event_manager_t * p_em, void * p_obj ); + +/* + * Destroy + */ +void event_manager_Destroy( vlc_event_manager_t * p_em ); + +/* + * Tells a specific event manager that it will handle event_type object + */ +int event_manager_RegisterEventType( vlc_event_manager_t * p_em, + vlc_event_type_t event_type ); + +/* + * Send an event to the listener attached to this p_em. + */ +void event_Send( vlc_event_manager_t * p_em, vlc_event_t * p_event ); + +/* + * Add a callback for an event. + */ +int event_Attach( vlc_event_manager_t * p_event_manager, + vlc_event_type_t event_type, + vlc_event_callback_t pf_callback, + void *p_user_data ); + +/* + * Remove a callback for an event. + */ +int event_Detach( vlc_event_manager_t *p_event_manager, + vlc_event_type_t event_type, + vlc_event_callback_t pf_callback, + void *p_user_data ); + +#endif /* VLC_EVENTS_H */ diff --git a/src/Makefile.am b/src/Makefile.am index d7ec8711d8..622202e90f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -265,6 +265,7 @@ SOURCES_libvlc_common = \ modules/configuration.h \ modules/configuration.c \ modules/configuration_chain.c \ + misc/events.c \ misc/image.c \ misc/messages.c \ misc/objects.c \ diff --git a/src/misc/events.c b/src/misc/events.c new file mode 100644 index 0000000000..5eb006ab0f --- /dev/null +++ b/src/misc/events.c @@ -0,0 +1,200 @@ +/***************************************************************************** + * events.c: events interface + * This library provides an interface to the send and receive events. + * It is more lightweight than variable based callback. + * Methode + ***************************************************************************** + * Copyright (C) 1998-2005 the VideoLAN team + * $Id$ + * + * Authors: Pierre d'Herbemont + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ + +#include + +#include /* required */ +#include /* malloc() */ + +#include + +#include +#include + +/***************************************************************************** + * Documentation : Read vlc_events.h + *****************************************************************************/ + +/***************************************************************************** + * Private types. + *****************************************************************************/ + +typedef struct vlc_event_listener_t +{ + void * p_user_data; + vlc_event_callback_t pf_callback; +} vlc_event_listener_t; + +typedef struct vlc_event_listeners_group_t +{ + vlc_event_type_t event_type; + DECL_ARRAY(struct vlc_event_listener_t *) listeners; +} vlc_event_listeners_group_t; + +/***************************************************************************** + * + *****************************************************************************/ + +/** + * Initialize event manager object + * p_this is the object that contains the event manager. But not + * necessarily a vlc_object_t (an input_item_t is not a vlc_object_t + * for instance). + */ +int event_manager_Create( vlc_event_manager_t * p_em, void * p_obj ) +{ + p_em->p_obj = p_obj; + ARRAY_INIT( p_em->listeners_groups ); + return VLC_SUCCESS; +} + +/** + * Destroy the event manager + */ +void event_manager_Destroy( vlc_event_manager_t * p_em ) +{ + struct vlc_event_listeners_group_t * listeners_group; + struct vlc_event_listener_t * listener; + + FOREACH_ARRAY( listeners_group, p_em->listeners_groups ) + FOREACH_ARRAY( listener, listeners_group->listeners ) + free( listener ); + FOREACH_END() + free( listeners_group ); + FOREACH_END() + free( p_em ); +} + +/** + * Destroy the event manager + */ +int event_manager_RegisterEventType( + vlc_event_manager_t * p_em, + vlc_event_type_t event_type ) +{ + vlc_event_listeners_group_t * listeners_group; + listeners_group = malloc(sizeof(vlc_event_listeners_group_t)); + + if( !listeners_group ) + return VLC_ENOMEM; + + listeners_group->event_type = event_type; + ARRAY_INIT( listeners_group->listeners ); + + ARRAY_APPEND( p_em->listeners_groups, listeners_group ); + + return VLC_SUCCESS; +} + +/** + * Send an event to the listener attached to this p_em. + */ +void event_Send( vlc_event_manager_t * p_em, + vlc_event_t * p_event ) +{ + vlc_event_listeners_group_t * listeners_group; + vlc_event_listener_t * listener; + + /* Fill event with the sending object now */ + p_event->p_obj = p_em->p_obj; + + FOREACH_ARRAY( listeners_group, p_em->listeners_groups ) + if( listeners_group->event_type == p_event->type ) + { + /* We found the group, now send every one the event */ + FOREACH_ARRAY( listener, listeners_group->listeners ) + listener->pf_callback( p_event, listener->p_user_data ); + FOREACH_END() + break; + } + FOREACH_END() +} + +/** + * Add a callback for an event. + */ +int event_Attach( vlc_event_manager_t * p_event_manager, + vlc_event_type_t event_type, + vlc_event_callback_t pf_callback, + void *p_user_data ) +{ + vlc_event_listeners_group_t * listeners_group; + vlc_event_listener_t * listener; + listener = malloc(sizeof(vlc_event_listener_t)); + if( !listener ) + return VLC_ENOMEM; + + listener->p_user_data = p_user_data; + listener->pf_callback = pf_callback; + + FOREACH_ARRAY( listeners_group, p_event_manager->listeners_groups ) + if( listeners_group->event_type == event_type ) + { + ARRAY_APPEND( listeners_group->listeners, listener ); + return VLC_SUCCESS; + } + FOREACH_END() + + free(listener); + return VLC_EGENERIC; +} + +/** + * Remove a callback for an event. + */ +int event_Detach( vlc_event_manager_t *p_event_manager, + vlc_event_type_t event_type, + vlc_event_callback_t pf_callback, + void *p_user_data ) +{ + vlc_event_listeners_group_t * listeners_group; + struct vlc_event_listener_t * listener; + FOREACH_ARRAY( listeners_group, p_event_manager->listeners_groups ) + if( listeners_group->event_type == event_type ) + { + FOREACH_ARRAY( listener, listeners_group->listeners ) + if( listener->pf_callback == pf_callback && + listener->p_user_data == p_user_data ) + { + /* that's our listener */ + free( listener ); + ARRAY_REMOVE( listeners_group->listeners, + fe_idx /* This comes from the macro (and that's why + I hate macro) */ ); + return VLC_SUCCESS; + } + FOREACH_END() + } + FOREACH_END() + + return VLC_EGENERIC; +} + +