demux:mkv: do not return VLC_EGENERIC on DEMUX_GET_LENGTH when the duration is unknown
[vlc.git] / lib / event.c
blobf027754181ef9696fa66cbb126180507fec6e90d
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(MediaDiscovererStarted)
193 DEF(MediaDiscovererEnded)
195 DEF(VlmMediaAdded)
196 DEF(VlmMediaRemoved)
197 DEF(VlmMediaChanged)
198 DEF(VlmMediaInstanceStarted)
199 DEF(VlmMediaInstanceStopped)
200 DEF(VlmMediaInstanceStatusInit)
201 DEF(VlmMediaInstanceStatusOpening)
202 DEF(VlmMediaInstanceStatusPlaying)
203 DEF(VlmMediaInstanceStatusPause)
204 DEF(VlmMediaInstanceStatusEnd)
205 DEF(VlmMediaInstanceStatusError)
207 #undef DEF
209 static const char unknown_event_name[] = "Unknown Event";
211 static int evcmp( const void *a, const void *b )
213 return (*(const int *)a) - ((event_name_t *)b)->type;
216 const char * libvlc_event_type_name( int event_type )
218 const event_name_t *p;
220 p = bsearch( &event_type, event_list,
221 sizeof(event_list)/sizeof(event_list[0]), sizeof(*p),
222 evcmp );
223 return p ? p->name : unknown_event_name;
226 /**************************************************************************
227 * libvlc_event_attach (public) :
229 * Add a callback for an event.
230 **************************************************************************/
231 int libvlc_event_attach(libvlc_event_manager_t *em, libvlc_event_type_t type,
232 libvlc_callback_t callback, void *opaque)
234 libvlc_event_listener_t *listener = malloc(sizeof (*listener));
235 if (unlikely(listener == NULL))
236 return ENOMEM;
238 listener->event_type = type;
239 listener->p_user_data = opaque;
240 listener->pf_callback = callback;
242 int i_ret;
243 vlc_mutex_lock(&em->lock);
244 if(vlc_array_append(&em->listeners, listener) != 0)
246 i_ret = VLC_EGENERIC;
247 free(listener);
249 else
250 i_ret = VLC_SUCCESS;
251 vlc_mutex_unlock(&em->lock);
252 return i_ret;
255 /**************************************************************************
256 * libvlc_event_detach (public) :
258 * Remove a callback for an event.
259 **************************************************************************/
260 void libvlc_event_detach(libvlc_event_manager_t *em, libvlc_event_type_t type,
261 libvlc_callback_t callback, void *opaque)
263 vlc_mutex_lock(&em->lock);
264 for (size_t i = 0; i < vlc_array_count(&em->listeners); i++)
266 libvlc_event_listener_t *listener;
268 listener = vlc_array_item_at_index(&em->listeners, i);
270 if (listener->event_type == type
271 && listener->pf_callback == callback
272 && listener->p_user_data == opaque)
273 { /* that's our listener */
274 vlc_array_remove(&em->listeners, i);
275 vlc_mutex_unlock(&em->lock);
276 free(listener);
277 return;
280 abort();