Fix CI with libpipewire02, libdrm. Remove png.h unused import. Cleanup style.

This commit is contained in:
Dan Shick 2020-03-13 12:43:24 -04:00 committed by Simon Ser
parent c0da39f022
commit 45699637d1
15 changed files with 480 additions and 514 deletions

View file

@ -5,7 +5,8 @@ packages:
- meson - meson
- wayland - wayland
- wayland-protocols - wayland-protocols
- pipewire - libpipewire02
- libdrm
sources: sources:
- https://github.com/emersion/xdg-desktop-portal-wlr - https://github.com/emersion/xdg-desktop-portal-wlr
tasks: tasks:

View file

@ -1,27 +1,20 @@
#ifndef LOGGER_H #ifndef LOGGER_H
#define LOGGER_H #define LOGGER_H
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
enum LOGLEVEL { enum LOGLEVEL { QUIET, ERROR, WARN, INFO, DEBUG, TRACE };
QUIET,
ERROR,
WARN,
INFO,
DEBUG,
TRACE
};
struct logger_properties{ struct logger_properties {
enum LOGLEVEL level; enum LOGLEVEL level;
FILE *__restrict__ dst; FILE *dst;
}; };
void init_logger(FILE *__restrict__ dst, enum LOGLEVEL level); void init_logger(FILE *dst, enum LOGLEVEL level);
enum LOGLEVEL get_loglevel(const char *level); enum LOGLEVEL get_loglevel(const char *level);
void logprint(enum LOGLEVEL level, char *msg, ...); void logprint(enum LOGLEVEL level, char *msg, ...);

View file

@ -1,6 +1,7 @@
#ifndef SCREENCAST_COMMON_H #ifndef SCREENCAST_COMMON_H
#define SCREENCAST_COMMON_H #define SCREENCAST_COMMON_H
#include <string.h>
#include <pipewire/pipewire.h> #include <pipewire/pipewire.h>
#include <spa/param/video/format-utils.h> #include <spa/param/video/format-utils.h>
#include <libdrm/drm_fourcc.h> #include <libdrm/drm_fourcc.h>
@ -24,7 +25,6 @@ struct simple_frame {
uint32_t tv_nsec; uint32_t tv_nsec;
enum wl_shm_format format; enum wl_shm_format format;
struct damage *damage; struct damage *damage;
struct wl_buffer *buffer; struct wl_buffer *buffer;
void *data; void *data;
}; };
@ -38,7 +38,6 @@ struct pwr_type {
}; };
struct screencast_context { struct screencast_context {
// pipewire // pipewire
struct pwr_type type; struct pwr_type type;
struct pw_loop *loop; struct pw_loop *loop;
@ -97,6 +96,5 @@ struct wayland_output {
}; };
uint32_t pipewire_from_wl_shm(void *data); uint32_t pipewire_from_wl_shm(void *data);
char *strdup(const char *src);
#endif /* SCREENCAST_COMMON_H */ #endif /* SCREENCAST_COMMON_H */

View file

@ -5,7 +5,6 @@
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <png.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -27,7 +26,8 @@ void wlr_frame_free(struct xdpw_state *state);
int wlr_screencopy_init(struct xdpw_state *state); int wlr_screencopy_init(struct xdpw_state *state);
void wlr_screencopy_uninit(struct screencast_context *ctx); void wlr_screencopy_uninit(struct screencast_context *ctx);
struct wayland_output *wlr_output_find_by_name(struct wl_list *output_list, const char* name); struct wayland_output *wlr_output_find_by_name(struct wl_list *output_list,
const char *name);
struct wayland_output *wlr_output_find(struct screencast_context *ctx, struct wayland_output *wlr_output_find(struct screencast_context *ctx,
struct wl_output *out, uint32_t id); struct wl_output *out, uint32_t id);
struct wayland_output *wlr_output_first(struct wl_list *output_list); struct wayland_output *wlr_output_first(struct wl_list *output_list);

View file

@ -8,7 +8,6 @@ project(
'c_std=c11', 'c_std=c11',
'warning_level=2', 'warning_level=2',
'werror=true', 'werror=true',
'debug=true',
], ],
) )

View file

@ -13,29 +13,31 @@ static const char *loglevels[] = {
static struct logger_properties logprops; static struct logger_properties logprops;
void init_logger(FILE *__restrict__ dst, enum LOGLEVEL level){ void init_logger(FILE *dst, enum LOGLEVEL level) {
logprops.dst = dst; logprops.dst = dst;
logprops.level = level; logprops.level = level;
} }
enum LOGLEVEL get_loglevel(const char *level){ enum LOGLEVEL get_loglevel(const char *level) {
int i; int i;
for(i = 0; i < NUM_LEVELS; i++){ for (i = 0; i < NUM_LEVELS; i++) {
if(!strcmp(level, loglevels[i])) return (enum LOGLEVEL) i; if (!strcmp(level, loglevels[i])) {
return (enum LOGLEVEL) i;
}
} }
fprintf(stderr, "Could not understand log level %s\n", level); fprintf(stderr, "Could not understand log level %s\n", level);
exit(EXIT_FAILURE); abort();
} }
void logprint(enum LOGLEVEL level, char *msg, ...){ void logprint(enum LOGLEVEL level, char *msg, ...) {
if (!logprops.dst) {
if(!logprops.dst){
fprintf(stderr, "Logger has been called, but was not initialized\n"); fprintf(stderr, "Logger has been called, but was not initialized\n");
exit(EXIT_FAILURE); abort();
} }
if(level > logprops.level || level == QUIET) return ; if (level > logprops.level || level == QUIET) {
return;
}
va_list args; va_list args;
char timestr[200]; char timestr[200];
@ -44,15 +46,12 @@ void logprint(enum LOGLEVEL level, char *msg, ...){
if (strftime(timestr, sizeof(timestr), "%Y/%m/%d %H:%M:%S", tmp) == 0) { if (strftime(timestr, sizeof(timestr), "%Y/%m/%d %H:%M:%S", tmp) == 0) {
fprintf(stderr, "strftime returned 0"); fprintf(stderr, "strftime returned 0");
exit(EXIT_FAILURE); abort();
} }
fprintf(logprops.dst, "%s", timestr); fprintf(logprops.dst, "%s", timestr);
fprintf(logprops.dst, " "); fprintf(logprops.dst, " ");
fprintf(logprops.dst, "[%s]", loglevels[level]); fprintf(logprops.dst, "[%s]", loglevels[level]);
fprintf(logprops.dst, " - "); fprintf(logprops.dst, " - ");
va_start(args, msg); va_start(args, msg);
@ -62,5 +61,4 @@ void logprint(enum LOGLEVEL level, char *msg, ...){
fprintf(logprops.dst, "\n"); fprintf(logprops.dst, "\n");
fflush(logprops.dst); fflush(logprops.dst);
} }

View file

@ -14,26 +14,23 @@ enum event_loop_fd {
static const char service_name[] = "org.freedesktop.impl.portal.desktop.wlr"; static const char service_name[] = "org.freedesktop.impl.portal.desktop.wlr";
int xdpw_usage(FILE* stream, int rc) int xdpw_usage(FILE* stream, int rc) {
{
static const char* usage = static const char* usage =
"Usage: xdg-desktop-portal-wlr [options]\n" "Usage: xdg-desktop-portal-wlr [options]\n"
"\n" "\n"
" -l, --loglevel=<loglevel> Select log level (default is ERROR).\n" " -l, --loglevel=<loglevel> Select log level (default is ERROR).\n"
" QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n" " QUIET, ERROR, WARN, INFO, DEBUG, TRACE\n"
" -o, --output=<name> Select output to capture.\n" " -o, --output=<name> Select output to capture.\n"
" -p,--pixelformat=BGRx|RGBx Force a pixelformat in pipewire\n" " -p,--pixelformat=BGRx|RGBx Force a pixelformat in pipewire\n"
" metadata (performs no conversion).\n" " metadata (performs no conversion).\n"
" -h,--help Get help (this text).\n" " -h,--help Get help (this text).\n"
"\n"; "\n";
fprintf(stream, "%s", usage); fprintf(stream, "%s", usage);
return rc; return rc;
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
const char* output_name = NULL; const char* output_name = NULL;
const char* forced_pixelformat = NULL; const char* forced_pixelformat = NULL;
enum LOGLEVEL loglevel = ERROR; enum LOGLEVEL loglevel = ERROR;

View file

@ -1,6 +1,6 @@
#include "pipewire_screencast.h" #include "pipewire_screencast.h"
static inline void init_type(struct pwr_type *type, struct pw_type *map) { static void init_type(struct pwr_type *type, struct pw_type *map) {
pw_type_get(map, SPA_TYPE__MediaType, &type->media_type); pw_type_get(map, SPA_TYPE__MediaType, &type->media_type);
pw_type_get(map, SPA_TYPE__MediaSubtype, &type->media_subtype); pw_type_get(map, SPA_TYPE__MediaSubtype, &type->media_subtype);
pw_type_get(map, SPA_TYPE_FORMAT__Video, &type->format_video); pw_type_get(map, SPA_TYPE_FORMAT__Video, &type->format_video);
@ -10,7 +10,6 @@ static inline void init_type(struct pwr_type *type, struct pw_type *map) {
static void writeFrameData(void *pwFramePointer, void *wlrFramePointer, static void writeFrameData(void *pwFramePointer, void *wlrFramePointer,
uint32_t height, uint32_t stride, bool inverted) { uint32_t height, uint32_t stride, bool inverted) {
if (!inverted) { if (!inverted) {
memcpy(pwFramePointer, wlrFramePointer, height * stride); memcpy(pwFramePointer, wlrFramePointer, height * stride);
return; return;
@ -21,6 +20,7 @@ static void writeFrameData(void *pwFramePointer, void *wlrFramePointer,
void *pwRowPointer = pwFramePointer + (i * stride); void *pwRowPointer = pwFramePointer + (i * stride);
memcpy(pwRowPointer, flippedWlrRowPointer, stride); memcpy(pwRowPointer, flippedWlrRowPointer, stride);
} }
return; return;
} }
@ -76,17 +76,15 @@ static void pwr_on_event(void *data, uint64_t expirations) {
pw_stream_queue_buffer(ctx->stream, pw_buf); pw_stream_queue_buffer(ctx->stream, pw_buf);
wlr_frame_free(state); wlr_frame_free(state);
} }
static void pwr_handle_stream_state_changed(void *data, static void pwr_handle_stream_state_changed(void *data,
enum pw_stream_state old, enum pw_stream_state old, enum pw_stream_state state, const char *error) {
enum pw_stream_state state,
const char *error) {
struct screencast_context *ctx = data; struct screencast_context *ctx = data;
ctx->node_id = pw_stream_get_node_id(ctx->stream); ctx->node_id = pw_stream_get_node_id(ctx->stream);
logprint(INFO, "pipewire: stream state changed to \"%s\"", pw_stream_state_as_string(state)); logprint(INFO, "pipewire: stream state changed to \"%s\"",
pw_stream_state_as_string(state));
logprint(INFO, "pipewire: node id is %d", ctx->node_id); logprint(INFO, "pipewire: node id is %d", ctx->node_id);
switch (state) { switch (state) {
@ -113,6 +111,7 @@ static void pwr_handle_stream_format_changed(void *data,
pw_stream_finish_format(stream, 0, NULL, 0); pw_stream_finish_format(stream, 0, NULL, 0);
return; return;
} }
spa_format_video_raw_parse(format, &ctx->pwr_format, &ctx->type.format_video); spa_format_video_raw_parse(format, &ctx->pwr_format, &ctx->type.format_video);
params[0] = spa_pod_builder_object( params[0] = spa_pod_builder_object(
@ -122,7 +121,8 @@ static void pwr_handle_stream_format_changed(void *data,
t->param_buffers.buffers, "iru", BUFFERS, SPA_POD_PROP_MIN_MAX(1, 32), t->param_buffers.buffers, "iru", BUFFERS, SPA_POD_PROP_MIN_MAX(1, 32),
":", t->param_buffers.align, "i", ALIGN); ":", t->param_buffers.align, "i", ALIGN);
params[1] = spa_pod_builder_object(&b, t->param.idMeta, t->param_meta.Meta, params[1] = spa_pod_builder_object(&b,
t->param.idMeta, t->param_meta.Meta,
":", t->param_meta.type, "I", ":", t->param_meta.type, "I",
t->meta.Header, ":", t->param_meta.size, t->meta.Header, ":", t->param_meta.size,
"i", sizeof(struct spa_meta_header)); "i", sizeof(struct spa_meta_header));
@ -137,8 +137,7 @@ static const struct pw_stream_events pwr_stream_events = {
}; };
static void pwr_handle_state_changed(void *data, enum pw_remote_state old, static void pwr_handle_state_changed(void *data, enum pw_remote_state old,
enum pw_remote_state pwr_remote_state, enum pw_remote_state pwr_remote_state, const char *error) {
const char *error) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
struct screencast_context *ctx = &state->screencast; struct screencast_context *ctx = &state->screencast;
struct pw_remote *remote = ctx->remote; struct pw_remote *remote = ctx->remote;
@ -163,7 +162,8 @@ static void pwr_handle_state_changed(void *data, enum pw_remote_state old,
ctx->stream = pw_stream_new( ctx->stream = pw_stream_new(
remote, "wlr_screeencopy", remote, "wlr_screeencopy",
pw_properties_new("media.class", "Video/Source", PW_NODE_PROP_MEDIA, pw_properties_new("media.class",
"Video/Source", PW_NODE_PROP_MEDIA,
"Video", PW_NODE_PROP_CATEGORY, "Source", "Video", PW_NODE_PROP_CATEGORY, "Source",
PW_NODE_PROP_ROLE, "Screen", NULL)); PW_NODE_PROP_ROLE, "Screen", NULL));
@ -185,8 +185,7 @@ static void pwr_handle_state_changed(void *data, enum pw_remote_state old,
&pwr_stream_events, ctx); &pwr_stream_events, ctx);
pw_stream_connect(ctx->stream, PW_DIRECTION_OUTPUT, NULL, pw_stream_connect(ctx->stream, PW_DIRECTION_OUTPUT, NULL,
PW_STREAM_FLAG_DRIVER | PW_STREAM_FLAG_MAP_BUFFERS, PW_STREAM_FLAG_DRIVER | PW_STREAM_FLAG_MAP_BUFFERS, params, 1);
params, 1);
break; break;
} }

View file

@ -9,8 +9,8 @@ int setup_outputs(struct xdpw_state *state) {
struct wayland_output *output, *tmp_o; struct wayland_output *output, *tmp_o;
wl_list_for_each_reverse_safe(output, tmp_o, &ctx->output_list, link) { wl_list_for_each_reverse_safe(output, tmp_o, &ctx->output_list, link) {
logprint(INFO, "wlroots: capturable output: %s model: %s: id: %i name: %s", output->make, logprint(INFO, "wlroots: capturable output: %s model: %s: id: %i name: %s",
output->model, output->id, output->name); output->make, output->model, output->id, output->name);
} }
struct wayland_output *out; struct wayland_output *out;
@ -18,13 +18,13 @@ int setup_outputs(struct xdpw_state *state) {
out = wlr_output_find_by_name(&ctx->output_list, ctx->output_name); out = wlr_output_find_by_name(&ctx->output_list, ctx->output_name);
if (!out) { if (!out) {
logprint(ERROR, "wlroots: no such output"); logprint(ERROR, "wlroots: no such output");
exit(EXIT_FAILURE); abort();
} }
} else { } else {
out = wlr_output_first(&ctx->output_list); out = wlr_output_first(&ctx->output_list);
if (!out) { if (!out) {
logprint(ERROR, "wlroots: no output found"); logprint(ERROR, "wlroots: no output found");
exit(EXIT_FAILURE); abort();
} }
} }
@ -39,12 +39,10 @@ int setup_outputs(struct xdpw_state *state) {
} }
void *start_screencast(void *data){ void *start_screencast(void *data) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
wlr_register_cb(state); wlr_register_cb(state);
// process at least one frame so that we know // process at least one frame so that we know
// some of the metadata required for the pipewire // some of the metadata required for the pipewire
// remote state connected event // remote state connected event
@ -54,7 +52,6 @@ void *start_screencast(void *data){
pwr_start(state); pwr_start(state);
return NULL; return NULL;
} }
static int method_screencast_create_session(sd_bus_message *msg, void *data, static int method_screencast_create_session(sd_bus_message *msg, void *data,
@ -80,13 +77,13 @@ static int method_screencast_create_session(sd_bus_message *msg, void *data,
char* key; char* key;
int innerRet = 0; int innerRet = 0;
while((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) {
innerRet = sd_bus_message_read(msg, "s", &key); innerRet = sd_bus_message_read(msg, "s", &key);
if (innerRet < 0) { if (innerRet < 0) {
return innerRet; return innerRet;
} }
if(strcmp(key, "session_handle_token") == 0) { if (strcmp(key, "session_handle_token") == 0) {
char* token; char* token;
sd_bus_message_read(msg, "v", "s", &token); sd_bus_message_read(msg, "v", "s", &token);
logprint(INFO, "dbus: option token: %s", token); logprint(INFO, "dbus: option token: %s", token);
@ -142,8 +139,8 @@ static int method_screencast_create_session(sd_bus_message *msg, void *data,
} }
static int method_screencast_select_sources(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { static int method_screencast_select_sources(sd_bus_message *msg, void *data,
sd_bus_error *ret_error) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
int ret = 0; int ret = 0;
@ -168,20 +165,20 @@ static int method_screencast_select_sources(sd_bus_message *msg, void *data, sd_
char* key; char* key;
int innerRet = 0; int innerRet = 0;
while((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) {
innerRet = sd_bus_message_read(msg, "s", &key); innerRet = sd_bus_message_read(msg, "s", &key);
if (innerRet < 0) { if (innerRet < 0) {
return innerRet; return innerRet;
} }
if(strcmp(key, "multiple") == 0) { if (strcmp(key, "multiple") == 0) {
bool multiple; bool multiple;
sd_bus_message_read(msg, "v", "b", &multiple); sd_bus_message_read(msg, "v", "b", &multiple);
logprint(INFO, "dbus: option multiple: %x", multiple); logprint(INFO, "dbus: option multiple: %x", multiple);
} else if(strcmp(key, "types") == 0) { } else if (strcmp(key, "types") == 0) {
uint32_t mask; uint32_t mask;
sd_bus_message_read(msg, "v", "u", &mask); sd_bus_message_read(msg, "v", "u", &mask);
logprint(INFO, "dbus: option types: %x", mask); logprint(INFO, "dbus: option types:%x", mask);
} else { } else {
logprint(WARN, "dbus: unknown option %s", key); logprint(WARN, "dbus: unknown option %s", key);
sd_bus_message_skip(msg, "v"); sd_bus_message_skip(msg, "v");
@ -219,8 +216,8 @@ static int method_screencast_select_sources(sd_bus_message *msg, void *data, sd_
return 0; return 0;
} }
static int method_screencast_start(sd_bus_message *msg, void *data, sd_bus_error *ret_error) { static int method_screencast_start(sd_bus_message *msg, void *data,
sd_bus_error *ret_error) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
struct screencast_context *ctx = &state->screencast; struct screencast_context *ctx = &state->screencast;
@ -247,7 +244,7 @@ static int method_screencast_start(sd_bus_message *msg, void *data, sd_bus_error
char* key; char* key;
int innerRet = 0; int innerRet = 0;
while((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) { while ((ret = sd_bus_message_enter_container(msg, 'e', "sv")) > 0) {
innerRet = sd_bus_message_read(msg, "s", &key); innerRet = sd_bus_message_read(msg, "s", &key);
if (innerRet < 0) { if (innerRet < 0) {
return innerRet; return innerRet;
@ -275,11 +272,10 @@ static int method_screencast_start(sd_bus_message *msg, void *data, sd_bus_error
return ret; return ret;
} }
while(ctx->node_id == 0){ while (ctx->node_id == 0) {
int ret = pw_loop_iterate(state->pw_loop, 0); int ret = pw_loop_iterate(state->pw_loop, 0);
if (ret < 0) { if (ret < 0) {
logprint(ERROR, "pipewire_loop_iterate failed: %s", logprint(ERROR, "pipewire_loop_iterate failed: %s", spa_strerror(ret));
spa_strerror(ret));
} }
} }
@ -288,6 +284,7 @@ static int method_screencast_start(sd_bus_message *msg, void *data, sd_bus_error
ctx->node_id, 2, ctx->node_id, 2,
"position", "(ii)", 0, 0, "position", "(ii)", 0, 0,
"size", "(ii)", ctx->simple_frame.width, ctx->simple_frame.height); "size", "(ii)", ctx->simple_frame.width, ctx->simple_frame.height);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
} }
@ -303,9 +300,12 @@ static int method_screencast_start(sd_bus_message *msg, void *data, sd_bus_error
static const sd_bus_vtable screencast_vtable[] = { static const sd_bus_vtable screencast_vtable[] = {
SD_BUS_VTABLE_START(0), SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("CreateSession", "oosa{sv}", "ua{sv}", method_screencast_create_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateSession", "oosa{sv}", "ua{sv}",
SD_BUS_METHOD("SelectSources", "oosa{sv}", "ua{sv}", method_screencast_select_sources, SD_BUS_VTABLE_UNPRIVILEGED), method_screencast_create_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Start", "oossa{sv}", "ua{sv}", method_screencast_start, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("SelectSources", "oosa{sv}", "ua{sv}",
method_screencast_select_sources, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Start", "oossa{sv}", "ua{sv}",
method_screencast_start, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END SD_BUS_VTABLE_END
}; };
@ -316,11 +316,10 @@ int init_screencast(struct xdpw_state *state, const char *output_name, const cha
state->screencast = (struct screencast_context) { 0 }; state->screencast = (struct screencast_context) { 0 };
state->screencast.forced_pixelformat = forced_pixelformat; state->screencast.forced_pixelformat = forced_pixelformat;
state->screencast.output_name = output_name; state->screencast.output_name = output_name;
state->screencast.simple_frame = (struct simple_frame){0}; state->screencast.simple_frame = (struct simple_frame) { 0 };
state->screencast.simple_frame.damage = &(struct damage){0}; state->screencast.simple_frame.damage = &(struct damage) { 0 };
int err; int err = wlr_screencopy_init(state);
err = wlr_screencopy_init(state);
if (err) { if (err) {
goto end; goto end;
} }
@ -328,7 +327,7 @@ int init_screencast(struct xdpw_state *state, const char *output_name, const cha
return sd_bus_add_object_vtable(state->bus, &slot, object_path, interface_name, return sd_bus_add_object_vtable(state->bus, &slot, object_path, interface_name,
screencast_vtable, state); screencast_vtable, state);
end: end:
wlr_screencopy_uninit(&state->screencast); wlr_screencopy_uninit(&state->screencast);
return err; return err;
} }

View file

@ -1,21 +1,13 @@
#include "screencast_common.h" #include "screencast_common.h"
char *strdup(const char *src) {
char *dst = malloc(strlen(src) + 1); // Space for length plus nul
if (dst == NULL)
return NULL; // No memory
strcpy(dst, src); // Copy the characters
return dst; // Return the new string
}
uint32_t pipewire_from_wl_shm(void *data) { uint32_t pipewire_from_wl_shm(void *data) {
struct screencast_context *ctx = data; struct screencast_context *ctx = data;
if(ctx->forced_pixelformat){ if (ctx->forced_pixelformat) {
if(strcmp(ctx->forced_pixelformat, "BGRx") == 0) { if (strcmp(ctx->forced_pixelformat, "BGRx") == 0) {
return ctx->type.video_format.BGRx; return ctx->type.video_format.BGRx;
} }
if(strcmp(ctx->forced_pixelformat, "RGBx") == 0){ if (strcmp(ctx->forced_pixelformat, "RGBx") == 0) {
return ctx->type.video_format.RGBx; return ctx->type.video_format.RGBx;
} }
} }
@ -40,6 +32,6 @@ uint32_t pipewire_from_wl_shm(void *data) {
case WL_SHM_FORMAT_NV12: case WL_SHM_FORMAT_NV12:
return ctx->type.video_format.NV12; return ctx->type.video_format.NV12;
default: default:
exit(EXIT_FAILURE); abort();
} }
} }

View file

@ -1,22 +1,21 @@
#define _POSIX_C_SOURCE 200809L
#include "wlr_screencast.h" #include "wlr_screencast.h"
#include "xdpw.h" #include "xdpw.h"
void wlr_frame_free(struct xdpw_state *state) { void wlr_frame_free(struct xdpw_state *state) {
zwlr_screencopy_frame_v1_destroy(state->screencast.wlr_frame); zwlr_screencopy_frame_v1_destroy(state->screencast.wlr_frame);
munmap(state->screencast.simple_frame.data, state->screencast.simple_frame.size); munmap(state->screencast.simple_frame.data, state->screencast.simple_frame.size);
wl_buffer_destroy(state->screencast.simple_frame.buffer); wl_buffer_destroy(state->screencast.simple_frame.buffer);
logprint(TRACE, "wlroots: frame destroyed"); logprint(TRACE, "wlroots: frame destroyed");
if(!state->screencast.quit && !state->screencast.err){ if (!state->screencast.quit && !state->screencast.err) {
wlr_register_cb(state); wlr_register_cb(state);
} }
} }
static struct wl_buffer *create_shm_buffer(struct screencast_context *ctx, static struct wl_buffer *create_shm_buffer(struct screencast_context *ctx,
enum wl_shm_format fmt, int width, enum wl_shm_format fmt, int width, int height, int stride,
int height, int stride,
void **data_out) { void **data_out) {
int size = stride * height; int size = stride * height;
@ -55,8 +54,7 @@ static struct wl_buffer *create_shm_buffer(struct screencast_context *ctx,
} }
static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame, static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame,
uint32_t format, uint32_t width, uint32_t height, uint32_t format, uint32_t width, uint32_t height, uint32_t stride) {
uint32_t stride) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
struct screencast_context *ctx = &state->screencast; struct screencast_context *ctx = &state->screencast;
@ -69,9 +67,10 @@ static void wlr_frame_buffer(void *data, struct zwlr_screencopy_frame_v1 *frame,
ctx->simple_frame.format = format; ctx->simple_frame.format = format;
ctx->simple_frame.buffer = create_shm_buffer(ctx, format, width, height, ctx->simple_frame.buffer = create_shm_buffer(ctx, format, width, height,
stride, &ctx->simple_frame.data); stride, &ctx->simple_frame.data);
if (ctx->simple_frame.buffer == NULL) { if (ctx->simple_frame.buffer == NULL) {
logprint(ERROR, "wlroots: failed to create buffer"); logprint(ERROR, "wlroots: failed to create buffer");
exit(EXIT_FAILURE); abort();
} }
zwlr_screencopy_frame_v1_copy_with_damage(frame, ctx->simple_frame.buffer); zwlr_screencopy_frame_v1_copy_with_damage(frame, ctx->simple_frame.buffer);
@ -85,12 +84,10 @@ static void wlr_frame_flags(void *data, struct zwlr_screencopy_frame_v1 *frame,
logprint(TRACE, "wlroots: flags event handler"); logprint(TRACE, "wlroots: flags event handler");
ctx->simple_frame.y_invert = flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT; ctx->simple_frame.y_invert = flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT;
} }
static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame, static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame,
uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) {
uint32_t tv_nsec) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
struct screencast_context *ctx = &state->screencast; struct screencast_context *ctx = &state->screencast;
@ -105,7 +102,6 @@ static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame,
} }
wlr_frame_free(state); wlr_frame_free(state);
} }
static void wlr_frame_failed(void *data, static void wlr_frame_failed(void *data,
@ -120,8 +116,7 @@ static void wlr_frame_failed(void *data,
} }
static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame, static void wlr_frame_damage(void *data, struct zwlr_screencopy_frame_v1 *frame,
uint32_t x, uint32_t y, uint32_t width, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
uint32_t height) {
struct xdpw_state *state = data; struct xdpw_state *state = data;
struct screencast_context *ctx = &state->screencast; struct screencast_context *ctx = &state->screencast;
@ -142,7 +137,6 @@ static const struct zwlr_screencopy_frame_v1_listener wlr_frame_listener = {
}; };
void wlr_register_cb(struct xdpw_state *state) { void wlr_register_cb(struct xdpw_state *state) {
struct screencast_context *ctx = &state->screencast; struct screencast_context *ctx = &state->screencast;
ctx->frame_callback = zwlr_screencopy_manager_v1_capture_output( ctx->frame_callback = zwlr_screencopy_manager_v1_capture_output(
@ -154,18 +148,15 @@ void wlr_register_cb(struct xdpw_state *state) {
} }
static void wlr_output_handle_geometry(void *data, struct wl_output *wl_output, static void wlr_output_handle_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y, int32_t phys_width, int32_t x, int32_t y, int32_t phys_width, int32_t phys_height,
int32_t phys_height, int32_t subpixel, int32_t subpixel, const char *make, const char *model, int32_t transform) {
const char *make, const char *model,
int32_t transform) {
struct wayland_output *output = data; struct wayland_output *output = data;
output->make = strdup(make); output->make = strdup(make);
output->model = strdup(model); output->model = strdup(model);
} }
static void wlr_output_handle_mode(void *data, struct wl_output *wl_output, static void wlr_output_handle_mode(void *data, struct wl_output *wl_output,
uint32_t flags, int32_t width, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
int32_t height, int32_t refresh) {
if (flags & WL_OUTPUT_MODE_CURRENT) { if (flags & WL_OUTPUT_MODE_CURRENT) {
struct wayland_output *output = data; struct wayland_output *output = data;
output->framerate = (float)refresh/1000; output->framerate = (float)refresh/1000;
@ -189,37 +180,37 @@ static const struct wl_output_listener wlr_output_listener = {
}; };
static void wlr_xdg_output_name(void* data, struct zxdg_output_v1* xdg_output, static void wlr_xdg_output_name(void* data, struct zxdg_output_v1* xdg_output,
const char* name){ const char* name) {
struct wayland_output *output = data; struct wayland_output *output = data;
output->name = strdup(name); output->name = strdup(name);
}; };
static void dontcare(){ static void noop() {
// This space intentionally left blank
} }
static const struct zxdg_output_v1_listener wlr_xdg_output_listener = { static const struct zxdg_output_v1_listener wlr_xdg_output_listener = {
.logical_position = dontcare, .logical_position = noop,
.logical_size = dontcare, .logical_size = noop,
.done = NULL, /* Deprecated */ .done = NULL, /* Deprecated */
.description = dontcare, .description = noop,
.name = wlr_xdg_output_name, .name = wlr_xdg_output_name,
}; };
void wlr_add_xdg_output_listener(struct wayland_output *output, void wlr_add_xdg_output_listener(struct wayland_output *output,
struct zxdg_output_v1* xdg_output){ struct zxdg_output_v1* xdg_output) {
output->xdg_output = xdg_output; output->xdg_output = xdg_output;
zxdg_output_v1_add_listener(output->xdg_output, &wlr_xdg_output_listener, zxdg_output_v1_add_listener(output->xdg_output, &wlr_xdg_output_listener,
output); output);
} }
static void wlr_init_xdg_outputs(struct screencast_context *ctx){ static void wlr_init_xdg_outputs(struct screencast_context *ctx) {
struct wayland_output *output, *tmp; struct wayland_output *output, *tmp;
wl_list_for_each_safe(output, tmp, &ctx->output_list, link) { wl_list_for_each_safe(output, tmp, &ctx->output_list, link) {
struct zxdg_output_v1 *xdg_output = struct zxdg_output_v1 *xdg_output =
zxdg_output_manager_v1_get_xdg_output( zxdg_output_manager_v1_get_xdg_output( ctx->xdg_output_manager,
ctx->xdg_output_manager, output->output); output->output);
wlr_add_xdg_output_listener(output, xdg_output); wlr_add_xdg_output_listener(output, xdg_output);
} }
} }
@ -232,17 +223,17 @@ struct wayland_output *wlr_output_first(struct wl_list *output_list) {
return NULL; return NULL;
} }
struct wayland_output *wlr_output_find_by_name(struct wl_list *output_list, const char* name) { struct wayland_output *wlr_output_find_by_name(struct wl_list *output_list,
const char* name) {
struct wayland_output *output, *tmp; struct wayland_output *output, *tmp;
wl_list_for_each_safe(output, tmp, output_list, link){ wl_list_for_each_safe(output, tmp, output_list, link) {
if (strcmp(output->name, name) == 0){ if (strcmp(output->name, name) == 0) {
return output; return output;
} }
} }
return NULL; return NULL;
} }
struct wayland_output *wlr_output_find(struct screencast_context *ctx, struct wayland_output *wlr_output_find(struct screencast_context *ctx,
struct wl_output *out, uint32_t id) { struct wl_output *out, uint32_t id) {
struct wayland_output *output, *tmp; struct wayland_output *output, *tmp;
@ -259,8 +250,7 @@ static void wlr_remove_output(struct wayland_output *out) {
} }
static void wlr_registry_handle_add(void *data, struct wl_registry *reg, static void wlr_registry_handle_add(void *data, struct wl_registry *reg,
uint32_t id, const char *interface, uint32_t id, const char *interface, uint32_t ver) {
uint32_t ver) {
struct screencast_context *ctx = data; struct screencast_context *ctx = data;
if (!strcmp(interface, wl_output_interface.name)) { if (!strcmp(interface, wl_output_interface.name)) {