event.c 7.62 KB
Newer Older
Filippo Carone's avatar
Filippo Carone committed
1
/*****************************************************************************
2
 * event.c: New libvlc event control API
Filippo Carone's avatar
Filippo Carone committed
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2007-2010 VLC authors and VideoLAN
Filippo Carone's avatar
Filippo Carone committed
5 6 7
 * $Id $
 *
 * Authors: Filippo Carone <filippo@carone.org>
8
 *          Pierre d'Herbemont <pdherbemont # videolan.org>
Filippo Carone's avatar
Filippo Carone committed
9
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
10 11 12
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
Filippo Carone's avatar
Filippo Carone committed
13 14 15 16
 * (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
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
17 18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
Filippo Carone's avatar
Filippo Carone committed
19
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
20 21 22
 * You should have received a copy of the GNU Lesser 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.
Filippo Carone's avatar
Filippo Carone committed
23 24
 *****************************************************************************/

25 26 27 28
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

29
#include <assert.h>
30
#include <errno.h>
31

32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include <vlc/libvlc.h>
#include "libvlc_internal.h"

#include <vlc_common.h>

/*
 * Event Handling
 */

/* Example usage
 *
 * struct libvlc_cool_object_t
 * {
 *        ...
46
 *        libvlc_event_manager_t event_manager;
47 48 49 50 51 52
 *        ...
 * }
 *
 * libvlc_my_cool_object_new()
 * {
 *        ...
53
 *        libvlc_event_manager_init(&p_self->event_manager, p_self)
54 55 56 57 58 59
 *        ...
 * }
 *
 * libvlc_my_cool_object_release()
 * {
 *         ...
60
 *         libvlc_event_manager_release(&p_self->event_manager);
61 62 63 64 65 66 67 68 69
 *         ...
 * }
 *
 * libvlc_my_cool_object_do_something()
 * {
 *        ...
 *        libvlc_event_t event;
 *        event.type = libvlc_MyCoolObjectDidSomething;
 *        event.u.my_cool_object_did_something.what_it_did = kSomething;
70
 *        libvlc_event_send(&p_self->event_manager, &event);
71 72 73 74 75 76 77 78 79 80
 * }
 * */

typedef struct libvlc_event_listener_t
{
    libvlc_event_type_t event_type;
    void *              p_user_data;
    libvlc_callback_t   pf_callback;
} libvlc_event_listener_t;

81 82 83
/*
 * Internal libvlc functions
 */
Filippo Carone's avatar
Filippo Carone committed
84

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
void libvlc_event_manager_init(libvlc_event_manager_t *em, void *obj)
{
    em->p_obj = obj;
    vlc_array_init(&em->listeners);
    vlc_mutex_init_recursive(&em->lock);
}

void libvlc_event_manager_destroy(libvlc_event_manager_t *em)
{
    vlc_mutex_destroy(&em->lock);

    for (size_t i = 0; i < vlc_array_count(&em->listeners); i++)
        free(vlc_array_item_at_index(&em->listeners, i));

    vlc_array_clear(&em->listeners);
}

102
/**************************************************************************
103
 *       libvlc_event_send (internal) :
104
 *
105
 * Send a callback.
106
 **************************************************************************/
107 108
void libvlc_event_send( libvlc_event_manager_t * p_em,
                        libvlc_event_t * p_event )
109
{
110 111 112
    /* Fill event with the sending object now */
    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++)
115
    {
116
        libvlc_event_listener_t *listener;
117

118 119
        listener = vlc_array_item_at_index(&p_em->listeners, i);
        if (listener->event_type == p_event->type)
120
            listener->pf_callback(p_event, listener->p_user_data);
121
    }
122
    vlc_mutex_unlock(&p_em->lock);
123 124
}

125 126 127 128
/*
 * Public libvlc functions
 */

129 130 131 132 133 134 135 136 137 138 139 140
#define DEF( a ) { libvlc_##a, #a, },

typedef struct
{
    int type;
    const char name[40];
} event_name_t;

static const event_name_t event_list[] = {
    DEF(MediaMetaChanged)
    DEF(MediaSubItemAdded)
    DEF(MediaDurationChanged)
141
    DEF(MediaParsedChanged)
142 143
    DEF(MediaFreed)
    DEF(MediaStateChanged)
144
    DEF(MediaSubItemTreeAdded)
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

    DEF(MediaPlayerMediaChanged)
    DEF(MediaPlayerNothingSpecial)
    DEF(MediaPlayerOpening)
    DEF(MediaPlayerBuffering)
    DEF(MediaPlayerPlaying)
    DEF(MediaPlayerPaused)
    DEF(MediaPlayerStopped)
    DEF(MediaPlayerForward)
    DEF(MediaPlayerBackward)
    DEF(MediaPlayerEndReached)
    DEF(MediaPlayerEncounteredError)
    DEF(MediaPlayerTimeChanged)
    DEF(MediaPlayerPositionChanged)
    DEF(MediaPlayerSeekableChanged)
    DEF(MediaPlayerPausableChanged)
    DEF(MediaPlayerTitleChanged)
    DEF(MediaPlayerSnapshotTaken)
    DEF(MediaPlayerLengthChanged)
164
    DEF(MediaPlayerVout)
165
    DEF(MediaPlayerScrambledChanged)
166 167 168
    DEF(MediaPlayerESAdded)
    DEF(MediaPlayerESDeleted)
    DEF(MediaPlayerESSelected)
169 170
    DEF(MediaPlayerCorked)
    DEF(MediaPlayerUncorked)
171 172
    DEF(MediaPlayerMuted)
    DEF(MediaPlayerUnmuted)
173
    DEF(MediaPlayerAudioVolume)
174
    DEF(MediaPlayerAudioDevice)
175
    DEF(MediaPlayerChapterChanged)
176 177 178 179 180

    DEF(MediaListItemAdded)
    DEF(MediaListWillAddItem)
    DEF(MediaListItemDeleted)
    DEF(MediaListWillDeleteItem)
181
    DEF(MediaListEndReached)
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201

    DEF(MediaListViewItemAdded)
    DEF(MediaListViewWillAddItem)
    DEF(MediaListViewItemDeleted)
    DEF(MediaListViewWillDeleteItem)

    DEF(MediaListPlayerPlayed)
    DEF(MediaListPlayerNextItemSet)
    DEF(MediaListPlayerStopped)

    DEF(MediaDiscovererStarted)
    DEF(MediaDiscovererEnded)

    DEF(VlmMediaAdded)
    DEF(VlmMediaRemoved)
    DEF(VlmMediaChanged)
    DEF(VlmMediaInstanceStarted)
    DEF(VlmMediaInstanceStopped)
    DEF(VlmMediaInstanceStatusInit)
    DEF(VlmMediaInstanceStatusOpening)
202 203 204 205
    DEF(VlmMediaInstanceStatusPlaying)
    DEF(VlmMediaInstanceStatusPause)
    DEF(VlmMediaInstanceStatusEnd)
    DEF(VlmMediaInstanceStatusError)
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
};
#undef DEF

static const char unknown_event_name[] = "Unknown Event";

static int evcmp( const void *a, const void *b )
{
    return (*(const int *)a) - ((event_name_t *)b)->type;
}

const char * libvlc_event_type_name( int event_type )
{
    const event_name_t *p;

    p = bsearch( &event_type, event_list,
                 sizeof(event_list)/sizeof(event_list[0]), sizeof(*p),
                 evcmp );
    return p ? p->name : unknown_event_name;
}

226
/**************************************************************************
227
 *       libvlc_event_attach (public) :
228 229 230
 *
 * Add a callback for an event.
 **************************************************************************/
231 232
int libvlc_event_attach(libvlc_event_manager_t *em, libvlc_event_type_t type,
                        libvlc_callback_t callback, void *opaque)
Filippo Carone's avatar
Filippo Carone committed
233
{
234 235
    libvlc_event_listener_t *listener = malloc(sizeof (*listener));
    if (unlikely(listener == NULL))
236
        return ENOMEM;
237

238 239 240
    listener->event_type = type;
    listener->p_user_data = opaque;
    listener->pf_callback = callback;
241

242 243 244 245
    vlc_mutex_lock(&em->lock);
    vlc_array_append(&em->listeners, listener);
    vlc_mutex_unlock(&em->lock);
    return 0;
Filippo Carone's avatar
Filippo Carone committed
246 247
}

248
/**************************************************************************
249
 *       libvlc_event_detach (public) :
250 251 252
 *
 * Remove a callback for an event.
 **************************************************************************/
253 254
void libvlc_event_detach(libvlc_event_manager_t *em, libvlc_event_type_t type,
                         libvlc_callback_t callback, void *opaque)
Filippo Carone's avatar
Filippo Carone committed
255
{
256
    vlc_mutex_lock(&em->lock);
257
    for (size_t i = 0; i < vlc_array_count(&em->listeners); i++)
258
    {
259 260 261 262 263 264 265 266 267 268 269 270 271
         libvlc_event_listener_t *listener;

         listener = vlc_array_item_at_index(&em->listeners, i);

         if (listener->event_type == type
          && listener->pf_callback == callback
          && listener->p_user_data == opaque)
         {   /* that's our listener */
             vlc_array_remove(&em->listeners, i);
             vlc_mutex_unlock(&em->lock);
             free(listener);
             return;
         }
272
    }
273
    abort();
Filippo Carone's avatar
Filippo Carone committed
274
}