mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-03-29 22:20:24 +00:00
Merged with master
This commit is contained in:
commit
c7c3ac7c9c
@ -150,6 +150,22 @@
|
||||
that sleeps indefinitely
|
||||
</div>
|
||||
</div>
|
||||
<!--working dir-->
|
||||
<div class="mb-3">
|
||||
<label for="appWorkingDir" class="form-label">Working Directory</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control monospace"
|
||||
id="appWorkingDir"
|
||||
aria-describedby="appWorkingDirHelp"
|
||||
v-model="editForm['working-dir']"
|
||||
/>
|
||||
<div id="appWorkingDirHelp" class="form-text">
|
||||
The working directory that should be passed to the process.
|
||||
For example, some applications use the working directory to search for configuration files.
|
||||
If not set, Sunshine will default to the parent directory of the command
|
||||
</div>
|
||||
</div>
|
||||
<!--buttons-->
|
||||
<div class="d-flex">
|
||||
<button @click="showEditForm = false" class="btn btn-secondary m-2">
|
||||
|
@ -5,18 +5,9 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sunshine</title>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
|
||||
<link href="/third_party/bootstrap.min.css" rel="stylesheet" />
|
||||
<script src="/third_party/bootstrap.bundle.min.js"></script>
|
||||
<script src="/third_party/vue.js"></script>
|
||||
</head>
|
||||
|
||||
<body></body>
|
||||
|
@ -5,18 +5,9 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sunshine</title>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
|
||||
<link href="/third_party/bootstrap.min.css" rel="stylesheet" />
|
||||
<script src="/third_party/bootstrap.bundle.min.js"></script>
|
||||
<script src="/third_party/vue.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
7
assets/web/third_party/bootstrap.bundle.min.js
vendored
Normal file
7
assets/web/third_party/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
assets/web/third_party/bootstrap.min.css
vendored
Normal file
7
assets/web/third_party/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
11965
assets/web/third_party/vue.js
vendored
Normal file
11965
assets/web/third_party/vue.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,7 @@ Package: sunshine
|
||||
Architecture: amd64
|
||||
Maintainer: @loki
|
||||
Priority: optional
|
||||
Version: 0.10.1
|
||||
Version: 0.10.2
|
||||
Depends: libssl1.1, libavdevice58, libboost-thread1.67.0 | libboost-thread1.71.0, libboost-filesystem1.67.0 | libboost-filesystem1.71.0, libboost-log1.67.0 | libboost-log1.71.0, libpulse0, libopus0, libxcb-shm0, libxcb-xfixes0, libxtst6, libevdev2, libdrm2
|
||||
Description: Gamestream host for Moonlight
|
||||
EOF
|
||||
|
@ -211,6 +211,27 @@ void getWelcomePage(resp_https_t response, req_https_t request) {
|
||||
response->write(header + content);
|
||||
}
|
||||
|
||||
void getBootstrapCss(resp_https_t response, req_https_t request) {
|
||||
print_req(request);
|
||||
|
||||
std::string content = read_file(WEB_DIR "third_party/bootstrap.min.css");
|
||||
response->write(content);
|
||||
}
|
||||
|
||||
void getBootstrapJs(resp_https_t response, req_https_t request) {
|
||||
print_req(request);
|
||||
|
||||
std::string content = read_file(WEB_DIR "third_party/bootstrap.bundle.min.js");
|
||||
response->write(content);
|
||||
}
|
||||
|
||||
void getVueJs(resp_https_t response, req_https_t request) {
|
||||
print_req(request);
|
||||
|
||||
std::string content = read_file(WEB_DIR "third_party/vue.js");
|
||||
response->write(content);
|
||||
}
|
||||
|
||||
void getApps(resp_https_t response, req_https_t request) {
|
||||
if(!authenticate(response, request)) return;
|
||||
|
||||
@ -490,24 +511,27 @@ void start() {
|
||||
ctx->use_certificate_chain_file(config::nvhttp.cert);
|
||||
ctx->use_private_key_file(config::nvhttp.pkey, boost::asio::ssl::context::pem);
|
||||
https_server_t server { ctx, 0 };
|
||||
server.default_resource = not_found;
|
||||
server.resource["^/$"]["GET"] = getIndexPage;
|
||||
server.resource["^/pin$"]["GET"] = getPinPage;
|
||||
server.resource["^/apps$"]["GET"] = getAppsPage;
|
||||
server.resource["^/clients$"]["GET"] = getClientsPage;
|
||||
server.resource["^/config$"]["GET"] = getConfigPage;
|
||||
server.resource["^/password$"]["GET"] = getPasswordPage;
|
||||
server.resource["^/welcome$"]["GET"] = getWelcomePage;
|
||||
server.resource["^/api/pin"]["POST"] = savePin;
|
||||
server.resource["^/api/apps$"]["GET"] = getApps;
|
||||
server.resource["^/api/apps$"]["POST"] = saveApp;
|
||||
server.resource["^/api/config$"]["GET"] = getConfig;
|
||||
server.resource["^/api/config$"]["POST"] = saveConfig;
|
||||
server.resource["^/api/password$"]["POST"] = savePassword;
|
||||
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
|
||||
server.config.reuse_address = true;
|
||||
server.config.address = "0.0.0.0"s;
|
||||
server.config.port = port_https;
|
||||
server.default_resource = not_found;
|
||||
server.resource["^/$"]["GET"] = getIndexPage;
|
||||
server.resource["^/pin$"]["GET"] = getPinPage;
|
||||
server.resource["^/apps$"]["GET"] = getAppsPage;
|
||||
server.resource["^/clients$"]["GET"] = getClientsPage;
|
||||
server.resource["^/config$"]["GET"] = getConfigPage;
|
||||
server.resource["^/password$"]["GET"] = getPasswordPage;
|
||||
server.resource["^/welcome$"]["GET"] = getWelcomePage;
|
||||
server.resource["^/api/pin"]["POST"] = savePin;
|
||||
server.resource["^/api/apps$"]["GET"] = getApps;
|
||||
server.resource["^/api/apps$"]["POST"] = saveApp;
|
||||
server.resource["^/api/config$"]["GET"] = getConfig;
|
||||
server.resource["^/api/config$"]["POST"] = saveConfig;
|
||||
server.resource["^/api/password$"]["POST"] = savePassword;
|
||||
server.resource["^/api/apps/([0-9]+)$"]["DELETE"] = deleteApp;
|
||||
server.resource["^/third_party/bootstrap.min.css$"]["GET"] = getBootstrapCss;
|
||||
server.resource["^/third_party/bootstrap.bundle.min.js$"]["GET"] = getBootstrapJs;
|
||||
server.resource["^/third_party/vue.js$"]["GET"] = getVueJs;
|
||||
server.config.reuse_address = true;
|
||||
server.config.address = "0.0.0.0"s;
|
||||
server.config.port = port_https;
|
||||
|
||||
try {
|
||||
server.bind();
|
||||
|
@ -9,12 +9,13 @@
|
||||
// They aren't likely to change any time soon.
|
||||
#define fourcc_code(a, b, c, d) ((std::uint32_t)(a) | ((std::uint32_t)(b) << 8) | \
|
||||
((std::uint32_t)(c) << 16) | ((std::uint32_t)(d) << 24))
|
||||
#define fourcc_mod_code(vendor, val) ((((uint64_t)vendor) << 56) | ((val)&0x00ffffffffffffffULL))
|
||||
#define DRM_FORMAT_R8 fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
|
||||
#define DRM_FORMAT_GR88 fourcc_code('G', 'R', '8', '8') /* [15:0] G:R 8:8 little endian */
|
||||
#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
|
||||
#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
|
||||
#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */
|
||||
|
||||
#define DRM_FORMAT_MOD_INVALID fourcc_mod_code(0, ((1ULL << 56) - 1))
|
||||
|
||||
#define SUNSHINE_SHADERS_DIR SUNSHINE_ASSETS_DIR "/shaders/opengl"
|
||||
|
||||
@ -278,11 +279,28 @@ int init() {
|
||||
} // namespace gbm
|
||||
|
||||
namespace egl {
|
||||
constexpr auto EGL_LINUX_DMA_BUF_EXT = 0x3270;
|
||||
constexpr auto EGL_LINUX_DRM_FOURCC_EXT = 0x3271;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_FD_EXT = 0x3272;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_OFFSET_EXT = 0x3273;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_PITCH_EXT = 0x3274;
|
||||
constexpr auto EGL_LINUX_DMA_BUF_EXT = 0x3270;
|
||||
constexpr auto EGL_LINUX_DRM_FOURCC_EXT = 0x3271;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_FD_EXT = 0x3272;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_OFFSET_EXT = 0x3273;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_PITCH_EXT = 0x3274;
|
||||
constexpr auto EGL_DMA_BUF_PLANE1_FD_EXT = 0x3275;
|
||||
constexpr auto EGL_DMA_BUF_PLANE1_OFFSET_EXT = 0x3276;
|
||||
constexpr auto EGL_DMA_BUF_PLANE1_PITCH_EXT = 0x3277;
|
||||
constexpr auto EGL_DMA_BUF_PLANE2_FD_EXT = 0x3278;
|
||||
constexpr auto EGL_DMA_BUF_PLANE2_OFFSET_EXT = 0x3279;
|
||||
constexpr auto EGL_DMA_BUF_PLANE2_PITCH_EXT = 0x327A;
|
||||
constexpr auto EGL_DMA_BUF_PLANE3_FD_EXT = 0x3440;
|
||||
constexpr auto EGL_DMA_BUF_PLANE3_OFFSET_EXT = 0x3441;
|
||||
constexpr auto EGL_DMA_BUF_PLANE3_PITCH_EXT = 0x3442;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT = 0x3443;
|
||||
constexpr auto EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT = 0x3444;
|
||||
constexpr auto EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT = 0x3445;
|
||||
constexpr auto EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT = 0x3446;
|
||||
constexpr auto EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT = 0x3447;
|
||||
constexpr auto EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT = 0x3448;
|
||||
constexpr auto EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT = 0x3449;
|
||||
constexpr auto EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT = 0x344A;
|
||||
|
||||
bool fail() {
|
||||
return eglGetError() != EGL_SUCCESS;
|
||||
@ -329,7 +347,6 @@ display_t make_display(util::Either<gbm::gbm_t::pointer, wl_display *> native_di
|
||||
"EGL_KHR_create_context",
|
||||
"EGL_KHR_surfaceless_context",
|
||||
"EGL_EXT_image_dma_buf_import",
|
||||
// "EGL_KHR_image_pixmap"
|
||||
};
|
||||
|
||||
for(auto ext : extensions) {
|
||||
@ -389,22 +406,87 @@ std::optional<ctx_t> make_ctx(display_t::pointer display) {
|
||||
|
||||
return ctx;
|
||||
}
|
||||
std::optional<rgb_t> import_source(display_t::pointer egl_display, const surface_descriptor_t &xrgb) {
|
||||
gl_drain_errors;
|
||||
|
||||
EGLAttrib img_attr_planes[13] {
|
||||
EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_XRGB8888,
|
||||
EGL_WIDTH, xrgb.width,
|
||||
EGL_HEIGHT, xrgb.height,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, xrgb.fd,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, xrgb.offset,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, xrgb.pitch,
|
||||
EGL_NONE
|
||||
};
|
||||
struct plane_attr_t {
|
||||
EGLAttrib fd;
|
||||
EGLAttrib offset;
|
||||
EGLAttrib pitch;
|
||||
EGLAttrib lo;
|
||||
EGLAttrib hi;
|
||||
};
|
||||
|
||||
inline plane_attr_t get_plane(std::uint32_t plane_indice) {
|
||||
switch(plane_indice) {
|
||||
case 0:
|
||||
return {
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT,
|
||||
};
|
||||
case 1:
|
||||
return {
|
||||
EGL_DMA_BUF_PLANE1_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE1_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE1_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT,
|
||||
};
|
||||
case 2:
|
||||
return {
|
||||
EGL_DMA_BUF_PLANE2_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE2_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE2_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT,
|
||||
};
|
||||
case 3:
|
||||
return {
|
||||
EGL_DMA_BUF_PLANE3_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE3_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE3_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT,
|
||||
};
|
||||
}
|
||||
|
||||
// Avoid warning
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<rgb_t> import_source(display_t::pointer egl_display, const surface_descriptor_t &xrgb) {
|
||||
EGLAttrib attribs[47];
|
||||
int atti = 0;
|
||||
attribs[atti++] = EGL_WIDTH;
|
||||
attribs[atti++] = xrgb.width;
|
||||
attribs[atti++] = EGL_HEIGHT;
|
||||
attribs[atti++] = xrgb.height;
|
||||
attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
attribs[atti++] = xrgb.fourcc;
|
||||
|
||||
for(auto x = 0; x < xrgb.obj_count; ++x) {
|
||||
auto plane_attr = get_plane(xrgb.plane_indices[x]);
|
||||
|
||||
attribs[atti++] = plane_attr.fd;
|
||||
attribs[atti++] = xrgb.fds[x];
|
||||
attribs[atti++] = plane_attr.offset;
|
||||
attribs[atti++] = xrgb.offsets[x];
|
||||
attribs[atti++] = plane_attr.pitch;
|
||||
attribs[atti++] = xrgb.pitches[x];
|
||||
|
||||
if(xrgb.modifier && xrgb.modifier != DRM_FORMAT_MOD_INVALID) {
|
||||
attribs[atti++] = plane_attr.lo;
|
||||
attribs[atti++] = xrgb.modifier & 0xFFFFFFFF;
|
||||
attribs[atti++] = plane_attr.hi;
|
||||
attribs[atti++] = xrgb.modifier >> 32;
|
||||
}
|
||||
}
|
||||
attribs[atti++] = EGL_NONE;
|
||||
|
||||
rgb_t rgb {
|
||||
egl_display,
|
||||
eglCreateImage(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, img_attr_planes),
|
||||
eglCreateImage(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs),
|
||||
gl::tex_t::make(1)
|
||||
};
|
||||
|
||||
@ -429,17 +511,17 @@ std::optional<nv12_t> import_target(display_t::pointer egl_display, std::array<f
|
||||
{ EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_R8,
|
||||
EGL_WIDTH, r8.width,
|
||||
EGL_HEIGHT, r8.height,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, r8.fd,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, r8.offset,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, r8.pitch,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, r8.fds[0],
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, r8.offsets[0],
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, r8.pitches[0],
|
||||
EGL_NONE },
|
||||
|
||||
{ EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_GR88,
|
||||
EGL_WIDTH, gr88.width,
|
||||
EGL_HEIGHT, gr88.height,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, r8.fd,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, gr88.offset,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, gr88.pitch,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT, r8.fds[0],
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT, gr88.offsets[0],
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT, gr88.pitches[0],
|
||||
EGL_NONE },
|
||||
};
|
||||
|
||||
@ -728,4 +810,4 @@ int sws_t::convert(nv12_t &nv12) {
|
||||
|
||||
void free_frame(AVFrame *frame) {
|
||||
av_frame_free(&frame);
|
||||
}
|
||||
}
|
||||
|
@ -213,12 +213,16 @@ KITTY_USING_MOVE_T(ctx_t, (std::tuple<display_t::pointer, EGLContext>), , {
|
||||
});
|
||||
|
||||
struct surface_descriptor_t {
|
||||
int fd;
|
||||
int obj_count;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int offset;
|
||||
int pitch;
|
||||
int fds[4];
|
||||
std::uint32_t fourcc;
|
||||
std::uint64_t modifier;
|
||||
std::uint32_t pitches[4];
|
||||
std::uint32_t offsets[4];
|
||||
std::uint32_t plane_indices[4];
|
||||
};
|
||||
|
||||
display_t make_display(util::Either<gbm::gbm_t::pointer, wl_display *> native_display);
|
||||
@ -245,14 +249,19 @@ public:
|
||||
// Allow cursor and the underlying image to be kept together
|
||||
class img_descriptor_t : public cursor_t {
|
||||
public:
|
||||
std::uint32_t format;
|
||||
std::uint32_t img_width, img_height;
|
||||
std::uint32_t obj_count;
|
||||
std::uint32_t strides[4];
|
||||
// std::uint32_t sizes[4];
|
||||
std::int32_t fds[4];
|
||||
std::uint32_t offsets[4];
|
||||
// std::uint32_t plane_indices[4];
|
||||
~img_descriptor_t() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
std::for_each_n(sd.fds, sd.obj_count, [](int fd) {
|
||||
close(fd);
|
||||
});
|
||||
|
||||
sd.obj_count = 0;
|
||||
}
|
||||
|
||||
surface_descriptor_t sd;
|
||||
|
||||
// Increment sequence when new rgb_t needs to be created
|
||||
std::uint64_t sequence;
|
||||
@ -295,4 +304,4 @@ public:
|
||||
bool fail();
|
||||
} // namespace egl
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -24,12 +24,56 @@ namespace fs = std::filesystem;
|
||||
namespace platf {
|
||||
|
||||
namespace kms {
|
||||
|
||||
class wrapper_fb {
|
||||
public:
|
||||
wrapper_fb(drmModeFB *fb)
|
||||
: fb { fb }, fb_id { fb->fb_id }, width { fb->width }, height { fb->height } {
|
||||
pixel_format = DRM_FORMAT_XRGB8888;
|
||||
modifier = DRM_FORMAT_MOD_INVALID;
|
||||
std::fill_n(handles, 4, 0);
|
||||
std::fill_n(pitches, 4, 0);
|
||||
std::fill_n(offsets, 4, 0);
|
||||
handles[0] = fb->handle;
|
||||
pitches[0] = fb->pitch;
|
||||
}
|
||||
|
||||
wrapper_fb(drmModeFB2 *fb2)
|
||||
: fb2 { fb2 }, fb_id { fb2->fb_id }, width { fb2->width }, height { fb2->height } {
|
||||
pixel_format = fb2->pixel_format;
|
||||
modifier = fb2->modifier;
|
||||
|
||||
memcpy(handles, fb2->handles, sizeof(handles));
|
||||
memcpy(pitches, fb2->pitches, sizeof(pitches));
|
||||
memcpy(offsets, fb2->offsets, sizeof(offsets));
|
||||
}
|
||||
|
||||
~wrapper_fb() {
|
||||
if(fb) {
|
||||
drmModeFreeFB(fb);
|
||||
}
|
||||
else if(fb2) {
|
||||
drmModeFreeFB2(fb2);
|
||||
}
|
||||
}
|
||||
|
||||
drmModeFB *fb = nullptr;
|
||||
drmModeFB2 *fb2 = nullptr;
|
||||
uint32_t fb_id;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t pixel_format;
|
||||
uint64_t modifier;
|
||||
uint32_t handles[4];
|
||||
uint32_t pitches[4];
|
||||
uint32_t offsets[4];
|
||||
};
|
||||
|
||||
using plane_res_t = util::safe_ptr<drmModePlaneRes, drmModeFreePlaneResources>;
|
||||
using encoder_t = util::safe_ptr<drmModeEncoder, drmModeFreeEncoder>;
|
||||
using res_t = util::safe_ptr<drmModeRes, drmModeFreeResources>;
|
||||
using plane_t = util::safe_ptr<drmModePlane, drmModeFreePlane>;
|
||||
using fb_t = util::safe_ptr<drmModeFB, drmModeFreeFB>;
|
||||
using fb2_t = util::safe_ptr<drmModeFB2, drmModeFreeFB2>;
|
||||
using fb_t = std::unique_ptr<wrapper_fb>;
|
||||
using crtc_t = util::safe_ptr<drmModeCrtc, drmModeFreeCrtc>;
|
||||
using obj_prop_t = util::safe_ptr<drmModeObjectProperties, drmModeFreeObjectProperties>;
|
||||
using prop_t = util::safe_ptr<drmModePropertyRes, drmModeFreeProperty>;
|
||||
@ -182,11 +226,11 @@ public:
|
||||
}
|
||||
|
||||
fb_t fb(plane_t::pointer plane) {
|
||||
return drmModeGetFB(fd.el, plane->fb_id);
|
||||
}
|
||||
|
||||
fb2_t fb2(plane_t::pointer plane) {
|
||||
return drmModeGetFB2(fd.el, plane->fb_id);
|
||||
auto fb = drmModeGetFB2(fd.el, plane->fb_id);
|
||||
if(fb) {
|
||||
return std::make_unique<wrapper_fb>(fb);
|
||||
}
|
||||
return std::make_unique<wrapper_fb>(drmModeGetFB(fd.el, plane->fb_id));
|
||||
}
|
||||
|
||||
crtc_t crtc(std::uint32_t id) {
|
||||
@ -332,11 +376,7 @@ struct kms_img_t : public img_t {
|
||||
}
|
||||
};
|
||||
|
||||
struct kms_vram_img_t : public egl::img_descriptor_t {
|
||||
file_t fb_fd;
|
||||
};
|
||||
|
||||
void print(plane_t::pointer plane, fb2_t::pointer fb, crtc_t::pointer crtc) {
|
||||
void print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer crtc) {
|
||||
if(crtc) {
|
||||
BOOST_LOG(debug) << "crtc("sv << crtc->x << ", "sv << crtc->y << ')';
|
||||
BOOST_LOG(debug) << "crtc("sv << crtc->width << ", "sv << crtc->height << ')';
|
||||
@ -403,7 +443,7 @@ public:
|
||||
continue;
|
||||
}
|
||||
|
||||
auto fb = card.fb2(plane.get());
|
||||
auto fb = card.fb(plane.get());
|
||||
if(!fb) {
|
||||
BOOST_LOG(error) << "Couldn't get drm fb for plane ["sv << plane->fb_id << "]: "sv << strerror(errno);
|
||||
return -1;
|
||||
@ -415,10 +455,16 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
file_t fb_fd = card.handleFD(fb->handles[0]);
|
||||
if(fb_fd.el < 0) {
|
||||
BOOST_LOG(error) << "Couldn't get primary file descriptor for Framebuffer ["sv << fb->fb_id << "]: "sv << strerror(errno);
|
||||
return -1;
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
if(!fb->handles[i]) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto fb_fd = card.handleFD(fb->handles[i]);
|
||||
if(fb_fd.el < 0) {
|
||||
BOOST_LOG(error) << "Couldn't get primary file descriptor for Framebuffer ["sv << fb->fb_id << "]: "sv << strerror(errno);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_LOG(info) << "Found monitor for DRM screencasting"sv;
|
||||
@ -435,6 +481,8 @@ public:
|
||||
return -1;
|
||||
}
|
||||
|
||||
//TODO: surf_sd = fb->to_sd();
|
||||
|
||||
auto crct = card.crtc(plane->crtc_id);
|
||||
kms::print(plane.get(), fb.get(), crct.get());
|
||||
|
||||
@ -486,10 +534,10 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline capture_e refresh(file_t *file) {
|
||||
inline capture_e refresh(file_t *file, egl::surface_descriptor_t *sd) {
|
||||
plane_t plane = drmModeGetPlane(card.fd.el, plane_id);
|
||||
|
||||
auto fb = card.fb2(plane.get());
|
||||
auto fb = card.fb(plane.get());
|
||||
if(!fb) {
|
||||
BOOST_LOG(error) << "Couldn't get drm fb for plane ["sv << plane->fb_id << "]: "sv << strerror(errno);
|
||||
return capture_e::error;
|
||||
@ -501,20 +549,43 @@ public:
|
||||
return capture_e::error;
|
||||
}
|
||||
|
||||
*file = card.handleFD(fb->handles[0]);
|
||||
if(file->el < 0) {
|
||||
BOOST_LOG(error) << "Couldn't get primary file descriptor for Framebuffer ["sv << fb->fb_id << "]: "sv << strerror(errno);
|
||||
return capture_e::error;
|
||||
auto obj_count = 4;
|
||||
|
||||
int x = 0;
|
||||
for(int y = 0; y < 4; ++y) {
|
||||
if(!fb->handles[y]) {
|
||||
// It's not clear wheter there could still be valid handles left.
|
||||
// So, continue anyway.
|
||||
// TODO: Is this redundent?
|
||||
--obj_count;
|
||||
continue;
|
||||
}
|
||||
|
||||
file[x] = card.handleFD(fb->handles[x]);
|
||||
if(file[x].el < 0) {
|
||||
BOOST_LOG(error) << "Couldn't get primary file descriptor for Framebuffer ["sv << fb->fb_id << "]: "sv << strerror(errno);
|
||||
return capture_e::error;
|
||||
}
|
||||
|
||||
sd->fds[x] = file[x].el;
|
||||
sd->offsets[x] = fb->offsets[y];
|
||||
sd->pitches[x] = fb->pitches[y];
|
||||
sd->plane_indices[x] = y;
|
||||
}
|
||||
|
||||
sd->width = fb->width;
|
||||
sd->height = fb->height;
|
||||
sd->modifier = fb->modifier;
|
||||
sd->fourcc = fb->pixel_format;
|
||||
sd->obj_count = obj_count;
|
||||
|
||||
if(
|
||||
fb->width != img_width ||
|
||||
fb->height != img_height) {
|
||||
return capture_e::reinit;
|
||||
}
|
||||
|
||||
pitch = fb->pitches[0];
|
||||
offset = fb->offsets[0];
|
||||
++x;
|
||||
|
||||
return capture_e::ok;
|
||||
}
|
||||
@ -526,8 +597,6 @@ public:
|
||||
int img_width, img_height;
|
||||
int img_offset_x, img_offset_y;
|
||||
|
||||
int pitch;
|
||||
int offset;
|
||||
int plane_id;
|
||||
|
||||
card_t card;
|
||||
@ -613,21 +682,16 @@ public:
|
||||
}
|
||||
|
||||
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
|
||||
file_t fb_fd;
|
||||
file_t fb_fd[4];
|
||||
|
||||
auto status = refresh(&fb_fd);
|
||||
egl::surface_descriptor_t sd;
|
||||
|
||||
auto status = refresh(fb_fd, &sd);
|
||||
if(status != capture_e::ok) {
|
||||
return status;
|
||||
}
|
||||
|
||||
auto rgb_opt = egl::import_source(display.get(),
|
||||
{
|
||||
fb_fd.el,
|
||||
img_width,
|
||||
img_height,
|
||||
offset,
|
||||
pitch,
|
||||
});
|
||||
auto rgb_opt = egl::import_source(display.get(), sd);
|
||||
|
||||
if(!rgb_opt) {
|
||||
return capture_e::error;
|
||||
@ -679,24 +743,20 @@ public:
|
||||
}
|
||||
|
||||
std::shared_ptr<img_t> alloc_img() override {
|
||||
auto img = std::make_shared<kms_vram_img_t>();
|
||||
auto img = std::make_shared<egl::img_descriptor_t>();
|
||||
|
||||
img->serial = std::numeric_limits<decltype(img->serial)>::max();
|
||||
img->data = nullptr;
|
||||
img->pixel_pitch = 4;
|
||||
|
||||
img->sequence = 0;
|
||||
|
||||
img->obj_count = 1;
|
||||
img->img_width = img_width;
|
||||
img->img_height = img_height;
|
||||
img->sequence = 0;
|
||||
img->sd.obj_count = 0;
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
int dummy_img(platf::img_t *img) override {
|
||||
snapshot(img, 1s, false);
|
||||
return 0;
|
||||
return snapshot(img, 1s, false) != capture_e::ok;
|
||||
}
|
||||
|
||||
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) {
|
||||
@ -734,25 +794,24 @@ public:
|
||||
}
|
||||
|
||||
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds /* timeout */, bool cursor) {
|
||||
file_t fb_fd;
|
||||
file_t fb_fd[4];
|
||||
|
||||
auto status = refresh(&fb_fd);
|
||||
auto img = (egl::img_descriptor_t *)img_out_base;
|
||||
img->reset();
|
||||
|
||||
auto status = refresh(fb_fd, &img->sd);
|
||||
if(status != capture_e::ok) {
|
||||
return status;
|
||||
}
|
||||
|
||||
auto img = (kms_vram_img_t *)img_out_base;
|
||||
|
||||
img->fb_fd = std::move(fb_fd);
|
||||
img->sequence = ++sequence;
|
||||
img->fds[0] = img->fb_fd.el;
|
||||
img->offsets[0] = offset;
|
||||
img->strides[0] = pitch;
|
||||
img->sequence = ++sequence;
|
||||
|
||||
if(!cursor || !cursor_opt) {
|
||||
img_out_base->data = nullptr;
|
||||
|
||||
|
||||
for(auto x = 0; x < img->sd.obj_count; ++x) {
|
||||
fb_fd[x].release();
|
||||
}
|
||||
return capture_e::ok;
|
||||
}
|
||||
|
||||
@ -761,6 +820,9 @@ public:
|
||||
img->x -= offset_x;
|
||||
img->y -= offset_y;
|
||||
|
||||
for(auto x = 0; x < img->sd.obj_count; ++x) {
|
||||
fb_fd[x].release();
|
||||
}
|
||||
return capture_e::ok;
|
||||
}
|
||||
|
||||
@ -897,7 +959,7 @@ std::vector<std::string> kms_display_names() {
|
||||
|
||||
auto end = std::end(card);
|
||||
for(auto plane = std::begin(card); plane != end; ++plane) {
|
||||
auto fb = card.fb2(plane.get());
|
||||
auto fb = card.fb(plane.get());
|
||||
if(!fb) {
|
||||
BOOST_LOG(error) << "Couldn't get drm fb for plane ["sv << plane->fb_id << "]: "sv << strerror(errno);
|
||||
continue;
|
||||
@ -970,4 +1032,4 @@ std::vector<std::string> kms_display_names() {
|
||||
return display_names;
|
||||
}
|
||||
|
||||
} // namespace platf
|
||||
} // namespace platf
|
||||
|
@ -350,20 +350,22 @@ public:
|
||||
auto nv12_opt = egl::import_target(
|
||||
display.get(),
|
||||
std::move(fds),
|
||||
{
|
||||
prime.objects[prime.layers[0].object_index[0]].fd,
|
||||
{ 1,
|
||||
(int)prime.width,
|
||||
(int)prime.height,
|
||||
(int)prime.layers[0].offset[0],
|
||||
(int)prime.layers[0].pitch[0],
|
||||
},
|
||||
{
|
||||
prime.objects[prime.layers[0].object_index[1]].fd,
|
||||
{ prime.objects[prime.layers[0].object_index[0]].fd, -1, -1, -1 },
|
||||
0,
|
||||
0,
|
||||
{ prime.layers[0].pitch[0] },
|
||||
{ prime.layers[0].offset[0] } },
|
||||
{ 1,
|
||||
(int)prime.width / 2,
|
||||
(int)prime.height / 2,
|
||||
(int)prime.layers[0].offset[1],
|
||||
(int)prime.layers[0].pitch[1],
|
||||
});
|
||||
{ prime.objects[prime.layers[0].object_index[1]].fd, -1, -1, -1 },
|
||||
0,
|
||||
0,
|
||||
{ prime.layers[0].pitch[1] },
|
||||
{ prime.layers[0].offset[1] } });
|
||||
|
||||
if(!nv12_opt) {
|
||||
return -1;
|
||||
@ -419,14 +421,7 @@ public:
|
||||
|
||||
rgb = egl::rgb_t {};
|
||||
|
||||
auto rgb_opt = egl::import_source(display.get(),
|
||||
{
|
||||
descriptor.fds[0],
|
||||
(int)descriptor.img_width,
|
||||
(int)descriptor.img_height,
|
||||
(int)descriptor.offsets[0],
|
||||
(int)descriptor.strides[0],
|
||||
});
|
||||
auto rgb_opt = egl::import_source(display.get(), descriptor.sd);
|
||||
|
||||
if(!rgb_opt) {
|
||||
return -1;
|
||||
@ -657,4 +652,4 @@ std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, int offs
|
||||
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram) {
|
||||
return make_hwdevice(width, height, 0, 0, vram);
|
||||
}
|
||||
} // namespace va
|
||||
} // namespace va
|
||||
|
@ -164,10 +164,15 @@ void dmabuf_t::frame(
|
||||
std::uint32_t obj_count) {
|
||||
auto next_frame = get_next_frame();
|
||||
|
||||
next_frame->format = format;
|
||||
next_frame->width = width;
|
||||
next_frame->height = height;
|
||||
next_frame->obj_count = obj_count;
|
||||
next_frame->sd.fourcc = format;
|
||||
next_frame->sd.width = width;
|
||||
next_frame->sd.height = height;
|
||||
next_frame->sd.modifier = (((std::uint64_t)high) << 32) | low;
|
||||
next_frame->obj_count = obj_count;
|
||||
|
||||
std::fill_n(next_frame->sd.fds + obj_count, 4 - obj_count, -1);
|
||||
std::fill_n(next_frame->sd.pitches + obj_count, 4 - obj_count, 0);
|
||||
std::fill_n(next_frame->sd.offsets + obj_count, 4 - obj_count, 0);
|
||||
}
|
||||
|
||||
void dmabuf_t::object(
|
||||
@ -180,11 +185,10 @@ void dmabuf_t::object(
|
||||
std::uint32_t plane_index) {
|
||||
auto next_frame = get_next_frame();
|
||||
|
||||
next_frame->fds[index] = fd;
|
||||
next_frame->sizes[index] = size;
|
||||
next_frame->strides[index] = stride;
|
||||
next_frame->offsets[index] = offset;
|
||||
next_frame->plane_indices[index] = plane_index;
|
||||
next_frame->sd.fds[index] = fd;
|
||||
next_frame->sd.pitches[index] = stride;
|
||||
next_frame->sd.offsets[index] = offset;
|
||||
next_frame->sd.plane_indices[index] = plane_index;
|
||||
}
|
||||
|
||||
void dmabuf_t::ready(
|
||||
@ -213,7 +217,7 @@ void dmabuf_t::cancel(
|
||||
|
||||
void frame_t::destroy() {
|
||||
for(auto x = 0; x < obj_count; ++x) {
|
||||
close(fds[x]);
|
||||
close(sd.fds[x]);
|
||||
}
|
||||
|
||||
obj_count = 0;
|
||||
|
@ -21,14 +21,9 @@ using display_internal_t = util::safe_ptr<wl_display, wl_display_disconnect>;
|
||||
|
||||
class frame_t {
|
||||
public:
|
||||
std::uint32_t format;
|
||||
std::uint32_t width, height;
|
||||
egl::surface_descriptor_t sd;
|
||||
|
||||
std::uint32_t obj_count;
|
||||
std::uint32_t strides[4];
|
||||
std::uint32_t sizes[4];
|
||||
std::int32_t fds[4];
|
||||
std::uint32_t offsets[4];
|
||||
std::uint32_t plane_indices[4];
|
||||
|
||||
void destroy();
|
||||
};
|
||||
|
@ -16,21 +16,6 @@ struct img_t : public platf::img_t {
|
||||
}
|
||||
};
|
||||
|
||||
class frame_descriptor_t : public egl::img_descriptor_t {
|
||||
public:
|
||||
~frame_descriptor_t() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
std::for_each_n(fds, obj_count, [](int fd) {
|
||||
close(fd);
|
||||
});
|
||||
|
||||
obj_count = 0;
|
||||
}
|
||||
};
|
||||
|
||||
class wlr_t : public platf::display_t {
|
||||
public:
|
||||
int init(platf::mem_type_e hwdevice_type, const std::string &display_name, int framerate) {
|
||||
@ -107,8 +92,8 @@ public:
|
||||
|
||||
if(
|
||||
dmabuf.status == dmabuf_t::REINIT ||
|
||||
current_frame->width != width ||
|
||||
current_frame->height != height) {
|
||||
current_frame->sd.width != width ||
|
||||
current_frame->sd.height != height) {
|
||||
|
||||
return platf::capture_e::reinit;
|
||||
}
|
||||
@ -170,14 +155,7 @@ public:
|
||||
|
||||
auto current_frame = dmabuf.current_frame;
|
||||
|
||||
auto rgb_opt = egl::import_source(egl_display.get(),
|
||||
{
|
||||
current_frame->fds[0],
|
||||
(int)current_frame->width,
|
||||
(int)current_frame->height,
|
||||
(int)current_frame->offsets[0],
|
||||
(int)current_frame->strides[0],
|
||||
});
|
||||
auto rgb_opt = egl::import_source(egl_display.get(), current_frame->sd);
|
||||
|
||||
if(!rgb_opt) {
|
||||
return platf::capture_e::reinit;
|
||||
@ -274,7 +252,7 @@ public:
|
||||
return status;
|
||||
}
|
||||
|
||||
auto img = (frame_descriptor_t *)img_out_base;
|
||||
auto img = (egl::img_descriptor_t *)img_out_base;
|
||||
img->reset();
|
||||
|
||||
auto current_frame = dmabuf.current_frame;
|
||||
@ -282,14 +260,8 @@ public:
|
||||
++sequence;
|
||||
img->sequence = sequence;
|
||||
|
||||
img->obj_count = 1;
|
||||
img->img_width = current_frame->width;
|
||||
img->img_height = current_frame->height;
|
||||
img->obj_count = current_frame->obj_count;
|
||||
|
||||
std::copy_n(std::begin(current_frame->fds), current_frame->obj_count, img->fds);
|
||||
std::copy_n(std::begin(current_frame->offsets), current_frame->obj_count, img->offsets);
|
||||
std::copy_n(std::begin(current_frame->strides), current_frame->obj_count, img->strides);
|
||||
img->sd = current_frame->sd;
|
||||
img->sd.obj_count = current_frame->obj_count;
|
||||
|
||||
// Prevent dmabuf from closing the file descriptors.
|
||||
current_frame->obj_count = 0;
|
||||
@ -298,13 +270,11 @@ public:
|
||||
}
|
||||
|
||||
std::shared_ptr<platf::img_t> alloc_img() override {
|
||||
auto img = std::make_shared<frame_descriptor_t>();
|
||||
auto img = std::make_shared<egl::img_descriptor_t>();
|
||||
|
||||
img->img_width = width;
|
||||
img->img_height = height;
|
||||
img->sequence = 0;
|
||||
img->serial = std::numeric_limits<decltype(img->serial)>::max();
|
||||
img->data = nullptr;
|
||||
img->sequence = 0;
|
||||
img->serial = std::numeric_limits<decltype(img->serial)>::max();
|
||||
img->data = nullptr;
|
||||
|
||||
return img;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include "main.h"
|
||||
#include "utility.h"
|
||||
@ -109,14 +110,17 @@ int proc_t::execute(int app_id) {
|
||||
if(proc.cmd.empty()) {
|
||||
BOOST_LOG(debug) << "Executing [Desktop]"sv;
|
||||
placebo = true;
|
||||
}
|
||||
else if(proc.output.empty() || proc.output == "null"sv) {
|
||||
BOOST_LOG(info) << "Executing: ["sv << proc.cmd << ']';
|
||||
_process = bp::child(_process_handle, proc.cmd, _env, bp::std_out > bp::null, bp::std_err > bp::null, ec);
|
||||
}
|
||||
else {
|
||||
BOOST_LOG(info) << "Executing: ["sv << proc.cmd << ']';
|
||||
_process = bp::child(_process_handle, proc.cmd, _env, bp::std_out > _pipe.get(), bp::std_err > _pipe.get(), ec);
|
||||
} else {
|
||||
boost::filesystem::path working_dir = proc.working_dir.empty() ?
|
||||
boost::filesystem::path(proc.cmd).parent_path() : boost::filesystem::path(proc.working_dir);
|
||||
if(proc.output.empty() || proc.output == "null"sv) {
|
||||
BOOST_LOG(info) << "Executing: ["sv << proc.cmd << ']';
|
||||
_process = bp::child(_process_handle, proc.cmd, _env, bp::start_dir(working_dir), bp::std_out > bp::null, bp::std_err > bp::null, ec);
|
||||
}
|
||||
else {
|
||||
BOOST_LOG(info) << "Executing: ["sv << proc.cmd << ']';
|
||||
_process = bp::child(_process_handle, proc.cmd, _env, bp::start_dir(working_dir), bp::std_out > _pipe.get(), bp::std_err > _pipe.get(), ec);
|
||||
}
|
||||
}
|
||||
|
||||
if(ec) {
|
||||
@ -275,6 +279,7 @@ std::optional<proc::proc_t> parse(const std::string &file_name) {
|
||||
auto output = app_node.get_optional<std::string>("output"s);
|
||||
auto name = parse_env_val(this_env, app_node.get<std::string>("name"s));
|
||||
auto cmd = app_node.get_optional<std::string>("cmd"s);
|
||||
auto working_dir = app_node.get_optional<std::string>("working-dir"s);
|
||||
|
||||
std::vector<proc::cmd_t> prep_cmds;
|
||||
if(prep_nodes_opt) {
|
||||
@ -312,6 +317,10 @@ std::optional<proc::proc_t> parse(const std::string &file_name) {
|
||||
ctx.cmd = parse_env_val(this_env, *cmd);
|
||||
}
|
||||
|
||||
if(working_dir) {
|
||||
ctx.working_dir = parse_env_val(this_env, *working_dir);
|
||||
}
|
||||
|
||||
ctx.name = std::move(name);
|
||||
ctx.prep_cmds = std::move(prep_cmds);
|
||||
ctx.detached = std::move(detached);
|
||||
|
@ -34,6 +34,7 @@ struct cmd_t {
|
||||
* cmd -- Runs indefinitely until:
|
||||
* No session is running and a different set of commands it to be executed
|
||||
* Command exits
|
||||
* working_dir -- the process working directory. This is required for some games to run properly.
|
||||
* cmd_output --
|
||||
* empty -- The output of the commands are appended to the output of sunshine
|
||||
* "null" -- The output of the commands are discarded
|
||||
@ -52,6 +53,7 @@ struct ctx_t {
|
||||
|
||||
std::string name;
|
||||
std::string cmd;
|
||||
std::string working_dir;
|
||||
std::string output;
|
||||
};
|
||||
|
||||
|
@ -46,6 +46,12 @@ struct argument_type<T(U)> { typedef U type; };
|
||||
element_type *operator->() { return ⪙ } \
|
||||
const element_type *operator->() const { return ⪙ } \
|
||||
\
|
||||
inline element_type release() { \
|
||||
element_type val = std::move(el); \
|
||||
el = element_type { init_val }; \
|
||||
return val; \
|
||||
} \
|
||||
\
|
||||
~move_t() z \
|
||||
\
|
||||
element_type el; \
|
||||
|
Loading…
x
Reference in New Issue
Block a user