EventManager.hpp 28.2 KB
Newer Older
1
/*****************************************************************************
2
 * EventManager.hpp: Exposes libvlc events
3
 *****************************************************************************
4
 * Copyright © 2015 libvlcpp authors & VideoLAN
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Authors: Hugo Beauzée-Luyssen <hugo@beauzee.fr>
 *
 * 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
 * (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 Lesser General Public License for more details.
 *
 * 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.
 *****************************************************************************/

#ifndef LIBVLC_EVENTMANAGER_HPP
#define LIBVLC_EVENTMANAGER_HPP

#include <string>
27

28
#include "common.hpp"
29
#include "Internal.hpp"
30

31
#include <algorithm>
32
#include <functional>
33
#include <vector>
34 35
#include <memory>

36 37
#define EXPECT_SIGNATURE(sig) static_assert(signature_match<decltype(f), sig>::value, "Expected a function with prototype " #sig)

38 39 40 41 42
namespace VLC
{

class Media;

43 44 45 46 47 48 49 50
/**
 * @brief This class serves as a base for all event managers.
 *
 * All events can be handled by providing a std::function.
 * libvlcpp will take ownership (ie. the function will be moved inside an internal list)
 * If the provided std::function is a lambda, it may capture anything you desire
 */
class EventManager : public Internal<libvlc_event_manager_t>
51
{
52 53 54 55
protected:
    template <typename T>
    using DecayPtr = typename std::add_pointer<typename std::decay<T>::type>::type;

56 57 58 59 60 61
private:
    // Polymorphic base to hold a templated implementation
    struct EventHandlerBase
    {
        using Wrapper = std::add_pointer<void(const libvlc_event_t*, void*)>::type;
        virtual ~EventHandlerBase() {}
62
        virtual void unregister() = 0;
63 64
    };

65
    template <typename Func>
66 67
    class EventHandler : public EventHandlerBase
    {
68
    public:
69 70
        EventHandler(EventManager& em, libvlc_event_e eventType, Func&& userCallback, Wrapper wrapper)
            : m_userCallback( std::forward<Func>(userCallback) )
71 72 73 74 75 76 77 78 79 80
            , m_eventManager(&em)
            , m_wrapper(wrapper)
            , m_eventType( eventType )
        {
            if (libvlc_event_attach( *m_eventManager, m_eventType, m_wrapper, &m_userCallback ) != 0)
                throw std::bad_alloc();
        }

        ~EventHandler()
        {
81 82
            // We unregister only when the object actually goes out of scope, IE. when it is
            // removed from EventManager's event handler vector
83 84 85
            libvlc_event_detach( *m_eventManager, m_eventType, m_wrapper, &m_userCallback );
        }

86 87
        virtual void unregister() override
        {
88
            m_eventManager->unregister(this);
89 90
        }

91 92 93
        EventHandler(const EventHandler&) = delete;

    private:
94 95 96 97
        // Deduced type is Func& in case of lvalue; Func in case of rvalue.
        // So we hold a reference to the callback when passed a lvalue, we
        // copy construct it when passing a rvalue
        Func m_userCallback;
98 99 100 101 102 103
        // EventManager always outlive EventHandler, no need for smart pointer
        EventManager* m_eventManager;
        Wrapper m_wrapper;
        libvlc_event_e m_eventType;
    };

104 105 106 107
private:
    // variadic template recursion termination
    void unregister(){}

108
public:
109
    template <typename T, typename... Args>
110
    void unregister(const T e, const Args... args)
111
    {
112
        static_assert(std::is_convertible<decltype(e), const EventHandlerBase*>::value, "Expected const RegisteredEvent");
113 114 115

        {
            auto it = std::find_if(begin(m_lambdas), end(m_lambdas), [&e](decltype(m_lambdas)::value_type &value) {
116
                return e == value.get();
117 118 119 120 121 122
            });
            if (it != end(m_lambdas))
                m_lambdas.erase( it );
        }

        unregister(args...);
123 124
    }

125 126 127 128 129 130
protected:
    EventManager(InternalPtr ptr)
        : Internal{ ptr, [](InternalPtr){ /* No-op; EventManager's are handled by their respective objects */ } }
    {
    }

131 132 133 134 135 136 137 138 139
public:
    EventManager(const EventManager& em)
        : Internal( em )
    {
        // Use an empty list of events
    }

    EventManager& operator=(const EventManager& em)
    {
140 141
        if (this == &em)
            return *this;
142 143 144 145 146 147 148
        Internal::operator=(em);
        return *this;
    }

    EventManager(EventManager&&) = default;
    EventManager& operator=(EventManager&&) = default;

149
    using RegisteredEvent = EventHandlerBase*;
150

151 152
protected:

153 154 155 156 157 158 159 160 161 162 163 164 165 166
    /**
     * @brief handle        Provides the common behavior for all event handlers
     * @param eventType     The libvlc type of event
     * @param f             The user provided std::function. This has to either match the expected parameter list
     *                      exactly, or it can take no arguments.
     * @param wrapper       Our implementation defined wrapper around the user's callback. It is expected to be able
     *                      able to decay to a regular C-style function pointer. It is currently implemented as a
     *                      captureless lambda (§5.1.2)
     * @return              A reference to an abstract EventHandler type. It is assumed that the EventManager will
     *                      outlive this reference. When EventManager::~EventManager is called, it will destroy all
     *                      the registered event handler, this making this reference a dangling reference, which is
     *                      undefined behavior.
     *                      When calling unregister() on this object, the reference should immediatly be considered invalid.
     */
167
    template <typename Func>
168
    RegisteredEvent handle(libvlc_event_e eventType, Func&& f, EventHandlerBase::Wrapper wrapper)
169
    {
170 171 172 173
        auto ptr = std::unique_ptr<EventHandlerBase>( new EventHandler<Func>(
                                *this, eventType, std::forward<Func>( f ), wrapper ) );
        auto raw = ptr.get();
        m_lambdas.push_back( std::move( ptr ) );
174
        return raw;
175 176
    }

177
    template <typename Func>
178
    RegisteredEvent handle(libvlc_event_e eventType, Func&& f)
179
    {
180 181
        EXPECT_SIGNATURE(void());
        return handle(eventType, std::forward<Func>( f ), [](const libvlc_event_t*, void* data)
182
        {
183
            auto callback = static_cast<DecayPtr<Func>>( data );
184 185 186 187 188 189 190
            (*callback)();
        });
    }

protected:
    // We store the EventHandlerBase's as unique_ptr in order for the function stored within
    // EventHandler<T> not to move to another memory location
191
    std::vector<std::unique_ptr<EventHandlerBase>> m_lambdas;
192 193
};

194
class MediaEventManager : public EventManager
195 196
{
    public:
197
        MediaEventManager(InternalPtr ptr) : EventManager( ptr ) {}
198

199 200 201 202 203
        /**
         * @brief onMetaChanged
         * @param f A std::function<void(libvlc_meta_t)>
         */
        template <typename Func>
204
        RegisteredEvent onMetaChanged( Func&& f)
205
        {
206 207
            EXPECT_SIGNATURE(void(libvlc_meta_t));
            return handle( libvlc_MediaMetaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
208
            {
209
                auto callback = static_cast<DecayPtr<Func>>(data);
210 211 212
                (*callback)( e->u.media_meta_changed.meta_type );
            });
        }
213

214 215 216 217 218
        /**
         * @brief onSubItemAdded
         * @param f A std::function<void(MediaPtr)>
         */
        template <typename Func>
219
        RegisteredEvent onSubItemAdded( Func&& f )
220
        {
221 222
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaSubItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
223
            {
224
                auto callback = static_cast<DecayPtr<Func>>(data);
225 226 227 228
                (*callback)( std::make_shared<Media>( e->u.media_subitem_added.new_child, true ) );
            });
        }

229
        template <typename Func>
230
        RegisteredEvent onDurationChanged( Func&& f )
231
        {
232 233
            EXPECT_SIGNATURE(void(int64_t));
            return handle(libvlc_MediaDurationChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
234
            {
235
                auto callback = static_cast<DecayPtr<Func>>(data);
236 237 238 239
                (*callback)( e->u.media_duration_changed.new_duration );
            });
        }

240
        template <typename Func>
241
        RegisteredEvent onParsedChanged( Func&& f )
242
        {
243 244
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaParsedChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
245
            {
246
                auto callback = static_cast<DecayPtr<Func>>(data);
247 248 249 250
                (*callback)( e->u.media_parsed_changed.new_status );
            });
        }

251
        template <typename Func>
252
        RegisteredEvent onFreed( Func&& f)
253
        {
254 255
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaFreed, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
256
            {
257
                auto callback = static_cast<DecayPtr<Func>>(data);
258 259 260 261
                (*callback)( std::make_shared<Media>( e->u.media_freed.md, true ) );
            });
        }

262
        template <typename Func>
263
        RegisteredEvent onStateChanged( Func&& f)
264
        {
265 266
            EXPECT_SIGNATURE(void(libvlc_state_t));
            return handle(libvlc_MediaStateChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
267
            {
268
                auto callback = static_cast<DecayPtr<Func>>(data);
269 270 271 272
                (*callback)( e->u.media_state_changed.new_state );
            });
        }

273
        template <typename Func>
274
        RegisteredEvent onSubItemTreeAdded( Func&& f)
275
        {
276 277
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaSubItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
278
            {
279
                auto callback = static_cast<DecayPtr<Func>>(data);
280 281 282
                (*callback)( std::make_shared<Media>( e->u.media_subitemtree_added.item, true ) );
            });
        }
283 284
};

285
class MediaPlayerEventManager : public EventManager
286 287
{
    public:
288 289
        MediaPlayerEventManager(InternalPtr ptr) : EventManager( ptr ) {}

290
        template <typename Func>
291
        RegisteredEvent onMediaChanged( Func&& f )
292
        {
293 294
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaPlayerMediaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
295
            {
296
                auto callback = static_cast<DecayPtr<Func>>( data );
297 298 299
                (*callback)( std::make_shared<Media>( e->u.media_player_media_changed.new_media, true ) );
            });
        }
300 301

        template <typename Func>
302
        RegisteredEvent onNothingSpecial( Func&& f )
303
        {
304
            return handle(libvlc_MediaPlayerNothingSpecial, std::forward<Func>( f ));
305 306
        }

307
        template <typename Func>
308
        RegisteredEvent onOpening( Func&& f )
309
        {
310
            return handle(libvlc_MediaPlayerOpening, std::forward<Func>( f ) );
311 312
        }

313
        template <typename Func>
314
        RegisteredEvent onBuffering( Func&& f )
315
        {
316
            return handle(libvlc_MediaPlayerBuffering, std::forward<Func>( f ) );
317 318
        }

319
        template <typename Func>
320
        RegisteredEvent onPlaying( Func&& f )
321
        {
322
            return handle( libvlc_MediaPlayerPlaying, std::forward<Func>( f ) );
323 324
        }

325
        template <typename Func>
326
        RegisteredEvent onPaused(Func&& f)
327
        {
328
            return handle( libvlc_MediaPlayerPaused, std::forward<Func>( f ) );
329 330
        }

331
        template <typename Func>
332
        RegisteredEvent onStopped(Func&& f)
333
        {
334
            return handle( libvlc_MediaPlayerStopped, std::forward<Func>( f ) );
335 336
        }

337
        template <typename Func>
338
        RegisteredEvent onForward(Func&& f)
339
        {
340
            return handle( libvlc_MediaPlayerForward, std::forward<Func>( f ) );
341 342
        }

343
        template <typename Func>
344
        RegisteredEvent onBackward(Func&& f)
345
        {
346
            return handle( libvlc_MediaPlayerBackward, std::forward<Func>( f ) );
347 348
        }

349
        template <typename Func>
350
        RegisteredEvent onEndReached(Func&& f)
351
        {
352
            return handle( libvlc_MediaPlayerEndReached, std::forward<Func>( f ) );
353 354
        }

355
        template <typename Func>
356
        RegisteredEvent onEncounteredError(Func&& f)
357
        {
358
            return handle( libvlc_MediaPlayerEncounteredError, std::forward<Func>( f ) );
359 360
        }

361
        template <typename Func>
362
        RegisteredEvent onTimeChanged( Func&& f )
363
        {
364 365
            EXPECT_SIGNATURE(void(libvlc_time_t));
            return handle( libvlc_MediaPlayerTimeChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
366
            {
367
                auto callback = static_cast<DecayPtr<Func>>( data );
368 369 370 371
                (*callback)( e->u.media_player_time_changed.new_time );
            });
        }

372
        template <typename Func>
373
        RegisteredEvent onPositionChanged( Func&& f )
374
        {
375 376
            EXPECT_SIGNATURE(void(float));
            return handle( libvlc_MediaPlayerPositionChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
377
            {
378
                auto callback = static_cast<DecayPtr<Func>>( data );
379 380 381 382
                (*callback)( e->u.media_player_position_changed.new_position );
            });
        }

383
        template <typename Func>
384
        RegisteredEvent onSeekableChanged( Func&& f )
385
        {
386 387
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaPlayerSeekableChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
388
            {
389
                auto callback = static_cast<DecayPtr<Func>>( data );
390 391 392 393
                (*callback)( e->u.media_player_seekable_changed.new_seekable );
            });
        }

394
        template <typename Func>
395
        RegisteredEvent onPausableChanged( Func&& f )
396
        {
397 398
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaPlayerSeekableChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
399
            {
400
                auto callback = static_cast<DecayPtr<Func>>( data );
401 402 403 404
                (*callback)( e->u.media_player_seekable_changed.new_seekable );
            });
        }

405
        template <typename Func>
406
        RegisteredEvent onTitleChanged( Func&& f )
407
        {
408 409
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerTitleChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
410
            {
411
                auto callback = static_cast<DecayPtr<Func>>( data );
412 413 414 415
                (*callback)( e->u.media_player_title_changed.new_title );
            });
        }

416
        template <typename Func>
417
        RegisteredEvent onSnapshotTaken( Func&& f )
418
        {
419 420
            EXPECT_SIGNATURE(void(std::string));
            return handle( libvlc_MediaPlayerSnapshotTaken, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
421
            {
422
                auto callback = static_cast<DecayPtr<Func>>( data );
423 424 425 426
                (*callback)( e->u.media_player_snapshot_taken.psz_filename );
            });
        }

427
        template <typename Func>
428
        RegisteredEvent onLengthChanged( Func&& f )
429
        {
430 431
            EXPECT_SIGNATURE(void(libvlc_time_t));
            return handle( libvlc_MediaPlayerLengthChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
432
            {
433
                auto callback = static_cast<DecayPtr<Func>>( data );
434 435 436 437
                (*callback)( e->u.media_player_length_changed.new_length );
            });
        }

438
        template <typename Func>
439
        RegisteredEvent onVout( Func&& f )
440
        {
441 442
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerVout, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
443
            {
444
                auto callback = static_cast<DecayPtr<Func>>( data );
445 446 447 448
                (*callback)( e->u.media_player_vout.new_count );
            });
        }

449
        template <typename Func>
450
        RegisteredEvent onScrambledChanged( Func&& f )
451
        {
452 453
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerScrambledChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
454
            {
455
                auto callback = static_cast<DecayPtr<Func>>( data );
456 457 458 459
                (*callback)( e->u.media_player_scrambled_changed.new_scrambled );
            });
        }

460
        template <typename Func>
461
        RegisteredEvent onESAdded( Func&& f )
462
        {
463 464
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
465
            {
466
                auto callback = static_cast<DecayPtr<Func>>( data );
467 468 469 470
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }

471
        template <typename Func>
472
        RegisteredEvent onESDeleted( Func&& f )
473
        {
474 475
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESDeleted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
476
            {
477
                auto callback = static_cast<DecayPtr<Func>>( data );
478 479 480 481
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }

482
        template <typename Func>
483
        RegisteredEvent onESSelected( Func&& f )
484
        {
485 486
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESSelected, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
487
            {
488
                auto callback = static_cast<DecayPtr<Func>>( data );
489 490 491
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }
492 493
};

494
class MediaListEventManager : public EventManager
495 496
{
    public:
497 498
        MediaListEventManager(InternalPtr ptr) : EventManager( ptr ) {}

499
        template <typename Func>
500
        RegisteredEvent onItemAdded( Func&& f )
501
        {
502 503
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
504
            {
505
                auto callback = static_cast<DecayPtr<Func>>( data );
506 507 508 509
                (*callback)( std::make_shared<Media>( e->u.media_list_item_added.item, true ), e->u.media_list_item_added.index );
            });
        }

510
        template <typename Func>
511
        RegisteredEvent onWillAddItem( Func&& f )
512
        {
513 514
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle( libvlc_MediaListWillAddItem, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
515
            {
516
                auto callback = static_cast<DecayPtr<Func>>( data );
517 518 519 520
                (*callback)(std::make_shared<Media>( e->u.media_list_will_add_item.item, true ), e->u.media_list_will_add_item.index );
            });
        }

521
        template <typename Func>
522
        RegisteredEvent onItemDeleted( Func&& f )
523
        {
524 525
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListItemDeleted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
526
            {
527
                auto callback = static_cast<DecayPtr<Func>>( data );
528 529 530 531
                (*callback)( std::make_shared<Media>( e->u.media_list_item_deleted.item, true ), e->u.media_list_item_deleted.index );
            });
        }

532
        template <typename Func>
533
        RegisteredEvent onWillDeleteItem( Func&& f )
534
        {
535 536
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListWillDeleteItem, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
537
            {
538
                auto callback = static_cast<DecayPtr<Func>>( data );
539 540 541
                (*callback)( std::make_shared<Media>( e->u.media_list_will_delete_item.item, true ), e->u.media_list_will_delete_item.index );
            });
        }
542 543
};

544 545 546
// MediaListView events are not being sent by VLC, so we don't implement them here

class MediaListPlayerEventManager : public EventManager
547 548
{
    public:
549 550
        MediaListPlayerEventManager(InternalPtr ptr) : EventManager( ptr ) {}

551
        template <typename Func>
552
        RegisteredEvent onPlayed(Func&& f)
553
        {
554
            return handle(libvlc_MediaListPlayerPlayed, std::forward<Func>( f ) );
555 556
        }

557
        template <typename Func>
558
        RegisteredEvent onNextItemSet( Func&& f )
559
        {
560 561
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaListPlayerNextItemSet, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
562
            {
563
                auto callback = static_cast<DecayPtr<Func>>( data );
564 565
                (*callback)( std::make_shared<Media>( e->u.media_list_player_next_item_set.item, true ) );
            });
566 567
        }

568
        template <typename Func>
569
        RegisteredEvent onStopped( Func&& f )
570
        {
571
            return handle(libvlc_MediaListPlayerStopped, std::forward<Func>( f ) );
572
        }
573
};
574

575 576 577 578 579
class MediaDiscovererEventManager : public EventManager
{
    public:
        MediaDiscovererEventManager(InternalPtr ptr) : EventManager( ptr ) {}

580
        template <typename Func>
581
        RegisteredEvent onStarted(Func&& f)
582
        {
583
            return handle(libvlc_MediaDiscovererStarted, std::forward<Func>( f ) );
584 585
        }

586
        template <typename Func>
587
        RegisteredEvent onStopped(Func&& f)
588
        {
589
            return handle(libvlc_MediaDiscovererEnded, std::forward<Func>( f ) );
590
        }
591
};
592

593 594 595 596 597
class VLMEventManager : public EventManager
{
    public:
        using EventManager::EventManager;

598
        template <typename Func>
599
        RegisteredEvent onMediaAdded( Func&& f )
600
        {
601 602
            EXPECT_SIGNATURE(void(std::string));
            return handle(libvlc_VlmMediaAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
603
            {
604
                auto callback = static_cast<DecayPtr<Func>>( data );
605 606
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "" );
            });
607 608
        }

609
        template <typename Func>
610
        RegisteredEvent onMediaRemoved( Func&& f )
611
        {
612 613
            EXPECT_SIGNATURE(void(std::string));
            return handle(libvlc_VlmMediaRemoved, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
614
            {
615
                auto callback = static_cast<DecayPtr<Func>>( data );
616 617
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "" );
            });
618 619
        }

620
        template <typename Func>
621
        RegisteredEvent onMediaChanged( Func&& f )
622
        {
623 624
            EXPECT_SIGNATURE(void(std::string));
            return handle(libvlc_VlmMediaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
625
            {
626
                auto callback = static_cast<DecayPtr<Func>>( data );
627 628 629
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "" );
            });
        }
630 631

        template <typename Func>
632
        RegisteredEvent onMediaInstanceStarted( Func&& f )
633
        {
634 635
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStarted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
636
            {
637
                auto callback = static_cast<DecayPtr<Func>>( data );
638 639 640
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
641 642
        }

643
        template <typename Func>
644
        RegisteredEvent onMediaInstanceStopped( Func&& f )
645
        {
646 647
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStopped, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
648
            {
649
                auto callback = static_cast<DecayPtr<Func>>( data );
650 651 652
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
653 654
        }

655
        template <typename Func>
656
        RegisteredEvent onMediaInstanceStatusInit( Func&& f )
657
        {
658 659
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusInit, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
660
            {
661
                auto callback = static_cast<DecayPtr<Func>>( data );
662 663 664
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
665 666
        }

667
        template <typename Func>
668
        RegisteredEvent onMediaInstanceStatusOpening( Func&& f )
669
        {
670 671
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusOpening, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
672
            {
673
                auto callback = static_cast<DecayPtr<Func>>( data );
674 675 676
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
677 678
        }

679
        template <typename Func>
680
        RegisteredEvent onMediaInstanceStatusPlaying( Func&& f )
681
        {
682 683
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusPlaying, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
684
            {
685
                auto callback = static_cast<DecayPtr<Func>>( data );
686 687 688
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
689 690
        }

691
        template <typename Func>
692
        RegisteredEvent onMediaInstanceStatusPause( Func&& f )
693
        {
694 695
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusPause, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
696
            {
697
                auto callback = static_cast<DecayPtr<Func>>( data );
698 699 700
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
701
        }
702

703
        template <typename Func>
704
        RegisteredEvent onMediaInstanceStatusEnd( Func&& f )
705
        {
706 707
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusEnd, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
708
            {
709
                auto callback = static_cast<DecayPtr<Func>>( data );
710 711 712
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
713
        }
714

715
        template <typename Func>
716
        RegisteredEvent onMediaInstanceStatusError( Func&& f )
717
        {
718 719
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusError, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
720
            {
721
                auto callback = static_cast<DecayPtr<Func>>( data );
722 723 724 725 726
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "",
                             e->u.vlm_media_event.psz_instance_name ? e->u.vlm_media_event.psz_instance_name : "" );
            });
        }
};
727 728 729
}

#endif // LIBVLC_EVENTMANAGER_HPP