main.cpp 5.51 KB
Newer Older
1 2 3
/*****************************************************************************
 * main.cpp: Simple test program
 *****************************************************************************
4
 * Copyright © 2015 libvlcpp authors & VideoLAN
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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.
 *****************************************************************************/

23
#include "vlcpp/vlc.hpp"
24 25 26

#include <iostream>
#include <thread>
27
#include <cstring>
28 29 30 31 32 33 34 35

int main(int ac, char** av)
{
    if (ac < 2)
    {
        std::cerr << "usage: " << av[0] << " <file to play>" << std::endl;
        return 1;
    }
36 37 38
    const char* vlcArgs = "-vv";
    auto instance = VLC::Instance(1, &vlcArgs);

39
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
40 41 42
    auto sds = instance.mediaDiscoverers( VLC::MediaDiscoverer::Category::Lan );
    for ( const auto& sd : sds )
        std::cout << "Found SD: " << sd.name() << "(" << sd.longName() << ")" << std::endl;
43
#endif
44

45 46 47
    instance.setExitHandler([] {
        std::cout << "Libvlc is exiting" << std::endl;
    });
48 49 50 51

    instance.logSet([](int lvl, const libvlc_log_t*, std::string message ) {
        std::cout << "Hooked VLC log: " << lvl << ' ' << message << std::endl;
    });
52

53 54
    auto media = VLC::Media(instance, av[1], VLC::Media::FromPath);
    auto mp = VLC::MediaPlayer(media);
55
    auto eventManager = mp.eventManager();
56
    eventManager.onPlaying([&media]() {
57 58
        std::cout << media.mrl() << " is playing" << std::endl;
    });
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    auto imgBuffer = malloc(480 * 320 * 4);
    mp.setVideoCallbacks([imgBuffer](void** pBuffer) -> void* {
        std::cout << "Lock" << std::endl;
        *pBuffer = imgBuffer;
        return NULL;
    }, [](void*, void*const*) {
        std::cout << "unlock" << std::endl;
    }, nullptr);

    mp.setVideoFormatCallbacks([](char* chroma, uint32_t* width, uint32_t* height, uint32_t* pitch, uint32_t* lines) -> int {
        memcpy(chroma, "RV32", 4);
        *width = 480;
        *height = 320;
        *pitch = *width * 4;
        *lines = 320;
        return 1;
    }, nullptr);


79
    mp.play();
80

81 82
    bool expected = true;

83 84 85 86 87
    mp.setAudioCallbacks([](const void*, uint32_t count, int64_t pts) {
            std::cout << "Playing " << count << " samples at pts " << pts << std::endl;
        }, nullptr, nullptr, nullptr, nullptr
    );

88
    auto handler = mp.eventManager().onPositionChanged([&expected](float pos) {
89 90 91 92
        std::cout << "position changed " << pos << std::endl;
        assert(expected);
    });
    std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
93
    handler->unregister();
94 95 96 97 98 99
    // handler must be considered a dangling reference from now on.
    // We might want to fix this, but is it worth the cost of a shared/weak_pointer?
    expected = false;

    std::this_thread::sleep_for( std::chrono::seconds( 2 ) );

100 101 102 103 104
    expected = true;
    auto l = [&expected] (float){
        std::cout << "Lambda called" << std::endl;
        assert(expected);
    };
105 106 107
    auto lFunc = std::function<void(float)>{ l };
    auto h1 = mp.eventManager().onTimeChanged(lFunc);
    auto h2 = mp.eventManager().onPositionChanged(lFunc);
108 109 110 111 112

    std::this_thread::sleep_for( std::chrono::seconds( 2 ) );

    // Unregistering multiple events at once.
    // h1 and h2 are now invalid.
113
    mp.eventManager().unregister(h1, h2);
114 115
    expected = false;

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
    std::this_thread::sleep_for( std::chrono::milliseconds(500) );

    // Using scopped event manager to automatically unregister events
    {
        expected = true;
        // This is a copy. Assigning to a reference wouldn't clear the registered events
        auto em = mp.eventManager();
        em.onPositionChanged([&expected](float) {
            assert(expected);
        });
        std::this_thread::sleep_for( std::chrono::seconds(1) );
    }
    // From here, the lambda declared in the scope isn't registered anymore
    expected = false;

    std::this_thread::sleep_for( std::chrono::milliseconds(500) );

    // Showing that copying an object shares the associated eventmanager
    auto mp2 = mp;
    expected = true;
136
    auto h3 = mp2.eventManager().onStopped([&expected]() {
137 138 139 140 141
        std::cout << "MediaPlayer stopped" << std::endl;
        assert(expected);
        // expect a single call since both media player share the same event manager
        expected = false;
    });
142
    mp.stop();
143 144 145 146 147
    // Unregister the RegisteredEvent from the other MP's event manager.
    // It will be unregistered from both, and when the object gets destroyed
    // by leaving the scope, it won't be unregistered from mp2's eventManager.
    // If it did, libvlc would assert as the event has been unregistered already.
    mp.eventManager().unregister(h3);
148 149 150 151 152 153 154

    // List audio filters
    auto audioFilters = instance.audioFilterList();
    for (const auto& f : audioFilters)
    {
        std::cout << f.name() << std::endl;
    }
155
    free(imgBuffer);
156
}