EventManager.hpp 28.8 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
        Internal::operator=(em);
        return *this;
    }

146
#if !defined(_MSC_VER) || _MSC_VER >= 1900
147 148
    EventManager(EventManager&&) = default;
    EventManager& operator=(EventManager&&) = default;
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
#else
    EventManager(EventManager&& em)
        : Internal( std::move( em ) )
        , m_lambdas(std::move( em.m_lambdas ) )
    {
    }

    EventManager& operator=(EventManager&& em)
    {
        if ( this == &em )
            return *this;
        Internal::operator=( std::move( em ) );
        m_lambdas = std::move( em.m_lambdas );
    }
#endif
164

165
    using RegisteredEvent = EventHandlerBase*;
166

167 168
protected:

169 170 171 172 173 174 175 176 177 178 179 180 181 182
    /**
     * @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.
     */
183
    template <typename Func>
184
    RegisteredEvent handle(libvlc_event_e eventType, Func&& f, EventHandlerBase::Wrapper wrapper)
185
    {
186 187 188 189
        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 ) );
190
        return raw;
191 192
    }

193
    template <typename Func>
194
    RegisteredEvent handle(libvlc_event_e eventType, Func&& f)
195
    {
196 197
        EXPECT_SIGNATURE(void());
        return handle(eventType, std::forward<Func>( f ), [](const libvlc_event_t*, void* data)
198
        {
199
            auto callback = static_cast<DecayPtr<Func>>( data );
200 201 202 203 204 205 206
            (*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
207
    std::vector<std::unique_ptr<EventHandlerBase>> m_lambdas;
208 209
};

210
class MediaEventManager : public EventManager
211 212
{
    public:
213
        MediaEventManager(InternalPtr ptr) : EventManager( ptr ) {}
214

215 216 217 218 219
        /**
         * @brief onMetaChanged
         * @param f A std::function<void(libvlc_meta_t)>
         */
        template <typename Func>
220
        RegisteredEvent onMetaChanged( Func&& f)
221
        {
222 223
            EXPECT_SIGNATURE(void(libvlc_meta_t));
            return handle( libvlc_MediaMetaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
224
            {
225
                auto callback = static_cast<DecayPtr<Func>>(data);
226 227 228
                (*callback)( e->u.media_meta_changed.meta_type );
            });
        }
229

230 231 232 233 234
        /**
         * @brief onSubItemAdded
         * @param f A std::function<void(MediaPtr)>
         */
        template <typename Func>
235
        RegisteredEvent onSubItemAdded( Func&& f )
236
        {
237 238
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaSubItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
239
            {
240
                auto callback = static_cast<DecayPtr<Func>>(data);
241 242 243 244
                (*callback)( std::make_shared<Media>( e->u.media_subitem_added.new_child, true ) );
            });
        }

245
        template <typename Func>
246
        RegisteredEvent onDurationChanged( Func&& f )
247
        {
248 249
            EXPECT_SIGNATURE(void(int64_t));
            return handle(libvlc_MediaDurationChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
250
            {
251
                auto callback = static_cast<DecayPtr<Func>>(data);
252 253 254 255
                (*callback)( e->u.media_duration_changed.new_duration );
            });
        }

256
        template <typename Func>
257
        RegisteredEvent onParsedChanged( Func&& f )
258
        {
259 260
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaParsedChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
261
            {
262
                auto callback = static_cast<DecayPtr<Func>>(data);
263 264 265 266
                (*callback)( e->u.media_parsed_changed.new_status );
            });
        }

267
        template <typename Func>
268
        RegisteredEvent onFreed( Func&& f)
269
        {
270 271
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaFreed, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
272
            {
273
                auto callback = static_cast<DecayPtr<Func>>(data);
274 275 276 277
                (*callback)( std::make_shared<Media>( e->u.media_freed.md, true ) );
            });
        }

278
        template <typename Func>
279
        RegisteredEvent onStateChanged( Func&& f)
280
        {
281 282
            EXPECT_SIGNATURE(void(libvlc_state_t));
            return handle(libvlc_MediaStateChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
283
            {
284
                auto callback = static_cast<DecayPtr<Func>>(data);
285 286 287 288
                (*callback)( e->u.media_state_changed.new_state );
            });
        }

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

301
class MediaPlayerEventManager : public EventManager
302 303
{
    public:
304 305
        MediaPlayerEventManager(InternalPtr ptr) : EventManager( ptr ) {}

306
        template <typename Func>
307
        RegisteredEvent onMediaChanged( Func&& f )
308
        {
309 310
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaPlayerMediaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
311
            {
312
                auto callback = static_cast<DecayPtr<Func>>( data );
313 314 315
                (*callback)( std::make_shared<Media>( e->u.media_player_media_changed.new_media, true ) );
            });
        }
316 317

        template <typename Func>
318
        RegisteredEvent onNothingSpecial( Func&& f )
319
        {
320
            return handle(libvlc_MediaPlayerNothingSpecial, std::forward<Func>( f ));
321 322
        }

323
        template <typename Func>
324
        RegisteredEvent onOpening( Func&& f )
325
        {
326
            return handle(libvlc_MediaPlayerOpening, std::forward<Func>( f ) );
327 328
        }

329
        template <typename Func>
330
        RegisteredEvent onBuffering( Func&& f )
331
        {
332 333 334 335 336 337
            EXPECT_SIGNATURE(void(float));
            return handle(libvlc_MediaPlayerBuffering, std::forward<Func>(f), [](const libvlc_event_t* e, void* data)
            {
                auto callback = static_cast<DecayPtr<Func>>( data );
                (*callback)( e->u.media_player_buffering.new_cache );
            });
338 339
        }

340
        template <typename Func>
341
        RegisteredEvent onPlaying( Func&& f )
342
        {
343
            return handle( libvlc_MediaPlayerPlaying, std::forward<Func>( f ) );
344 345
        }

346
        template <typename Func>
347
        RegisteredEvent onPaused(Func&& f)
348
        {
349
            return handle( libvlc_MediaPlayerPaused, std::forward<Func>( f ) );
350 351
        }

352
        template <typename Func>
353
        RegisteredEvent onStopped(Func&& f)
354
        {
355
            return handle( libvlc_MediaPlayerStopped, std::forward<Func>( f ) );
356 357
        }

358
        template <typename Func>
359
        RegisteredEvent onForward(Func&& f)
360
        {
361
            return handle( libvlc_MediaPlayerForward, std::forward<Func>( f ) );
362 363
        }

364
        template <typename Func>
365
        RegisteredEvent onBackward(Func&& f)
366
        {
367
            return handle( libvlc_MediaPlayerBackward, std::forward<Func>( f ) );
368 369
        }

370
        template <typename Func>
371
        RegisteredEvent onEndReached(Func&& f)
372
        {
373
            return handle( libvlc_MediaPlayerEndReached, std::forward<Func>( f ) );
374 375
        }

376
        template <typename Func>
377
        RegisteredEvent onEncounteredError(Func&& f)
378
        {
379
            return handle( libvlc_MediaPlayerEncounteredError, std::forward<Func>( f ) );
380 381
        }

382
        template <typename Func>
383
        RegisteredEvent onTimeChanged( Func&& f )
384
        {
385 386
            EXPECT_SIGNATURE(void(libvlc_time_t));
            return handle( libvlc_MediaPlayerTimeChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
387
            {
388
                auto callback = static_cast<DecayPtr<Func>>( data );
389 390 391 392
                (*callback)( e->u.media_player_time_changed.new_time );
            });
        }

393
        template <typename Func>
394
        RegisteredEvent onPositionChanged( Func&& f )
395
        {
396 397
            EXPECT_SIGNATURE(void(float));
            return handle( libvlc_MediaPlayerPositionChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
398
            {
399
                auto callback = static_cast<DecayPtr<Func>>( data );
400 401 402 403
                (*callback)( e->u.media_player_position_changed.new_position );
            });
        }

404
        template <typename Func>
405
        RegisteredEvent onSeekableChanged( Func&& f )
406
        {
407 408
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaPlayerSeekableChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
409
            {
410
                auto callback = static_cast<DecayPtr<Func>>( data );
411 412 413 414
                (*callback)( e->u.media_player_seekable_changed.new_seekable );
            });
        }

415
        template <typename Func>
416
        RegisteredEvent onPausableChanged( Func&& f )
417
        {
418 419
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaPlayerSeekableChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
420
            {
421
                auto callback = static_cast<DecayPtr<Func>>( data );
422 423 424 425
                (*callback)( e->u.media_player_seekable_changed.new_seekable );
            });
        }

426
        template <typename Func>
427
        RegisteredEvent onTitleChanged( Func&& f )
428
        {
429 430
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerTitleChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
431
            {
432
                auto callback = static_cast<DecayPtr<Func>>( data );
433 434 435 436
                (*callback)( e->u.media_player_title_changed.new_title );
            });
        }

437
        template <typename Func>
438
        RegisteredEvent onSnapshotTaken( Func&& f )
439
        {
440 441
            EXPECT_SIGNATURE(void(std::string));
            return handle( libvlc_MediaPlayerSnapshotTaken, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
442
            {
443
                auto callback = static_cast<DecayPtr<Func>>( data );
444 445 446 447
                (*callback)( e->u.media_player_snapshot_taken.psz_filename );
            });
        }

448
        template <typename Func>
449
        RegisteredEvent onLengthChanged( Func&& f )
450
        {
451 452
            EXPECT_SIGNATURE(void(libvlc_time_t));
            return handle( libvlc_MediaPlayerLengthChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
453
            {
454
                auto callback = static_cast<DecayPtr<Func>>( data );
455 456 457 458
                (*callback)( e->u.media_player_length_changed.new_length );
            });
        }

459
        template <typename Func>
460
        RegisteredEvent onVout( Func&& f )
461
        {
462 463
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerVout, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
464
            {
465
                auto callback = static_cast<DecayPtr<Func>>( data );
466 467 468 469
                (*callback)( e->u.media_player_vout.new_count );
            });
        }

470
        template <typename Func>
471
        RegisteredEvent onScrambledChanged( Func&& f )
472
        {
473 474
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerScrambledChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
475
            {
476
                auto callback = static_cast<DecayPtr<Func>>( data );
477 478 479 480
                (*callback)( e->u.media_player_scrambled_changed.new_scrambled );
            });
        }

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

492
        template <typename Func>
493
        RegisteredEvent onESDeleted( Func&& f )
494
        {
495 496
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESDeleted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
497
            {
498
                auto callback = static_cast<DecayPtr<Func>>( data );
499 500 501 502
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }

503
        template <typename Func>
504
        RegisteredEvent onESSelected( Func&& f )
505
        {
506 507
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESSelected, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
508
            {
509
                auto callback = static_cast<DecayPtr<Func>>( data );
510 511 512
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }
513 514
};

515
class MediaListEventManager : public EventManager
516 517
{
    public:
518 519
        MediaListEventManager(InternalPtr ptr) : EventManager( ptr ) {}

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

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

542
        template <typename Func>
543
        RegisteredEvent onItemDeleted( Func&& f )
544
        {
545 546
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListItemDeleted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
547
            {
548
                auto callback = static_cast<DecayPtr<Func>>( data );
549 550 551 552
                (*callback)( std::make_shared<Media>( e->u.media_list_item_deleted.item, true ), e->u.media_list_item_deleted.index );
            });
        }

553
        template <typename Func>
554
        RegisteredEvent onWillDeleteItem( Func&& f )
555
        {
556 557
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListWillDeleteItem, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
558
            {
559
                auto callback = static_cast<DecayPtr<Func>>( data );
560 561 562
                (*callback)( std::make_shared<Media>( e->u.media_list_will_delete_item.item, true ), e->u.media_list_will_delete_item.index );
            });
        }
563 564
};

565 566 567
// MediaListView events are not being sent by VLC, so we don't implement them here

class MediaListPlayerEventManager : public EventManager
568 569
{
    public:
570 571
        MediaListPlayerEventManager(InternalPtr ptr) : EventManager( ptr ) {}

572
        template <typename Func>
573
        RegisteredEvent onPlayed(Func&& f)
574
        {
575
            return handle(libvlc_MediaListPlayerPlayed, std::forward<Func>( f ) );
576 577
        }

578
        template <typename Func>
579
        RegisteredEvent onNextItemSet( Func&& f )
580
        {
581 582
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaListPlayerNextItemSet, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
583
            {
584
                auto callback = static_cast<DecayPtr<Func>>( data );
585 586
                (*callback)( std::make_shared<Media>( e->u.media_list_player_next_item_set.item, true ) );
            });
587 588
        }

589
        template <typename Func>
590
        RegisteredEvent onStopped( Func&& f )
591
        {
592
            return handle(libvlc_MediaListPlayerStopped, std::forward<Func>( f ) );
593
        }
594
};
595

596 597 598 599 600
class MediaDiscovererEventManager : public EventManager
{
    public:
        MediaDiscovererEventManager(InternalPtr ptr) : EventManager( ptr ) {}

601
        template <typename Func>
602
        RegisteredEvent onStarted(Func&& f)
603
        {
604
            return handle(libvlc_MediaDiscovererStarted, std::forward<Func>( f ) );
605 606
        }

607
        template <typename Func>
608
        RegisteredEvent onStopped(Func&& f)
609
        {
610
            return handle(libvlc_MediaDiscovererEnded, std::forward<Func>( f ) );
611
        }
612
};
613

614 615 616 617 618
class VLMEventManager : public EventManager
{
    public:
        using EventManager::EventManager;

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

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

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

        template <typename Func>
653
        RegisteredEvent onMediaInstanceStarted( Func&& f )
654
        {
655 656
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStarted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
657
            {
658
                auto callback = static_cast<DecayPtr<Func>>( data );
659 660 661
                (*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 : "" );
            });
662 663
        }

664
        template <typename Func>
665
        RegisteredEvent onMediaInstanceStopped( Func&& f )
666
        {
667 668
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStopped, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
669
            {
670
                auto callback = static_cast<DecayPtr<Func>>( data );
671 672 673
                (*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 : "" );
            });
674 675
        }

676
        template <typename Func>
677
        RegisteredEvent onMediaInstanceStatusInit( Func&& f )
678
        {
679 680
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusInit, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
681
            {
682
                auto callback = static_cast<DecayPtr<Func>>( data );
683 684 685
                (*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 : "" );
            });
686 687
        }

688
        template <typename Func>
689
        RegisteredEvent onMediaInstanceStatusOpening( Func&& f )
690
        {
691 692
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusOpening, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
693
            {
694
                auto callback = static_cast<DecayPtr<Func>>( data );
695 696 697
                (*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 : "" );
            });
698 699
        }

700
        template <typename Func>
701
        RegisteredEvent onMediaInstanceStatusPlaying( Func&& f )
702
        {
703 704
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusPlaying, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
705
            {
706
                auto callback = static_cast<DecayPtr<Func>>( data );
707 708 709
                (*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 : "" );
            });
710 711
        }

712
        template <typename Func>
713
        RegisteredEvent onMediaInstanceStatusPause( Func&& f )
714
        {
715 716
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusPause, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
717
            {
718
                auto callback = static_cast<DecayPtr<Func>>( data );
719 720 721
                (*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 : "" );
            });
722
        }
723

724
        template <typename Func>
725
        RegisteredEvent onMediaInstanceStatusEnd( Func&& f )
726
        {
727 728
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusEnd, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
729
            {
730
                auto callback = static_cast<DecayPtr<Func>>( data );
731 732 733
                (*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 : "" );
            });
734
        }
735

736
        template <typename Func>
737
        RegisteredEvent onMediaInstanceStatusError( Func&& f )
738
        {
739 740
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusError, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
741
            {
742
                auto callback = static_cast<DecayPtr<Func>>( data );
743 744 745 746 747
                (*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 : "" );
            });
        }
};
748 749 750
}

#endif // LIBVLC_EVENTMANAGER_HPP