]> git.sesse.net Git - vlc/blob - src/control/event.c
770348fcac0e064cd7cf09520a949620307fdac6
[vlc] / src / control / event.c
1 /*****************************************************************************
2  * event.c: New libvlc event control API
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id $
6  *
7  * Authors: Filippo Carone <filippo@carone.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "libvlc_internal.h"
25 #include <vlc/libvlc.h>
26
27
28 /*
29  * Private functions
30  */
31
32 static int handle_event( vlc_object_t *p_this, char const *psz_cmd,
33                          vlc_value_t oldval, vlc_value_t newval,
34                          void *p_data )
35 {
36     struct libvlc_callback_entry_t *entry = p_data; /* FIXME: we need some locking here */
37     libvlc_event_t event;
38     event.type = entry->i_event_type;
39     switch ( event.type )
40     {
41         case VOLUME_CHANGED:
42             event.value_type = BOOLEAN_EVENT;
43             break;
44         case INPUT_POSITION_CHANGED:
45             break;
46         default:
47             break;
48     }
49     event.old_value = oldval;
50     event.new_value = newval;
51
52     /* Call the client entry */
53     entry->f_callback( entry->p_instance, &event, entry->p_user_data );
54
55     return VLC_SUCCESS;
56 }
57
58 static inline void add_callback_entry( struct libvlc_callback_entry_t *entry,
59                                        struct libvlc_callback_entry_list_t **list )
60 {
61     struct libvlc_callback_entry_list_t *new_listitem;
62
63     /* malloc/free strategy:
64      *  - alloc-ded in add_callback_entry
65      *  - free-ed by libvlc_event_remove_callback
66      *  - free-ed in libvlc_destroy threw libvlc_event_remove_callback
67      *    when entry is destroyed
68      */
69     new_listitem = malloc( sizeof( struct libvlc_callback_entry_list_t ) );
70     new_listitem->elmt = entry;
71     new_listitem->next = *list;
72     new_listitem->prev = NULL;
73
74     if(*list)
75         (*list)->prev = new_listitem;
76
77     *list = new_listitem;
78 }
79
80 /*
81  * Public libvlc functions
82  */
83
84 void libvlc_event_add_callback( libvlc_instance_t *p_instance,
85                                 libvlc_event_type_t i_event_type,
86                                 libvlc_callback_t f_callback,
87                                 void *user_data,
88                                 libvlc_exception_t *p_e )
89 {
90     struct libvlc_callback_entry_t *entry;
91     const char *callback_name = NULL;
92     int res;
93
94     if ( !f_callback )
95         RAISEVOID (" Callback function is null ");
96
97     /* malloc/free strategy:
98      *  - alloc-ded in libvlc_event_add_callback
99      *  - free-ed by libvlc_event_add_callback on error
100      *  - free-ed by libvlc_event_remove_callback
101      *  - free-ed in libvlc_destroy threw libvlc_event_remove_callback
102      *    when entry is destroyed
103      */
104     entry = malloc( sizeof( struct libvlc_callback_entry_t ) );
105     entry->f_callback = f_callback;
106     entry->i_event_type = i_event_type;
107     entry->p_user_data = user_data;
108     
109     switch ( i_event_type )
110     {
111         case VOLUME_CHANGED:
112             callback_name = "volume-change";
113             break;
114         case INPUT_POSITION_CHANGED:
115             break;
116         default:
117             free( entry );
118             RAISEVOID( "Unsupported event." );
119     }
120
121     res = var_AddCallback( p_instance->p_libvlc_int,
122                            callback_name,
123                            handle_event,
124                            entry );
125     
126     if (res != VLC_SUCCESS)
127     {
128         free ( entry );
129         RAISEVOID("Internal callback registration was not successful. Callback not registered.");
130     }
131     
132     add_callback_entry( entry, &p_instance->p_callback_list );
133
134     return;
135 }
136
137 void libvlc_event_remove_all_callbacks( libvlc_instance_t *p_instance,
138                                        libvlc_exception_t *p_e )
139 {
140     struct libvlc_callback_entry_list_t *p_listitem = p_instance->p_callback_list;
141
142     while( p_listitem )
143     {
144         libvlc_event_remove_callback( p_instance,
145             p_listitem->elmt->i_event_type,
146             p_listitem->elmt->f_callback,
147             p_listitem->elmt->p_user_data,
148             p_e);
149         /* libvlc_event_remove_callback will reset the p_callback_list */
150         p_listitem = p_instance->p_callback_list;
151     }
152 }
153
154 void libvlc_event_remove_callback( libvlc_instance_t *p_instance,
155                                    libvlc_event_type_t i_event_type,
156                                    libvlc_callback_t f_callback,
157                                    void *p_user_data,
158                                    libvlc_exception_t *p_e )
159 {
160     struct libvlc_callback_entry_list_t *p_listitem = p_instance->p_callback_list;
161
162     while( p_listitem )
163     {
164         if( p_listitem->elmt->f_callback == f_callback
165             && ( p_listitem->elmt->i_event_type == i_event_type )
166             && ( p_listitem->elmt->p_user_data == p_user_data )
167         
168         )
169         {
170             const char * callback_name = NULL;
171             int res;
172
173             if( p_listitem->prev )
174                 p_listitem->prev->next = p_listitem->next;
175             else
176                 p_instance->p_callback_list = p_listitem->next;
177
178             p_listitem->next->prev = p_listitem->prev;
179
180             switch ( i_event_type )
181             {
182                 case VOLUME_CHANGED:
183                     callback_name = "volume-change";
184                     break;
185                 case INPUT_POSITION_CHANGED:
186                     break;
187                 default:
188                     RAISEVOID( "Unsupported event." );
189             }
190
191             res = var_DelCallback( p_instance->p_libvlc_int,
192                                    callback_name, handle_event,
193                                    p_listitem->elmt );
194
195             if (res != VLC_SUCCESS)
196             {
197                 RAISEVOID("Internal callback unregistration was not successful. Callback not unregistered.");
198             }
199
200             free( p_listitem->elmt ); /* FIXME: need some locking here */
201             free( p_listitem );
202             break;
203         }
204         p_listitem = p_listitem->next;
205     }
206 }