Add exec_before and exec_after

Adds an option to execute some program before and after screencast (e.g.
for disabling notifications during a cast)
This commit is contained in:
David96 2021-03-15 15:16:50 +01:00 committed by Simon Ser
parent d3e1f7100c
commit 4c2d8fc808
4 changed files with 52 additions and 0 deletions

View file

@ -6,6 +6,8 @@
struct config_screencast {
char *output_name;
double max_fps;
char *exec_before;
char *exec_after;
};
struct xdpw_config {

View file

@ -20,6 +20,8 @@ void finish_config(struct xdpw_config *config) {
// screencast
free(&config->screencast_conf.output_name);
free(&config->screencast_conf.exec_before);
free(&config->screencast_conf.exec_after);
}
static void getstring_from_conffile(dictionary *d,
@ -79,6 +81,8 @@ static void config_parse_file(const char *configfile, struct xdpw_config *config
// screencast
getstring_from_conffile(d, "screencast:output_name", &config->screencast_conf.output_name, NULL);
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);
iniparser_freedict(d);
logprint(DEBUG, "config: config file parsed");

View file

@ -18,8 +18,36 @@
static const char object_path[] = "/org/freedesktop/portal/desktop";
static const char interface_name[] = "org.freedesktop.impl.portal.ScreenCast";
void exec_with_shell(char *command) {
pid_t pid = fork();
if (pid < 0) {
perror("fork");
} else if (pid == 0) {
char *const argv[] = {
"sh",
"-c",
command,
NULL,
};
execvp("sh", argv);
perror("execvp");
exit(127);
}
}
void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
struct xdpw_screencast_instance *cast, struct xdpw_wlr_output *out, bool with_cursor) {
// only run exec_before if there's no other instance running that already ran it
if (wl_list_empty(&ctx->screencast_instances)) {
char *exec_before = ctx->state->config->screencast_conf.exec_before;
if (exec_before) {
logprint(INFO, "xdpw: executing %s before screencast", exec_before);
exec_with_shell(exec_before);
}
}
cast->ctx = ctx;
cast->target_output = out;
cast->framerate = out->framerate;
@ -34,6 +62,16 @@ void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
void xdpw_screencast_instance_destroy(struct xdpw_screencast_instance *cast) {
assert(cast->refcount == 0); // Fails assert if called by screencast_finish
logprint(DEBUG, "xdpw: destroying cast instance");
// make sure this is the last running instance that is being destroyed
if (wl_list_length(&cast->link) == 1) {
char *exec_after = cast->ctx->state->config->screencast_conf.exec_after;
if (exec_after) {
logprint(INFO, "xdpw: executing %s after screencast", exec_after);
exec_with_shell(exec_after);
}
}
wl_list_remove(&cast->link);
xdpw_pwr_stream_destroy(cast);
free(cast);

View file

@ -25,6 +25,8 @@ The configuration files use the INI file format. Example:
[screencast]
output_name=HDMI-A-1
max_fps=30
exec_before=disable_notifications.sh
exec_after=enable_notifications.sh
```
# SCREENCAST OPTIONS
@ -44,6 +46,12 @@ These options need to be placed under the **[screencast]** section.
This is useful to reduce CPU usage when capturing frames at the output's
refresh rate is unnecessary.
**exec_before** = _command_
Execute _command_ before starting a screencast. The command will be executed within sh.
**exec_after** = _command_
Execute _command_ after ending all screencasts. The command will be executed within sh.
# SEE ALSO
**pipewire**(1)