modules: replace hardcoded CLOCK_FREQ multiples by VTICK_FROM_SEC()
[vlc.git] / lib / event.c
blob7ac9d3788647f3139f9c82f749aebb9cc3f61ce3
1 /*****************************************************************************
2 * event.c: New libvlc event control API
3 *****************************************************************************
4 * Copyright (C) 2007-2010 VLC authors and VideoLAN
5 * $Id $
7 * Authors: Filippo Carone <filippo@carone.org>
8 * Pierre d'Herbemont <pdherbemont # videolan.org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
29 #include <assert.h>
30 #include <errno.h>
32 #include <vlc/libvlc.h>
33 #include "libvlc_internal.h"
35 #include <vlc_common.h>
38 * Event Handling
41 /* Example usage
43 * struct libvlc_cool_object_t
44 * {
45 * ...
46 * libvlc_event_manager_t event_manager;
47 * ...
48 * }
50 * libvlc_my_cool_object_new()
51 * {
52 * ...
53 * libvlc_event_manager_init(&p_self->event_manager, p_self)
54 * ...
55 * }
57 * libvlc_my_cool_object_release()
58 * {
59 * ...
60 * libvlc_event_manager_release(&p_self->event_manager);
61 * ...
62 * }
64 * libvlc_my_cool_object_do_something()
65 * {
66 * ...
67 * libvlc_event_t event;
68 * event.type = libvlc_MyCoolObjectDidSomething;
69 * event.u.my_cool_object_did_something.what_it_did = kSomething;
70 * libvlc_event_send(&p_self->event_manager, &event);
71 * }
72 * */
74 typedef struct libvlc_event_listener_t
76 libvlc_event_type_t event_type;
77 void * p_user_data;
78 libvlc_callback_t pf_callback;
79 } libvlc_event_listener_t;
82 * Internal libvlc functions
85 void libvlc_event_manager_init(libvlc_event_manager_t *em, void *obj)
87 em->p_obj = obj;
88 vlc_array_init(&em->listeners);
89 vlc_mutex_init_recursive(&em->lock);
92 void libvlc_event_manager_destroy(libvlc_event_manager_t *em)
94 vlc_mutex_destroy(&em->lock);
96 for (size_t i = 0; i < vlc_array_count(&em->listeners); i++)
97 free(vlc_array_item_at_index(&em->listeners, i));
99 vlc_array_clear(&em->listeners);
102 /**************************************************************************
103 * libvlc_event_send (internal) :
105 * Send a callback.
106 **************************************************************************/
107 void libvlc_event_send( libvlc_event_manager_t * p_em,
108 libvlc_event_t * p_event )
110 /* Fill event with the sending object now */
111 p_event->p_obj = p_em->p_obj;
113 vlc_mutex_lock(&p_em->lock);
114 for (size_t i = 0; i < vlc_array_count(&p_em->listeners); i++)
116 libvlc_event_listener_t *listener;
118 listener = vlc_array_item_at_index(&p_em->listeners, i);
119 if (listener->event_type == p_event->type)
120 listener->pf_callback(p_event, listener->p_user_data);
122 vlc_mutex_unlock(&p_em->lock);
126 * Public libvlc functions
129 #define DEF( a ) { libvlc_##a, #a, },
131 typedef struct
133 int type;
134 const char name[40];
135 } event_name_t;
137 static const event_name_t event_list[] = {
138 DEF(MediaMetaChanged)
139 DEF(MediaSubItemAdded)
140 DEF(MediaDurationChanged)
141 DEF(MediaParsedChanged)
142 DEF(MediaFreed)
143 DEF(MediaStateChanged)
144 DEF(MediaSubItemTreeAdded)
146 DEF(MediaPlayerMediaChanged)
147 DEF(MediaPlayerNothingSpecial)
148 DEF(MediaPlayerOpening)
149 DEF(MediaPlayerBuffering)
150 DEF(MediaPlayerPlaying)
151 DEF(MediaPlayerPaused)
152 DEF(MediaPlayerStopped)
153 DEF(MediaPlayerForward)
154 DEF(MediaPlayerBackward)
155 DEF(MediaPlayerEndReached)
156 DEF(MediaPlayerEncounteredError)
157 DEF(MediaPlayerTimeChanged)
158 DEF(MediaPlayerPositionChanged)
159 DEF(MediaPlayerSeekableChanged)
160 DEF(MediaPlayerPausableChanged)
161 DEF(MediaPlayerTitleChanged)
162 DEF(MediaPlayerSnapshotTaken)
163 DEF(MediaPlayerLengthChanged)
164 DEF(MediaPlayerVout)
165 DEF(MediaPlayerScrambledChanged)
166 DEF(MediaPlayerESAdded)
167 DEF(MediaPlayerESDeleted)
168 DEF(MediaPlayerESSelected)
169 DEF(MediaPlayerCorked)
170 DEF(MediaPlayerUncorked)
171 DEF(MediaPlayerMuted)
172 DEF(MediaPlayerUnmuted)
173 DEF(MediaPlayerAudioVolume)
174 DEF(MediaPlayerAudioDevice)
175 DEF(MediaPlayerChapterChanged)
177 DEF(MediaListItemAdded)
178 DEF(MediaListWillAddItem)
179 DEF(MediaListItemDeleted)
180 DEF(MediaListWillDeleteItem)
181 DEF(MediaListEndReached)
183 DEF(MediaListViewItemAdded)
184 DEF(MediaListViewWillAddItem)
185 DEF(MediaListViewItemDeleted)
186 DEF(MediaListViewWillDeleteItem)
188 DEF(MediaListPlayerPlayed)
189 DEF(MediaListPlayerNextItemSet)
190 DEF(MediaListPlayerStopped)
192 DEF(VlmMediaAdded)
193 DEF(VlmMediaRemoved)
194 DEF(VlmMediaChanged)
195 DEF(VlmMediaInstanceStarted)
196 DEF(VlmMediaInstanceStopped)
197 DEF(VlmMediaInstanceStatusInit)
198 DEF(VlmMediaInstanceStatusOpening)
199 DEF(VlmMediaInstanceStatusPlaying)
200 DEF(VlmMediaInstanceStatusPause)
201 DEF(VlmMediaInstanceStatusEnd)
202 DEF(VlmMediaInstanceStatusError)
204 #undef DEF
206 static const char unknown_event_name[] = "Unknown Event";
208 static int evcmp( const void *a, const void *b )
210 return (*(const int *)a) - ((event_name_t *)b)->type;
213 const char * libvlc_event_type_name( int event_type )
215 const event_name_t *p;
217 p = bsearch( &event_type, event_list,
218 sizeof(event_list)/sizeof(event_list[0]), sizeof(*p),
219 evcmp );
220 return p ? p->name : unknown_event_name;
223 /**************************************************************************
224 * libvlc_event_attach (public) :
226 * Add a callback for an event.
227 **************************************************************************/
228 int libvlc_event_attach(libvlc_event_manager_t *em, libvlc_event_type_t type,
229 libvlc_callback_t callback, void *opaque)
231 libvlc_event_listener_t *listener = malloc(sizeof (*listener));
232 if (unlikely(listener == NULL))
233 return ENOMEM;
235 listener->event_type = type;
236 listener->p_user_data = opaque;
237 listener->pf_callback = callback;
239 int i_ret;
240 vlc_mutex_lock(&em->lock);
241 if(vlc_array_append(&em->listeners, listener) != 0)
243 i_ret = VLC_EGENERIC;
244 free(listener);
246 else
247 i_ret = VLC_SUCCESS;
248 vlc_mutex_unlock(&em->lock);
249 return i_ret;
252 /**************************************************************************
253 * libvlc_event_detach (public) :
255 * Remove a callback for an event.
256 **************************************************************************/
257 void libvlc_event_detach(libvlc_event_manager_t *em, libvlc_event_type_t type,
258 libvlc_callback_t callback, void *opaque)
260 vlc_mutex_lock(&em->lock);
261 for (size_t i = 0; i < vlc_array_count(&em->listeners); i++)
263 libvlc_event_listener_t *listener;
265 listener = vlc_array_item_at_index(&em->listeners, i);
267 if (listener->event_type == type
268 && listener->pf_callback == callback
269 && listener->p_user_data == opaque)
270 { /* that's our listener */
271 vlc_array_remove(&em->listeners, i);
272 vlc_mutex_unlock(&em->lock);
273 free(listener);
274 return;
277 abort();