Skip to content

Commit

Permalink
screencast: add option to select cropping region
Browse files Browse the repository at this point in the history
  • Loading branch information
columbarius committed Jun 1, 2022
1 parent 95d9762 commit 6f1e972
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ struct config_screencast {
char *chooser_cmd;
enum xdpw_chooser_types chooser_type;
bool force_mod_linear;
enum xdpw_cropmode cropmode;
struct xdpw_frame_crop region;
};

struct xdpw_config {
Expand Down
1 change: 1 addition & 0 deletions include/screencast_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,4 +210,5 @@ 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);
const char *cropmode_str(enum xdpw_cropmode cropmode);
#endif /* SCREENCAST_COMMON_H */
36 changes: 36 additions & 0 deletions src/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ void print_config(enum LOGLEVEL loglevel, struct xdpw_config *config) {
logprint(loglevel, "config: chooser_cmd: %s", config->screencast_conf.chooser_cmd);
logprint(loglevel, "config: chooser_type: %s", chooser_type_str(config->screencast_conf.chooser_type));
logprint(loglevel, "config: force_mod_linear: %d", config->screencast_conf.force_mod_linear);
logprint(loglevel, "config: cropmode: %s", cropmode_str(config->screencast_conf.cropmode));
logprint(loglevel, "config: cropping_region x: %u", config->screencast_conf.region.x);
logprint(loglevel, "config: cropping_region y: %u", config->screencast_conf.region.y);
logprint(loglevel, "config: cropping_region width: %u", config->screencast_conf.region.width);
logprint(loglevel, "config: cropping_region height: %u", config->screencast_conf.region.height);
}

// NOTE: calling finish_config won't prepare the config to be read again from config file
Expand Down Expand Up @@ -60,6 +65,28 @@ static void parse_bool(bool *dest, const char* value) {
}
}

static void parse_region(struct xdpw_frame_crop *dest, const char* value) {
if (value == NULL || *value == '\0') {
logprint(TRACE, "config: skipping empty value in config file");
return;
}
sscanf(value, "%u,%u:%ux%u", &dest->x, &dest->y, &dest->width, &dest->height);
}

static void parse_cropmode(enum xdpw_cropmode *dest, const char* value) {
if (value == NULL || *value == '\0') {
logprint(TRACE, "config: skipping empty value in config file");
return;
}
if (strcmp(value, "none") == 0) {
*dest = XDPW_CROP_NONE;
} else if (strcmp(value, "wlroots") == 0) {
*dest = XDPW_CROP_WLROOTS;
} else if (strcmp(value, "pipewire") == 0) {
*dest = XDPW_CROP_PIPEWIRE;
}
}

static int handle_ini_screencast(struct config_screencast *screencast_conf, const char *key, const char *value) {
if (strcmp(key, "output_name") == 0) {
parse_string(&screencast_conf->output_name, value);
Expand All @@ -78,6 +105,10 @@ static int handle_ini_screencast(struct config_screencast *screencast_conf, cons
free(chooser_type);
} else if (strcmp(key, "force_mod_linear") == 0) {
parse_bool(&screencast_conf->force_mod_linear, value);
} else if (strcmp(key, "cropmode") == 0) {
parse_cropmode(&screencast_conf->cropmode, value);
} else if (strcmp(key, "region") == 0) {
parse_region(&screencast_conf->region, value);
} else {
logprint(TRACE, "config: skipping invalid key in config file");
return 0;
Expand All @@ -100,6 +131,11 @@ static int handle_ini_config(void *data, const char* section, const char *key, c
static void default_config(struct xdpw_config *config) {
config->screencast_conf.max_fps = 0;
config->screencast_conf.chooser_type = XDPW_CHOOSER_DEFAULT;
config->screencast_conf.cropmode = XDPW_CROP_NONE;
config->screencast_conf.region.x = 0;
config->screencast_conf.region.y = 0;
config->screencast_conf.region.width = 0;
config->screencast_conf.region.height = 0;
}

static bool file_exists(const char *path) {
Expand Down
10 changes: 10 additions & 0 deletions src/screencast/screencast.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
cast->avoid_dmabufs = false;
cast->teardown = false;
wl_list_init(&cast->buffer_list);
if (ctx->state->config->screencast_conf.chooser_type == XDPW_CHOOSER_NONE &&
ctx->state->config->screencast_conf.cropmode != XDPW_CROP_NONE &&
ctx->state->config->screencast_conf.region.width != 0 &&
ctx->state->config->screencast_conf.region.height != 0) {
cast->cropmode = ctx->state->config->screencast_conf.cropmode;
cast->current_frame.crop.x = ctx->state->config->screencast_conf.region.x;
cast->current_frame.crop.y = ctx->state->config->screencast_conf.region.y;
cast->current_frame.crop.width = ctx->state->config->screencast_conf.region.width;
cast->current_frame.crop.height = ctx->state->config->screencast_conf.region.height;
}
logprint(INFO, "xdpw: screencast instance %p has %d references", cast, cast->refcount);
wl_list_insert(&ctx->screencast_instances, &cast->link);
logprint(INFO, "xdpw: %d active screencast instances",
Expand Down
13 changes: 13 additions & 0 deletions src/screencast/screencast_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -404,3 +404,16 @@ const char *chooser_type_str(enum xdpw_chooser_types chooser_type) {
fprintf(stderr, "Could not find chooser type %d\n", chooser_type);
abort();
}

const char *cropmode_str(enum xdpw_cropmode cropmode) {
switch (cropmode) {
case XDPW_CROP_NONE:
return "none";
case XDPW_CROP_WLROOTS:
return "wlroots";
case XDPW_CROP_PIPEWIRE:
return "pipewire";
}
fprintf(stderr, "Could not find chooser type %d\n", cropmode);
abort();
}
11 changes: 11 additions & 0 deletions xdg-desktop-portal-wlr.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ These options need to be placed under the **[screencast]** section.

This option is experimental and can be removed or replaced in future versions.

**cropmode** = _type_
Specifies the mode to crop the output to the defined region.

The supported types are:
- none: No cropping, ignore region.
- wlroots: Crop inside the compositor. Better performance.
- pipewire: Send cropping information via PipeWire.

**region** = _offset_x_,_offset_y_:_width_x_height_
Specifies the region the output is cropped to. Only works with **chooser_type** = none.

## OUTPUT CHOOSER

The chooser can be any program or script with the following behaviour:
Expand Down

0 comments on commit 6f1e972

Please sign in to comment.