Instance.hpp 21.8 KB
Newer Older
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
1
/*****************************************************************************
2
 * Instance.hpp: Instance API
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
3
 *****************************************************************************
4
 * Copyright © 2015 libvlcpp authors & VideoLAN
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
5
 *
6
 * Authors: Alexey Sokolov <alexey+vlc@asokolov.org>
7
 *          Hugo Beauzée-Luyssen <hugo@beauzee.fr>
8
 *          Bastien Penavayre <bastienpenava@gmail.com>
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 *
 * 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_CXX_INSTANCE_H
#define LIBVLC_CXX_INSTANCE_H

28
#include "common.hpp"
29
#include "Internal.hpp"
30
#include "structures.hpp"
31
#include "Dialog.hpp"
32
#include "MediaDiscoverer.hpp"
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
33

34 35
#include <string>
#include <vector>
36
#include <cstring>
37
#include <cstdio>
38

39 40
namespace VLC
{
41 42

#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
43
using Question = libvlc_dialog_question_type;
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
44

45 46
namespace DialogType
{
47
#if !defined(_MSC_VER) || _MSC_VER >= 1900
48 49 50
    static constexpr Question normal = LIBVLC_DIALOG_QUESTION_NORMAL;
    static constexpr Question warning = LIBVLC_DIALOG_QUESTION_WARNING;
    static constexpr Question critical = LIBVLC_DIALOG_QUESTION_CRITICAL;
51 52 53 54 55
#else
    static const Question normal = LIBVLC_DIALOG_QUESTION_NORMAL;
    static const Question warning = LIBVLC_DIALOG_QUESTION_WARNING;
    static const Question critical = LIBVLC_DIALOG_QUESTION_CRITICAL;
#endif
56
}
57
#endif
58

59
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
60
class Instance : protected CallbackOwner<8>, public Internal<libvlc_instance_t>
61 62 63
#else
class Instance : protected CallbackOwner<5>, public Internal<libvlc_instance_t>
#endif
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
64
{
65
private:
66
    enum class CallbackIdx : unsigned int
67
    {
68 69 70
        Exit = 0,
        Log,
        ErrorDisplay,
71
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
72 73 74 75 76
        LoginDisplay,
        QuestionDisplay,
        ProgressDisplay,
        CancelDialog,
        ProgressUpdate
77
#endif
78
    };
79

80
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
81
    std::shared_ptr<libvlc_dialog_cbs> m_callbacks_pointers;
82
#endif
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
public:
    /**
     * Create and initialize a libvlc instance. This functions accept a list
     * of "command line" arguments similar to the main(). These arguments
     * affect the LibVLC instance default configuration.
     *
     * \version Arguments are meant to be passed from the command line to
     * LibVLC, just like VLC media player does. The list of valid arguments
     * depends on the LibVLC version, the operating system and platform, and
     * set of available LibVLC plugins. Invalid or unsupported arguments will
     * cause the function to fail (i.e. return NULL). Also, some arguments
     * may alter the behaviour or otherwise interfere with other LibVLC
     * functions.
     *
     * \warning There is absolutely no warranty or promise of forward,
     * backward and cross-platform compatibility with regards to
     * Instance::Instance() arguments. We recommend that you do not use them,
     * other than when debugging.
     *
     * \param argc  the number of arguments (should be 0)
     *
     * \param argv  list of arguments (should be NULL)
     */
106
    Instance(int argc, const char *const * argv)
107 108 109 110
        : Internal{ libvlc_new( argc, argv ), libvlc_release }
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
          , m_callbacks_pointers { std::make_shared<libvlc_dialog_cbs>() }
#endif
111 112
    {
    }
113

114 115 116 117 118 119 120
    /**
     * Create an empty VLC instance.
     *
     * Calling any method on such an instance is undefined.
    */
    Instance() = default;

121 122 123 124 125
    /**
     * Check if 2 Instance objects contain the same libvlc_instance_t.
     * \param another another Instance
     * \return true if they contain the same libvlc_instance_t
     */
126 127 128 129 130
    bool operator==(const Instance& another) const
    {
        return m_obj == another.m_obj;
    }

131

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
132 133 134
    /**
     * Try to start a user interface for the libvlc instance.
     *
135
     * \param name  interface name, or empty string for default
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
136
     */
137
    bool addIntf(const std::string& name)
138
    {
139
        return libvlc_add_intf( *this, name.length() > 0 ? name.c_str() : nullptr ) == 0;
140
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
141 142 143 144 145 146 147 148 149 150 151 152

    /**
     * Registers a callback for the LibVLC exit event. This is mostly useful
     * if the VLC playlist and/or at least one interface are started with
     * libvlc_playlist_play() or Instance::addIntf() respectively. Typically,
     * this function will wake up your application main loop (from another
     * thread).
     *
     * \note This function should be called before the playlist or interface
     * are started. Otherwise, there is a small race condition: the exit
     * event could be raised before the handler is registered.
     *
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
153 154 155
     * \param cb  callback to invoke when LibVLC wants to exit, or nullptr to
     * disable the exit handler (as by default). It is expected to be a
     * std::function<void()>, or an equivalent Callable type
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
156
     */
157 158
    template <typename ExitCb>
    void setExitHandler(ExitCb&& exitCb)
159
    {
160 161
        static_assert(signature_match_or_nullptr<ExitCb, void()>::value, "Mismatched exit callback" );
        libvlc_set_exit_handler( *this,
162 163
            CallbackWrapper<(unsigned int)CallbackIdx::Exit, void(*)(void*)>::wrap( *m_callbacks, std::forward<ExitCb>( exitCb ) ),
            m_callbacks.get() );
164
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
165 166 167 168 169 170 171 172 173 174 175 176

    /**
     * Sets the application name. LibVLC passes this as the user agent string
     * when a protocol requires it.
     *
     * \param name  human-readable application name, e.g. "FooBar player
     * 1.2.3"
     *
     * \param http  HTTP User Agent, e.g. "FooBar/1.2.3 Python/2.6.0"
     *
     * \version LibVLC 1.1.1 or later
     */
177 178
    void setUserAgent(const std::string& name, const std::string& http)
    {
179
        libvlc_set_user_agent( *this, name.c_str(), http.c_str() );
180
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
181 182 183 184 185 186 187 188 189 190 191 192 193

    /**
     * Sets some meta-information about the application. See also
     * Instance::setUserAgent() .
     *
     * \param id  Java-style application identifier, e.g. "com.acme.foobar"
     *
     * \param version  application version numbers, e.g. "1.2.3"
     *
     * \param icon  application icon name, e.g. "foobar"
     *
     * \version LibVLC 2.1.0 or later.
     */
194 195
    void setAppId(const std::string& id, const std::string& version, const std::string& icon)
    {
196
        libvlc_set_app_id( *this, id.c_str(), version.c_str(), icon.c_str() );
197
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
198 199 200 201 202 203 204 205 206 207

    /**
     * Unsets the logging callback for a LibVLC instance. This is rarely
     * needed: the callback is implicitly unset when the instance is
     * destroyed. This function will wait for any pending callbacks
     * invocation to complete (causing a deadlock if called from within the
     * callback).
     *
     * \version LibVLC 2.1.0 or later
     */
208 209
    void logUnset()
    {
210
        libvlc_log_unset( *this );
211
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
212 213 214 215 216 217 218 219 220 221

    /**
     * Sets the logging callback for a LibVLC instance. This function is
     * thread-safe: it will wait for any pending callbacks invocation to
     * complete.
     *
     * \note Some log messages (especially debug) are emitted by LibVLC while
     * is being initialized. These messages cannot be captured with this
     * interface.
     *
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
222 223 224
     * \param logCb A std::function<void(int, const libvlc_log_t*, std::string)>
     *              or an equivalent Callable type instance.
     *
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
225 226 227 228 229
     * \warning A deadlock may occur if this function is called from the
     * callback.
     *
     * \version LibVLC 2.1.0 or later
     */
230 231
    template <typename LogCb>
    void logSet(LogCb&& logCb)
232
    {
233 234 235
        static_assert(signature_match<LogCb, void(int, const libvlc_log_t*, std::string)>::value,
                      "Mismatched log callback" );
        auto wrapper = [logCb](int level, const libvlc_log_t* ctx, const char* format, va_list va) {
236 237 238 239 240
            const char* psz_module;
            const char* psz_file;
            unsigned int i_line;
            libvlc_log_get_context( ctx, &psz_module, &psz_file, &i_line );

241 242 243
#ifndef _MSC_VER
            VaCopy vaCopy(va);
            int len = vsnprintf(nullptr, 0, format, vaCopy.va);
244 245 246 247 248 249
            if (len < 0)
                return;
            std::unique_ptr<char[]> message{ new char[len + 1] };
            char* psz_msg = message.get();
            if (vsnprintf(psz_msg, len + 1, format, va) < 0 )
                return;
250 251 252 253
            char* psz_ctx;
            if (asprintf(&psz_ctx, "[%s] (%s:%d) %s", psz_module, psz_file, i_line, psz_msg) < 0)
                return;
            std::unique_ptr<char, void(*)(void*)> ctxPtr(psz_ctx, &free);
254 255
#else
            //MSVC treats passing nullptr as 1st vsnprintf(_s) as an error
256 257 258
            char psz_msg[512];
            if ( vsnprintf(psz_msg, sizeof(psz_msg) - 1, format, va) < 0 )
                return;
259 260
            char psz_ctx[1024];
            sprintf_s(psz_ctx, "[%s] (%s:%d) %s", psz_module, psz_file, i_line, psz_msg);
261
#endif
262
            logCb( level, ctx, std::string{ psz_ctx } );
263
        };
264 265
        libvlc_log_set(*this, CallbackWrapper<(unsigned int)CallbackIdx::Log, libvlc_log_cb>::wrap( *m_callbacks, std::move(wrapper)),
            m_callbacks.get() );
266
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
267 268 269 270 271 272 273 274 275

    /**
     * Sets up logging to a file.
     *
     * \param stream  FILE pointer opened for writing (the FILE pointer must
     * remain valid until Instance::logUnset() )
     *
     * \version LibVLC 2.1.0 or later
     */
276 277
    void logSetFile(FILE * stream)
    {
278
        libvlc_log_set_file( *this, stream );
279
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
280 281 282 283 284 285

    /**
     * Returns a list of audio filters that are available.
     *
     * \see ModuleDescription
     */
286 287
    std::vector<ModuleDescription> audioFilterList()
    {
288 289
        std::unique_ptr<libvlc_module_description_t, decltype(&libvlc_module_description_list_release)>
                ptr( libvlc_audio_filter_list_get(*this), libvlc_module_description_list_release );
290 291 292
        if ( ptr == nullptr )
            return {};
        libvlc_module_description_t* p = ptr.get();
293 294 295
        std::vector<ModuleDescription> res;
        while ( p != NULL )
        {
296
            res.emplace_back( p );
297 298 299 300 301
            p = p->p_next;
        }
        return res;
    }

Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
302 303 304 305 306 307

    /**
     * Returns a list of video filters that are available.
     *
     * \see ModuleDescription
     */
308 309
    std::vector<ModuleDescription> videoFilterList()
    {
310 311
        std::unique_ptr<libvlc_module_description_t, decltype(&libvlc_module_description_list_release)>
                ptr( libvlc_video_filter_list_get(*this), &libvlc_module_description_list_release );
312 313 314
        if ( ptr == nullptr )
            return {};
        libvlc_module_description_t* p = ptr.get();
315 316 317
        std::vector<ModuleDescription> res;
        while ( p != NULL )
        {
318
            res.emplace_back( p );
319 320 321 322
            p = p->p_next;
        }
        return res;
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
323 324 325 326

    /**
     * Gets the list of available audio output modules.
     *
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
327
     * \see AudioOutputDescription
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
328
     */
329 330
    std::vector<AudioOutputDescription> audioOutputList()
    {
331 332 333 334
        std::unique_ptr<libvlc_audio_output_t, decltype(&libvlc_audio_output_list_release)>
                result( libvlc_audio_output_list_get(*this), libvlc_audio_output_list_release );
        if ( result == nullptr )
            return {};
335
        std::vector<AudioOutputDescription> res;
336 337

        libvlc_audio_output_t* p = result.get();
338 339
        while ( p != NULL )
        {
340
            res.emplace_back( p );
341 342 343 344
            p = p->p_next;
        }
        return res;
    }
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363

    /**
     * Gets a list of audio output devices for a given audio output module,
     *
     * \see Audio::outputDeviceSet() .
     *
     * \note Not all audio outputs support this. In particular, an empty
     * (NULL) list of devices does imply that the specified audio output does
     * not work.
     *
     * \note The list might not be exhaustive.
     *
     * \warning Some audio output devices in the list might not actually work
     * in some circumstances. By default, it is recommended to not specify
     * any explicit audio device.
     *
     * \param psz_aout  audio output name (as returned by
     * Instance::audioOutputList() )
     *
364
     * \return A vector containing all audio output devices for this module
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
365 366 367
     *
     * \version LibVLC 2.1.0 or later.
     */
368 369
    std::vector<AudioOutputDeviceDescription> audioOutputDeviceList(const std::string& aout)
    {
370 371 372 373
        std::unique_ptr<libvlc_audio_output_device_t, decltype(&libvlc_audio_output_device_list_release)>
                devices(  libvlc_audio_output_device_list_get( *this, aout.c_str() ), libvlc_audio_output_device_list_release );
        if ( devices == nullptr )
            return {};
374
        std::vector<AudioOutputDeviceDescription> res;
375 376

        for ( auto p = devices.get(); p != nullptr; p = p->p_next )
377
            res.emplace_back( p );
378 379
        return res;
    }
380

381
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
382
#if !defined(_MSC_VER) || _MSC_VER >= 1900
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
    /**
     * Called when an error message needs to be displayed.
     *
     * \param title title of the dialog
     * \param text text of the dialog
     */
    using ErrorCb = void(std::string &&title, std::string &&text);
    /**
     *Called when a login dialog needs to be displayed.
     *
     *You can interact with this dialog by using the postLogin method on dialog to post an answer or the dismiss method to cancel this dialog.
     *
     *\note to receive this callack, CancelCb should not be NULL.
     *\param dialog used to interact with the dialog
     *\param title title of the dialog
     *\param text text of the dialog
     *\param defaultUserName user name that should be set on the user form
     *\param askToStore if true, ask the user if he wants to save the credentials
     */
    using LoginCb = void(Dialog &&dialog, std::string &&title, std::string &&text, std::string &&defaultUserName, bool askToStore);
    /**
     * Called when a question dialog needs to be displayed
     *
     * You can interact with this dialog by using the postAction method on dialog
     * to post an answer or dismiss method to cancel this dialog.
     *
     * \note to receive this callack, CancelCb should not be
     * NULL.
     *
     * \param dialog used to interact with the dialog
     * \param title title of the diaog
     * \param text text of the dialog
     * \param qtype question type (or severity) of the dialog
     * \param cancel text of the cancel button
     * \param action1 text of the first button, if NULL, don't display this
     * button
     * \param action2 text of the second button, if NULL, don't display
     * this button
     */
    using QuestionCb = void(Dialog &&dialog, std::string &&title, std::string &&text, Question qType, std::string &&cancel, std::string &&action1, std::string &&action2);
    /**
     * Called when a progress dialog needs to be displayed
     *
     * If cancellable (cancel != NULL), you can cancel this dialog by
     * calling the dismiss method on dialog
     *
     * \note to receive this callack, CancelCb and
     * UpdtProgressCb should not be NULL.
     *
     * \param dialog used to interact with the dialog
     * \param title title of the diaog
     * \param text text of the dialog
     * \param indeterminate true if the progress dialog is indeterminate
     * \param position initial position of the progress bar (between 0.0 and
     * 1.0)
     * \param cancel text of the cancel button, if NULL the dialog is not
     * cancellable
     */
    using DspProgressCb = void(Dialog &&dialog, std::string &&title, std::string &&text, bool intermediate, float position, std::string &&cancel);
    /**
     * Called when a displayed dialog needs to be cancelled
     *
     * The implementation must call the method dismiss on dialog to really release
     * the dialog.
     *
     * \param dialog used to interact with the dialog
     */
    using CancelCb = void(Dialog &&dialog);
    /**
     * Called when a progress dialog needs to be updated
     *
     * \param dialog used to interact with the dialog
     * \param position osition of the progress bar (between 0.0 and 1.0)
     * \param text new text of the progress dialog
     */
    using UpdtProgressCb = void(Dialog &&dialog, float position, std::string &&text);
459 460 461 462 463 464 465 466
#else
    typedef void (*ErrorCb)(std::string &&title, std::string &&text);
    typedef void (*LoginCb)(Dialog &&dialog, std::string &&title, std::string &&text, std::string &&defaultUserName, bool askToStore);
    typedef void (*QuestionCb)(Dialog &&dialog, std::string &&title, std::string &&text, Question qType, std::string &&cancel, std::string &&action1, std::string &&action2);
    typedef void (*DspProgressCb)(Dialog &&dialog, std::string &&title, std::string &&text, bool intermediate, float position, std::string &&cancel);
    typedef void (*CancelCb)(Dialog &&dialog);
    typedef void (*UpdtProgressCb)(Dialog &&dialog, float position, std::string &&text);
#endif
467 468 469 470 471 472 473 474 475 476 477 478 479
    /**
     * Replaces all the dialog callbacks for this Instance instance
     *
     * \param error   lambda callback that will get called when an error message needs to be displayed.     \see ErrorCb
     * \param login   lambda callback that will get called when a login dialog needs to be displayed. \see LoginCb
     * \param question   lambda callback that will get called when a question dialog needs to be displayed. \see QuestionCb
     * \param dspProgress   lambda callback that will get called when a progress dialog needs to be displayed. \see DspProgressCb
     * \param cancel   lambda callback that will get called when a displayed dialog needs to be cancelled. \see CancelCb
     * \param updtProgress   lambda callback that will get called when a progress dialog needs to be updated. \see UpdtProgressCb
     */
    template <class Error, class Login, class Question, class DspProgress, class Cancel, class UpdtProgress>
    void setDialogHandlers(Error&& error, Login&& login, Question&& question, DspProgress&& dspProgress, Cancel &&cancel, UpdtProgress &&updtProgress)
    {
480
#if !defined(_MSC_VER) || _MSC_VER >= 1900
481 482 483 484 485 486
        static_assert(signature_match_or_nullptr<Error, ErrorCb>::value, "Mismatched error display callback prototype");
        static_assert(signature_match_or_nullptr<Login, LoginCb>::value, "Mismatched login display callback prototype");
        static_assert(signature_match_or_nullptr<Question, QuestionCb>::value, "Mismatched question display callback prototype");
        static_assert(signature_match_or_nullptr<DspProgress, DspProgressCb>::value, "Mismatched progress display callback prototype");
        static_assert(signature_match_or_nullptr<Cancel, CancelCb>::value, "Mismatched cancel callback prototype");
        static_assert(signature_match_or_nullptr<UpdtProgress, UpdtProgressCb>::value, "Mismatched update progress callback prototype");
487
#endif
488 489 490 491 492 493 494 495 496
        libvlc_dialog_cbs tmp = {
            CallbackWrapper<(unsigned)CallbackIdx::ErrorDisplay, decltype(libvlc_dialog_cbs::pf_display_error)>::wrap(*m_callbacks, std::forward<Error>(error)),
            CallbackWrapper<(unsigned)CallbackIdx::LoginDisplay, decltype(libvlc_dialog_cbs::pf_display_login)>::wrap(*m_callbacks, std::forward<Login>(login)),
            CallbackWrapper<(unsigned)CallbackIdx::QuestionDisplay, decltype(libvlc_dialog_cbs::pf_display_question)>::wrap(*m_callbacks, std::forward<Question>(question)),
            CallbackWrapper<(unsigned)CallbackIdx::ProgressDisplay, decltype(libvlc_dialog_cbs::pf_display_progress)>::wrap(*m_callbacks, std::forward<DspProgress>(dspProgress)),
            CallbackWrapper<(unsigned)CallbackIdx::CancelDialog, decltype(libvlc_dialog_cbs::pf_cancel)>::wrap(*m_callbacks, std::forward<Cancel>(cancel)),
            CallbackWrapper<(unsigned)CallbackIdx::ProgressUpdate, decltype(libvlc_dialog_cbs::pf_update_progress)>::wrap(*m_callbacks, std::forward<UpdtProgress>(updtProgress))
        };
        m_callbacks_pointers = std::make_shared<libvlc_dialog_cbs>(tmp);
497 498 499 500 501 502 503 504 505 506 507 508
        libvlc_dialog_set_callbacks(*this, m_callbacks_pointers.get(), m_callbacks.get());
    }

    /**
     * Unset all callbacks
     */
    void unsetDialogHandlers()
    {
        memset(m_callbacks_pointers.get(), 0, sizeof(libvlc_dialog_cbs));
        std::fill(m_callbacks->begin() + 2, m_callbacks->end(), nullptr);
        libvlc_dialog_set_callbacks(*this, nullptr, nullptr);
    }
509

510
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
511 512 513 514 515 516 517 518 519 520 521
    /**
     * Get media discoverer services by category
     *
     * \version LibVLC 3.0.0 and later.
     *
     * \param category  The category of services to fetch
     *
     * \return A vector containing the available media discoverers
     */
    std::vector<MediaDiscoverer::Description> mediaDiscoverers(MediaDiscoverer::Category category)
    {
522 523
        libvlc_media_discoverer_description_t** pp_descs;
        auto nbSd = libvlc_media_discoverer_list_get( *this, static_cast<libvlc_media_discoverer_category_t>( category ),
524
                                                      &pp_descs );
525
        if ( nbSd <= 0 )
526
            return {};
527
        auto releaser = [nbSd](libvlc_media_discoverer_description_t** ptr) {
528 529
            libvlc_media_discoverer_list_release( ptr, nbSd );
        };
530
        std::unique_ptr<libvlc_media_discoverer_description_t*, decltype(releaser)> descPtr( pp_descs, releaser );
531 532 533 534 535 536
        std::vector<MediaDiscoverer::Description> res;
        res.reserve( nbSd );
        for ( auto i = 0u; i < nbSd; ++i )
            res.emplace_back( pp_descs[i]->psz_name, pp_descs[i]->psz_longname, pp_descs[i]->i_cat );
        return res;
    }
537
#endif
538

539
#endif
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
540 541 542 543 544 545
};

} // namespace VLC

#endif