Skip to content

Commit

Permalink
Add support for config file
Browse files Browse the repository at this point in the history
Closes: #60
  • Loading branch information
columbarius authored Mar 3, 2021
1 parent e103e12 commit 07154bb
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 30 deletions.
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 @@ -16,12 +16,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 @@ -55,6 +60,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 @@ -69,6 +75,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

0 comments on commit 07154bb

Please sign in to comment.