Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 2b0e4884e1eb0affaa2be5b098112eb4c53fbadb
  • master par défaut
  • script
  • new-devel
  • devel
  • timingView-edit
  • fix-mpv
7 résultats

MpvContainer.cc

Blame
  • MpvContainer.cc 2,89 Kio
    #include "MpvContainer.hh"
    
    #include <mpv/client.h>
    
    using namespace Vivy;
    using namespace std::string_literals;
    
    void
    MpvContainer::mpvEventWakeUpCB(void *user)
    {
        MpvContainer *container = reinterpret_cast<MpvContainer *>(user);
        emit container->mpvEvent();
    }
    
    MpvContainer::MpvContainer()
        : mpv(mpv_create())
    {
        if (mpv == nullptr)
            throw std::runtime_error("Failed to create the MPV context");
    
        setAttribute(Qt::WA_DontCreateNativeAncestors);
        setAttribute(Qt::WA_NativeWindow);
    
        quint64 wid = winId();
        mpv_set_option(mpv, "wid", MPV_FORMAT_INT64, &wid);
        mpv_set_option_string(mpv, "input-default-bindings", "no");
        mpv_set_option_string(mpv, "input-vo-keyboard", "no");
        mpv_request_log_messages(mpv, "info");
        mpv_observe_property(mpv, 0, "time-pos", MPV_FORMAT_DOUBLE);
    
        connect(this, &MpvContainer::mpvEvent, this, &MpvContainer::onMpvEvent, Qt::QueuedConnection);
        mpv_set_wakeup_callback(mpv, &MpvContainer::mpvEventWakeUpCB, this);
    
        if (mpv_initialize(mpv) < 0)
            throw std::runtime_error("Failed to initialize the mpv context");
    }
    
    MpvContainer::~MpvContainer() noexcept
    {
        // TODO: Do that in a private method
        if (mpv) {
            mpv_handle *tmp_mpv = mpv;
            mpv                 = nullptr; // Stop all other callbacks here
            mpv_destroy(tmp_mpv);
        }
    }
    
    void
    MpvContainer::handleMpvEvent(mpv_event *event) noexcept
    {
        // Declare here variables that can be used in the switch-case statements
        qint64 w, h;
        union {
            mpv_event_log_message *msg;
            mpv_event_property *prop;
            mpv_handle *tmp_mpv;
        };
    
        switch (event->event_id) {
        case MPV_EVENT_SHUTDOWN:
            tmp_mpv = mpv;
            mpv = nullptr;
            mpv_destroy(mpv);
            break;
    
        case MPV_EVENT_VIDEO_RECONFIG:
            if (mpv_get_property(mpv, "dwidth", MPV_FORMAT_INT64, &w) >= 0 &&
                mpv_get_property(mpv, "dheight", MPV_FORMAT_INT64, &h) >= 0 && (w > 0 && h > 0)) {
                qDebug() << "Reconfigure video to" << w << "x" << h;
            }
            break;
    
        case MPV_EVENT_LOG_MESSAGE:
            msg = reinterpret_cast<mpv_event_log_message *>(event->data);
            qDebug() << "MPV message: [" << msg->prefix << "]" << msg->level << ":" << msg->text;
            break;
    
        case MPV_EVENT_PROPERTY_CHANGE:
            prop = reinterpret_cast<mpv_event_property *>(event->data);
            if (prop->name == "time-pos"s) {
                if (prop->format == MPV_FORMAT_DOUBLE) {
                    double time = *reinterpret_cast<double *>(prop->data);
                    qDebug() << "Playback time:" << time;
                } else {
                    qCritical() << "Got playback time but not a double!";
                }
            }
            break;
        }
    }
    
    void
    MpvContainer::onMpvEvent() noexcept
    {
        while (mpv) {
            mpv_event *event = mpv_wait_event(mpv, 0);
            if (event->event_id == MPV_EVENT_NONE)
                break;
            handleMpvEvent(event);
        }
    }