Skip to content
Extraits de code Groupes Projets
Sélectionner une révision Git
  • 283d80d9b267c46f334a85bb8756a9d52d4fd7e5
  • master par défaut protégée
  • rust-playlist-sync
  • rust
  • fix-qt-deprecated-qvariant-type
  • fix-mpris-qtwindow-race-condition
  • rust-appimage-wayland
  • windows-build-rebased
  • v2.5 protégée
  • v2.4 protégée
  • v2.3-1 protégée
  • v2.3 protégée
  • v2.2 protégée
  • v2.1 protégée
  • v2.0 protégée
  • v1.8-3 protégée
  • v1.8-2 protégée
  • v1.8-1 protégée
  • v1.8 protégée
  • v1.7 protégée
  • v1.6 protégée
  • v1.5 protégée
  • v1.4 protégée
  • v1.3 protégée
  • v1.2 protégée
  • v1.1 protégée
  • v1.0 protégée
27 résultats

mpv.c

Blame
  • mpv.c 7,53 Kio
    #define _POSIX_C_SOURCE 200809L
    
    #include "mpv.h"
    
    #include <lektor/common.h>
    #include <lektor/database.h>
    #include <strings.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <sqlite3.h>
    
    enum {
        STATE_STOP  = 0,
        STATE_PLAY  = 1,
        STATE_PAUSE = 2,
    };
    
    void
    lmpv_free(mpv_handle **ctx)
    {
        RETURN_UNLESS(ctx && *ctx, "Missing mpv ctx", NOTHING);
        static const char *cmd[] = {"quit", NULL};
        mpv_command(*ctx, cmd);
        mpv_destroy(*ctx);
        *ctx = NULL;
        LOG_INFO("WINDOW", "The mpv context was destroyed");
    }
    
    mpv_handle *
    lmpv_prepare(volatile sqlite3 *db)
    {
        mpv_handle *ctx = mpv_create();
        int status;
        RETURN_UNLESS(ctx, "Failed to create context", NULL);
        char _opt[LKT_LINE_MAX];
    
    #define MPV_SET_OPTION(opt, value)                                  \
        if ((status = mpv_set_option_string(ctx, opt, value)) < 0) {    \
            LOG_ERROR("WINDOW", "Failed to set %s to %s: %s",           \
                    opt, value, mpv_error_string(status));              \
            return NULL;                                                \
        }
    #define MPV_SET_FROM_INI(opt, section, key)                                 \
        if (!database_config_get_text(db, section, key, _opt, LKT_LINE_MAX)) {  \
            LOG_WARN("WINDOW", "Failed to get option "                          \
                            key " in section " section);                        \
            return ctx;                                                         \
        }                                                                       \
        MPV_SET_OPTION(opt, _opt);
    
        MPV_SET_OPTION("input-default-bindings", "yes");
        MPV_SET_OPTION("input-vo-keyboard",      "yes");
        MPV_SET_OPTION("replaygain",             "track");
        MPV_SET_OPTION("gpu-context",            "x11");   /* Wayland you sucks */
        MPV_SET_OPTION("demuxer-readahead-secs", "5.0");
        MPV_SET_OPTION("demuxer-max-bytes",      "100M");
        MPV_SET_OPTION("hwdec",                  "yes");
        MPV_SET_FROM_INI("osd-font-size", "player", "font_size");
        MPV_SET_FROM_INI("osd-font",      "player", "font_name");
        MPV_SET_FROM_INI("osd-duration",  "player", "msg_duration");
        return ctx;
    #undef MPV_SET_OPTION
    #undef MPV_SET_FROM_INI
    }
    
    int
    lmpv_observe_properties(mpv_handle *ctx)
    {
        return (mpv_observe_property(ctx, 0, "ao-volume", MPV_FORMAT_INT64) >= 0) &&
               (mpv_observe_property(ctx, 0, "duration",  MPV_FORMAT_INT64) >= 0) &&
               (mpv_observe_property(ctx, 0, "time-pos",  MPV_FORMAT_INT64) >= 0) &&
               (mpv_observe_property(ctx, 0, "pause",     MPV_FORMAT_FLAG)  >= 0);
    }
    
    mpv_handle *
    lmpv_new(unsigned long int wid, volatile sqlite3 *db)
    {
        mpv_handle *ctx = lmpv_prepare(db);
        int status;
    
        if ((status = mpv_set_property(ctx, "wid", MPV_FORMAT_INT64, &wid)) < 0) {
            LOG_ERROR("WINDOW", "Failed to set wid: %s", mpv_error_string(status));
            goto error;
        }
    
        if ((status = mpv_initialize(ctx)) < 0) {
            LOG_ERROR("WINDOW", "Failed to init mpv: %s", mpv_error_string(status));
            goto error;
        }
    
        if (!lmpv_observe_properties(ctx)) {
            LOG_ERROR("WINDOW", "Failed to observe properties");
            goto error;
        }
    
        LOG_INFO("WINDOW", "Create mpv context");
        return ctx;
    error:
        lmpv_free(&ctx);
        return NULL;
    }
    
    int
    lmpv_set_volume(mpv_handle *ctx, int vol)
    {
        RETURN_UNLESS(ctx, "Missing mpv ctx", 1);
        int status;
        char str[5];
        memset(str, 0, 5);
        safe_snprintf(str, 4, "%d", vol);
        const char *cmd[] = {"set", "ao-volume", str, NULL};
        if ((status = mpv_command_async(ctx, 0, cmd)) < 0) {
            LOG_ERROR("WINDOW", "Failed to execute command: %s", mpv_error_string(status));
            return 1;
        }
        return 0;
    }
    
    int
    lmpv_load_file(mpv_handle *ctx, const char *file)
    {
        RETURN_UNLESS(ctx, "Missing mpv ctx", 1);
        RETURN_IF(access(file, R_OK), "Failed to read file", 1);
        const char *cmd1[] = { "loadfile", file, "replace", NULL };
        const char *cmd2[] = { "set", "pause", "0", NULL };
        int status;
        if ((status = mpv_command_async(ctx, 0, cmd1)) < 0) {
            LOG_ERROR("WINDOW", "Failed to add '%s': %s", file, mpv_error_string(status));
            return 1;
        }
        if ((status = mpv_command_async(ctx, 0, cmd2)) < 0) {
            LOG_ERROR("WINDOW", "Failed to set state to play: %s", mpv_error_string(status));
            return 1;
        }
        return 0;
    }
    
    int
    lmpv_toggle_pause(mpv_handle *ctx)
    {
        RETURN_UNLESS(ctx, "Missing mpv ctx", 1);
        const char *cmd[] = {"cycle", "pause", "up", NULL};
        int status;
        if ((status = mpv_command_async(ctx, 0, cmd)) < 0) {
            LOG_ERROR("WINDOW", "Failed issus command: %s", mpv_error_string(status));
            return 1;
        }
        return 0;
    }
    
    int
    lmpv_handle(struct lkt_module *mod, mpv_handle *ctx, struct queue *queue,
                volatile int *time_pos, volatile int *time_duration,
                volatile int *state)
    {
        size_t ao_volume;
        mpv_event *event = NULL;
        mpv_event_property *prop;
        RETURN_UNLESS(ctx, "Invalid argument", 1);
    
    loop:
        event = mpv_wait_event(ctx, 0);
    
        switch (event->event_id) {
        case MPV_EVENT_PAUSE:
            *state = STATE_PAUSE;
            lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PAUSE);
            break;
    
        case MPV_EVENT_UNPAUSE:
            *state = STATE_PLAY;
            lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PLAY);
            break;
    
        case MPV_EVENT_SHUTDOWN:
            *time_pos = (*time_duration = 0);
            *state = STATE_STOP;
            lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_STOP);
            reg_call(mod->reg, "close", 1, mod->data);
            return 1;
    
        case MPV_EVENT_NONE:
            return 1;
    
        case MPV_EVENT_IDLE:
            if (*state != STATE_STOP && *time_pos > 0)
                lkt_queue_send(queue, lkt_event_play_next, NULL);
            break;
    
        case MPV_EVENT_PROPERTY_CHANGE:
            prop = (mpv_event_property *) event->data;
            if (prop->format == MPV_FORMAT_NONE)
                break;
            /* MPV volume (BUG: The flag is not MPV_FORMAT_NONE only at the end of the song...) */
            if (STR_MATCH(prop->name, "ao-volume")
                && prop->format == MPV_FORMAT_INT64) {
                ao_volume = *(int *) prop->data;
                lkt_queue_send(queue, lkt_event_prop_vol, (void *) ao_volume);
            }
            /* File duration */
            if (STR_MATCH(prop->name, "duration")
                && prop->format == MPV_FORMAT_INT64) {
                *time_duration = *(int *) prop->data;
                lkt_queue_send(queue, lkt_event_prop_dur, (void *) (size_t) *time_duration);
            }
            if (STR_MATCH(prop->name, "time-pos")
                && prop->format == MPV_FORMAT_INT64) {
                *time_pos = *(int *) prop->data;
                lkt_queue_send(queue, lkt_event_prop_time, (void *) (size_t) *time_pos);
            }
            /* Pause state */
            if (STR_MATCH(prop->name, "pause")
                && prop->format == MPV_FORMAT_FLAG) {
                if (* (bool *) prop->data) {
                    lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PAUSE);
                    *state = STATE_PAUSE;
                } else {
                    lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PLAY);
                    *state = STATE_PLAY;
                }
            }
            break;
    
        /* Ignored */
        case MPV_EVENT_VIDEO_RECONFIG:
        case MPV_EVENT_AUDIO_RECONFIG:
            break;
    
        case MPV_EVENT_COMMAND_REPLY:
            free((void *) event->reply_userdata);
            break;
    
        default:
            LOG_WARN("WINDOW", "Unhandled mpv event '%s'", mpv_event_name(event->event_id));
            break;
        }
        goto loop; /* A loop without indentation. Ugly but better for not-really-wide screens */
    }