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 { struct config_screencast {
char *output_name; char *output_name;
double max_fps; double max_fps;
char *exec_before;
char *exec_after;
}; };
struct xdpw_config { struct xdpw_config {

View file

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

View file

@ -18,8 +18,36 @@
static const char object_path[] = "/org/freedesktop/portal/desktop"; static const char object_path[] = "/org/freedesktop/portal/desktop";
static const char interface_name[] = "org.freedesktop.impl.portal.ScreenCast"; 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, void xdpw_screencast_instance_init(struct xdpw_screencast_context *ctx,
struct xdpw_screencast_instance *cast, struct xdpw_wlr_output *out, bool with_cursor) { 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->ctx = ctx;
cast->target_output = out; cast->target_output = out;
cast->framerate = out->framerate; 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) { void xdpw_screencast_instance_destroy(struct xdpw_screencast_instance *cast) {
assert(cast->refcount == 0); // Fails assert if called by screencast_finish assert(cast->refcount == 0); // Fails assert if called by screencast_finish
logprint(DEBUG, "xdpw: destroying cast instance"); 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); wl_list_remove(&cast->link);
xdpw_pwr_stream_destroy(cast); xdpw_pwr_stream_destroy(cast);
free(cast); free(cast);

View file

@ -25,6 +25,8 @@ The configuration files use the INI file format. Example:
[screencast] [screencast]
output_name=HDMI-A-1 output_name=HDMI-A-1
max_fps=30 max_fps=30
exec_before=disable_notifications.sh
exec_after=enable_notifications.sh
``` ```
# SCREENCAST OPTIONS # 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 This is useful to reduce CPU usage when capturing frames at the output's
refresh rate is unnecessary. 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 # SEE ALSO
**pipewire**(1) **pipewire**(1)