mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-26 07:55:58 +01:00
Add support for config file
Closes: https://github.com/emersion/xdg-desktop-portal-wlr/issues/60
This commit is contained in:
parent
e103e120e2
commit
07154bb1e3
13 changed files with 206 additions and 30 deletions
|
@ -6,6 +6,7 @@ packages:
|
||||||
- pipewire-dev
|
- pipewire-dev
|
||||||
- wayland-dev
|
- wayland-dev
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
|
- iniparser-dev
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/emersion/xdg-desktop-portal-wlr
|
- https://github.com/emersion/xdg-desktop-portal-wlr
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
@ -6,6 +6,7 @@ packages:
|
||||||
- wayland
|
- wayland
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- pipewire
|
- pipewire
|
||||||
|
- iniparser
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/emersion/xdg-desktop-portal-wlr
|
- https://github.com/emersion/xdg-desktop-portal-wlr
|
||||||
tasks:
|
tasks:
|
||||||
|
|
|
@ -6,6 +6,7 @@ packages:
|
||||||
- pkgconf
|
- pkgconf
|
||||||
- wayland
|
- wayland
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
|
- iniparser
|
||||||
sources:
|
sources:
|
||||||
- https://github.com/emersion/xdg-desktop-portal-wlr
|
- https://github.com/emersion/xdg-desktop-portal-wlr
|
||||||
tasks:
|
tasks:
|
||||||
|
|
2
contrib/config.sample
Normal file
2
contrib/config.sample
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
[screencast]
|
||||||
|
output=
|
18
include/config.h
Normal file
18
include/config.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
struct config_screencast {
|
||||||
|
char *output_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct xdpw_config {
|
||||||
|
struct config_screencast screencast_conf;
|
||||||
|
};
|
||||||
|
|
||||||
|
void print_config(enum LOGLEVEL loglevel, struct xdpw_config *config);
|
||||||
|
void finish_config(struct xdpw_config *config);
|
||||||
|
void init_config(char ** const configfile, struct xdpw_config *config);
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define DEFAULT_LOGLEVEL ERROR
|
||||||
|
|
||||||
enum LOGLEVEL { QUIET, ERROR, WARN, INFO, DEBUG, TRACE };
|
enum LOGLEVEL { QUIET, ERROR, WARN, INFO, DEBUG, TRACE };
|
||||||
|
|
||||||
struct logger_properties {
|
struct logger_properties {
|
||||||
|
|
|
@ -57,9 +57,6 @@ struct xdpw_screencast_context {
|
||||||
struct zxdg_output_manager_v1* xdg_output_manager;
|
struct zxdg_output_manager_v1* xdg_output_manager;
|
||||||
struct wl_shm *shm;
|
struct wl_shm *shm;
|
||||||
|
|
||||||
// cli options
|
|
||||||
const char *output_name;
|
|
||||||
|
|
||||||
// sessions
|
// sessions
|
||||||
struct wl_list screencast_instances;
|
struct wl_list screencast_instances;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "screencast_common.h"
|
#include "screencast_common.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
struct xdpw_state {
|
struct xdpw_state {
|
||||||
struct wl_list xdpw_sessions;
|
struct wl_list xdpw_sessions;
|
||||||
|
@ -21,6 +22,7 @@ struct xdpw_state {
|
||||||
uint32_t screencast_source_types; // bitfield of enum source_types
|
uint32_t screencast_source_types; // bitfield of enum source_types
|
||||||
uint32_t screencast_cursor_modes; // bitfield of enum cursor_modes
|
uint32_t screencast_cursor_modes; // bitfield of enum cursor_modes
|
||||||
uint32_t screencast_version;
|
uint32_t screencast_version;
|
||||||
|
struct xdpw_config *config;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xdpw_request {
|
struct xdpw_request {
|
||||||
|
@ -41,7 +43,7 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
int xdpw_screenshot_init(struct xdpw_state *state);
|
int xdpw_screenshot_init(struct xdpw_state *state);
|
||||||
int xdpw_screencast_init(struct xdpw_state *state, const char *output_name);
|
int xdpw_screencast_init(struct xdpw_state *state);
|
||||||
|
|
||||||
struct xdpw_request *xdpw_request_create(sd_bus *bus, const char *object_path);
|
struct xdpw_request *xdpw_request_create(sd_bus *bus, const char *object_path);
|
||||||
void xdpw_request_destroy(struct xdpw_request *req);
|
void xdpw_request_destroy(struct xdpw_request *req);
|
||||||
|
|
|
@ -16,12 +16,17 @@ add_project_arguments(cc.get_supported_arguments([
|
||||||
'-D_POSIX_C_SOURCE=200809L',
|
'-D_POSIX_C_SOURCE=200809L',
|
||||||
]), language: 'c')
|
]), language: 'c')
|
||||||
|
|
||||||
|
prefix = get_option('prefix')
|
||||||
|
sysconfdir = get_option('sysconfdir')
|
||||||
|
add_project_arguments('-DSYSCONFDIR="@0@"'.format(join_paths(prefix, sysconfdir)), language : 'c')
|
||||||
|
|
||||||
inc = include_directories('include')
|
inc = include_directories('include')
|
||||||
|
|
||||||
rt = cc.find_library('rt')
|
rt = cc.find_library('rt')
|
||||||
pipewire = dependency('libpipewire-0.3', version: '>= 0.3.2')
|
pipewire = dependency('libpipewire-0.3', version: '>= 0.3.2')
|
||||||
wayland_client = dependency('wayland-client')
|
wayland_client = dependency('wayland-client')
|
||||||
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
|
wayland_protos = dependency('wayland-protocols', version: '>=1.14')
|
||||||
|
iniparser = cc.find_library('iniparser', dirs: [join_paths(get_option('prefix'),get_option('libdir'))])
|
||||||
|
|
||||||
if get_option('sd-bus-provider') == 'auto'
|
if get_option('sd-bus-provider') == 'auto'
|
||||||
assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto')
|
assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto')
|
||||||
|
@ -55,6 +60,7 @@ executable(
|
||||||
files([
|
files([
|
||||||
'src/core/main.c',
|
'src/core/main.c',
|
||||||
'src/core/logger.c',
|
'src/core/logger.c',
|
||||||
|
'src/core/config.c',
|
||||||
'src/core/request.c',
|
'src/core/request.c',
|
||||||
'src/core/session.c',
|
'src/core/session.c',
|
||||||
'src/screenshot/screenshot.c',
|
'src/screenshot/screenshot.c',
|
||||||
|
@ -69,6 +75,7 @@ executable(
|
||||||
sdbus,
|
sdbus,
|
||||||
pipewire,
|
pipewire,
|
||||||
rt,
|
rt,
|
||||||
|
iniparser,
|
||||||
],
|
],
|
||||||
include_directories: [inc],
|
include_directories: [inc],
|
||||||
install: true,
|
install: true,
|
||||||
|
|
118
src/core/config.c
Normal file
118
src/core/config.c
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
#include "config.h"
|
||||||
|
#include "xdpw.h"
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
#include <dictionary.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <iniparser.h>
|
||||||
|
|
||||||
|
void print_config(enum LOGLEVEL loglevel, struct xdpw_config *config) {
|
||||||
|
logprint(loglevel, "config: outputname %s", config->screencast_conf.output_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: calling finish_config won't prepare the config to be read again from config file
|
||||||
|
// with init_config since to pointers and other values won't be reset to NULL, or 0
|
||||||
|
void finish_config(struct xdpw_config *config) {
|
||||||
|
logprint(DEBUG, "config: destroying config");
|
||||||
|
|
||||||
|
// screencast
|
||||||
|
free(&config->screencast_conf.output_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getstring_from_conffile(dictionary *d,
|
||||||
|
const char *key, char **dest, const char *fallback) {
|
||||||
|
if (*dest != NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *c = iniparser_getstring(d, key, fallback);
|
||||||
|
if (c == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Allow keys without value as default
|
||||||
|
if (strcmp(c, "") != 0) {
|
||||||
|
*dest = strdup(c);
|
||||||
|
} else {
|
||||||
|
*dest = fallback ? strdup(fallback) : NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool file_exists(const char *path) {
|
||||||
|
return path && access(path, R_OK) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *config_path(char *prefix, char *filename) {
|
||||||
|
if (!prefix || !prefix[0] || !filename || !filename[0]) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *config_folder = "xdg-desktop-portal-wlr";
|
||||||
|
|
||||||
|
size_t size = 3 + strlen(prefix) + strlen(config_folder) + strlen(filename);
|
||||||
|
char *path = calloc(size, sizeof(char));
|
||||||
|
snprintf(path, size, "%s/%s/%s", prefix, config_folder, filename);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void config_parse_file(const char *configfile, struct xdpw_config *config) {
|
||||||
|
dictionary *d = NULL;
|
||||||
|
if (configfile) {
|
||||||
|
logprint(INFO, "config: using config file %s", *configfile);
|
||||||
|
d = iniparser_load(configfile);
|
||||||
|
} else {
|
||||||
|
logprint(INFO, "config: no config file found");
|
||||||
|
}
|
||||||
|
if (configfile && !d) {
|
||||||
|
logprint(ERROR, "config: unable to load config file %s", configfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// screencast
|
||||||
|
getstring_from_conffile(d, "screencast:output_name", &config->screencast_conf.output_name, NULL);
|
||||||
|
|
||||||
|
iniparser_freedict(d);
|
||||||
|
logprint(DEBUG, "config: config file parsed");
|
||||||
|
print_config(DEBUG, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *get_config_path(void) {
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
size_t size_fallback = 1 + strlen(home) + strlen("/.config");
|
||||||
|
char *config_home_fallback = calloc(size_fallback, sizeof(char));
|
||||||
|
snprintf(config_home_fallback, size_fallback, "%s/.config", home);
|
||||||
|
|
||||||
|
char *prefix[4];
|
||||||
|
prefix[0] = getenv("XDG_CONFIG_HOME");
|
||||||
|
prefix[1] = config_home_fallback;
|
||||||
|
prefix[2] = SYSCONFDIR "/xdg";
|
||||||
|
prefix[3] = SYSCONFDIR;
|
||||||
|
|
||||||
|
char *config[2];
|
||||||
|
config[0] = getenv("XDG_CURRENT_DESKTOP");
|
||||||
|
config[1] = "config";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
for (size_t j = 0; j < 2; j++) {
|
||||||
|
char *path = config_path(prefix[i], config[j]);
|
||||||
|
if (!path) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
logprint(TRACE, "config: trying config file %s", path);
|
||||||
|
if (file_exists(path)) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_config(char ** const configfile, struct xdpw_config *config) {
|
||||||
|
if (*configfile == NULL) {
|
||||||
|
*configfile = get_config_path();
|
||||||
|
}
|
||||||
|
|
||||||
|
config_parse_file(*configfile, config);
|
||||||
|
}
|
|
@ -5,17 +5,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
static int NUM_LEVELS = 6;
|
|
||||||
|
|
||||||
static const char *loglevels[] = {
|
|
||||||
"QUIET",
|
|
||||||
"ERROR",
|
|
||||||
"WARN",
|
|
||||||
"INFO",
|
|
||||||
"DEBUG",
|
|
||||||
"TRACE"
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct logger_properties logprops;
|
static struct logger_properties logprops;
|
||||||
|
|
||||||
void init_logger(FILE *dst, enum LOGLEVEL level) {
|
void init_logger(FILE *dst, enum LOGLEVEL level) {
|
||||||
|
@ -24,16 +13,43 @@ void init_logger(FILE *dst, enum LOGLEVEL level) {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum LOGLEVEL get_loglevel(const char *level) {
|
enum LOGLEVEL get_loglevel(const char *level) {
|
||||||
int i;
|
if (strcmp(level, "QUIET") == 0) {
|
||||||
for (i = 0; i < NUM_LEVELS; i++) {
|
return QUIET;
|
||||||
if (!strcmp(level, loglevels[i])) {
|
} else if (strcmp(level, "ERROR") == 0) {
|
||||||
return (enum LOGLEVEL) i;
|
return ERROR;
|
||||||
}
|
} else if (strcmp(level, "WARN") == 0) {
|
||||||
|
return WARN;
|
||||||
|
} else if (strcmp(level, "INFO") == 0) {
|
||||||
|
return INFO;
|
||||||
|
} else if (strcmp(level, "DEBUG") == 0) {
|
||||||
|
return DEBUG;
|
||||||
|
} else if (strcmp(level, "TRACE") == 0) {
|
||||||
|
return TRACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "Could not understand log level %s\n", level);
|
fprintf(stderr, "Could not understand log level %s\n", level);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *print_loglevel(enum LOGLEVEL loglevel) {
|
||||||
|
switch (loglevel) {
|
||||||
|
case QUIET:
|
||||||
|
return "QUIET";
|
||||||
|
case ERROR:
|
||||||
|
return "ERROR";
|
||||||
|
case WARN:
|
||||||
|
return "WARN";
|
||||||
|
case INFO:
|
||||||
|
return "INFO";
|
||||||
|
case DEBUG:
|
||||||
|
return "DEBUG";
|
||||||
|
case TRACE:
|
||||||
|
return "TRACE";
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Could not find log level %d\n", loglevel);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
void logprint(enum LOGLEVEL level, char *msg, ...) {
|
void logprint(enum LOGLEVEL level, char *msg, ...) {
|
||||||
if (!logprops.dst) {
|
if (!logprops.dst) {
|
||||||
fprintf(stderr, "Logger has been called, but was not initialized\n");
|
fprintf(stderr, "Logger has been called, but was not initialized\n");
|
||||||
|
@ -56,7 +72,7 @@ void logprint(enum LOGLEVEL level, char *msg, ...) {
|
||||||
|
|
||||||
fprintf(logprops.dst, "%s", timestr);
|
fprintf(logprops.dst, "%s", timestr);
|
||||||
fprintf(logprops.dst, " ");
|
fprintf(logprops.dst, " ");
|
||||||
fprintf(logprops.dst, "[%s]", loglevels[level]);
|
fprintf(logprops.dst, "[%s]", print_loglevel(level));
|
||||||
fprintf(logprops.dst, " - ");
|
fprintf(logprops.dst, " - ");
|
||||||
|
|
||||||
va_start(args, msg);
|
va_start(args, msg);
|
||||||
|
|
|
@ -24,6 +24,8 @@ static int xdpw_usage(FILE* stream, int rc) {
|
||||||
" QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n"
|
" QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n"
|
||||||
" -o, --output=<name> Select output to capture.\n"
|
" -o, --output=<name> Select output to capture.\n"
|
||||||
" metadata (performs no conversion).\n"
|
" metadata (performs no conversion).\n"
|
||||||
|
" -c, --config=<config file> Select config file.\n"
|
||||||
|
" (default is $XDG_CONFIG_HOME/xdg-desktop-portal-wlr/config)\n"
|
||||||
" -r, --replace Replace a running instance.\n"
|
" -r, --replace Replace a running instance.\n"
|
||||||
" -h, --help Get help (this text).\n"
|
" -h, --help Get help (this text).\n"
|
||||||
"\n";
|
"\n";
|
||||||
|
@ -39,14 +41,16 @@ static int handle_name_lost(sd_bus_message *m, void *userdata, sd_bus_error *ret
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
const char* output_name = NULL;
|
struct xdpw_config config = {0};
|
||||||
enum LOGLEVEL loglevel = ERROR;
|
char *configfile = NULL;
|
||||||
|
enum LOGLEVEL loglevel = DEFAULT_LOGLEVEL;
|
||||||
bool replace = false;
|
bool replace = false;
|
||||||
|
|
||||||
static const char* shortopts = "l:o:rh";
|
static const char* shortopts = "l:o:c:rh";
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
{ "loglevel", required_argument, NULL, 'l' },
|
{ "loglevel", required_argument, NULL, 'l' },
|
||||||
{ "output", required_argument, NULL, 'o' },
|
{ "output", required_argument, NULL, 'o' },
|
||||||
|
{ "config", required_argument, NULL, 'c' },
|
||||||
{ "replace", no_argument, NULL, 'r' },
|
{ "replace", no_argument, NULL, 'r' },
|
||||||
{ "help", no_argument, NULL, 'h' },
|
{ "help", no_argument, NULL, 'h' },
|
||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
|
@ -62,7 +66,10 @@ int main(int argc, char *argv[]) {
|
||||||
loglevel = get_loglevel(optarg);
|
loglevel = get_loglevel(optarg);
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
output_name = optarg;
|
config.screencast_conf.output_name = strdup(optarg);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
configfile = strdup(optarg);
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
replace = true;
|
replace = true;
|
||||||
|
@ -75,6 +82,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
init_logger(stderr, loglevel);
|
init_logger(stderr, loglevel);
|
||||||
|
init_config(&configfile, &config);
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
@ -111,12 +119,13 @@ int main(int argc, char *argv[]) {
|
||||||
.screencast_source_types = MONITOR,
|
.screencast_source_types = MONITOR,
|
||||||
.screencast_cursor_modes = HIDDEN | EMBEDDED,
|
.screencast_cursor_modes = HIDDEN | EMBEDDED,
|
||||||
.screencast_version = XDP_CAST_PROTO_VER,
|
.screencast_version = XDP_CAST_PROTO_VER,
|
||||||
|
.config = &config,
|
||||||
};
|
};
|
||||||
|
|
||||||
wl_list_init(&state.xdpw_sessions);
|
wl_list_init(&state.xdpw_sessions);
|
||||||
|
|
||||||
xdpw_screenshot_init(&state);
|
xdpw_screenshot_init(&state);
|
||||||
ret = xdpw_screencast_init(&state, output_name);
|
ret = xdpw_screencast_init(&state);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
logprint(ERROR, "xdpw: failed to initialize screencast");
|
logprint(ERROR, "xdpw: failed to initialize screencast");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -217,6 +226,8 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: cleanup
|
// TODO: cleanup
|
||||||
|
finish_config(&config);
|
||||||
|
free(configfile);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,9 @@ int setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess
|
||||||
}
|
}
|
||||||
|
|
||||||
struct xdpw_wlr_output *out;
|
struct xdpw_wlr_output *out;
|
||||||
if (ctx->output_name) {
|
if (ctx->state->config->screencast_conf.output_name) {
|
||||||
out = xdpw_wlr_output_find_by_name(&ctx->output_list, ctx->output_name);
|
out = xdpw_wlr_output_find_by_name(&ctx->output_list,
|
||||||
|
ctx->state->config->screencast_conf.output_name);
|
||||||
if (!out) {
|
if (!out) {
|
||||||
logprint(ERROR, "wlroots: no such output");
|
logprint(ERROR, "wlroots: no such output");
|
||||||
abort();
|
abort();
|
||||||
|
@ -434,12 +435,11 @@ static const sd_bus_vtable screencast_vtable[] = {
|
||||||
SD_BUS_VTABLE_END
|
SD_BUS_VTABLE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
int xdpw_screencast_init(struct xdpw_state *state, const char *output_name) {
|
int xdpw_screencast_init(struct xdpw_state *state) {
|
||||||
sd_bus_slot *slot = NULL;
|
sd_bus_slot *slot = NULL;
|
||||||
|
|
||||||
state->screencast = (struct xdpw_screencast_context) { 0 };
|
state->screencast = (struct xdpw_screencast_context) { 0 };
|
||||||
state->screencast.state = state;
|
state->screencast.state = state;
|
||||||
state->screencast.output_name = output_name;
|
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
err = xdpw_pwr_core_connect(state);
|
err = xdpw_pwr_core_connect(state);
|
||||||
|
|
Loading…
Reference in a new issue