Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for config file #75

Merged
merged 8 commits into from
Mar 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .builds/alpine.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ packages:
- pipewire-dev
- wayland-dev
- wayland-protocols
- iniparser-dev
sources:
- https://github.com/emersion/xdg-desktop-portal-wlr
tasks:
Expand Down
1 change: 1 addition & 0 deletions .builds/archlinux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ packages:
- wayland
- wayland-protocols
- pipewire
- iniparser
sources:
- https://github.com/emersion/xdg-desktop-portal-wlr
tasks:
Expand Down
1 change: 1 addition & 0 deletions .builds/freebsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ packages:
- pkgconf
- wayland
- wayland-protocols
- iniparser
sources:
- https://github.com/emersion/xdg-desktop-portal-wlr
tasks:
Expand Down
2 changes: 2 additions & 0 deletions contrib/config.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[screencast]
output=
18 changes: 18 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions include/logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <stdio.h>

#define DEFAULT_LOGLEVEL ERROR

enum LOGLEVEL { QUIET, ERROR, WARN, INFO, DEBUG, TRACE };

struct logger_properties {
Expand Down
3 changes: 0 additions & 3 deletions include/screencast_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ struct xdpw_screencast_context {
struct zxdg_output_manager_v1* xdg_output_manager;
struct wl_shm *shm;

// cli options
const char *output_name;

// sessions
struct wl_list screencast_instances;
};
Expand Down
4 changes: 3 additions & 1 deletion include/xdpw.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#endif

#include "screencast_common.h"
#include "config.h"

struct xdpw_state {
struct wl_list xdpw_sessions;
Expand All @@ -21,6 +22,7 @@ struct xdpw_state {
uint32_t screencast_source_types; // bitfield of enum source_types
uint32_t screencast_cursor_modes; // bitfield of enum cursor_modes
uint32_t screencast_version;
struct xdpw_config *config;
};

struct xdpw_request {
Expand All @@ -41,7 +43,7 @@ enum {
};

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);
void xdpw_request_destroy(struct xdpw_request *req);
Expand Down
7 changes: 7 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,17 @@ add_project_arguments(cc.get_supported_arguments([
'-D_POSIX_C_SOURCE=200809L',
]), 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')

rt = cc.find_library('rt')
pipewire = dependency('libpipewire-0.3', version: '>= 0.3.2')
wayland_client = dependency('wayland-client')
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'
assert(get_option('auto_features').auto(), 'sd-bus-provider must not be set to auto since auto_features != auto')
Expand Down Expand Up @@ -59,6 +64,7 @@ executable(
files([
'src/core/main.c',
'src/core/logger.c',
'src/core/config.c',
'src/core/request.c',
'src/core/session.c',
'src/screenshot/screenshot.c',
Expand All @@ -73,6 +79,7 @@ executable(
sdbus,
pipewire,
rt,
iniparser,
],
include_directories: [inc],
install: true,
Expand Down
118 changes: 118 additions & 0 deletions src/core/config.c
Original file line number Diff line number Diff line change
@@ -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);
}
50 changes: 33 additions & 17 deletions src/core/logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,6 @@
#include <string.h>
#include <time.h>

static int NUM_LEVELS = 6;

static const char *loglevels[] = {
"QUIET",
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE"
};

static struct logger_properties logprops;

void init_logger(FILE *dst, enum LOGLEVEL level) {
Expand All @@ -24,16 +13,43 @@ void init_logger(FILE *dst, enum LOGLEVEL level) {
}

enum LOGLEVEL get_loglevel(const char *level) {
int i;
for (i = 0; i < NUM_LEVELS; i++) {
if (!strcmp(level, loglevels[i])) {
return (enum LOGLEVEL) i;
}
if (strcmp(level, "QUIET") == 0) {
return QUIET;
} else if (strcmp(level, "ERROR") == 0) {
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);
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, ...) {
if (!logprops.dst) {
fprintf(stderr, "Logger has been called, but was not initialized\n");
Expand All @@ -56,7 +72,7 @@ void logprint(enum LOGLEVEL level, char *msg, ...) {

fprintf(logprops.dst, "%s", timestr);
fprintf(logprops.dst, " ");
fprintf(logprops.dst, "[%s]", loglevels[level]);
fprintf(logprops.dst, "[%s]", print_loglevel(level));
fprintf(logprops.dst, " - ");

va_start(args, msg);
Expand Down
21 changes: 16 additions & 5 deletions src/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ static int xdpw_usage(FILE* stream, int rc) {
" QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n"
" -o, --output=<name> Select output to capture.\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"
" -h, --help Get help (this text).\n"
"\n";
Expand All @@ -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[]) {
const char* output_name = NULL;
enum LOGLEVEL loglevel = ERROR;
struct xdpw_config config = {0};
char *configfile = NULL;
enum LOGLEVEL loglevel = DEFAULT_LOGLEVEL;
bool replace = false;

static const char* shortopts = "l:o:rh";
static const char* shortopts = "l:o:c:rh";
static const struct option longopts[] = {
{ "loglevel", required_argument, NULL, 'l' },
{ "output", required_argument, NULL, 'o' },
{ "config", required_argument, NULL, 'c' },
{ "replace", no_argument, NULL, 'r' },
{ "help", no_argument, NULL, 'h' },
{ NULL, 0, NULL, 0 }
Expand All @@ -62,7 +66,10 @@ int main(int argc, char *argv[]) {
loglevel = get_loglevel(optarg);
break;
case 'o':
output_name = optarg;
config.screencast_conf.output_name = strdup(optarg);
break;
case 'c':
configfile = strdup(optarg);
break;
case 'r':
replace = true;
Expand All @@ -75,6 +82,7 @@ int main(int argc, char *argv[]) {
}

init_logger(stderr, loglevel);
init_config(&configfile, &config);

int ret = 0;

Expand Down Expand Up @@ -111,12 +119,13 @@ int main(int argc, char *argv[]) {
.screencast_source_types = MONITOR,
.screencast_cursor_modes = HIDDEN | EMBEDDED,
.screencast_version = XDP_CAST_PROTO_VER,
.config = &config,
};

wl_list_init(&state.xdpw_sessions);

xdpw_screenshot_init(&state);
ret = xdpw_screencast_init(&state, output_name);
ret = xdpw_screencast_init(&state);
if (ret < 0) {
logprint(ERROR, "xdpw: failed to initialize screencast");
goto error;
Expand Down Expand Up @@ -217,6 +226,8 @@ int main(int argc, char *argv[]) {
}

// TODO: cleanup
finish_config(&config);
free(configfile);

return EXIT_SUCCESS;

Expand Down
Loading