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 graphical display chooser #59

Merged
merged 3 commits into from
Apr 2, 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
2 changes: 2 additions & 0 deletions contrib/config.sample
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[screencast]
output_name=
max_fps=30
chooser_cmd="slurp -f %o -o"
chooser_type=simple
3 changes: 3 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
#define CONFIG_H

#include "logger.h"
#include "screencast_common.h"

struct config_screencast {
char *output_name;
double max_fps;
char *exec_before;
char *exec_after;
char *chooser_cmd;
enum xdpw_chooser_types chooser_type;
};

struct xdpw_config {
Expand Down
14 changes: 14 additions & 0 deletions include/screencast_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ enum source_types {
WINDOW = 2,
};

enum xdpw_chooser_types {
XDPW_CHOOSER_DEFAULT,
XDPW_CHOOSER_NONE,
XDPW_CHOOSER_SIMPLE,
XDPW_CHOOSER_DMENU,
};

struct xdpw_output_chooser {
enum xdpw_chooser_types type;
char *cmd;
};

struct xdpw_frame_damage {
uint32_t x;
uint32_t y;
Expand Down Expand Up @@ -113,4 +125,6 @@ enum spa_video_format xdpw_format_pw_from_wl_shm(
struct xdpw_screencast_instance *cast);
enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format);

enum xdpw_chooser_types get_chooser_type(const char *chooser_type);
const char *chooser_type_str(enum xdpw_chooser_types chooser_type);
#endif /* SCREENCAST_COMMON_H */
1 change: 1 addition & 0 deletions include/wlr_screencast.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct xdpw_wlr_output *xdpw_wlr_output_find_by_name(struct wl_list *output_list
struct xdpw_wlr_output *xdpw_wlr_output_first(struct wl_list *output_list);
struct xdpw_wlr_output *xdpw_wlr_output_find(struct xdpw_screencast_context *ctx,
struct wl_output *out, uint32_t id);
struct xdpw_wlr_output *xdpw_wlr_output_chooser(struct xdpw_screencast_context *ctx);

void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast);
void xdpw_wlr_register_cb(struct xdpw_screencast_instance *cast);
Expand Down
37 changes: 24 additions & 13 deletions src/core/config.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "config.h"
#include "xdpw.h"
#include "logger.h"
#include "screencast_common.h"

#include <dictionary.h>
#include <stdio.h>
Expand All @@ -11,6 +12,8 @@

void print_config(enum LOGLEVEL loglevel, struct xdpw_config *config) {
logprint(loglevel, "config: outputname %s", config->screencast_conf.output_name);
logprint(loglevel, "config: chooser_cmd: %s\n", config->screencast_conf.chooser_cmd);
logprint(loglevel, "config: chooser_type: %s\n", chooser_type_str(config->screencast_conf.chooser_type));
}

// NOTE: calling finish_config won't prepare the config to be read again from config file
Expand All @@ -22,6 +25,7 @@ void finish_config(struct xdpw_config *config) {
free(&config->screencast_conf.output_name);
free(&config->screencast_conf.exec_before);
free(&config->screencast_conf.exec_after);
free(&config->screencast_conf.chooser_cmd);
}

static void getstring_from_conffile(dictionary *d,
Expand Down Expand Up @@ -53,19 +57,6 @@ static bool file_exists(const char *path) {
return path && access(path, R_OK) != -1;
}

static char *config_path(const char *prefix, const 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) {
Expand All @@ -83,12 +74,32 @@ static void config_parse_file(const char *configfile, struct xdpw_config *config
getdouble_from_conffile(d, "screencast:max_fps", &config->screencast_conf.max_fps, 0);
getstring_from_conffile(d, "screencast:exec_before", &config->screencast_conf.exec_before, NULL);
getstring_from_conffile(d, "screencast:exec_after", &config->screencast_conf.exec_after, NULL);
getstring_from_conffile(d, "screencast:chooser_cmd", &config->screencast_conf.chooser_cmd, NULL);
if (!config->screencast_conf.chooser_type) {
char *chooser_type = NULL;
getstring_from_conffile(d, "screencast:chooser_type", &chooser_type, "default");
config->screencast_conf.chooser_type = get_chooser_type(chooser_type);
free(chooser_type);
}

iniparser_freedict(d);
logprint(DEBUG, "config: config file parsed");
print_config(DEBUG, config);
}

static char *config_path(const char *prefix, const 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 char *get_config_path(void) {
const char *home = getenv("HOME");
size_t size_fallback = 1 + strlen(home) + strlen("/.config");
Expand Down
2 changes: 1 addition & 1 deletion src/core/logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ enum LOGLEVEL get_loglevel(const char *level) {
}

fprintf(stderr, "Could not understand log level %s\n", level);
abort();
exit(1);
}

static const char *print_loglevel(enum LOGLEVEL loglevel) {
Expand Down
1 change: 1 addition & 0 deletions src/core/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ int main(int argc, char *argv[]) {
break;
case 'o':
config.screencast_conf.output_name = strdup(optarg);
config.screencast_conf.chooser_type = XDPW_CHOOSER_NONE;
break;
case 'c':
configfile = strdup(optarg);
Expand Down
34 changes: 13 additions & 21 deletions src/screencast/screencast.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void xdpw_screencast_instance_destroy(struct xdpw_screencast_instance *cast) {
free(cast);
}

int setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess, bool with_cursor) {
bool setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess, bool with_cursor) {

struct xdpw_wlr_output *output, *tmp_o;
wl_list_for_each_reverse_safe(output, tmp_o, &ctx->output_list, link) {
Expand All @@ -86,19 +86,10 @@ int setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess
}

struct xdpw_wlr_output *out;
if (ctx->state->config->screencast_conf.output_name) {
out = xdpw_wlr_output_find_by_name(&ctx->output_list,
ctx->state->config->screencast_conf.output_name);
if (!out) {
logprint(ERROR, "wlroots: no such output");
abort();
}
} else {
out = xdpw_wlr_output_first(&ctx->output_list);
if (!out) {
logprint(ERROR, "wlroots: no output found");
abort();
}
out = xdpw_wlr_output_chooser(ctx);
if (!out) {
logprint(ERROR, "wlroots: no output found");
return false;
}

struct xdpw_screencast_instance *cast, *tmp_c;
Expand Down Expand Up @@ -130,7 +121,7 @@ int setup_outputs(struct xdpw_screencast_context *ctx, struct xdpw_session *sess
logprint(INFO, "wlroots: output: %s",
sess->screencast_instance->target_output->name);

return 0;
return true;

}

Expand Down Expand Up @@ -310,22 +301,23 @@ static int method_screencast_select_sources(sd_bus_message *msg, void *data,
return ret;
}

ret = -1;
bool output_selection_canceled = 1;
wl_list_for_each_reverse_safe(sess, tmp_s, &state->xdpw_sessions, link) {
if (strcmp(sess->session_handle, session_handle) == 0) {
logprint(DEBUG, "dbus: select sources: found matching session %s", sess->session_handle);
ret = setup_outputs(ctx, sess, cursor_embedded);
output_selection_canceled = !setup_outputs(ctx, sess, cursor_embedded);
}
}
if (ret < 0) {
return ret;
}

ret = sd_bus_message_new_method_return(msg, &reply);
if (ret < 0) {
return ret;
}
ret = sd_bus_message_append(reply, "ua{sv}", PORTAL_RESPONSE_SUCCESS, 0);
if (output_selection_canceled) {
ret = sd_bus_message_append(reply, "ua{sv}", PORTAL_RESPONSE_CANCELLED, 0);
} else {
ret = sd_bus_message_append(reply, "ua{sv}", PORTAL_RESPONSE_SUCCESS, 0);
}
if (ret < 0) {
return ret;
}
Expand Down
29 changes: 29 additions & 0 deletions src/screencast/screencast_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,32 @@ enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format) {
return SPA_VIDEO_FORMAT_UNKNOWN;
}
}

enum xdpw_chooser_types get_chooser_type(const char *chooser_type) {
if (!chooser_type || strcmp(chooser_type, "default") == 0) {
return XDPW_CHOOSER_DEFAULT;
} else if (strcmp(chooser_type, "none") == 0) {
return XDPW_CHOOSER_NONE;
} else if (strcmp(chooser_type, "simple") == 0) {
return XDPW_CHOOSER_SIMPLE;
} else if (strcmp(chooser_type, "dmenu") == 0) {
return XDPW_CHOOSER_DMENU;
}
fprintf(stderr, "Could not understand chooser type %s\n", chooser_type);
exit(1);
}

const char *chooser_type_str(enum xdpw_chooser_types chooser_type) {
switch (chooser_type) {
case XDPW_CHOOSER_DEFAULT:
return "default";
case XDPW_CHOOSER_NONE:
return "none";
case XDPW_CHOOSER_SIMPLE:
return "simple";
case XDPW_CHOOSER_DMENU:
return "dmenu";
}
fprintf(stderr, "Could not find chooser type %d\n", chooser_type);
abort();
}
Loading