Skip to content
Extraits de code Groupes Projets
Vérifiée Valider 4f95b65f rédigé par Kubat's avatar Kubat
Parcourir les fichiers

UI: Handle MPV events + set locale correctly for MPV

parent a6a50920
Aucune branche associée trouvée
Aucune étiquette associée trouvée
1 requête de fusion!15Video playback with mpv
......@@ -26,22 +26,35 @@ MpvContainer::MpvContainer()
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, "pause", MPV_FORMAT_FLAG);
mpv_observe_property(mpv, 0, "duration", MPV_FORMAT_DOUBLE);
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)
if (int rc = mpv_initialize(mpv); rc < 0) {
printMpvError(rc);
throw std::runtime_error("Failed to initialize the mpv context");
}
}
void
MpvContainer::registerMpvTimeCallback(void (*callback)(double)) noexcept
{
if (mpv_time_callback)
qWarning() << "Override a previous mpv callback, was" << mpv_time_callback
if (mpvTimeCallback)
qWarning() << "Override a previous mpv callback, was" << mpvTimeCallback
<< "and now will be" << callback;
mpv_time_callback = callback;
mpvTimeCallback = callback;
}
void
MpvContainer::registerMpvDurationCallback(void (*callback)(double)) noexcept
{
if (mpvDurationCallback)
qWarning() << "Override a previous mpv callback, was" << mpvDurationCallback
<< "and now will be" << callback;
mpvDurationCallback = callback;
}
void
......@@ -49,6 +62,7 @@ MpvContainer::closeMpv() noexcept
{
if (mpv) {
registerMpvTimeCallback(nullptr);
registerMpvDurationCallback(nullptr);
mpv_handle *tmp_mpv = mpv;
mpv = nullptr; // Stop all other callbacks here
mpv_destroy(tmp_mpv);
......@@ -65,17 +79,24 @@ MpvContainer::handleMpvEvent(mpv_event *event) noexcept
{
// Declare here variables that can be used in the switch-case statements
qint64 w, h;
double time;
union {
mpv_event_log_message *msg;
mpv_event_property *prop;
};
auto checkProp = [](mpv_event_property *prop, const std::string &str,
int format) noexcept -> bool {
return (prop->name == str) && (prop->format == format);
};
switch (event->event_id) {
case MPV_EVENT_SHUTDOWN:
closeMpv();
break;
case MPV_EVENT_VIDEO_RECONFIG:
// TODO: Those are sync calls, prefer async calls
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;
......@@ -89,14 +110,37 @@ MpvContainer::handleMpvEvent(mpv_event *event) noexcept
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!";
if (checkProp(prop, "time-pos"s, MPV_FORMAT_DOUBLE) && mpvTimeCallback) {
time = *reinterpret_cast<double *>(prop->data);
mpvTimeCallback(time);
}
else if (checkProp(prop, "duration"s, MPV_FORMAT_DOUBLE) && mpvDurationCallback) {
time = *reinterpret_cast<double *>(prop->data);
mpvDurationCallback(time);
}
else if (checkProp(prop, "pause"s, MPV_FORMAT_FLAG)) {
isPlaybackPaused = *reinterpret_cast<bool *>(prop->data);
emit mpvPlaybackToggled(!isPlaybackPaused);
}
break;
case MPV_EVENT_PAUSE:
isPlaybackPaused = true;
break;
case MPV_EVENT_UNPAUSE:
isPlaybackPaused = false;
break;
case MPV_EVENT_START_FILE:
qDebug() << "MPV: Begin of file";
break;
case MPV_EVENT_END_FILE:
qDebug() << "MPV: Reached end of file!";
break;
// Explicitly ignored
......@@ -104,14 +148,10 @@ MpvContainer::handleMpvEvent(mpv_event *event) noexcept
case MPV_EVENT_GET_PROPERTY_REPLY:
case MPV_EVENT_SET_PROPERTY_REPLY:
case MPV_EVENT_COMMAND_REPLY:
case MPV_EVENT_START_FILE:
case MPV_EVENT_END_FILE:
case MPV_EVENT_FILE_LOADED:
case MPV_EVENT_TRACKS_CHANGED:
case MPV_EVENT_TRACK_SWITCHED:
case MPV_EVENT_IDLE:
case MPV_EVENT_PAUSE:
case MPV_EVENT_UNPAUSE:
case MPV_EVENT_TICK:
case MPV_EVENT_SCRIPT_INPUT_DISPATCH:
case MPV_EVENT_CLIENT_MESSAGE:
......@@ -131,8 +171,46 @@ MpvContainer::onMpvEvent() noexcept
{
while (mpv) {
mpv_event *event = mpv_wait_event(mpv, 0);
if (event->event_id == MPV_EVENT_NONE)
if (event == nullptr || event->event_id == MPV_EVENT_NONE)
break;
handleMpvEvent(event);
}
}
void
MpvContainer::loadFile(const QString &filename) noexcept
{
const QByteArray c_filename = filename.toUtf8();
const char *args[] = { "loadfile", c_filename.data(), nullptr };
printMpvError(mpv_command_async(mpv, 0, args));
}
void
MpvContainer::printMpvError(int rc) const noexcept
{
if (rc == MPV_ERROR_SUCCESS)
return;
qCritical() << "MPV error:" << mpv_error_string(rc);
}
void
MpvContainer::mpvPlay() noexcept
{
if (isPlaybackPaused)
mpvTogglePlayback();
}
void
MpvContainer::mpvPause() noexcept
{
if (!isPlaybackPaused)
mpvTogglePlayback();
}
void
MpvContainer::mpvTogglePlayback() noexcept
{
const char *cmd[] = { "cycle", "pause", "up", nullptr };
printMpvError(mpv_command_async(mpv, 0, cmd));
}
......@@ -18,27 +18,39 @@ class MpvContainer : public QWidget {
VIVY_UNMOVABLE_OBJECT(MpvContainer)
private:
bool isPlaybackPaused{ true };
mpv_handle *mpv{ nullptr };
void (*mpv_time_callback)(double){ nullptr };
void (*mpvTimeCallback)(double){ nullptr };
void (*mpvDurationCallback)(double){ nullptr };
public:
explicit MpvContainer();
~MpvContainer() noexcept override;
void loadFile(const QString &) noexcept;
// Register a callback for time change, don't use Qt's signals for that.
void registerMpvTimeCallback(void (*)(double)) noexcept;
void registerMpvDurationCallback(void (*)(double)) noexcept;
private:
void handleMpvEvent(mpv_event *) noexcept;
void closeMpv() noexcept;
void printMpvError(int) const noexcept;
// Must be static to be passed as a function ptr
static void mpvEventWakeUpCB(void *) noexcept;
public slots:
void mpvPlay() noexcept;
void mpvPause() noexcept;
void mpvTogglePlayback() noexcept;
private slots:
void onMpvEvent() noexcept;
signals:
void mpvEvent();
void mpvPlaybackToggled(bool isPlaying);
};
}
......@@ -4,6 +4,7 @@
#include <QtGlobal>
#include <QIcon>
#include <QFontDatabase>
#include <locale>
using namespace Vivy;
......@@ -34,6 +35,9 @@ VivyApplication::setTheme(Theme theme) noexcept
int
VivyApplication::exec() noexcept
{
// For MPV
std::setlocale(LC_NUMERIC, "C");
// Add fonts
fontIdMonospace = QFontDatabase::addApplicationFont(":/fonts/FiraCode-Regular.ttf");
fontIdMonospaceBold = QFontDatabase::addApplicationFont(":/fonts/FiraCode-Bold.ttf");
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter