EventManager.hpp 26 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
/*****************************************************************************
 * libvlc_EventManager.hpp: Exposes libvlc events
 *****************************************************************************
 * Copyright © 2014 the VideoLAN team
 *
 * 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
#include <iostream>
28

29
#include "common.hpp"
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
30
#include "Internal.hpp"
31

32 33 34 35 36
#include <functional>
#include <unordered_map>
#include <memory>
#include <atomic>

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

39 40 41 42 43
namespace VLC
{

class Media;

44
using EventToken = unsigned int;
45

46 47 48 49 50 51 52 53
/**
 * @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>
54
{
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
protected:
    template <typename T>
    using Decay = typename std::decay<T>::type;

    template <typename T>
    using DecayPtr = typename std::add_pointer<typename std::decay<T>::type>::type;

    template <typename, typename, typename = void>
    struct signature_match : std::false_type {};

    template <typename Func, typename Ret, typename... Args>
    struct signature_match<Func, Ret(Args...),
        typename std::enable_if<
            std::is_convertible<
                decltype(std::declval<Func>()(std::declval<Args>()...)),
                Ret
            >::value
        >::type
    > : std::true_type {};

75 76 77 78 79 80 81 82
private:
    // Polymorphic base to hold a templated implementation
    struct EventHandlerBase
    {
        using Wrapper = std::add_pointer<void(const libvlc_event_t*, void*)>::type;
        virtual ~EventHandlerBase() {}
    };

83
    template <typename Func>
84 85
    class EventHandler : public EventHandlerBase
    {
86
    public:
87 88
        EventHandler(EventManager& em, libvlc_event_e eventType, Func&& userCallback, Wrapper wrapper)
            : m_userCallback( std::forward<Func>(userCallback) )
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
            , 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()
        {
            libvlc_event_detach( *m_eventManager, m_eventType, m_wrapper, &m_userCallback );
        }

        EventHandler(const EventHandler&) = delete;

    private:
105
        Decay<Func> m_userCallback;
106 107 108 109 110 111 112 113 114 115 116 117 118
        // EventManager always outlive EventHandler, no need for smart pointer
        EventManager* m_eventManager;
        Wrapper m_wrapper;
        libvlc_event_e m_eventType;
    };

protected:
    EventManager(InternalPtr ptr)
        : Internal{ ptr, [](InternalPtr){ /* No-op; EventManager's are handled by their respective objects */ } }
        , m_lastEvent(0)
    {
    }

119 120
    template <typename Func>
    EventToken handle(libvlc_event_e eventType, Func&& f, EventHandlerBase::Wrapper wrapper)
121 122
    {
        auto token = ++m_lastEvent;
123 124
        m_lambdas[token] = std::unique_ptr<EventHandlerBase>( new EventHandler<Func>(
                                                                  *this, eventType, std::forward<Func>( f ), wrapper ) );
125 126 127
        return token;
    }

128 129
    template <typename Func>
    EventToken handle(libvlc_event_e eventType, Func&& f)
130
    {
131 132
        EXPECT_SIGNATURE(void());
        return handle(eventType, std::forward<Func>( f ), [](const libvlc_event_t*, void* data)
133
        {
134
            auto callback = static_cast<DecayPtr<Func>>( data );
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
            (*callback)();
        });
    }

    void unregister(EventToken t)
    {
        if (t == 0)
            return;
        m_lambdas.erase(t);
    }

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
    std::unordered_map<EventToken, std::unique_ptr<EventHandlerBase>> m_lambdas;
    std::atomic_uint m_lastEvent;
151 152
};

153
class MediaEventManager : public EventManager
154 155
{
    public:
156
        MediaEventManager(InternalPtr ptr) : EventManager( ptr ) {}
157

158 159 160 161 162 163
        /**
         * @brief onMetaChanged
         * @param f A std::function<void(libvlc_meta_t)>
         */
        template <typename Func>
        EventToken onMetaChanged( Func&& f)
164
        {
165 166
            EXPECT_SIGNATURE(void(libvlc_meta_t));
            return handle( libvlc_MediaMetaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
167
            {
168
                auto callback = static_cast<DecayPtr<Func>>(data);
169 170 171
                (*callback)( e->u.media_meta_changed.meta_type );
            });
        }
172

173 174 175 176 177 178
        /**
         * @brief onSubItemAdded
         * @param f A std::function<void(MediaPtr)>
         */
        template <typename Func>
        EventToken onSubItemAdded( Func&& f )
179
        {
180 181
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaSubItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
182
            {
183
                auto callback = static_cast<DecayPtr<Func>>(data);
184 185 186 187
                (*callback)( std::make_shared<Media>( e->u.media_subitem_added.new_child, true ) );
            });
        }

188 189
        template <typename Func>
        EventToken onDurationChanged( Func&& f )
190
        {
191 192
            EXPECT_SIGNATURE(void(int64_t));
            return handle(libvlc_MediaDurationChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
193
            {
194
                auto callback = static_cast<DecayPtr<Func>>(data);
195 196 197 198
                (*callback)( e->u.media_duration_changed.new_duration );
            });
        }

199 200
        template <typename Func>
        EventToken onParsedChanged( Func&& f )
201
        {
202 203
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaParsedChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
204
            {
205
                auto callback = static_cast<DecayPtr<Func>>(data);
206 207 208 209
                (*callback)( e->u.media_parsed_changed.new_status );
            });
        }

210 211
        template <typename Func>
        EventToken onFreed( Func&& f)
212
        {
213 214
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaFreed, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
215
            {
216
                auto callback = static_cast<DecayPtr<Func>>(data);
217 218 219 220
                (*callback)( std::make_shared<Media>( e->u.media_freed.md, true ) );
            });
        }

221 222
        template <typename Func>
        EventToken onStateChanged( Func&& f)
223
        {
224 225
            EXPECT_SIGNATURE(void(libvlc_state_t));
            return handle(libvlc_MediaStateChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
226
            {
227
                auto callback = static_cast<DecayPtr<Func>>(data);
228 229 230 231
                (*callback)( e->u.media_state_changed.new_state );
            });
        }

232 233
        template <typename Func>
        EventToken onSubItemTreeAdded( Func&& f)
234
        {
235 236
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaSubItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
237
            {
238
                auto callback = static_cast<DecayPtr<Func>>(data);
239 240 241
                (*callback)( std::make_shared<Media>( e->u.media_subitemtree_added.item, true ) );
            });
        }
242 243
};

244
class MediaPlayerEventManager : public EventManager
245 246
{
    public:
247 248
        MediaPlayerEventManager(InternalPtr ptr) : EventManager( ptr ) {}

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

        template <typename Func>
        EventToken onNothingSpecial( Func&& f )
262
        {
263
            return handle(libvlc_MediaPlayerNothingSpecial, std::forward<Func>( f ));
264 265
        }

266 267
        template <typename Func>
        EventToken onOpening( Func&& f )
268
        {
269
            return handle(libvlc_MediaPlayerOpening, std::forward<Func>( f ) );
270 271
        }

272 273
        template <typename Func>
        EventToken onBuffering( Func&& f )
274
        {
275
            return handle(libvlc_MediaPlayerBuffering, std::forward<Func>( f ) );
276 277
        }

278 279
        template <typename Func>
        EventToken onPlaying( Func&& f )
280
        {
281
            return handle( libvlc_MediaPlayerPlaying, std::forward<Func>( f ) );
282 283
        }

284 285
        template <typename Func>
        EventToken onPaused(Func&& f)
286
        {
287
            return handle( libvlc_MediaPlayerPaused, std::forward<Func>( f ) );
288 289
        }

290 291
        template <typename Func>
        EventToken onStopped(Func&& f)
292
        {
293
            return handle( libvlc_MediaPlayerStopped, std::forward<Func>( f ) );
294 295
        }

296 297
        template <typename Func>
        EventToken onForward(Func&& f)
298
        {
299
            return handle( libvlc_MediaPlayerForward, std::forward<Func>( f ) );
300 301
        }

302 303
        template <typename Func>
        EventToken onBackward(Func&& f)
304
        {
305
            return handle( libvlc_MediaPlayerBackward, std::forward<Func>( f ) );
306 307
        }

308 309
        template <typename Func>
        EventToken onEndReached(Func&& f)
310
        {
311
            return handle( libvlc_MediaPlayerEndReached, std::forward<Func>( f ) );
312 313
        }

314 315
        template <typename Func>
        EventToken onEncounteredError(Func&& f)
316
        {
317
            return handle( libvlc_MediaPlayerEncounteredError, std::forward<Func>( f ) );
318 319
        }

320 321
        template <typename Func>
        EventToken onTimeChanged( Func&& f )
322
        {
323 324
            EXPECT_SIGNATURE(void(libvlc_time_t));
            return handle( libvlc_MediaPlayerTimeChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
325
            {
326
                auto callback = static_cast<DecayPtr<Func>>( data );
327 328 329 330
                (*callback)( e->u.media_player_time_changed.new_time );
            });
        }

331 332
        template <typename Func>
        EventToken onPositionChanged( Func&& f )
333
        {
334 335
            EXPECT_SIGNATURE(void(float));
            return handle( libvlc_MediaPlayerPositionChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
336
            {
337
                auto callback = static_cast<DecayPtr<Func>>( data );
338 339 340 341
                (*callback)( e->u.media_player_position_changed.new_position );
            });
        }

342 343
        template <typename Func>
        EventToken onSeekableChanged( Func&& f )
344
        {
345 346
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaPlayerSeekableChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
347
            {
348
                auto callback = static_cast<DecayPtr<Func>>( data );
349 350 351 352
                (*callback)( e->u.media_player_seekable_changed.new_seekable );
            });
        }

353 354
        template <typename Func>
        EventToken onPausableChanged( Func&& f )
355
        {
356 357
            EXPECT_SIGNATURE(void(bool));
            return handle( libvlc_MediaPlayerSeekableChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
358
            {
359
                auto callback = static_cast<DecayPtr<Func>>( data );
360 361 362 363
                (*callback)( e->u.media_player_seekable_changed.new_seekable );
            });
        }

364 365
        template <typename Func>
        EventToken onTitleChanged( Func&& f )
366
        {
367 368
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerTitleChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
369
            {
370
                auto callback = static_cast<DecayPtr<Func>>( data );
371 372 373 374
                (*callback)( e->u.media_player_title_changed.new_title );
            });
        }

375 376
        template <typename Func>
        EventToken onSnapshotTaken( Func&& f )
377
        {
378 379
            EXPECT_SIGNATURE(void(std::string));
            return handle( libvlc_MediaPlayerSnapshotTaken, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
380
            {
381
                auto callback = static_cast<DecayPtr<Func>>( data );
382 383 384 385
                (*callback)( e->u.media_player_snapshot_taken.psz_filename );
            });
        }

386 387
        template <typename Func>
        EventToken onLengthChanged( Func&& f )
388
        {
389 390
            EXPECT_SIGNATURE(void(libvlc_time_t));
            return handle( libvlc_MediaPlayerLengthChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
391
            {
392
                auto callback = static_cast<DecayPtr<Func>>( data );
393 394 395 396
                (*callback)( e->u.media_player_length_changed.new_length );
            });
        }

397 398
        template <typename Func>
        EventToken onVout( Func&& f )
399
        {
400 401
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerVout, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
402
            {
403
                auto callback = static_cast<DecayPtr<Func>>( data );
404 405 406 407
                (*callback)( e->u.media_player_vout.new_count );
            });
        }

408 409
        template <typename Func>
        EventToken onScrambledChanged( Func&& f )
410
        {
411 412
            EXPECT_SIGNATURE(void(int));
            return handle( libvlc_MediaPlayerScrambledChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
413
            {
414
                auto callback = static_cast<DecayPtr<Func>>( data );
415 416 417 418
                (*callback)( e->u.media_player_scrambled_changed.new_scrambled );
            });
        }

419 420
        template <typename Func>
        EventToken onESAdded( Func&& f )
421
        {
422 423
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
424
            {
425
                auto callback = static_cast<DecayPtr<Func>>( data );
426 427 428 429
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }

430 431
        template <typename Func>
        EventToken onESDeleted( Func&& f )
432
        {
433 434
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESDeleted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
435
            {
436
                auto callback = static_cast<DecayPtr<Func>>( data );
437 438 439 440
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }

441 442
        template <typename Func>
        EventToken onESSelected( Func&& f )
443
        {
444 445
            EXPECT_SIGNATURE(void(libvlc_track_type_t, int));
            return handle( libvlc_MediaPlayerESSelected, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
446
            {
447
                auto callback = static_cast<DecayPtr<Func>>( data );
448 449 450
                (*callback)( e->u.media_player_es_changed.i_type, e->u.media_player_es_changed.i_id );
            });
        }
451 452
};

453
class MediaListEventManager : public EventManager
454 455
{
    public:
456 457
        MediaListEventManager(InternalPtr ptr) : EventManager( ptr ) {}

458 459
        template <typename Func>
        EventToken onItemAdded( Func&& f )
460
        {
461 462
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListItemAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
463
            {
464
                auto callback = static_cast<DecayPtr<Func>>( data );
465 466 467 468
                (*callback)( std::make_shared<Media>( e->u.media_list_item_added.item, true ), e->u.media_list_item_added.index );
            });
        }

469 470
        template <typename Func>
        EventToken onWillAddItem( Func&& f )
471
        {
472 473
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle( libvlc_MediaListWillAddItem, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
474
            {
475
                auto callback = static_cast<DecayPtr<Func>>( data );
476 477 478 479
                (*callback)(std::make_shared<Media>( e->u.media_list_will_add_item.item, true ), e->u.media_list_will_add_item.index );
            });
        }

480 481
        template <typename Func>
        EventToken onItemDeleted( Func&& f )
482
        {
483 484
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListItemDeleted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
485
            {
486
                auto callback = static_cast<DecayPtr<Func>>( data );
487 488 489 490
                (*callback)( std::make_shared<Media>( e->u.media_list_item_deleted.item, true ), e->u.media_list_item_deleted.index );
            });
        }

491 492
        template <typename Func>
        EventToken onWillDeleteItem( Func&& f )
493
        {
494 495
            EXPECT_SIGNATURE(void(MediaPtr, int));
            return handle(libvlc_MediaListWillDeleteItem, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
496
            {
497
                auto callback = static_cast<DecayPtr<Func>>( data );
498 499 500
                (*callback)( std::make_shared<Media>( e->u.media_list_will_delete_item.item, true ), e->u.media_list_will_delete_item.index );
            });
        }
501 502
};

503 504 505
// MediaListView events are not being sent by VLC, so we don't implement them here

class MediaListPlayerEventManager : public EventManager
506 507
{
    public:
508 509
        MediaListPlayerEventManager(InternalPtr ptr) : EventManager( ptr ) {}

510 511
        template <typename Func>
        EventToken onPlayed(Func&& f)
512
        {
513
            return handle(libvlc_MediaListPlayerPlayed, std::forward<Func>( f ) );
514 515
        }

516 517
        template <typename Func>
        EventToken onNextItemSet( Func&& f )
518
        {
519 520
            EXPECT_SIGNATURE(void(MediaPtr));
            return handle(libvlc_MediaListPlayerNextItemSet, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
521
            {
522
                auto callback = static_cast<DecayPtr<Func>>( data );
523 524
                (*callback)( std::make_shared<Media>( e->u.media_list_player_next_item_set.item, true ) );
            });
525 526
        }

527 528
        template <typename Func>
        EventToken onStopped( Func&& f )
529
        {
530
            return handle(libvlc_MediaListPlayerStopped, std::forward<Func>( f ) );
531
        }
532
};
533

534 535 536 537 538
class MediaDiscovererEventManager : public EventManager
{
    public:
        MediaDiscovererEventManager(InternalPtr ptr) : EventManager( ptr ) {}

539 540
        template <typename Func>
        EventToken onStarted(Func&& f)
541
        {
542
            return handle(libvlc_MediaDiscovererStarted, std::forward<Func>( f ) );
543 544
        }

545 546
        template <typename Func>
        EventToken onStopped(Func&& f)
547
        {
548
            return handle(libvlc_MediaDiscovererEnded, std::forward<Func>( f ) );
549
        }
550
};
551

552 553 554 555 556
class VLMEventManager : public EventManager
{
    public:
        using EventManager::EventManager;

557 558
        template <typename Func>
        EventToken onMediaAdded( Func&& f )
559
        {
560 561
            EXPECT_SIGNATURE(void(std::string));
            return handle(libvlc_VlmMediaAdded, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
562
            {
563
                auto callback = static_cast<DecayPtr<Func>>( data );
564 565
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "" );
            });
566 567
        }

568 569
        template <typename Func>
        EventToken onMediaRemoved( Func&& f )
570
        {
571 572
            EXPECT_SIGNATURE(void(std::string));
            return handle(libvlc_VlmMediaRemoved, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
573
            {
574
                auto callback = static_cast<DecayPtr<Func>>( data );
575 576
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "" );
            });
577 578
        }

579 580
        template <typename Func>
        EventToken onMediaChanged( Func&& f )
581
        {
582 583
            EXPECT_SIGNATURE(void(std::string));
            return handle(libvlc_VlmMediaChanged, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
584
            {
585
                auto callback = static_cast<DecayPtr<Func>>( data );
586 587 588
                (*callback)( e->u.vlm_media_event.psz_media_name ? e->u.vlm_media_event.psz_media_name : "" );
            });
        }
589 590 591

        template <typename Func>
        EventToken onMediaInstanceStarted( Func&& f )
592
        {
593 594
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStarted, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
595
            {
596
                auto callback = static_cast<DecayPtr<Func>>( data );
597 598 599
                (*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 : "" );
            });
600 601
        }

602 603
        template <typename Func>
        EventToken onMediaInstanceStopped( Func&& f )
604
        {
605 606
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStopped, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
607
            {
608
                auto callback = static_cast<DecayPtr<Func>>( data );
609 610 611
                (*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 : "" );
            });
612 613
        }

614 615
        template <typename Func>
        EventToken onMediaInstanceStatusInit( Func&& f )
616
        {
617 618
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusInit, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
619
            {
620
                auto callback = static_cast<DecayPtr<Func>>( data );
621 622 623
                (*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 : "" );
            });
624 625
        }

626 627
        template <typename Func>
        EventToken onMediaInstanceStatusOpening( Func&& f )
628
        {
629 630
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusOpening, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
631
            {
632
                auto callback = static_cast<DecayPtr<Func>>( data );
633 634 635
                (*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 : "" );
            });
636 637
        }

638 639
        template <typename Func>
        EventToken onMediaInstanceStatusPlaying( Func&& f )
640
        {
641 642
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusPlaying, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
643
            {
644
                auto callback = static_cast<DecayPtr<Func>>( data );
645 646 647
                (*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 : "" );
            });
648 649
        }

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

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

674 675
        template <typename Func>
        EventToken onMediaInstanceStatusError( Func&& f )
676
        {
677 678
            EXPECT_SIGNATURE(void(std::string, std::string));
            return handle(libvlc_VlmMediaInstanceStatusError, std::forward<Func>( f ), [](const libvlc_event_t* e, void* data)
679
            {
680
                auto callback = static_cast<DecayPtr<Func>>( data );
681 682 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
}

#endif // LIBVLC_EVENTMANAGER_HPP