mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-06-21 09:55:39 +02:00
Merge remote-tracking branch 'origin/master' into module_mpris
This commit is contained in:
commit
6fea536354
42 changed files with 1112 additions and 157 deletions
|
@ -112,13 +112,13 @@ readint_from_fd(int fd)
|
|||
static int
|
||||
initialize(struct private *m)
|
||||
{
|
||||
int backlight_fd = open("/sys/class/backlight", O_RDONLY);
|
||||
int backlight_fd = open("/sys/class/backlight", O_RDONLY | O_CLOEXEC);
|
||||
if (backlight_fd == -1) {
|
||||
LOG_ERRNO("/sys/class/backlight");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int base_dir_fd = openat(backlight_fd, m->device, O_RDONLY);
|
||||
int base_dir_fd = openat(backlight_fd, m->device, O_RDONLY | O_CLOEXEC);
|
||||
close(backlight_fd);
|
||||
|
||||
if (base_dir_fd == -1) {
|
||||
|
@ -126,7 +126,7 @@ initialize(struct private *m)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int max_fd = openat(base_dir_fd, "max_brightness", O_RDONLY);
|
||||
int max_fd = openat(base_dir_fd, "max_brightness", O_RDONLY | O_CLOEXEC);
|
||||
if (max_fd == -1) {
|
||||
LOG_ERRNO("/sys/class/backlight/%s/max_brightness", m->device);
|
||||
close(base_dir_fd);
|
||||
|
@ -136,7 +136,7 @@ initialize(struct private *m)
|
|||
m->max_brightness = readint_from_fd(max_fd);
|
||||
close(max_fd);
|
||||
|
||||
int current_fd = openat(base_dir_fd, "brightness", O_RDONLY);
|
||||
int current_fd = openat(base_dir_fd, "brightness", O_RDONLY | O_CLOEXEC);
|
||||
close(base_dir_fd);
|
||||
|
||||
if (current_fd == -1) {
|
||||
|
|
|
@ -259,13 +259,13 @@ initialize(struct private *m)
|
|||
{
|
||||
char line_buf[512];
|
||||
|
||||
int pw_fd = open("/sys/class/power_supply", O_RDONLY);
|
||||
int pw_fd = open("/sys/class/power_supply", O_RDONLY | O_CLOEXEC);
|
||||
if (pw_fd < 0) {
|
||||
LOG_ERRNO("/sys/class/power_supply");
|
||||
return false;
|
||||
}
|
||||
|
||||
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY);
|
||||
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY | O_CLOEXEC);
|
||||
close(pw_fd);
|
||||
|
||||
if (base_dir_fd < 0) {
|
||||
|
@ -274,7 +274,7 @@ initialize(struct private *m)
|
|||
}
|
||||
|
||||
{
|
||||
int fd = openat(base_dir_fd, "manufacturer", O_RDONLY);
|
||||
int fd = openat(base_dir_fd, "manufacturer", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_WARN("/sys/class/power_supply/%s/manufacturer: %s", m->battery, strerror(errno));
|
||||
m->manufacturer = NULL;
|
||||
|
@ -285,7 +285,7 @@ initialize(struct private *m)
|
|||
}
|
||||
|
||||
{
|
||||
int fd = openat(base_dir_fd, "model_name", O_RDONLY);
|
||||
int fd = openat(base_dir_fd, "model_name", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_WARN("/sys/class/power_supply/%s/model_name: %s", m->battery, strerror(errno));
|
||||
m->model = NULL;
|
||||
|
@ -298,7 +298,7 @@ initialize(struct private *m)
|
|||
if (faccessat(base_dir_fd, "energy_full_design", O_RDONLY, 0) == 0
|
||||
&& faccessat(base_dir_fd, "energy_full", O_RDONLY, 0) == 0) {
|
||||
{
|
||||
int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY);
|
||||
int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_ERRNO("/sys/class/power_supply/%s/energy_full_design", m->battery);
|
||||
goto err;
|
||||
|
@ -309,7 +309,7 @@ initialize(struct private *m)
|
|||
}
|
||||
|
||||
{
|
||||
int fd = openat(base_dir_fd, "energy_full", O_RDONLY);
|
||||
int fd = openat(base_dir_fd, "energy_full", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_ERRNO("/sys/class/power_supply/%s/energy_full", m->battery);
|
||||
goto err;
|
||||
|
@ -325,7 +325,7 @@ initialize(struct private *m)
|
|||
if (faccessat(base_dir_fd, "charge_full_design", O_RDONLY, 0) == 0
|
||||
&& faccessat(base_dir_fd, "charge_full", O_RDONLY, 0) == 0) {
|
||||
{
|
||||
int fd = openat(base_dir_fd, "charge_full_design", O_RDONLY);
|
||||
int fd = openat(base_dir_fd, "charge_full_design", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_ERRNO("/sys/class/power_supply/%s/charge_full_design", m->battery);
|
||||
goto err;
|
||||
|
@ -336,7 +336,7 @@ initialize(struct private *m)
|
|||
}
|
||||
|
||||
{
|
||||
int fd = openat(base_dir_fd, "charge_full", O_RDONLY);
|
||||
int fd = openat(base_dir_fd, "charge_full", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_ERRNO("/sys/class/power_supply/%s/charge_full", m->battery);
|
||||
goto err;
|
||||
|
@ -362,13 +362,13 @@ update_status(struct module *mod)
|
|||
{
|
||||
struct private *m = mod->private;
|
||||
|
||||
int pw_fd = open("/sys/class/power_supply", O_RDONLY);
|
||||
int pw_fd = open("/sys/class/power_supply", O_RDONLY | O_CLOEXEC);
|
||||
if (pw_fd < 0) {
|
||||
LOG_ERRNO("/sys/class/power_supply");
|
||||
return false;
|
||||
}
|
||||
|
||||
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY);
|
||||
int base_dir_fd = openat(pw_fd, m->battery, O_RDONLY | O_CLOEXEC);
|
||||
close(pw_fd);
|
||||
|
||||
if (base_dir_fd < 0) {
|
||||
|
@ -376,14 +376,14 @@ update_status(struct module *mod)
|
|||
return false;
|
||||
}
|
||||
|
||||
int status_fd = openat(base_dir_fd, "status", O_RDONLY);
|
||||
int status_fd = openat(base_dir_fd, "status", O_RDONLY | O_CLOEXEC);
|
||||
if (status_fd < 0) {
|
||||
LOG_ERRNO("/sys/class/power_supply/%s/status", m->battery);
|
||||
close(base_dir_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
int capacity_fd = openat(base_dir_fd, "capacity", O_RDONLY);
|
||||
int capacity_fd = openat(base_dir_fd, "capacity", O_RDONLY | O_CLOEXEC);
|
||||
if (capacity_fd < 0) {
|
||||
LOG_ERRNO("/sys/class/power_supply/%s/capacity", m->battery);
|
||||
close(status_fd);
|
||||
|
@ -391,12 +391,12 @@ update_status(struct module *mod)
|
|||
return false;
|
||||
}
|
||||
|
||||
int energy_fd = openat(base_dir_fd, "energy_now", O_RDONLY);
|
||||
int power_fd = openat(base_dir_fd, "power_now", O_RDONLY);
|
||||
int charge_fd = openat(base_dir_fd, "charge_now", O_RDONLY);
|
||||
int current_fd = openat(base_dir_fd, "current_now", O_RDONLY);
|
||||
int time_to_empty_fd = openat(base_dir_fd, "time_to_empty_now", O_RDONLY);
|
||||
int time_to_full_fd = openat(base_dir_fd, "time_to_full_now", O_RDONLY);
|
||||
int energy_fd = openat(base_dir_fd, "energy_now", O_RDONLY | O_CLOEXEC);
|
||||
int power_fd = openat(base_dir_fd, "power_now", O_RDONLY | O_CLOEXEC);
|
||||
int charge_fd = openat(base_dir_fd, "charge_now", O_RDONLY | O_CLOEXEC);
|
||||
int current_fd = openat(base_dir_fd, "current_now", O_RDONLY | O_CLOEXEC);
|
||||
int time_to_empty_fd = openat(base_dir_fd, "time_to_empty_now", O_RDONLY | O_CLOEXEC);
|
||||
int time_to_full_fd = openat(base_dir_fd, "time_to_full_now", O_RDONLY | O_CLOEXEC);
|
||||
|
||||
long capacity = readint_from_fd(capacity_fd);
|
||||
long energy = energy_fd >= 0 ? readint_from_fd(energy_fd) : -1;
|
||||
|
|
|
@ -124,7 +124,7 @@ refresh_cpu_stats(struct cpu_stats *cpu_stats, size_t core_count)
|
|||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
fp = fopen("/proc/stat", "r");
|
||||
fp = fopen("/proc/stat", "re");
|
||||
if (NULL == fp) {
|
||||
LOG_ERRNO("unable to open /proc/stat");
|
||||
return;
|
||||
|
|
|
@ -105,7 +105,7 @@ refresh_device_stats(struct private *m)
|
|||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
fp = fopen("/proc/diskstats", "r");
|
||||
fp = fopen("/proc/diskstats", "re");
|
||||
if (NULL == fp) {
|
||||
LOG_ERRNO("unable to open /proc/diskstats");
|
||||
return;
|
||||
|
|
|
@ -330,7 +330,7 @@ run_init(int *inotify_fd, int *inotify_wd, FILE **file, char *dwl_info_filename)
|
|||
return 1;
|
||||
}
|
||||
|
||||
*file = fopen(dwl_info_filename, "r");
|
||||
*file = fopen(dwl_info_filename, "re");
|
||||
if (*file == NULL) {
|
||||
inotify_rm_watch(*inotify_fd, *inotify_wd);
|
||||
close(*inotify_fd);
|
||||
|
|
|
@ -664,7 +664,7 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m
|
|||
char path[64];
|
||||
snprintf(path, sizeof(path), "/proc/%u/comm", ws->window.pid);
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
/* Application may simply have terminated */
|
||||
free(ws->window.application);
|
||||
|
@ -876,6 +876,7 @@ content(struct module *mod)
|
|||
struct tag_set tags = {
|
||||
.tags = (struct tag *[]){
|
||||
tag_new_string(mod, "name", name),
|
||||
tag_new_string(mod, "output", ws->output),
|
||||
tag_new_bool(mod, "visible", ws->visible),
|
||||
tag_new_bool(mod, "focused", ws->focused),
|
||||
tag_new_bool(mod, "urgent", ws->urgent),
|
||||
|
@ -887,7 +888,7 @@ content(struct module *mod)
|
|||
|
||||
tag_new_string(mod, "mode", m->mode),
|
||||
},
|
||||
.count = 9,
|
||||
.count = 10,
|
||||
};
|
||||
|
||||
if (ws->focused) {
|
||||
|
|
|
@ -54,7 +54,7 @@ get_mem_stats(uint64_t *mem_free, uint64_t *mem_total)
|
|||
size_t len = 0;
|
||||
ssize_t read = 0;
|
||||
|
||||
fp = fopen("/proc/meminfo", "r");
|
||||
fp = fopen("/proc/meminfo", "re");
|
||||
if (NULL == fp) {
|
||||
LOG_ERRNO("unable to open /proc/meminfo");
|
||||
return false;
|
||||
|
|
|
@ -48,6 +48,12 @@ plugin_script_enabled = get_option('plugin-script').allowed()
|
|||
json_sway_xkb = dependency('json-c', required: get_option('plugin-sway-xkb'))
|
||||
plugin_sway_xkb_enabled = json_sway_xkb.found()
|
||||
|
||||
json_niri_language = dependency('json-c', required: get_option('plugin-niri-language'))
|
||||
plugin_niri_language_enabled = json_niri_language.found()
|
||||
|
||||
json_niri_workspaces = dependency('json-c', required: get_option('plugin-niri-workspaces'))
|
||||
plugin_niri_workspaces_enabled = json_niri_workspaces.found()
|
||||
|
||||
xcb_xkb = dependency('xcb-xkb', required: get_option('plugin-xkb'))
|
||||
plugin_xkb_enabled = backend_x11 and xcb_xkb.found()
|
||||
|
||||
|
@ -128,6 +134,14 @@ if plugin_sway_xkb_enabled
|
|||
mod_data += {'sway-xkb': [['i3-common.c', 'i3-common.h'], [dynlist, json_sway_xkb]]}
|
||||
endif
|
||||
|
||||
if plugin_niri_language_enabled
|
||||
mod_data += {'niri-language': [['niri-common.c', 'niri-common.h'], [dynlist, json_niri_language]]}
|
||||
endif
|
||||
|
||||
if plugin_niri_workspaces_enabled
|
||||
mod_data += {'niri-workspaces': [['niri-common.c', 'niri-common.h'], [dynlist, json_niri_workspaces]]}
|
||||
endif
|
||||
|
||||
if plugin_xkb_enabled
|
||||
mod_data += {'xkb': [[], [xcb_stuff, xcb_xkb]]}
|
||||
endif
|
||||
|
|
|
@ -39,6 +39,7 @@ struct private
|
|||
bool repeat;
|
||||
bool random;
|
||||
bool consume;
|
||||
bool single;
|
||||
int volume;
|
||||
char *album;
|
||||
char *artist;
|
||||
|
@ -176,6 +177,7 @@ content(struct module *mod)
|
|||
tag_new_bool(mod, "repeat", m->repeat),
|
||||
tag_new_bool(mod, "random", m->random),
|
||||
tag_new_bool(mod, "consume", m->consume),
|
||||
tag_new_bool(mod, "single", m->single),
|
||||
tag_new_int_range(mod, "volume", m->volume, 0, 100),
|
||||
tag_new_string(mod, "album", m->album),
|
||||
tag_new_string(mod, "artist", m->artist),
|
||||
|
@ -187,7 +189,7 @@ content(struct module *mod)
|
|||
tag_new_int_realtime(
|
||||
mod, "elapsed", elapsed, 0, m->duration, realtime),
|
||||
},
|
||||
.count = 13,
|
||||
.count = 14,
|
||||
};
|
||||
|
||||
mtx_unlock(&mod->lock);
|
||||
|
@ -336,6 +338,7 @@ update_status(struct module *mod)
|
|||
m->repeat = mpd_status_get_repeat(status);
|
||||
m->random = mpd_status_get_random(status);
|
||||
m->consume = mpd_status_get_consume(status);
|
||||
m->single = mpd_status_get_single_state(status) == MPD_SINGLE_ONESHOT;
|
||||
m->volume = mpd_status_get_volume(status);
|
||||
m->duration = mpd_status_get_total_time(status) * 1000;
|
||||
m->elapsed.value = mpd_status_get_elapsed_ms(status);
|
||||
|
|
|
@ -1576,7 +1576,7 @@ out:
|
|||
static struct module *
|
||||
network_new(struct particle *label, int poll_interval, int left_spacing, int right_spacing)
|
||||
{
|
||||
int urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
int urandom_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||
if (urandom_fd < 0) {
|
||||
LOG_ERRNO("failed to open /dev/urandom");
|
||||
return NULL;
|
||||
|
|
377
modules/niri-common.c
Normal file
377
modules/niri-common.c
Normal file
|
@ -0,0 +1,377 @@
|
|||
#include <errno.h>
|
||||
#include <json-c/json.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/un.h>
|
||||
#include <threads.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../log.h"
|
||||
#include "niri-common.h"
|
||||
|
||||
#define LOG_MODULE "niri:common"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
|
||||
static struct niri_socket instance = {
|
||||
.fd = -1,
|
||||
.abort_fd = -1,
|
||||
};
|
||||
|
||||
static void
|
||||
workspace_free(struct niri_workspace *workspace)
|
||||
{
|
||||
free(workspace->name);
|
||||
free(workspace);
|
||||
}
|
||||
|
||||
static void
|
||||
parser(char *response)
|
||||
{
|
||||
enum json_tokener_error error = json_tokener_success;
|
||||
struct json_object *json = json_tokener_parse_verbose(response, &error);
|
||||
if (error != json_tokener_success) {
|
||||
LOG_WARN("failed to parse niri socket's response");
|
||||
return;
|
||||
}
|
||||
|
||||
enum niri_event events = 0;
|
||||
struct json_object_iterator it = json_object_iter_begin(json);
|
||||
struct json_object_iterator end = json_object_iter_end(json);
|
||||
while (!json_object_iter_equal(&it, &end)) {
|
||||
char const *key = json_object_iter_peek_name(&it);
|
||||
|
||||
// "WorkspacesChanged": {
|
||||
// "workspaces": [
|
||||
// {
|
||||
// "id": 3,
|
||||
// "idx": 1,
|
||||
// "name": null,
|
||||
// "output": "DP-4",
|
||||
// "is_active": true,
|
||||
// "is_focused": true,
|
||||
// "active_window_id": 24
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
// }
|
||||
if (strcmp(key, "WorkspacesChanged") == 0) {
|
||||
mtx_lock(&instance.mtx);
|
||||
tll_foreach(instance.workspaces, it) { tll_remove_and_free(instance.workspaces, it, workspace_free); }
|
||||
mtx_unlock(&instance.mtx);
|
||||
|
||||
json_object *obj = json_object_iter_peek_value(&it);
|
||||
json_object *workspaces = json_object_object_get(obj, "workspaces");
|
||||
|
||||
size_t length = json_object_array_length(workspaces);
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
json_object *ws_obj = json_object_array_get_idx(workspaces, i);
|
||||
|
||||
// only add workspaces on the current yambar's monitor
|
||||
struct json_object *output = json_object_object_get(ws_obj, "output");
|
||||
if (strcmp(instance.monitor, json_object_get_string(output)) != 0)
|
||||
continue;
|
||||
|
||||
struct niri_workspace *ws = calloc(1, sizeof(*ws));
|
||||
ws->idx = json_object_get_int(json_object_object_get(ws_obj, "idx"));
|
||||
ws->id = json_object_get_int(json_object_object_get(ws_obj, "id"));
|
||||
ws->active = json_object_get_boolean(json_object_object_get(ws_obj, "is_active"));
|
||||
ws->focused = json_object_get_boolean(json_object_object_get(ws_obj, "is_focused"));
|
||||
ws->empty = json_object_get_int(json_object_object_get(ws_obj, "active_window_id")) == 0;
|
||||
|
||||
char const *name = json_object_get_string(json_object_object_get(ws_obj, "name"));
|
||||
if (name)
|
||||
ws->name = strdup(name);
|
||||
|
||||
mtx_lock(&instance.mtx);
|
||||
bool inserted = false;
|
||||
tll_foreach(instance.workspaces, it)
|
||||
{
|
||||
if (it->item->idx > ws->idx) {
|
||||
tll_insert_before(instance.workspaces, it, ws);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inserted)
|
||||
tll_push_back(instance.workspaces, ws);
|
||||
mtx_unlock(&instance.mtx);
|
||||
|
||||
events |= workspaces_changed;
|
||||
}
|
||||
}
|
||||
|
||||
// "WorkspaceActivated": {
|
||||
// "id": 7,
|
||||
// "focused":true
|
||||
// }
|
||||
else if (strcmp(key, "WorkspaceActivated") == 0) {
|
||||
json_object *obj = json_object_iter_peek_value(&it);
|
||||
int id = json_object_get_int(json_object_object_get(obj, "id"));
|
||||
|
||||
mtx_lock(&instance.mtx);
|
||||
tll_foreach(instance.workspaces, it)
|
||||
{
|
||||
bool b = it->item->id == id;
|
||||
it->item->focused = b;
|
||||
it->item->active = b;
|
||||
}
|
||||
mtx_unlock(&instance.mtx);
|
||||
|
||||
events |= workspace_activated;
|
||||
}
|
||||
|
||||
// "WorkspaceActiveWindowChanged": {
|
||||
// "workspace_id": 3,
|
||||
// "active_window_id": 8
|
||||
// }
|
||||
else if (strcmp(key, "WorkspaceActiveWindowChanged") == 0) {
|
||||
json_object *obj = json_object_iter_peek_value(&it);
|
||||
int id = json_object_get_int(json_object_object_get(obj, "id"));
|
||||
bool empty = json_object_get_int(json_object_object_get(obj, "active_window_id")) == 0;
|
||||
|
||||
mtx_lock(&instance.mtx);
|
||||
tll_foreach(instance.workspaces, it)
|
||||
{
|
||||
if (it->item->id == id) {
|
||||
it->item->empty = empty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mtx_unlock(&instance.mtx);
|
||||
|
||||
events |= workspace_active_window_changed;
|
||||
}
|
||||
|
||||
//
|
||||
// "KeyboardLayoutsChanged": {
|
||||
// "keyboard_layouts": {
|
||||
// "names": [
|
||||
// "English (US)",
|
||||
// "Russian"
|
||||
// ],
|
||||
// "current_idx": 0
|
||||
// }
|
||||
// }
|
||||
else if (strcmp(key, "KeyboardLayoutsChanged") == 0) {
|
||||
tll_foreach(instance.keyboard_layouts, it) { tll_remove_and_free(instance.keyboard_layouts, it, free); }
|
||||
|
||||
json_object *obj = json_object_iter_peek_value(&it);
|
||||
json_object *kb_layouts = json_object_object_get(obj, "keyboard_layouts");
|
||||
|
||||
instance.keyboard_layout_index = json_object_get_int(json_object_object_get(kb_layouts, "current_idx"));
|
||||
|
||||
json_object *names = json_object_object_get(kb_layouts, "names");
|
||||
size_t names_length = json_object_array_length(names);
|
||||
for (size_t i = 0; i < names_length; ++i) {
|
||||
char const *name = json_object_get_string(json_object_array_get_idx(names, i));
|
||||
tll_push_back(instance.keyboard_layouts, strdup(name));
|
||||
}
|
||||
|
||||
events |= keyboard_layouts_changed;
|
||||
}
|
||||
|
||||
// "KeyboardLayoutSwitched": {
|
||||
// "idx": 1
|
||||
// }
|
||||
else if (strcmp(key, "KeyboardLayoutSwitched") == 0) {
|
||||
json_object *obj = json_object_iter_peek_value(&it);
|
||||
instance.keyboard_layout_index = json_object_get_int(json_object_object_get(obj, "idx"));
|
||||
|
||||
events |= keyboard_layouts_switched;
|
||||
}
|
||||
|
||||
json_object_iter_next(&it);
|
||||
}
|
||||
|
||||
json_object_put(json);
|
||||
|
||||
mtx_lock(&instance.mtx);
|
||||
tll_foreach(instance.subscribers, it)
|
||||
{
|
||||
if (it->item->events & events)
|
||||
if (write(it->item->fd, &(uint64_t){1}, sizeof(uint64_t)) == -1)
|
||||
LOG_ERRNO("failed to write");
|
||||
}
|
||||
mtx_unlock(&instance.mtx);
|
||||
}
|
||||
|
||||
static int
|
||||
run(void *userdata)
|
||||
{
|
||||
static char msg[] = "\"EventStream\"\n";
|
||||
static char expected[] = "{\"Ok\":\"Handled\"}";
|
||||
|
||||
if (write(instance.fd, msg, sizeof(msg) / sizeof(msg[0])) == -1) {
|
||||
LOG_ERRNO("failed to sent message to niri socket");
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
static char buffer[8192];
|
||||
if (read(instance.fd, buffer, sizeof(buffer) / sizeof(buffer[0]) - 1) == -1) {
|
||||
LOG_ERRNO("failed to read response of niri socket");
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
char *saveptr;
|
||||
char *response = strtok_r(buffer, "\n", &saveptr);
|
||||
if (response == NULL || strcmp(expected, response) != 0) {
|
||||
// unexpected first response, something went wrong
|
||||
LOG_ERR("unexpected response of niri socket");
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
while ((response = strtok_r(NULL, "\n", &saveptr)) != NULL)
|
||||
parser(response);
|
||||
|
||||
while (true) {
|
||||
struct pollfd fds[] = {
|
||||
(struct pollfd){.fd = instance.abort_fd, .events = POLLIN},
|
||||
(struct pollfd){.fd = instance.fd, .events = POLLIN},
|
||||
};
|
||||
|
||||
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
LOG_ERRNO("failed to poll");
|
||||
break;
|
||||
}
|
||||
|
||||
if (fds[0].revents & POLLIN)
|
||||
break;
|
||||
|
||||
static char buffer[8192];
|
||||
ssize_t length = read(fds[1].fd, buffer, sizeof(buffer) / sizeof(buffer[0]));
|
||||
|
||||
if (length == 0)
|
||||
break;
|
||||
|
||||
if (length == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
|
||||
LOG_ERRNO("unable to read niri socket");
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[length] = '\0';
|
||||
saveptr = NULL;
|
||||
response = strtok_r(buffer, "\n", &saveptr);
|
||||
do {
|
||||
parser(response);
|
||||
} while ((response = strtok_r(NULL, "\n", &saveptr)) != NULL);
|
||||
}
|
||||
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
struct niri_socket *
|
||||
niri_socket_open(char const *monitor)
|
||||
{
|
||||
if (instance.fd >= 0)
|
||||
return &instance;
|
||||
|
||||
char const *path = getenv("NIRI_SOCKET");
|
||||
if (path == NULL) {
|
||||
LOG_ERR("NIRI_SOCKET is empty. Is niri running?");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((instance.fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) {
|
||||
LOG_ERRNO("failed to create socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
|
||||
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
|
||||
|
||||
if (connect(instance.fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||
LOG_ERRNO("failed to connect to niri socket");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((instance.abort_fd = eventfd(0, EFD_CLOEXEC)) == -1) {
|
||||
LOG_ERRNO("failed to create abort_fd");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (mtx_init(&instance.mtx, mtx_plain) != thrd_success) {
|
||||
LOG_ERR("failed to initialize mutex");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (thrd_create(&instance.thrd, run, NULL) != thrd_success) {
|
||||
LOG_ERR("failed to create thread");
|
||||
mtx_destroy(&instance.mtx);
|
||||
goto error;
|
||||
}
|
||||
|
||||
instance.monitor = monitor;
|
||||
|
||||
return &instance;
|
||||
|
||||
error:
|
||||
if (instance.fd >= 0)
|
||||
close(instance.fd);
|
||||
if (instance.abort_fd >= 0)
|
||||
close(instance.abort_fd);
|
||||
instance.fd = -1;
|
||||
instance.abort_fd = -1;
|
||||
instance.monitor = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
socket_close(void)
|
||||
{
|
||||
if (write(instance.abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t))
|
||||
LOG_ERRNO("failed to write to abort_fd");
|
||||
|
||||
thrd_join(instance.thrd, NULL);
|
||||
|
||||
close(instance.abort_fd);
|
||||
close(instance.fd);
|
||||
instance.abort_fd = -1;
|
||||
instance.fd = -1;
|
||||
|
||||
mtx_destroy(&instance.mtx);
|
||||
|
||||
tll_free_and_free(instance.subscribers, free);
|
||||
tll_free_and_free(instance.workspaces, workspace_free);
|
||||
tll_free_and_free(instance.keyboard_layouts, free);
|
||||
}
|
||||
|
||||
void
|
||||
niri_socket_close(void)
|
||||
{
|
||||
static once_flag flag = ONCE_FLAG_INIT;
|
||||
call_once(&flag, socket_close);
|
||||
}
|
||||
|
||||
int
|
||||
niri_socket_subscribe(enum niri_event events)
|
||||
{
|
||||
int fd = eventfd(0, EFD_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
LOG_ERRNO("failed to create eventfd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct niri_subscriber *subscriber = calloc(1, sizeof(*subscriber));
|
||||
subscriber->events = events;
|
||||
subscriber->fd = fd;
|
||||
|
||||
mtx_lock(&instance.mtx);
|
||||
tll_push_back(instance.subscribers, subscriber);
|
||||
mtx_unlock(&instance.mtx);
|
||||
|
||||
return subscriber->fd;
|
||||
}
|
45
modules/niri-common.h
Normal file
45
modules/niri-common.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <threads.h>
|
||||
#include <tllist.h>
|
||||
|
||||
enum niri_event {
|
||||
workspaces_changed = (1 << 0),
|
||||
workspace_activated = (1 << 1),
|
||||
workspace_active_window_changed = (1 << 2),
|
||||
keyboard_layouts_changed = (1 << 3),
|
||||
keyboard_layouts_switched = (1 << 4),
|
||||
};
|
||||
|
||||
struct niri_subscriber {
|
||||
int events;
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct niri_workspace {
|
||||
int id;
|
||||
int idx;
|
||||
char *name;
|
||||
bool active;
|
||||
bool focused;
|
||||
bool empty;
|
||||
};
|
||||
|
||||
struct niri_socket {
|
||||
char const *monitor;
|
||||
int abort_fd;
|
||||
int fd;
|
||||
|
||||
tll(struct niri_subscriber *) subscribers;
|
||||
tll(struct niri_workspace *) workspaces;
|
||||
tll(char *) keyboard_layouts;
|
||||
size_t keyboard_layout_index;
|
||||
|
||||
thrd_t thrd;
|
||||
mtx_t mtx;
|
||||
};
|
||||
|
||||
struct niri_socket *niri_socket_open(char const *monitor);
|
||||
void niri_socket_close(void);
|
||||
int niri_socket_subscribe(enum niri_event events);
|
160
modules/niri-language.c
Normal file
160
modules/niri-language.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
#include <errno.h>
|
||||
#include <json-c/json.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LOG_MODULE "niri-language"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
#include "niri-common.h"
|
||||
|
||||
#include "../log.h"
|
||||
#include "../particles/dynlist.h"
|
||||
#include "../plugin.h"
|
||||
|
||||
struct private
|
||||
{
|
||||
struct particle *label;
|
||||
struct niri_socket *niri;
|
||||
};
|
||||
|
||||
static void
|
||||
destroy(struct module *module)
|
||||
{
|
||||
struct private *private = module->private;
|
||||
private->label->destroy(private->label);
|
||||
|
||||
free(private);
|
||||
|
||||
module_default_destroy(module);
|
||||
}
|
||||
|
||||
static const char *
|
||||
description(const struct module *module)
|
||||
{
|
||||
return "niri-lang";
|
||||
}
|
||||
|
||||
static struct exposable *
|
||||
content(struct module *module)
|
||||
{
|
||||
const struct private *private = module->private;
|
||||
|
||||
if (private->niri == NULL)
|
||||
return dynlist_exposable_new(&((struct exposable *){0}), 0, 0, 0);
|
||||
|
||||
mtx_lock(&module->lock);
|
||||
mtx_lock(&private->niri->mtx);
|
||||
|
||||
char *name = "???";
|
||||
size_t i = 0;
|
||||
tll_foreach(private->niri->keyboard_layouts, it)
|
||||
{
|
||||
if (i++ == private->niri->keyboard_layout_index)
|
||||
name = it->item;
|
||||
}
|
||||
|
||||
struct tag_set tags = {
|
||||
.tags = (struct tag *[]){tag_new_string(module, "language", name)},
|
||||
.count = 1,
|
||||
};
|
||||
|
||||
struct exposable *exposable = private->label->instantiate(private->label, &tags);
|
||||
tag_set_destroy(&tags);
|
||||
mtx_unlock(&private->niri->mtx);
|
||||
mtx_unlock(&module->lock);
|
||||
return exposable;
|
||||
}
|
||||
|
||||
static int
|
||||
run(struct module *module)
|
||||
{
|
||||
struct private *private = module->private;
|
||||
|
||||
/* Ugly, but I didn't find better way for waiting
|
||||
* the monitor's name to be set */
|
||||
char const *monitor;
|
||||
do {
|
||||
monitor = module->bar->output_name(module->bar);
|
||||
usleep(50);
|
||||
} while (monitor == NULL);
|
||||
|
||||
private->niri = niri_socket_open(monitor);
|
||||
if (private->niri == NULL)
|
||||
return 1;
|
||||
|
||||
int fd = niri_socket_subscribe(keyboard_layouts_changed | keyboard_layouts_switched);
|
||||
if (fd == -1) {
|
||||
niri_socket_close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
module->bar->refresh(module->bar);
|
||||
|
||||
while (true) {
|
||||
struct pollfd fds[] = {
|
||||
(struct pollfd){.fd = module->abort_fd, .events = POLLIN},
|
||||
(struct pollfd){.fd = fd, .events = POLLIN},
|
||||
};
|
||||
|
||||
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
LOG_ERRNO("failed to poll");
|
||||
break;
|
||||
}
|
||||
|
||||
if (fds[0].revents & POLLIN)
|
||||
break;
|
||||
|
||||
if (read(fds[1].fd, &(uint64_t){0}, sizeof(uint64_t)) == -1)
|
||||
LOG_ERRNO("failed to read from eventfd");
|
||||
|
||||
module->bar->refresh(module->bar);
|
||||
}
|
||||
|
||||
niri_socket_close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct module *
|
||||
niri_language_new(struct particle *label)
|
||||
{
|
||||
struct private *private = calloc(1, sizeof(struct private));
|
||||
private->label = label;
|
||||
|
||||
struct module *module = module_common_new();
|
||||
module->private = private;
|
||||
module->run = &run;
|
||||
module->destroy = &destroy;
|
||||
module->content = &content;
|
||||
module->description = &description;
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
static struct module *
|
||||
from_conf(struct yml_node const *node, struct conf_inherit inherited)
|
||||
{
|
||||
struct yml_node const *content = yml_get_value(node, "content");
|
||||
return niri_language_new(conf_to_particle(content, inherited));
|
||||
}
|
||||
|
||||
static bool
|
||||
verify_conf(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
static struct attr_info const attrs[] = {
|
||||
MODULE_COMMON_ATTRS,
|
||||
};
|
||||
return conf_verify_dict(chain, node, attrs);
|
||||
}
|
||||
|
||||
const struct module_iface module_niri_language_iface = {
|
||||
.verify_conf = &verify_conf,
|
||||
.from_conf = &from_conf,
|
||||
};
|
||||
|
||||
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
|
||||
extern const struct module_iface iface __attribute__((weak, alias("module_niri_language_iface")));
|
||||
#endif
|
163
modules/niri-workspaces.c
Normal file
163
modules/niri-workspaces.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define LOG_MODULE "niri-workspaces"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
#include "niri-common.h"
|
||||
|
||||
#include "../log.h"
|
||||
#include "../particles/dynlist.h"
|
||||
#include "../plugin.h"
|
||||
|
||||
struct private
|
||||
{
|
||||
struct particle *label;
|
||||
struct niri_socket *niri;
|
||||
};
|
||||
|
||||
static void
|
||||
destroy(struct module *module)
|
||||
{
|
||||
struct private *private = module->private;
|
||||
private->label->destroy(private->label);
|
||||
|
||||
free(private);
|
||||
|
||||
module_default_destroy(module);
|
||||
}
|
||||
|
||||
static const char *
|
||||
description(const struct module *module)
|
||||
{
|
||||
return "niri-ws";
|
||||
}
|
||||
|
||||
static struct exposable *
|
||||
content(struct module *module)
|
||||
{
|
||||
struct private const *private = module->private;
|
||||
|
||||
if (private->niri == NULL)
|
||||
return dynlist_exposable_new(&((struct exposable *){0}), 0, 0, 0);
|
||||
|
||||
mtx_lock(&module->lock);
|
||||
mtx_lock(&private->niri->mtx);
|
||||
|
||||
size_t i = 0;
|
||||
struct exposable *exposable[tll_length(private->niri->workspaces)];
|
||||
tll_foreach(private->niri->workspaces, it)
|
||||
{
|
||||
struct tag_set tags = {
|
||||
.tags = (struct tag*[]){
|
||||
tag_new_int(module, "id", it->item->idx),
|
||||
tag_new_string(module, "name", it->item->name),
|
||||
tag_new_bool(module, "active", it->item->active),
|
||||
tag_new_bool(module, "focused", it->item->focused),
|
||||
tag_new_bool(module, "empty", it->item->empty),
|
||||
},
|
||||
.count = 5,
|
||||
};
|
||||
|
||||
exposable[i++] = private->label->instantiate(private->label, &tags);
|
||||
tag_set_destroy(&tags);
|
||||
}
|
||||
|
||||
mtx_unlock(&private->niri->mtx);
|
||||
mtx_unlock(&module->lock);
|
||||
return dynlist_exposable_new(exposable, i, 0, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
run(struct module *module)
|
||||
{
|
||||
struct private *private = module->private;
|
||||
|
||||
/* Ugly, but I didn't find better way for waiting
|
||||
* the monitor's name to be set */
|
||||
char const *monitor;
|
||||
do {
|
||||
monitor = module->bar->output_name(module->bar);
|
||||
usleep(50);
|
||||
} while (monitor == NULL);
|
||||
|
||||
private->niri = niri_socket_open(monitor);
|
||||
if (private->niri == NULL)
|
||||
return 1;
|
||||
|
||||
int fd = niri_socket_subscribe(workspaces_changed | workspace_activated | workspace_active_window_changed);
|
||||
if (fd == -1) {
|
||||
niri_socket_close();
|
||||
return 1;
|
||||
}
|
||||
|
||||
module->bar->refresh(module->bar);
|
||||
|
||||
while (true) {
|
||||
struct pollfd fds[] = {
|
||||
(struct pollfd){.fd = module->abort_fd, .events = POLLIN},
|
||||
(struct pollfd){.fd = fd, .events = POLLIN},
|
||||
};
|
||||
|
||||
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
LOG_ERRNO("failed to poll");
|
||||
break;
|
||||
}
|
||||
|
||||
if (fds[0].revents & POLLIN)
|
||||
break;
|
||||
|
||||
if (read(fds[1].fd, &(uint64_t){0}, sizeof(uint64_t)) == -1)
|
||||
LOG_ERRNO("failed to read from eventfd");
|
||||
|
||||
module->bar->refresh(module->bar);
|
||||
}
|
||||
|
||||
niri_socket_close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct module *
|
||||
niri_workspaces_new(struct particle *label)
|
||||
{
|
||||
struct private *private = calloc(1, sizeof(struct private));
|
||||
private->label = label;
|
||||
|
||||
struct module *module = module_common_new();
|
||||
module->private = private;
|
||||
module->run = &run;
|
||||
module->destroy = &destroy;
|
||||
module->content = &content;
|
||||
module->description = &description;
|
||||
|
||||
return module;
|
||||
}
|
||||
|
||||
static struct module *
|
||||
from_conf(struct yml_node const *node, struct conf_inherit inherited)
|
||||
{
|
||||
struct yml_node const *content = yml_get_value(node, "content");
|
||||
return niri_workspaces_new(conf_to_particle(content, inherited));
|
||||
}
|
||||
|
||||
static bool
|
||||
verify_conf(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
static struct attr_info const attrs[] = {
|
||||
MODULE_COMMON_ATTRS,
|
||||
};
|
||||
return conf_verify_dict(chain, node, attrs);
|
||||
}
|
||||
|
||||
const struct module_iface module_niri_workspaces_iface = {
|
||||
.verify_conf = &verify_conf,
|
||||
.from_conf = &from_conf,
|
||||
};
|
||||
|
||||
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
|
||||
extern const struct module_iface iface __attribute__((weak, alias("module_niri_workspaces_iface")));
|
||||
#endif
|
|
@ -45,6 +45,16 @@ struct output_informations {
|
|||
};
|
||||
static struct output_informations const output_informations_null;
|
||||
|
||||
static void
|
||||
output_informations_destroy(struct output_informations *output_informations)
|
||||
{
|
||||
free(output_informations->name);
|
||||
free(output_informations->description);
|
||||
free(output_informations->icon);
|
||||
free(output_informations->form_factor);
|
||||
free(output_informations->bus);
|
||||
}
|
||||
|
||||
struct data;
|
||||
struct private
|
||||
{
|
||||
|
@ -213,18 +223,23 @@ node_find_route(struct data *data, bool is_sink)
|
|||
static void
|
||||
node_unhook_binded_node(struct data *data, bool is_sink)
|
||||
{
|
||||
struct private *private = data->module->private;
|
||||
|
||||
struct node **target_node = NULL;
|
||||
struct spa_hook *target_listener = NULL;
|
||||
void **target_proxy = NULL;
|
||||
struct output_informations *output_informations = NULL;
|
||||
|
||||
if (is_sink) {
|
||||
target_node = &data->binded_sink;
|
||||
target_listener = &data->node_sink_listener;
|
||||
target_proxy = &data->node_sink;
|
||||
output_informations = &private->sink_informations;
|
||||
} else {
|
||||
target_node = &data->binded_source;
|
||||
target_listener = &data->node_source_listener;
|
||||
target_proxy = &data->node_source;
|
||||
output_informations = &private->source_informations;
|
||||
}
|
||||
|
||||
if (*target_node == NULL)
|
||||
|
@ -235,6 +250,9 @@ node_unhook_binded_node(struct data *data, bool is_sink)
|
|||
|
||||
*target_node = NULL;
|
||||
*target_proxy = NULL;
|
||||
|
||||
output_informations_destroy(output_informations);
|
||||
*output_informations = output_informations_null;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -350,7 +368,7 @@ device_events_param(void *userdata, int seq, uint32_t id, uint32_t index, uint32
|
|||
if (binded_node == NULL)
|
||||
return;
|
||||
|
||||
/* Node's device is the the same as route's device */
|
||||
/* Node's device is the same as route's device */
|
||||
if (output_informations->device_id != route->device->id)
|
||||
return;
|
||||
|
||||
|
@ -398,18 +416,18 @@ node_events_info(void *userdata, struct pw_node_info const *info)
|
|||
struct spa_dict_item const *item = NULL;
|
||||
|
||||
item = spa_dict_lookup_item(info->props, "node.name");
|
||||
if (item != NULL)
|
||||
X_FREE_SET(output_informations->name, X_STRDUP(item->value));
|
||||
X_FREE_SET(output_informations->name, item != NULL ? X_STRDUP(item->value) : NULL);
|
||||
|
||||
item = spa_dict_lookup_item(info->props, "node.description");
|
||||
if (item != NULL)
|
||||
X_FREE_SET(output_informations->description, X_STRDUP(item->value));
|
||||
X_FREE_SET(output_informations->description, item != NULL ? X_STRDUP(item->value) : NULL);
|
||||
|
||||
item = spa_dict_lookup_item(info->props, "device.id");
|
||||
if (item != NULL) {
|
||||
uint32_t value = 0;
|
||||
spa_atou32(item->value, &value, 10);
|
||||
output_informations->device_id = value;
|
||||
} else {
|
||||
output_informations->device_id = 0;
|
||||
}
|
||||
|
||||
item = spa_dict_lookup_item(info->props, "card.profile.device");
|
||||
|
@ -417,30 +435,29 @@ node_events_info(void *userdata, struct pw_node_info const *info)
|
|||
uint32_t value = 0;
|
||||
spa_atou32(item->value, &value, 10);
|
||||
output_informations->card_profile_device_id = value;
|
||||
} else {
|
||||
output_informations->card_profile_device_id = 0;
|
||||
}
|
||||
|
||||
/* Device's information has an more important priority than node's information */
|
||||
/* icon_name */
|
||||
struct route *route = node_find_route(data, node_data->is_sink);
|
||||
if (route != NULL && route->icon_name != NULL)
|
||||
output_informations->icon = X_STRDUP(route->icon_name);
|
||||
X_FREE_SET(output_informations->icon, X_STRDUP(route->icon_name));
|
||||
else {
|
||||
item = spa_dict_lookup_item(info->props, "device.icon-name");
|
||||
if (item != NULL)
|
||||
X_FREE_SET(output_informations->icon, X_STRDUP(item->value));
|
||||
X_FREE_SET(output_informations->icon, item != NULL ? X_STRDUP(item->value) : NULL);
|
||||
}
|
||||
/* form_factor */
|
||||
if (route != NULL && route->form_factor != NULL)
|
||||
output_informations->form_factor = X_STRDUP(route->form_factor);
|
||||
X_FREE_SET(output_informations->form_factor, X_STRDUP(route->form_factor));
|
||||
else {
|
||||
item = spa_dict_lookup_item(info->props, "device.form-factor");
|
||||
if (item != NULL)
|
||||
X_FREE_SET(output_informations->form_factor, X_STRDUP(item->value));
|
||||
X_FREE_SET(output_informations->form_factor, item != NULL ? X_STRDUP(item->value) : NULL);
|
||||
}
|
||||
|
||||
item = spa_dict_lookup_item(info->props, "device.bus");
|
||||
if (item != NULL)
|
||||
X_FREE_SET(output_informations->bus, X_STRDUP(item->value));
|
||||
X_FREE_SET(output_informations->bus, item != NULL ? X_STRDUP(item->value) : NULL);
|
||||
|
||||
data->module->bar->refresh(data->module->bar);
|
||||
}
|
||||
|
@ -827,18 +844,8 @@ destroy(struct module *module)
|
|||
pipewire_deinit(private->data);
|
||||
private->label->destroy(private->label);
|
||||
|
||||
/* sink */
|
||||
free(private->sink_informations.name);
|
||||
free(private->sink_informations.description);
|
||||
free(private->sink_informations.icon);
|
||||
free(private->sink_informations.form_factor);
|
||||
free(private->sink_informations.bus);
|
||||
/* source */
|
||||
free(private->source_informations.name);
|
||||
free(private->source_informations.description);
|
||||
free(private->source_informations.icon);
|
||||
free(private->source_informations.form_factor);
|
||||
free(private->source_informations.bus);
|
||||
output_informations_destroy(&private->sink_informations);
|
||||
output_informations_destroy(&private->source_informations);
|
||||
|
||||
free(private);
|
||||
module_default_destroy(module);
|
||||
|
|
|
@ -438,7 +438,7 @@ run(struct module *mod)
|
|||
}
|
||||
|
||||
// Create refresh timer.
|
||||
priv->refresh_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||
priv->refresh_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||
if (priv->refresh_timer_fd < 0) {
|
||||
LOG_ERRNO("failed to create timerfd");
|
||||
pa_mainloop_free(priv->mainloop);
|
||||
|
|
|
@ -161,13 +161,10 @@ content(struct module *mod)
|
|||
static void
|
||||
find_mount_points(const char *dev_path, mount_point_list_t *mount_points)
|
||||
{
|
||||
int fd = open("/proc/self/mountinfo", O_RDONLY | O_CLOEXEC);
|
||||
FILE *f = fd >= 0 ? fdopen(fd, "r") : NULL;
|
||||
FILE *f = fopen("/proc/self/mountinfo", "re");
|
||||
|
||||
if (fd < 0 || f == NULL) {
|
||||
if (f == NULL) {
|
||||
LOG_ERRNO("failed to open /proc/self/mountinfo");
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ update_application(struct module *mod)
|
|||
char path[1024];
|
||||
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
int fd = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1)
|
||||
return;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue