diff --git a/inc/common/queue.h b/inc/common/queue.h index 5d5e5115f2658086054e999a6bab423f4226b1ba..286dd54618f4b9f9fc606ada852d697f9baa6869 100644 --- a/inc/common/queue.h +++ b/inc/common/queue.h @@ -3,13 +3,26 @@ #include <pthread.h> #include <common/common.h> +#define LKT_PLAY_STOP ((void *) (size_t) 0) +#define LKT_PLAY_PLAY ((void *) (size_t) 1) +#define LKT_PLAY_PAUSE ((void *) (size_t) 2) +#define LKT_PLAY_TOGGLE ((void *) (size_t) 3) + enum lkt_event_type { - lkt_event_null = 0, /* NULL */ - lkt_event_play_pos = (1 << 1), /* size_t */ - lkt_event_play_file = (1 << 2), /* const char* */ + lkt_event_null = 0, /* NULL */ + lkt_event_play_pos = (1 << 1), /* size_t */ + lkt_event_play_file = (1 << 2), /* const char* */ + lkt_event_play_next = (1 << 3), /* NULL */ + lkt_event_play_prev = (1 << 4), /* NULL */ + lkt_event_play_toggle = (1 << 5), /* size_t, `LKT_PLAY_.*` */ + lkt_event_prop_vol = (1 << 6), /* size_t */ + lkt_event_prop_dur = (1 << 7), /* size_t */ + lkt_event_prop_time = (1 << 8), /* size_t */ }; -#define lkt_event_play (lkt_event_play_pos | lkt_event_play_file) +#define lkt_event_play (lkt_event_play_pos | lkt_event_play_file | \ + lkt_event_play_next | lkt_event_play_prev \ + ) typedef struct { unsigned int type; diff --git a/inc/lektor/module/module_x11.h b/inc/lektor/module/module_x11.h deleted file mode 100644 index 14c9fb7e9bdd448a3a39dd49ca1c341836128723..0000000000000000000000000000000000000000 --- a/inc/lektor/module/module_x11.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include <stdbool.h> -#include <sqlite3.h> -#include <lektor/window.h> - -#if defined(_STATIC_MODULES) -/* The only function with a setted filename */ -int load_x11(void *mod, struct lkt_state *srv, void *handle); -#endif - -/* Below there are needed functions for a window module. - * Names are not fixed but they follow a convention (to get a code easy - * to read). They should not be used in lektor! They will be loaded into - * the struct lkt_win by the module_set_function. - */ -bool module_x11_new(struct lkt_win *const win); -void module_x11_close(struct lkt_win *const win); -void module_x11_free(struct lkt_win *const win); -void module_x11_attach(struct lkt_win *const win, void *server); - -bool module_x11_toggle_pause(struct lkt_win *const win); -bool module_x11_load_file(struct lkt_win *const win, const char *filepath); -bool module_x11_set_volume(struct lkt_win *const win, int vol); - -bool module_x11_get_duration(struct lkt_win *const win, int *dur_sec); -bool module_x11_get_elapsed(struct lkt_win *const win, int *elapsed_sec); - -bool module_x11_handle_events(struct lkt_win *const win, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_events); diff --git a/inc/lektor/module/mpv.h b/inc/lektor/module/mpv.h index ab28af195e1430dccaaa06cde9745d47f83f17c5..821bdd12b97d4273bc9b275d821515a92dcff647 100644 --- a/inc/lektor/module/mpv.h +++ b/inc/lektor/module/mpv.h @@ -2,8 +2,10 @@ #include <sqlite3.h> #include <mpv/client.h> -#include <lektor/net.h> #include <common/common.h> +#include <common/queue.h> + +struct lkt_win *win; void lmpv_free(mpv_handle **ctx); mpv_handle *lmpv_new(unsigned long int wid, volatile sqlite3 *db); @@ -13,5 +15,5 @@ mpv_handle *lmpv_prepare(volatile sqlite3 *db); int lmpv_set_volume(mpv_handle *ctx, int vol); int lmpv_load_file(mpv_handle *ctx, const char *file); int lmpv_toggle_pause(mpv_handle *ctx); -int lmpv_handle(struct lkt_win *win, mpv_handle *ctx, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_flag, +int lmpv_handle(struct lkt_win *win, mpv_handle *ctx, struct queue *queue, volatile int *time_pos, volatile int *time_duration); diff --git a/meson.build b/meson.build index c5955d01dfd1975683f4823c8836a3f29f837b13..c73a83c2b77a585050199de16d311ac03bd6888f 100644 --- a/meson.build +++ b/meson.build @@ -33,9 +33,6 @@ if get_option('static_modules').enabled() if get_option('module_sdl').enabled() add_global_arguments('-D_STATIC_SDL2', language: 'c') endif - if get_option('module_x11').enabled() - add_global_arguments('-D_STATIC_X11', language: 'c') - endif endif ## Module list @@ -126,20 +123,6 @@ else bin_deps = [ declare_dependency( link_with: lib.get_shared_lib(), include_directories: includes) ] endif -# X11 window module -if get_option('module_x11').enabled() - assert(dep_x11.found() and dep_mpv.found(), 'Asking to build x11 module, but missing dependencies') - lib_mod_x11 = both_libraries ( '_module_x11' - , files(['src/module/module_x11.c', 'src/module/mpv.c']) - , include_directories: includes - , dependencies: [ dep_x11, dep_mpv, bin_deps ] - , install: get_option('static_modules').disabled() - , install_dir: 'lib/lektor' ) - if get_option('static_modules').enabled() - lektor_modules += [ lib_mod_x11.get_static_lib() ] - endif -endif - # SQL2 window module if get_option('module_sdl').enabled() assert(dep_x11.found() and dep_mpv.found(), 'Asking to build x11 module, but missing dependencies') diff --git a/src/module/module_sdl2.c b/src/module/module_sdl2.c index 81292ef28a209cb417b98a0bf4a00a0ad17bd004..b8fdbe640aeede8ab06551f6ea5b01a26fec37fe 100644 --- a/src/module/module_sdl2.c +++ b/src/module/module_sdl2.c @@ -1,12 +1,12 @@ #define _POSIX_C_SOURCE 200809L -#include <lektor/commands.h> #include <common/common.h> +#include <common/queue.h> #include <lektor/module/module_sdl2.h> #include <lektor/module/mpv.h> -#include <mthread/mthread.h> #include <lektor/thread.h> #include <lektor/reg.h> +#include <lektor/net.h> #include <sched.h> #include <assert.h> @@ -36,13 +36,11 @@ struct module_sdl2_window { volatile int mpv_duration; /* Because don't need to be persistent */ /* Thread related */ - mthread_mutex_t mtx; struct poller_thread self; volatile int launched; /* SDL you sucks */ /* Things from the server */ - volatile sqlite3 *db; - mpd_idle_flag *mpd_idle_events; + struct queue *queue; }; /* Private functions. */ @@ -181,8 +179,7 @@ loop: else if (event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == SDLK_RETURN2 || event.key.keysym.sym == SDLK_KP_ENTER) - command_next(sdl2->db, (struct lkt_win *) win, - sdl2->mpd_idle_events); + lkt_queue_send(sdl2->queue, lkt_event_play_next, NULL); else if (event.key.keysym.sym == SDLK_LEFT) { const char *cmd_seek[] = { "seek", "-5", "relative", NULL }; @@ -205,26 +202,26 @@ loop: case SDL_TEXTINPUT: if (STR_MATCH(event.text.text, ">")) - command_next(sdl2->db, (struct lkt_win *) win, - sdl2->mpd_idle_events); + lkt_queue_send(sdl2->queue, lkt_event_play_next, NULL); else if (STR_MATCH(event.text.text, "<")) - command_previous(sdl2->db, (struct lkt_win *) win, - sdl2->mpd_idle_events); + lkt_queue_send(sdl2->queue, lkt_event_play_prev, NULL); else if (STR_MATCH(event.text.text, "o")) { const char *cmd[] = { "show-progress", NULL }; mpv_command_async((mpv_handle *) sdl2->mpv, 0, cmd); } else if (STR_MATCH(event.text.text, "i")) { + /* struct kara_metadata mdt; int id; char *str; if (database_queue_current_kara(sdl2->db, &mdt, &id)) { mdtcat(&mdt, &str); const char *cmd[] = { "show-text", str, "4000", NULL }; - /* Same size, only on 64bit arch... - FIXME: Do something else in 32bits */ + // Same size, only on 64bit arch... + // FIXME: Do something else in 32bits mpv_command_async((mpv_handle *) sdl2->mpv, (uint64_t) str, cmd); } + */ } else LOG_ERROR("WINDOW", "Not handled text '%s'", event.text.text); break; @@ -239,8 +236,7 @@ loop: if (event.type == wakeup_on_mpv_events) lmpv_handle((struct lkt_win *) win, (mpv_handle *) sdl2->mpv, - sdl2->db, sdl2->mpd_idle_events, &sdl2->mpv_time_pos, - &sdl2->mpv_duration); + sdl2->queue, &sdl2->mpv_time_pos, &sdl2->mpv_duration); } if (redraw) { @@ -287,11 +283,8 @@ module_sdl2_new(struct lkt_win *const win) memset(win->window, 0, sizeof(struct module_sdl2_window)); /* Yeah, this is how it is done. */ - mthread_mutex_t mtx = MTHREAD_MUTEX_INITIALIZER; struct module_sdl2_window *sdl2 = win->window; - sdl2->mtx = mtx; - sdl2->db = win->srv->db; - sdl2->mpd_idle_events = &win->srv->mpd_idle_events; + sdl2->queue = &win->srv->queue; /* Start the SDL thread */ arg = malloc(sizeof(struct poller_thread_arg)); diff --git a/src/module/module_x11.c b/src/module/module_x11.c deleted file mode 100644 index 061440ab2ad8e0dee9cac3634dc08ffaf9cfd32c..0000000000000000000000000000000000000000 --- a/src/module/module_x11.c +++ /dev/null @@ -1,278 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include <common/common.h> -#include <lektor/module/module_x11.h> -#include <lektor/module/mpv.h> -#include <lektor/database.h> -#include <lektor/commands.h> -#include <lektor/reg.h> - -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> -#include <X11/Xatom.h> -#include <mpv/client.h> - -#define WIDTH 400 -#define HEIGHT 200 - -struct module_x11_window { - /* X11 related, the master and slave window */ - Display *master_display; - Display *child_display; - Window master_win; - Window child_win; - - /* X11 related, some X11 properties */ - int screen; - XSetWindowAttributes attrs; - Atom wm_delete; - XColor black; - bool is_fullscreen; - - /* Mpv related */ - mpv_handle *mpv; - volatile int mpv_time_pos; // Don't write it in the database // - volatile int mpv_duration; // Because don't need to be persistent // -}; - -static inline bool -lx11_new(struct module_x11_window *ret) -{ - ret->master_display = XOpenDisplay(NULL); - RETURN_UNLESS(ret->master_display, "Can't open display", false); - ret->screen = DefaultScreen(ret->master_display); - Colormap colormap = DefaultColormap(ret->master_display, ret->screen); - XAllocNamedColor(ret->master_display, colormap, "black", - &ret->black, &ret->black); - - // Initialize container window attributes - ret->attrs.event_mask - = SubstructureRedirectMask - | SubstructureNotifyMask - | StructureNotifyMask - | ExposureMask - | KeyReleaseMask - | VisibilityChangeMask - ; - ret->attrs.do_not_propagate_mask = 1; - ret->attrs.background_pixel = ret->black.pixel; - unsigned long attrs_mask = CWEventMask - | NoEventMask - | CWBackPixel - ; - - // Create and map container window - ret->master_win = XCreateWindow(ret->master_display, RootWindow(ret->master_display, ret->screen), - 0, 0, WIDTH, HEIGHT, 1, CopyFromParent, InputOutput, - CopyFromParent, attrs_mask, &ret->attrs); - - XMapWindow(ret->master_display, ret->master_win); - XStoreName(ret->master_display, ret->master_win, "Lektor Player"); - ret->wm_delete = XInternAtom(ret->master_display, "WM_DELETE_WINDOW", True); - XSetWMProtocols(ret->master_display, ret->master_win, &ret->wm_delete, 1); - - ret->child_display = NULL; - ret->child_win = 0; - - return true; -} - -static inline bool -lx11_handle(struct module_x11_window *win) -{ - XEvent event; - - RETURN_UNLESS(win && win->mpv, "Invalid argument", true); - - for (;;) { - - if (!XCheckWindowEvent(win->master_display, win->master_win, - win->attrs.event_mask, &event)) - return true; - - // Map child window when it requests and store its display and window id - if (event.type == MapRequest) { - XMapWindow(event.xmaprequest.display, event.xmaprequest.window); - - win->child_display = event.xmaprequest.display; - win->child_win = event.xmaprequest.window; - } - - // Propagate resize event to child window, and also resize it - // after MapRequest - if (event.type == ConfigureNotify || event.type == MapRequest) { - if (win->child_win) { - // Get container window attributes - XWindowAttributes attrs; - XGetWindowAttributes(win->master_display, win->master_win, - &attrs); - - // Move and resize child - XMoveResizeWindow(win->child_display, win->child_win, - 2, 2, attrs.width - 6, attrs.height - 6); - } - } - - // Key press - if (event.type == KeyRelease) { - LOG_INFO("WINDOW", "Release key: 0x%x", event.xkey.keycode); - if (event.xkey.keycode == 0x47) - XClearWindow(win->master_display, win->master_win); - } - - // Refresh container window - if (event.type == Expose) - XClearWindow(win->master_display, win->master_win); - - // Close button - if (event.type == ClientMessage) { - if ((long unsigned int) event.xclient.data.l[0] == win->wm_delete) - return false; - } - - } - return true; -} - -bool -module_x11_new(struct lkt_win *const win) -{ - RETURN_UNLESS(win, "Invalid argument", false); - struct module_x11_window *x11_win = win->window; - - if (x11_win == NULL) { - x11_win = calloc(1, sizeof(struct module_x11_window)); - memset(x11_win, 0, sizeof(struct module_x11_window)); - RETURN_UNLESS(x11_win, "Out of memory", false); - RETURN_UNLESS(lx11_new(x11_win), "Can't create X11 window", false); - LOG_INFO("WINDOW", "%s", "Created the X11 window"); - } - - if (x11_win->mpv == NULL) { - x11_win->mpv = lmpv_new(x11_win->master_win, win->srv->db); - RETURN_UNLESS(x11_win->mpv, "Failed to create mpv", false); - } - - win->window = x11_win; - return true; -} - -void -module_x11_close(struct lkt_win *const win) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", NOTHING); - struct module_x11_window *const x11_win = win->window; - lmpv_free(&x11_win->mpv); - x11_win->child_display = NULL; - x11_win->child_win = (x11_win->mpv_time_pos = (x11_win->mpv_duration = 0)); -} - -void -module_x11_free(struct lkt_win *const win) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", NOTHING); - struct module_x11_window *const x11_win = win->window; - lmpv_free(&x11_win->mpv); - XCloseDisplay(x11_win->master_display); - free(x11_win); - win->window = NULL; -} - -bool -module_x11_toggle_pause(struct lkt_win *const win) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", false); - return ! lmpv_toggle_pause(((struct module_x11_window *) win->window)->mpv); -} - -bool -module_x11_load_file(struct lkt_win *const win, const char *filepath) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", false); - struct module_x11_window *xwin = win->window; - bool ret = ! lmpv_load_file(xwin->mpv, filepath); - xwin->mpv_duration = 0; - xwin->mpv_time_pos = 0; - return ret; -} - -bool -module_x11_set_volume(struct lkt_win *const win, int vol) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", false); - return ! lmpv_set_volume(((struct module_x11_window *) win->window)->mpv, - vol); -} - -bool -module_x11_get_duration(struct lkt_win *const win, int *dur_sec) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", false); - struct module_x11_window *win_x11 = win->window; - *dur_sec = win_x11->mpv_duration; - return true; -} - -bool -module_x11_get_elapsed(struct lkt_win *const win, int *elapsed_sec) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", false); - struct module_x11_window *win_x11 = win->window; - *elapsed_sec = win_x11->mpv_time_pos; - return true; -} - -bool -module_x11_handle_events(struct lkt_win *const win, volatile sqlite3 *db, - mpd_idle_flag *mpd_idle_events) -{ - RETURN_UNLESS(win && win->window, "Invalid arguments", false); - struct module_x11_window *xwin = win->window; - return lx11_handle(xwin) && - ! lmpv_handle(win, xwin->mpv, db, mpd_idle_events, - &xwin->mpv_time_pos, &xwin->mpv_duration); -} - -/* The module stuff */ - -int -#if ! defined(_STATIC_MODULES) -module_set_function(void *arg__, struct lkt_state *srv, void *handle__) -#else -load_x11(void *arg__, struct lkt_state *srv, void *handle__) -#endif -{ - RETURN_UNLESS(arg__, "Invalid arguments", 1); - struct lkt_win *win = (struct lkt_win *) arg__; - win->srv = srv; - - win->new = module_x11_new; - win->close = module_x11_close; - win->free = module_x11_free; - win->toggle_pause = module_x11_toggle_pause; - win->load_file = module_x11_load_file; - win->set_volume = module_x11_set_volume; - win->get_duration = module_x11_get_duration; - win->get_elapsed = module_x11_get_elapsed; - win->handle_events = module_x11_handle_events; - win->handle = handle__; - - return !module_x11_new(&srv->win); -} - -REG_BEGIN(x11_reg) -REG_ADD_NAMED("new", module_x11_new) -REG_ADD_NAMED("free", module_x11_free) -REG_ADD_NAMED("handle", module_x11_handle_events) -REG_ADD(module_x11_close) -REG_ADD(module_x11_toggle_pause) -REG_ADD(module_x11_load_file) -REG_ADD(module_x11_set_volume) -REG_ADD(module_x11_get_duration) -REG_ADD(module_x11_get_elapsed) -REG_END() -REG_EXPORT(x11_reg) diff --git a/src/module/mpv.c b/src/module/mpv.c index 06763230a2e673f62054c8b7238d0dd48d633167..2023814497f05de19df397460c041bf13d582e12 100644 --- a/src/module/mpv.c +++ b/src/module/mpv.c @@ -144,15 +144,14 @@ lmpv_toggle_pause(mpv_handle *ctx) } int -lmpv_handle(struct lkt_win *win, mpv_handle *ctx, volatile sqlite3 *db, mpd_idle_flag *mpd_idle_events, - volatile int *time_pos, volatile int *time_duration) +lmpv_handle(struct lkt_win *win, mpv_handle *ctx, struct queue *queue, + volatile int *time_pos, volatile int *time_duration) { - int ao_volume; + size_t ao_volume; struct lkt_queue_state state; mpv_event *event = NULL; mpv_event_property *prop; - RETURN_UNLESS(db && mpd_idle_events && ctx && win, "Invalid argument", 1); - RETURN_UNLESS(database_queue_state(db, &state), "Failed to get queue state", 1); + RETURN_UNLESS(ctx && win, "Invalid argument", 1); loop: event = mpv_wait_event(ctx, 0); @@ -160,12 +159,12 @@ loop: switch (event->event_id) { case MPV_EVENT_PAUSE: case MPV_EVENT_UNPAUSE: - database_queue_toggle_pause(db); + lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_TOGGLE); break; case MPV_EVENT_SHUTDOWN: *time_pos = (*time_duration = 0); - database_queue_stop(db); + lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_STOP); win->close(win); return 1; @@ -174,7 +173,7 @@ loop: case MPV_EVENT_IDLE: if (state.current > 0 && *time_pos > 0) - command_next(db, win, mpd_idle_events); + lkt_queue_send(queue, lkt_event_play_next, NULL); break; case MPV_EVENT_PROPERTY_CHANGE: @@ -185,23 +184,27 @@ loop: if (STR_MATCH(prop->name, "ao-volume") && prop->format == MPV_FORMAT_INT64) { ao_volume = *(int *) prop->data; - database_config_queue(db, "volume", ao_volume); + 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; - database_config_queue(db, "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; - database_config_queue(db, "elapsed", *(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) - database_queue_set_paused(db, *(bool *) prop->data); + && prop->format == MPV_FORMAT_FLAG) { + if (* (bool *) prop->data) + lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PAUSE); + else + lkt_queue_send(queue, lkt_event_play_toggle, LKT_PLAY_PLAY); + } break; /* Ignored */