main.cpp 6.55 KB
Newer Older
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
1
2
3
/*****************************************************************************
 * main.cpp: Simple test program
 *****************************************************************************
4
 * Copyright © 2015 libvlcpp authors & VideoLAN
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
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
    const char* vlcArgs = "-vv";
37
38
39
    auto imgBuffer = malloc(480 * 320 * 4);
    std::unique_ptr<uint8_t, decltype(&free)> imgBufferPtr{
        static_cast<uint8_t*>( imgBuffer ), &free };
40
41
    auto instance = VLC::Instance(1, &vlcArgs);

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

48
49
50
    instance.setExitHandler([] {
        std::cout << "Libvlc is exiting" << std::endl;
    });
51
52
53
54

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

56
57
58
59
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
    auto media = VLC::Media(av[1], VLC::Media::FromPath);
    auto mp = VLC::MediaPlayer(instance, media);
#else
60
61
    auto media = VLC::Media(instance, av[1], VLC::Media::FromPath);
    auto mp = VLC::MediaPlayer(media);
62
#endif
63
    auto eventManager = mp.eventManager();
64
    eventManager.onPlaying([&media]() {
65
66
        std::cout << media.mrl() << " is playing" << std::endl;
    });
67

68
69
70
    mp.setVideoCallbacks([imgBuffer](void** pBuffer) -> void* {
        std::cout << "Lock" << std::endl;
        *pBuffer = imgBuffer;
71
        return nullptr;
72
73
74
75
76
77
78
79
80
81
82
83
84
85
    }, [](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);


86
    mp.play();
87

88
89
    bool expected = true;

90
91
92
93
94
    mp.setAudioCallbacks([](const void*, uint32_t count, int64_t pts) {
            std::cout << "Playing " << count << " samples at pts " << pts << std::endl;
        }, nullptr, nullptr, nullptr, nullptr
    );

95
    auto handler = mp.eventManager().onPositionChanged([&expected](float pos) {
96
97
98
99
        std::cout << "position changed " << pos << std::endl;
        assert(expected);
    });
    std::this_thread::sleep_for( std::chrono::seconds( 2 ) );
100
    handler->unregister();
101
102
103
104
105
106
    // 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 ) );

107
108
109
110
111
    expected = true;
    auto l = [&expected] (float){
        std::cout << "Lambda called" << std::endl;
        assert(expected);
    };
112
113
114
    auto lFunc = std::function<void(float)>{ l };
    auto h1 = mp.eventManager().onTimeChanged(lFunc);
    auto h2 = mp.eventManager().onPositionChanged(lFunc);
115
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
116
117
118
119
    mp.eventManager().onTitleSelectionChanged(
                [](const VLC::TitleDescription& t, int idx ) {
        std::cout << "New title selected: " << t.name() << " at index " << idx << std::endl;
    });
120
#endif
121
122
123
124
125

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

    // Unregistering multiple events at once.
    // h1 and h2 are now invalid.
126
    mp.eventManager().unregister(h1, h2);
127
128
    expected = false;

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
    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) );

146
147
148
149
150
151
152
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
    auto tracks = mp.tracks( VLC::MediaTrack::Type::Video );
    std::cout << "Got " << tracks.size() << " tracks" << std::endl;
    mp.selectTracks( VLC::MediaTrack::Type::Video, tracks );
    std::this_thread::sleep_for( std::chrono::milliseconds(1000) );
#endif

153
154
155
    // Showing that copying an object shares the associated eventmanager
    auto mp2 = mp;
    expected = true;
156
    auto h3 = mp2.eventManager().onStopped([&expected]() {
157
158
159
160
161
        std::cout << "MediaPlayer stopped" << std::endl;
        assert(expected);
        // expect a single call since both media player share the same event manager
        expected = false;
    });
162
163
164
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(4, 0, 0, 0)
    mp.stopAsync();
#else
165
    mp.stop();
166
#endif
167
168
169
170
171
    // 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);
172
173
174
175
176
177
178

    // List audio filters
    auto audioFilters = instance.audioFilterList();
    for (const auto& f : audioFilters)
    {
        std::cout << f.name() << std::endl;
    }
179
180
    // Check that we don't use the old media player when releasing its event manager
    mp = VLC::MediaPlayer{};
181
}