clang: adjust formatting rules (#1015)

This commit is contained in:
ReenigneArcher
2023-03-27 21:45:29 -04:00
committed by GitHub
parent 79cf382cd9
commit 21eb4eb6dd
103 changed files with 26883 additions and 25173 deletions

View File

@@ -7,7 +7,7 @@
BasedOnStyle: LLVM BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: DontAlign AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: Consecutive AlignConsecutiveAssignments: false
AlignOperands: Align AlignOperands: Align
AllowAllArgumentsOnNextLine: false AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false AllowAllConstructorInitializersOnNextLine: false
@@ -18,8 +18,9 @@ AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLambdasOnASingleLine: All AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None AlignTrailingComments: false
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakAfterReturnType: All
AlwaysBreakTemplateDeclarations: MultiLine
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BraceWrapping: BraceWrapping:
AfterCaseLabel: false AfterCaseLabel: false
@@ -37,32 +38,32 @@ BraceWrapping:
SplitEmptyRecord: true SplitEmptyRecord: true
BreakBeforeBinaryOperators: None BreakBeforeBinaryOperators: None
BreakBeforeTernaryOperators: false BreakBeforeTernaryOperators: false
BreakConstructorInitializers: BeforeColon BreakConstructorInitializers: AfterColon
BreakInheritanceList: BeforeColon BreakInheritanceList: AfterColon
ColumnLimit: 0 ColumnLimit: 0
CompactNamespaces: false CompactNamespaces: false
ContinuationIndentWidth: 2 ContinuationIndentWidth: 2
IndentCaseLabels: false IndentCaseLabels: true
IndentPPDirectives: None IndentPPDirectives: BeforeHash
IndentWidth: 2 IndentWidth: 2
KeepEmptyLinesAtTheStartOfBlocks: true KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 2 MaxEmptyLinesToKeep: 1
NamespaceIndentation: None NamespaceIndentation: All
ObjCSpaceAfterProperty: false ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true ObjCSpaceBeforeProtocolList: true
PointerAlignment: Right PointerAlignment: Right
ReflowComments: false ReflowComments: false
SpaceAfterCStyleCast: false SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: true SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: true SpaceBeforeInheritanceColon: false
SpaceBeforeParens: Never SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1 SpacesBeforeTrailingComments: 2
SpacesInAngles: Never SpacesInAngles: Never
SpacesInCStyleCastParentheses: false SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false SpacesInContainerLiterals: false

View File

@@ -0,0 +1,40 @@
# standard imports
import os
import subprocess
# variables
directories = [
'src',
'tools',
os.path.join('third-party', 'glad'),
os.path.join('third-party', 'nvfbc'),
os.path.join('third-party', 'wayland-protocols')
]
file_types = [
'cpp',
'h',
'm',
'mm'
]
def clang_format(file: str):
print(f'Formatting {file} ...')
subprocess.run(['clang-format', '-i', file])
def main():
"""
Main entry point.
"""
# walk the directories
for directory in directories:
for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
if os.path.isfile(file_path) and file.rsplit('.')[-1] in file_types:
clang_format(file=file_path)
if __name__ == '__main__':
main()

View File

@@ -25,10 +25,13 @@ struct audio_ctx_t {
platf::sink_t sink; platf::sink_t sink;
}; };
static int start_audio_control(audio_ctx_t &ctx); static int
static void stop_audio_control(audio_ctx_t &); start_audio_control(audio_ctx_t &ctx);
static void
stop_audio_control(audio_ctx_t &);
int map_stream(int channels, bool quality); int
map_stream(int channels, bool quality);
constexpr auto SAMPLE_RATE = 48000; constexpr auto SAMPLE_RATE = 48000;
@@ -85,7 +88,8 @@ opus_stream_config_t stream_configs[MAX_STREAM_CONFIG] {
auto control_shared = safe::make_shared<audio_ctx_t>(start_audio_control, stop_audio_control); auto control_shared = safe::make_shared<audio_ctx_t>(start_audio_control, stop_audio_control);
void encodeThread(sample_queue_t samples, config_t config, void *channel_data) { void
encodeThread(sample_queue_t samples, config_t config, void *channel_data) {
auto packets = mail::man->queue<packet_t>(mail::audio_packets); auto packets = mail::man->queue<packet_t>(mail::audio_packets);
auto stream = &stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])]; auto stream = &stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])];
@@ -121,7 +125,8 @@ void encodeThread(sample_queue_t samples, config_t config, void *channel_data) {
} }
} }
void capture(safe::mail_t mail, config_t config, void *channel_data) { void
capture(safe::mail_t mail, config_t config, void *channel_data) {
auto shutdown_event = mail->event<bool>(mail::shutdown); auto shutdown_event = mail->event<bool>(mail::shutdown);
auto stream = &stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])]; auto stream = &stream_configs[map_stream(config.channels, config.flags[config_t::HIGH_QUALITY])];
@@ -226,7 +231,8 @@ void capture(safe::mail_t mail, config_t config, void *channel_data) {
} }
} }
int map_stream(int channels, bool quality) { int
map_stream(int channels, bool quality) {
int shift = quality ? 1 : 0; int shift = quality ? 1 : 0;
switch (channels) { switch (channels) {
case 2: case 2:
@@ -239,7 +245,8 @@ int map_stream(int channels, bool quality) {
return STEREO; return STEREO;
} }
int start_audio_control(audio_ctx_t &ctx) { int
start_audio_control(audio_ctx_t &ctx) {
auto fg = util::fail_guard([]() { auto fg = util::fail_guard([]() {
BOOST_LOG(warning) << "There will be no audio"sv; BOOST_LOG(warning) << "There will be no audio"sv;
}); });
@@ -266,7 +273,8 @@ int start_audio_control(audio_ctx_t &ctx) {
return 0; return 0;
} }
void stop_audio_control(audio_ctx_t &ctx) { void
stop_audio_control(audio_ctx_t &ctx) {
// restore audio-sink if applicable // restore audio-sink if applicable
if (!ctx.restore_sink) { if (!ctx.restore_sink) {
return; return;

View File

@@ -41,7 +41,8 @@ struct config_t {
using buffer_t = util::buffer_t<std::uint8_t>; using buffer_t = util::buffer_t<std::uint8_t>;
using packet_t = std::pair<void *, buffer_t>; using packet_t = std::pair<void *, buffer_t>;
void capture(safe::mail_t mail, config_t config, void *channel_data); void
capture(safe::mail_t mail, config_t config, void *channel_data);
} // namespace audio } // namespace audio
#endif #endif

View File

@@ -12,7 +12,8 @@ extern "C" {
using namespace std::literals; using namespace std::literals;
namespace cbs { namespace cbs {
void close(CodedBitstreamContext *c) { void
close(CodedBitstreamContext *c) {
ff_cbs_close(&c); ff_cbs_close(&c);
} }
@@ -31,7 +32,8 @@ public:
std::fill_n((std::uint8_t *) this, sizeof(*this), 0); std::fill_n((std::uint8_t *) this, sizeof(*this), 0);
} }
frag_t &operator=(frag_t &&o) { frag_t &
operator=(frag_t &&o) {
std::copy((std::uint8_t *) &o, (std::uint8_t *) (&o + 1), (std::uint8_t *) this); std::copy((std::uint8_t *) &o, (std::uint8_t *) (&o + 1), (std::uint8_t *) this);
o.data = nullptr; o.data = nullptr;
@@ -40,7 +42,6 @@ public:
return *this; return *this;
}; };
~frag_t() { ~frag_t() {
if (data || units) { if (data || units) {
ff_cbs_fragment_free(this); ff_cbs_fragment_free(this);
@@ -48,7 +49,8 @@ public:
} }
}; };
util::buffer_t<std::uint8_t> write(const cbs::ctx_t &cbs_ctx, std::uint8_t nal, void *uh, AVCodecID codec_id) { util::buffer_t<std::uint8_t>
write(const cbs::ctx_t &cbs_ctx, std::uint8_t nal, void *uh, AVCodecID codec_id) {
cbs::frag_t frag; cbs::frag_t frag;
auto err = ff_cbs_insert_unit_content(&frag, -1, nal, uh, nullptr); auto err = ff_cbs_insert_unit_content(&frag, -1, nal, uh, nullptr);
if (err < 0) { if (err < 0) {
@@ -73,14 +75,16 @@ util::buffer_t<std::uint8_t> write(const cbs::ctx_t &cbs_ctx, std::uint8_t nal,
return data; return data;
} }
util::buffer_t<std::uint8_t> write(std::uint8_t nal, void *uh, AVCodecID codec_id) { util::buffer_t<std::uint8_t>
write(std::uint8_t nal, void *uh, AVCodecID codec_id) {
cbs::ctx_t cbs_ctx; cbs::ctx_t cbs_ctx;
ff_cbs_init(&cbs_ctx, codec_id, nullptr); ff_cbs_init(&cbs_ctx, codec_id, nullptr);
return write(cbs_ctx, nal, uh, codec_id); return write(cbs_ctx, nal, uh, codec_id);
} }
util::buffer_t<std::uint8_t> make_sps_h264(const AVCodecContext *ctx) { util::buffer_t<std::uint8_t>
make_sps_h264(const AVCodecContext *ctx) {
H264RawSPS sps {}; H264RawSPS sps {};
/* b_per_p == ctx->max_b_frames for h264 */ /* b_per_p == ctx->max_b_frames for h264 */
@@ -91,7 +95,6 @@ util::buffer_t<std::uint8_t> make_sps_h264(const AVCodecContext *ctx) {
auto mb_width = (FFALIGN(ctx->width, 16) / 16) * 16; auto mb_width = (FFALIGN(ctx->width, 16) / 16) * 16;
auto mb_height = (FFALIGN(ctx->height, 16) / 16) * 16; auto mb_height = (FFALIGN(ctx->height, 16) / 16) * 16;
sps.nal_unit_header.nal_ref_idc = 3; sps.nal_unit_header.nal_ref_idc = 3;
sps.nal_unit_header.nal_unit_type = H264_NAL_SPS; sps.nal_unit_header.nal_unit_type = H264_NAL_SPS;
@@ -168,7 +171,8 @@ util::buffer_t<std::uint8_t> make_sps_h264(const AVCodecContext *ctx) {
return write(sps.nal_unit_header.nal_unit_type, (void *) &sps.nal_unit_header, AV_CODEC_ID_H264); return write(sps.nal_unit_header.nal_unit_type, (void *) &sps.nal_unit_header, AV_CODEC_ID_H264);
} }
hevc_t make_sps_hevc(const AVCodecContext *avctx, const AVPacket *packet) { hevc_t
make_sps_hevc(const AVCodecContext *avctx, const AVPacket *packet) {
cbs::ctx_t ctx; cbs::ctx_t ctx;
if (ff_cbs_init(&ctx, AV_CODEC_ID_H265, nullptr)) { if (ff_cbs_init(&ctx, AV_CODEC_ID_H265, nullptr)) {
return {}; return {};
@@ -184,7 +188,6 @@ hevc_t make_sps_hevc(const AVCodecContext *avctx, const AVPacket *packet) {
return {}; return {};
} }
auto vps_p = ((CodedBitstreamH265Context *) ctx->priv_data)->active_vps; auto vps_p = ((CodedBitstreamH265Context *) ctx->priv_data)->active_vps;
auto sps_p = ((CodedBitstreamH265Context *) ctx->priv_data)->active_sps; auto sps_p = ((CodedBitstreamH265Context *) ctx->priv_data)->active_sps;
@@ -209,7 +212,6 @@ hevc_t make_sps_hevc(const AVCodecContext *avctx, const AVPacket *packet) {
vui.transfer_characteristics = avctx->color_trc; vui.transfer_characteristics = avctx->color_trc;
vui.matrix_coefficients = avctx->colorspace; vui.matrix_coefficients = avctx->colorspace;
vui.vui_timing_info_present_flag = vps.vps_timing_info_present_flag; vui.vui_timing_info_present_flag = vps.vps_timing_info_present_flag;
vui.vui_num_units_in_tick = vps.vps_num_units_in_tick; vui.vui_num_units_in_tick = vps.vps_num_units_in_tick;
vui.vui_time_scale = vps.vps_time_scale; vui.vui_time_scale = vps.vps_time_scale;
@@ -228,7 +230,6 @@ hevc_t make_sps_hevc(const AVCodecContext *avctx, const AVPacket *packet) {
cbs::ctx_t write_ctx; cbs::ctx_t write_ctx;
ff_cbs_init(&write_ctx, AV_CODEC_ID_H265, nullptr); ff_cbs_init(&write_ctx, AV_CODEC_ID_H265, nullptr);
return hevc_t { return hevc_t {
nal_t { nal_t {
write(write_ctx, vps.nal_unit_header.nal_unit_type, (void *) &vps.nal_unit_header, AV_CODEC_ID_H265), write(write_ctx, vps.nal_unit_header.nal_unit_type, (void *) &vps.nal_unit_header, AV_CODEC_ID_H265),
@@ -242,7 +243,8 @@ hevc_t make_sps_hevc(const AVCodecContext *avctx, const AVPacket *packet) {
}; };
} }
util::buffer_t<std::uint8_t> read_sps_h264(const AVPacket *packet) { util::buffer_t<std::uint8_t>
read_sps_h264(const AVPacket *packet) {
cbs::ctx_t ctx; cbs::ctx_t ctx;
if (ff_cbs_init(&ctx, AV_CODEC_ID_H264, nullptr)) { if (ff_cbs_init(&ctx, AV_CODEC_ID_H264, nullptr)) {
return {}; return {};
@@ -262,14 +264,16 @@ util::buffer_t<std::uint8_t> read_sps_h264(const AVPacket *packet) {
return write(h264->nal_unit_type, (void *) h264, AV_CODEC_ID_H264); return write(h264->nal_unit_type, (void *) h264, AV_CODEC_ID_H264);
} }
h264_t make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet) { h264_t
make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet) {
return h264_t { return h264_t {
make_sps_h264(ctx), make_sps_h264(ctx),
read_sps_h264(packet), read_sps_h264(packet),
}; };
} }
bool validate_sps(const AVPacket *packet, int codec_id) { bool
validate_sps(const AVPacket *packet, int codec_id) {
cbs::ctx_t ctx; cbs::ctx_t ctx;
if (ff_cbs_init(&ctx, (AVCodecID) codec_id, nullptr)) { if (ff_cbs_init(&ctx, (AVCodecID) codec_id, nullptr)) {
return false; return false;

View File

@@ -22,13 +22,16 @@ struct h264_t {
nal_t sps; nal_t sps;
}; };
hevc_t make_sps_hevc(const AVCodecContext *ctx, const AVPacket *packet); hevc_t
h264_t make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet); make_sps_hevc(const AVCodecContext *ctx, const AVPacket *packet);
h264_t
make_sps_h264(const AVCodecContext *ctx, const AVPacket *packet);
/** /**
* Check if SPS->VUI is present * Check if SPS->VUI is present
*/ */
bool validate_sps(const AVPacket *packet, int codec_id); bool
validate_sps(const AVPacket *packet, int codec_id);
} // namespace cbs } // namespace cbs
#endif #endif

View File

@@ -71,7 +71,8 @@ enum coder_e : int {
cavlc = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC, cavlc = NV_ENC_H264_ENTROPY_CODING_MODE_CAVLC,
}; };
std::optional<preset_e> preset_from_view(const std::string_view &preset) { std::optional<preset_e>
preset_from_view(const std::string_view &preset) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (preset == #x##sv) return x if (preset == #x##sv) return x
_CONVERT_(p1); _CONVERT_(p1);
@@ -85,7 +86,8 @@ std::optional<preset_e> preset_from_view(const std::string_view &preset) {
return std::nullopt; return std::nullopt;
} }
std::optional<tune_e> tune_from_view(const std::string_view &tune) { std::optional<tune_e>
tune_from_view(const std::string_view &tune) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (tune == #x##sv) return x if (tune == #x##sv) return x
_CONVERT_(hq); _CONVERT_(hq);
@@ -96,7 +98,8 @@ std::optional<tune_e> tune_from_view(const std::string_view &tune) {
return std::nullopt; return std::nullopt;
} }
std::optional<rc_e> rc_from_view(const std::string_view &rc) { std::optional<rc_e>
rc_from_view(const std::string_view &rc) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (rc == #x##sv) return x if (rc == #x##sv) return x
_CONVERT_(constqp); _CONVERT_(constqp);
@@ -106,7 +109,8 @@ std::optional<rc_e> rc_from_view(const std::string_view &rc) {
return std::nullopt; return std::nullopt;
} }
int coder_from_view(const std::string_view &coder) { int
coder_from_view(const std::string_view &coder) {
if (coder == "auto"sv) return _auto; if (coder == "auto"sv) return _auto;
if (coder == "cabac"sv || coder == "ac"sv) return cabac; if (coder == "cabac"sv || coder == "ac"sv) return cabac;
if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc; if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
@@ -194,7 +198,8 @@ enum coder_e : int {
cavlc = AMF_VIDEO_ENCODER_CALV cavlc = AMF_VIDEO_ENCODER_CALV
}; };
std::optional<int> quality_from_view(const std::string_view &quality_type, int codec) { std::optional<int>
quality_from_view(const std::string_view &quality_type, int codec) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (quality_type == #x##sv) return codec == 0 ? (int) quality_hevc_e::x : (int) quality_h264_e::x if (quality_type == #x##sv) return codec == 0 ? (int) quality_hevc_e::x : (int) quality_h264_e::x
_CONVERT_(quality); _CONVERT_(quality);
@@ -204,7 +209,8 @@ std::optional<int> quality_from_view(const std::string_view &quality_type, int c
return std::nullopt; return std::nullopt;
} }
std::optional<int> rc_from_view(const std::string_view &rc, int codec) { std::optional<int>
rc_from_view(const std::string_view &rc, int codec) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (rc == #x##sv) return codec == 0 ? (int) rc_hevc_e::x : (int) rc_h264_e::x if (rc == #x##sv) return codec == 0 ? (int) rc_hevc_e::x : (int) rc_h264_e::x
_CONVERT_(cqp); _CONVERT_(cqp);
@@ -215,7 +221,8 @@ std::optional<int> rc_from_view(const std::string_view &rc, int codec) {
return std::nullopt; return std::nullopt;
} }
std::optional<int> usage_from_view(const std::string_view &rc, int codec) { std::optional<int>
usage_from_view(const std::string_view &rc, int codec) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (rc == #x##sv) return codec == 0 ? (int) usage_hevc_e::x : (int) usage_h264_e::x if (rc == #x##sv) return codec == 0 ? (int) usage_hevc_e::x : (int) usage_h264_e::x
_CONVERT_(transcoding); _CONVERT_(transcoding);
@@ -226,7 +233,8 @@ std::optional<int> usage_from_view(const std::string_view &rc, int codec) {
return std::nullopt; return std::nullopt;
} }
int coder_from_view(const std::string_view &coder) { int
coder_from_view(const std::string_view &coder) {
if (coder == "auto"sv) return _auto; if (coder == "auto"sv) return _auto;
if (coder == "cabac"sv || coder == "ac"sv) return cabac; if (coder == "cabac"sv || coder == "ac"sv) return cabac;
if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc; if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
@@ -252,7 +260,8 @@ enum cavlc_e : int {
disabled = false disabled = false
}; };
std::optional<int> preset_from_view(const std::string_view &preset) { std::optional<int>
preset_from_view(const std::string_view &preset) {
#define _CONVERT_(x) \ #define _CONVERT_(x) \
if (preset == #x##sv) return x if (preset == #x##sv) return x
_CONVERT_(veryslow); _CONVERT_(veryslow);
@@ -266,7 +275,8 @@ std::optional<int> preset_from_view(const std::string_view &preset) {
return std::nullopt; return std::nullopt;
} }
std::optional<int> coder_from_view(const std::string_view &coder) { std::optional<int>
coder_from_view(const std::string_view &coder) {
if (coder == "auto"sv) return _auto; if (coder == "auto"sv) return _auto;
if (coder == "cabac"sv || coder == "ac"sv) return disabled; if (coder == "cabac"sv || coder == "ac"sv) return disabled;
if (coder == "cavlc"sv || coder == "vlc"sv) return enabled; if (coder == "cavlc"sv || coder == "vlc"sv) return enabled;
@@ -283,7 +293,8 @@ enum coder_e : int {
cavlc cavlc
}; };
int coder_from_view(const std::string_view &coder) { int
coder_from_view(const std::string_view &coder) {
if (coder == "auto"sv) return _auto; if (coder == "auto"sv) return _auto;
if (coder == "cabac"sv || coder == "ac"sv) return cabac; if (coder == "cabac"sv || coder == "ac"sv) return cabac;
if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc; if (coder == "cavlc"sv || coder == "vlc"sv) return cavlc;
@@ -291,19 +302,22 @@ int coder_from_view(const std::string_view &coder) {
return -1; return -1;
} }
int allow_software_from_view(const std::string_view &software) { int
allow_software_from_view(const std::string_view &software) {
if (software == "allowed"sv || software == "forced") return 1; if (software == "allowed"sv || software == "forced") return 1;
return 0; return 0;
} }
int force_software_from_view(const std::string_view &software) { int
force_software_from_view(const std::string_view &software) {
if (software == "forced") return 1; if (software == "forced") return 1;
return 0; return 0;
} }
int rt_from_view(const std::string_view &rt) { int
rt_from_view(const std::string_view &rt) {
if (rt == "disabled" || rt == "off" || rt == "0") return 0; if (rt == "disabled" || rt == "off" || rt == "0") return 0;
return 1; return 1;
@@ -431,19 +445,23 @@ sunshine_t sunshine {
{}, // prep commands {}, // prep commands
}; };
bool endline(char ch) { bool
endline(char ch) {
return ch == '\r' || ch == '\n'; return ch == '\r' || ch == '\n';
} }
bool space_tab(char ch) { bool
space_tab(char ch) {
return ch == ' ' || ch == '\t'; return ch == ' ' || ch == '\t';
} }
bool whitespace(char ch) { bool
whitespace(char ch) {
return space_tab(ch) || endline(ch); return space_tab(ch) || endline(ch);
} }
std::string to_string(const char *begin, const char *end) { std::string
to_string(const char *begin, const char *end) {
std::string result; std::string result;
KITTY_WHILE_LOOP(auto pos = begin, pos != end, { KITTY_WHILE_LOOP(auto pos = begin, pos != end, {
@@ -459,7 +477,8 @@ std::string to_string(const char *begin, const char *end) {
} }
template <class It> template <class It>
It skip_list(It skipper, It end) { It
skip_list(It skipper, It end) {
int stack = 1; int stack = 1;
while (skipper != end && stack) { while (skipper != end && stack) {
if (*skipper == '[') { if (*skipper == '[') {
@@ -511,7 +530,8 @@ parse_option(std::string_view::const_iterator begin, std::string_view::const_ite
std::make_pair(to_string(begin, end_name), to_string(begin_val, endl))); std::make_pair(to_string(begin, end_name), to_string(begin_val, endl)));
} }
std::unordered_map<std::string, std::string> parse_config(const std::string_view &file_content) { std::unordered_map<std::string, std::string>
parse_config(const std::string_view &file_content) {
std::unordered_map<std::string, std::string> vars; std::unordered_map<std::string, std::string> vars;
auto pos = std::begin(file_content); auto pos = std::begin(file_content);
@@ -536,7 +556,8 @@ std::unordered_map<std::string, std::string> parse_config(const std::string_view
return vars; return vars;
} }
void string_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input) { void
string_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input) {
auto it = vars.find(name); auto it = vars.find(name);
if (it == std::end(vars)) { if (it == std::end(vars)) {
return; return;
@@ -547,7 +568,8 @@ void string_f(std::unordered_map<std::string, std::string> &vars, const std::str
vars.erase(it); vars.erase(it);
} }
void string_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input, const std::vector<std::string_view> &allowed_vals) { void
string_restricted_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input, const std::vector<std::string_view> &allowed_vals) {
std::string temp; std::string temp;
string_f(vars, name, temp); string_f(vars, name, temp);
@@ -559,7 +581,8 @@ void string_restricted_f(std::unordered_map<std::string, std::string> &vars, con
} }
} }
void path_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, fs::path &input) { void
path_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, fs::path &input) {
// appdata needs to be retrieved once only // appdata needs to be retrieved once only
static auto appdata = platf::appdata(); static auto appdata = platf::appdata();
@@ -583,7 +606,8 @@ void path_f(std::unordered_map<std::string, std::string> &vars, const std::strin
} }
} }
void path_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input) { void
path_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::string &input) {
fs::path temp = input; fs::path temp = input;
path_f(vars, name, temp); path_f(vars, name, temp);
@@ -591,7 +615,8 @@ void path_f(std::unordered_map<std::string, std::string> &vars, const std::strin
input = temp.string(); input = temp.string();
} }
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) { void
int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input) {
auto it = vars.find(name); auto it = vars.find(name);
if (it == std::end(vars)) { if (it == std::end(vars)) {
@@ -616,7 +641,8 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
vars.erase(it); vars.erase(it);
} }
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::optional<int> &input) { void
int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::optional<int> &input) {
auto it = vars.find(name); auto it = vars.find(name);
if (it == std::end(vars)) { if (it == std::end(vars)) {
@@ -642,7 +668,8 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
} }
template <class F> template <class F>
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, F &&f) { void
int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, F &&f) {
std::string tmp; std::string tmp;
string_f(vars, name, tmp); string_f(vars, name, tmp);
if (!tmp.empty()) { if (!tmp.empty()) {
@@ -651,7 +678,8 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
} }
template <class F> template <class F>
void int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::optional<int> &input, F &&f) { void
int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::optional<int> &input, F &&f) {
std::string tmp; std::string tmp;
string_f(vars, name, tmp); string_f(vars, name, tmp);
if (!tmp.empty()) { if (!tmp.empty()) {
@@ -659,7 +687,8 @@ void int_f(std::unordered_map<std::string, std::string> &vars, const std::string
} }
} }
void int_between_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, const std::pair<int, int> &range) { void
int_between_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, int &input, const std::pair<int, int> &range) {
int temp = input; int temp = input;
int_f(vars, name, temp); int_f(vars, name, temp);
@@ -670,7 +699,8 @@ void int_between_f(std::unordered_map<std::string, std::string> &vars, const std
} }
} }
bool to_bool(std::string &boolean) { bool
to_bool(std::string &boolean) {
std::for_each(std::begin(boolean), std::end(boolean), [](char ch) { return (char) std::tolower(ch); }); std::for_each(std::begin(boolean), std::end(boolean), [](char ch) { return (char) std::tolower(ch); });
return boolean == "true"sv || return boolean == "true"sv ||
@@ -681,7 +711,8 @@ bool to_bool(std::string &boolean) {
(std::find(std::begin(boolean), std::end(boolean), '1') != std::end(boolean)); (std::find(std::begin(boolean), std::end(boolean), '1') != std::end(boolean));
} }
void bool_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, bool &input) { void
bool_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, bool &input) {
std::string tmp; std::string tmp;
string_f(vars, name, tmp); string_f(vars, name, tmp);
@@ -692,7 +723,8 @@ void bool_f(std::unordered_map<std::string, std::string> &vars, const std::strin
input = to_bool(tmp); input = to_bool(tmp);
} }
void double_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input) { void
double_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input) {
std::string tmp; std::string tmp;
string_f(vars, name, tmp); string_f(vars, name, tmp);
@@ -710,7 +742,8 @@ void double_f(std::unordered_map<std::string, std::string> &vars, const std::str
input = val; input = val;
} }
void double_between_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input, const std::pair<double, double> &range) { void
double_between_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, double &input, const std::pair<double, double> &range) {
double temp = input; double temp = input;
double_f(vars, name, temp); double_f(vars, name, temp);
@@ -721,7 +754,8 @@ void double_between_f(std::unordered_map<std::string, std::string> &vars, const
} }
} }
void list_string_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::vector<std::string> &input) { void
list_string_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::vector<std::string> &input) {
std::string string; std::string string;
string_f(vars, name, string); string_f(vars, name, string);
@@ -763,7 +797,8 @@ void list_string_f(std::unordered_map<std::string, std::string> &vars, const std
} }
} }
void list_prep_cmd_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::vector<prep_cmd_t> &input) { void
list_prep_cmd_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::vector<prep_cmd_t> &input) {
std::string string; std::string string;
string_f(vars, name, string); string_f(vars, name, string);
@@ -790,7 +825,8 @@ void list_prep_cmd_f(std::unordered_map<std::string, std::string> &vars, const s
} }
} }
void list_int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::vector<int> &input) { void
list_int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::vector<int> &input) {
std::vector<std::string> list; std::vector<std::string> list;
list_string_f(vars, name, list); list_string_f(vars, name, list);
@@ -815,7 +851,8 @@ void list_int_f(std::unordered_map<std::string, std::string> &vars, const std::s
} }
} }
void map_int_int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::unordered_map<int, int> &input) { void
map_int_int_f(std::unordered_map<std::string, std::string> &vars, const std::string &name, std::unordered_map<int, int> &input) {
std::vector<int> list; std::vector<int> list;
list_int_f(vars, name, list); list_int_f(vars, name, list);
@@ -834,7 +871,8 @@ void map_int_int_f(std::unordered_map<std::string, std::string> &vars, const std
} }
} }
int apply_flags(const char *line) { int
apply_flags(const char *line) {
int ret = 0; int ret = 0;
while (*line != '\0') { while (*line != '\0') {
switch (*line) { switch (*line) {
@@ -861,7 +899,8 @@ int apply_flags(const char *line) {
return ret; return ret;
} }
void apply_config(std::unordered_map<std::string, std::string> &&vars) { void
apply_config(std::unordered_map<std::string, std::string> &&vars) {
if (!fs::exists(stream.file_apps.c_str())) { if (!fs::exists(stream.file_apps.c_str())) {
fs::copy_file(SUNSHINE_ASSETS_DIR "/apps.json", stream.file_apps); fs::copy_file(SUNSHINE_ASSETS_DIR "/apps.json", stream.file_apps);
} }
@@ -1047,7 +1086,8 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
} }
} }
int parse(int argc, char *argv[]) { int
parse(int argc, char *argv[]) {
std::unordered_map<std::string, std::string> cmd_vars; std::unordered_map<std::string, std::string> cmd_vars;
for (auto x = 1; x < argc; ++x) { for (auto x = 1; x < argc; ++x) {

View File

@@ -119,8 +119,10 @@ enum flag_e : std::size_t {
} }
struct prep_cmd_t { struct prep_cmd_t {
prep_cmd_t(std::string &&do_cmd, std::string &&undo_cmd) : do_cmd(std::move(do_cmd)), undo_cmd(std::move(undo_cmd)) {} prep_cmd_t(std::string &&do_cmd, std::string &&undo_cmd):
explicit prep_cmd_t(std::string &&do_cmd) : do_cmd(std::move(do_cmd)) {} do_cmd(std::move(do_cmd)), undo_cmd(std::move(undo_cmd)) {}
explicit prep_cmd_t(std::string &&do_cmd):
do_cmd(std::move(do_cmd)) {}
std::string do_cmd; std::string do_cmd;
std::string undo_cmd; std::string undo_cmd;
}; };
@@ -155,7 +157,9 @@ extern nvhttp_t nvhttp;
extern input_t input; extern input_t input;
extern sunshine_t sunshine; extern sunshine_t sunshine;
int parse(int argc, char *argv[]); int
std::unordered_map<std::string, std::string> parse_config(const std::string_view &file_content); parse(int argc, char *argv[]);
std::unordered_map<std::string, std::string>
parse_config(const std::string_view &file_content);
} // namespace config } // namespace config
#endif #endif

View File

@@ -52,7 +52,8 @@ enum class op_e {
REMOVE REMOVE
}; };
void print_req(const req_https_t &request) { void
print_req(const req_https_t &request) {
BOOST_LOG(debug) << "METHOD :: "sv << request->method; BOOST_LOG(debug) << "METHOD :: "sv << request->method;
BOOST_LOG(debug) << "DESTINATION :: "sv << request->path; BOOST_LOG(debug) << "DESTINATION :: "sv << request->path;
@@ -69,7 +70,8 @@ void print_req(const req_https_t &request) {
BOOST_LOG(debug) << " [--] "sv; BOOST_LOG(debug) << " [--] "sv;
} }
void send_unauthorized(resp_https_t response, req_https_t request) { void
send_unauthorized(resp_https_t response, req_https_t request) {
auto address = request->remote_endpoint().address().to_string(); auto address = request->remote_endpoint().address().to_string();
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv; BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv;
const SimpleWeb::CaseInsensitiveMultimap headers { const SimpleWeb::CaseInsensitiveMultimap headers {
@@ -78,7 +80,8 @@ void send_unauthorized(resp_https_t response, req_https_t request) {
response->write(SimpleWeb::StatusCode::client_error_unauthorized, headers); response->write(SimpleWeb::StatusCode::client_error_unauthorized, headers);
} }
void send_redirect(resp_https_t response, req_https_t request, const char *path) { void
send_redirect(resp_https_t response, req_https_t request, const char *path) {
auto address = request->remote_endpoint().address().to_string(); auto address = request->remote_endpoint().address().to_string();
BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv; BOOST_LOG(info) << "Web UI: ["sv << address << "] -- not authorized"sv;
const SimpleWeb::CaseInsensitiveMultimap headers { const SimpleWeb::CaseInsensitiveMultimap headers {
@@ -87,7 +90,8 @@ void send_redirect(resp_https_t response, req_https_t request, const char *path)
response->write(SimpleWeb::StatusCode::redirection_temporary_redirect, headers); response->write(SimpleWeb::StatusCode::redirection_temporary_redirect, headers);
} }
bool authenticate(resp_https_t response, req_https_t request) { bool
authenticate(resp_https_t response, req_https_t request) {
auto address = request->remote_endpoint().address().to_string(); auto address = request->remote_endpoint().address().to_string();
auto ip_type = net::from_address(address); auto ip_type = net::from_address(address);
@@ -132,7 +136,8 @@ bool authenticate(resp_https_t response, req_https_t request) {
return true; return true;
} }
void not_found(resp_https_t response, req_https_t request) { void
not_found(resp_https_t response, req_https_t request) {
pt::ptree tree; pt::ptree tree;
tree.put("root.<xmlattr>.status_code", 404); tree.put("root.<xmlattr>.status_code", 404);
@@ -146,7 +151,8 @@ void not_found(resp_https_t response, req_https_t request) {
} }
// todo - combine these functions into a single function that accepts the page, i.e "index", "pin", "apps" // todo - combine these functions into a single function that accepts the page, i.e "index", "pin", "apps"
void getIndexPage(resp_https_t response, req_https_t request) { void
getIndexPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -156,7 +162,8 @@ void getIndexPage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getPinPage(resp_https_t response, req_https_t request) { void
getPinPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -166,7 +173,8 @@ void getPinPage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getAppsPage(resp_https_t response, req_https_t request) { void
getAppsPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -179,7 +187,8 @@ void getAppsPage(resp_https_t response, req_https_t request) {
response->write(header + content, headers); response->write(header + content, headers);
} }
void getClientsPage(resp_https_t response, req_https_t request) { void
getClientsPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -189,7 +198,8 @@ void getClientsPage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getConfigPage(resp_https_t response, req_https_t request) { void
getConfigPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -199,7 +209,8 @@ void getConfigPage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getPasswordPage(resp_https_t response, req_https_t request) { void
getPasswordPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -209,7 +220,8 @@ void getPasswordPage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getWelcomePage(resp_https_t response, req_https_t request) { void
getWelcomePage(resp_https_t response, req_https_t request) {
print_req(request); print_req(request);
if (!config::sunshine.username.empty()) { if (!config::sunshine.username.empty()) {
send_redirect(response, request, "/"); send_redirect(response, request, "/");
@@ -220,7 +232,8 @@ void getWelcomePage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getTroubleshootingPage(resp_https_t response, req_https_t request) { void
getTroubleshootingPage(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -230,7 +243,8 @@ void getTroubleshootingPage(resp_https_t response, req_https_t request) {
response->write(header + content); response->write(header + content);
} }
void getFaviconImage(resp_https_t response, req_https_t request) { void
getFaviconImage(resp_https_t response, req_https_t request) {
// todo - combine function with getSunshineLogoImage and possibly getNodeModules // todo - combine function with getSunshineLogoImage and possibly getNodeModules
// todo - use mime_types map // todo - use mime_types map
print_req(request); print_req(request);
@@ -241,7 +255,8 @@ void getFaviconImage(resp_https_t response, req_https_t request) {
response->write(SimpleWeb::StatusCode::success_ok, in, headers); response->write(SimpleWeb::StatusCode::success_ok, in, headers);
} }
void getSunshineLogoImage(resp_https_t response, req_https_t request) { void
getSunshineLogoImage(resp_https_t response, req_https_t request) {
// todo - combine function with getFaviconImage and possibly getNodeModules // todo - combine function with getFaviconImage and possibly getNodeModules
// todo - use mime_types map // todo - use mime_types map
print_req(request); print_req(request);
@@ -252,12 +267,14 @@ void getSunshineLogoImage(resp_https_t response, req_https_t request) {
response->write(SimpleWeb::StatusCode::success_ok, in, headers); response->write(SimpleWeb::StatusCode::success_ok, in, headers);
} }
bool isChildPath(fs::path const &base, fs::path const &query) { bool
isChildPath(fs::path const &base, fs::path const &query) {
auto relPath = fs::relative(base, query); auto relPath = fs::relative(base, query);
return *(relPath.begin()) != fs::path(".."); return *(relPath.begin()) != fs::path("..");
} }
void getNodeModules(resp_https_t response, req_https_t request) { void
getNodeModules(resp_https_t response, req_https_t request) {
print_req(request); print_req(request);
fs::path webDirPath(WEB_DIR); fs::path webDirPath(WEB_DIR);
fs::path nodeModulesPath(webDirPath / "node_modules"); fs::path nodeModulesPath(webDirPath / "node_modules");
@@ -290,7 +307,8 @@ void getNodeModules(resp_https_t response, req_https_t request) {
} }
} }
void getApps(resp_https_t response, req_https_t request) { void
getApps(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -299,7 +317,8 @@ void getApps(resp_https_t response, req_https_t request) {
response->write(content); response->write(content);
} }
void getLogs(resp_https_t response, req_https_t request) { void
getLogs(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -310,7 +329,8 @@ void getLogs(resp_https_t response, req_https_t request) {
response->write(SimpleWeb::StatusCode::success_ok, content, headers); response->write(SimpleWeb::StatusCode::success_ok, content, headers);
} }
void saveApp(resp_https_t response, req_https_t request) { void
saveApp(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -380,7 +400,8 @@ void saveApp(resp_https_t response, req_https_t request) {
proc::refresh(config::stream.file_apps); proc::refresh(config::stream.file_apps);
} }
void deleteApp(resp_https_t response, req_https_t request) { void
deleteApp(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -428,7 +449,8 @@ void deleteApp(resp_https_t response, req_https_t request) {
proc::refresh(config::stream.file_apps); proc::refresh(config::stream.file_apps);
} }
void uploadCover(resp_https_t response, req_https_t request) { void
uploadCover(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
std::stringstream ss; std::stringstream ss;
@@ -489,7 +511,8 @@ void uploadCover(resp_https_t response, req_https_t request) {
outputTree.put("path", path); outputTree.put("path", path);
} }
void getConfig(resp_https_t response, req_https_t request) { void
getConfig(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -514,7 +537,8 @@ void getConfig(resp_https_t response, req_https_t request) {
} }
} }
void saveConfig(resp_https_t response, req_https_t request) { void
saveConfig(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -549,7 +573,8 @@ void saveConfig(resp_https_t response, req_https_t request) {
} }
} }
void restart(resp_https_t response, req_https_t request) { void
restart(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -580,7 +605,8 @@ void restart(resp_https_t response, req_https_t request) {
outputTree.put("status", true); outputTree.put("status", true);
} }
void savePassword(resp_https_t response, req_https_t request) { void
savePassword(resp_https_t response, req_https_t request) {
if (!config::sunshine.username.empty() && !authenticate(response, request)) return; if (!config::sunshine.username.empty() && !authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -637,7 +663,8 @@ void savePassword(resp_https_t response, req_https_t request) {
} }
} }
void savePin(resp_https_t response, req_https_t request) { void
savePin(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -667,7 +694,8 @@ void savePin(resp_https_t response, req_https_t request) {
} }
} }
void unpairAll(resp_https_t response, req_https_t request) { void
unpairAll(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -683,7 +711,8 @@ void unpairAll(resp_https_t response, req_https_t request) {
outputTree.put("status", true); outputTree.put("status", true);
} }
void closeApp(resp_https_t response, req_https_t request) { void
closeApp(resp_https_t response, req_https_t request) {
if (!authenticate(response, request)) return; if (!authenticate(response, request)) return;
print_req(request); print_req(request);
@@ -700,7 +729,8 @@ void closeApp(resp_https_t response, req_https_t request) {
outputTree.put("status", true); outputTree.put("status", true);
} }
void start() { void
start() {
auto shutdown_event = mail::man->event<bool>(mail::shutdown); auto shutdown_event = mail::man->event<bool>(mail::shutdown);
auto port_https = map_port(PORT_HTTPS); auto port_https = map_port(PORT_HTTPS);

View File

@@ -10,10 +10,10 @@
#define WEB_DIR SUNSHINE_ASSETS_DIR "/web/" #define WEB_DIR SUNSHINE_ASSETS_DIR "/web/"
namespace confighttp { namespace confighttp {
constexpr auto PORT_HTTPS = 1; constexpr auto PORT_HTTPS = 1;
void start(); void
start();
} // namespace confighttp } // namespace confighttp
// mime types map // mime types map

View File

@@ -6,15 +6,18 @@
namespace crypto { namespace crypto {
using asn1_string_t = util::safe_ptr<ASN1_STRING, ASN1_STRING_free>; using asn1_string_t = util::safe_ptr<ASN1_STRING, ASN1_STRING_free>;
cert_chain_t::cert_chain_t() : _certs {}, _cert_ctx { X509_STORE_CTX_new() } {} cert_chain_t::cert_chain_t():
void cert_chain_t::add(x509_t &&cert) { _certs {}, _cert_ctx { X509_STORE_CTX_new() } {}
void
cert_chain_t::add(x509_t &&cert) {
x509_store_t x509_store { X509_STORE_new() }; x509_store_t x509_store { X509_STORE_new() };
X509_STORE_add_cert(x509_store.get(), cert.get()); X509_STORE_add_cert(x509_store.get(), cert.get());
_certs.emplace_back(std::make_pair(std::move(cert), std::move(x509_store))); _certs.emplace_back(std::make_pair(std::move(cert), std::move(x509_store)));
} }
static int openssl_verify_cb(int ok, X509_STORE_CTX *ctx) { static int
openssl_verify_cb(int ok, X509_STORE_CTX *ctx) {
int err_code = X509_STORE_CTX_get_error(ctx); int err_code = X509_STORE_CTX_get_error(ctx);
switch (err_code) { switch (err_code) {
@@ -39,7 +42,8 @@ static int openssl_verify_cb(int ok, X509_STORE_CTX *ctx) {
* *
* To circumvent this, x509_store_t instance will be created for each instance of the certificates. * To circumvent this, x509_store_t instance will be created for each instance of the certificates.
*/ */
const char *cert_chain_t::verify(x509_t::element_type *cert) { const char *
cert_chain_t::verify(x509_t::element_type *cert) {
int err_code = 0; int err_code = 0;
for (auto &[_, x509_store] : _certs) { for (auto &[_, x509_store] : _certs) {
auto fg = util::fail_guard([this]() { auto fg = util::fail_guard([this]() {
@@ -72,7 +76,8 @@ const char *cert_chain_t::verify(x509_t::element_type *cert) {
namespace cipher { namespace cipher {
static int init_decrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool padding) { static int
init_decrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool padding) {
ctx.reset(EVP_CIPHER_CTX_new()); ctx.reset(EVP_CIPHER_CTX_new());
if (!ctx) { if (!ctx) {
@@ -95,7 +100,8 @@ static int init_decrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool paddi
return 0; return 0;
} }
static int init_encrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool padding) { static int
init_encrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool padding) {
ctx.reset(EVP_CIPHER_CTX_new()); ctx.reset(EVP_CIPHER_CTX_new());
// Gen 7 servers use 128-bit AES ECB // Gen 7 servers use 128-bit AES ECB
@@ -115,7 +121,8 @@ static int init_encrypt_gcm(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool paddi
return 0; return 0;
} }
static int init_encrypt_cbc(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool padding) { static int
init_encrypt_cbc(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool padding) {
ctx.reset(EVP_CIPHER_CTX_new()); ctx.reset(EVP_CIPHER_CTX_new());
// Gen 7 servers use 128-bit AES ECB // Gen 7 servers use 128-bit AES ECB
@@ -128,7 +135,8 @@ static int init_encrypt_cbc(cipher_ctx_t &ctx, aes_t *key, aes_t *iv, bool paddi
return 0; return 0;
} }
int gcm_t::decrypt(const std::string_view &tagged_cipher, std::vector<std::uint8_t> &plaintext, aes_t *iv) { int
gcm_t::decrypt(const std::string_view &tagged_cipher, std::vector<std::uint8_t> &plaintext, aes_t *iv) {
if (!decrypt_ctx && init_decrypt_gcm(decrypt_ctx, &key, iv, padding)) { if (!decrypt_ctx && init_decrypt_gcm(decrypt_ctx, &key, iv, padding)) {
return -1; return -1;
} }
@@ -162,7 +170,8 @@ int gcm_t::decrypt(const std::string_view &tagged_cipher, std::vector<std::uint8
return 0; return 0;
} }
int gcm_t::encrypt(const std::string_view &plaintext, std::uint8_t *tagged_cipher, aes_t *iv) { int
gcm_t::encrypt(const std::string_view &plaintext, std::uint8_t *tagged_cipher, aes_t *iv) {
if (!encrypt_ctx && init_encrypt_gcm(encrypt_ctx, &key, iv, padding)) { if (!encrypt_ctx && init_encrypt_gcm(encrypt_ctx, &key, iv, padding)) {
return -1; return -1;
} }
@@ -196,7 +205,8 @@ int gcm_t::encrypt(const std::string_view &plaintext, std::uint8_t *tagged_ciphe
return len + size; return len + size;
} }
int ecb_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext) { int
ecb_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext) {
int len; int len;
auto fg = util::fail_guard([this]() { auto fg = util::fail_guard([this]() {
@@ -225,7 +235,8 @@ int ecb_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &pl
return 0; return 0;
} }
int ecb_t::encrypt(const std::string_view &plaintext, std::vector<std::uint8_t> &cipher) { int
ecb_t::encrypt(const std::string_view &plaintext, std::vector<std::uint8_t> &cipher) {
auto fg = util::fail_guard([this]() { auto fg = util::fail_guard([this]() {
EVP_CIPHER_CTX_reset(encrypt_ctx.get()); EVP_CIPHER_CTX_reset(encrypt_ctx.get());
}); });
@@ -255,7 +266,8 @@ int ecb_t::encrypt(const std::string_view &plaintext, std::vector<std::uint8_t>
return 0; return 0;
} }
int cbc_t::encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_t *iv) { int
cbc_t::encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_t *iv) {
if (!encrypt_ctx && init_encrypt_cbc(encrypt_ctx, &key, iv, padding)) { if (!encrypt_ctx && init_encrypt_cbc(encrypt_ctx, &key, iv, padding)) {
return -1; return -1;
} }
@@ -282,18 +294,19 @@ int cbc_t::encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_
return size + len; return size + len;
} }
ecb_t::ecb_t(const aes_t &key, bool padding) ecb_t::ecb_t(const aes_t &key, bool padding):
: cipher_t { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_new(), key, padding } {} cipher_t { EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_new(), key, padding } {}
cbc_t::cbc_t(const aes_t &key, bool padding) cbc_t::cbc_t(const aes_t &key, bool padding):
: cipher_t { nullptr, nullptr, key, padding } {} cipher_t { nullptr, nullptr, key, padding } {}
gcm_t::gcm_t(const crypto::aes_t &key, bool padding) gcm_t::gcm_t(const crypto::aes_t &key, bool padding):
: cipher_t { nullptr, nullptr, key, padding } {} cipher_t { nullptr, nullptr, key, padding } {}
} // namespace cipher } // namespace cipher
aes_t gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin) { aes_t
gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin) {
aes_t key; aes_t key;
std::string salt_pin; std::string salt_pin;
@@ -309,13 +322,15 @@ aes_t gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &p
return key; return key;
} }
sha256_t hash(const std::string_view &plaintext) { sha256_t
hash(const std::string_view &plaintext) {
sha256_t hsh; sha256_t hsh;
EVP_Digest(plaintext.data(), plaintext.size(), hsh.data(), nullptr, EVP_sha256(), nullptr); EVP_Digest(plaintext.data(), plaintext.size(), hsh.data(), nullptr, EVP_sha256(), nullptr);
return hsh; return hsh;
} }
x509_t x509(const std::string_view &x) { x509_t
x509(const std::string_view &x) {
bio_t io { BIO_new(BIO_s_mem()) }; bio_t io { BIO_new(BIO_s_mem()) };
BIO_write(io.get(), x.data(), x.size()); BIO_write(io.get(), x.data(), x.size());
@@ -326,7 +341,8 @@ x509_t x509(const std::string_view &x) {
return p; return p;
} }
pkey_t pkey(const std::string_view &k) { pkey_t
pkey(const std::string_view &k) {
bio_t io { BIO_new(BIO_s_mem()) }; bio_t io { BIO_new(BIO_s_mem()) };
BIO_write(io.get(), k.data(), k.size()); BIO_write(io.get(), k.data(), k.size());
@@ -337,7 +353,8 @@ pkey_t pkey(const std::string_view &k) {
return p; return p;
} }
std::string pem(x509_t &x509) { std::string
pem(x509_t &x509) {
bio_t bio { BIO_new(BIO_s_mem()) }; bio_t bio { BIO_new(BIO_s_mem()) };
PEM_write_bio_X509(bio.get(), x509.get()); PEM_write_bio_X509(bio.get(), x509.get());
@@ -347,7 +364,8 @@ std::string pem(x509_t &x509) {
return { mem_ptr->data, mem_ptr->length }; return { mem_ptr->data, mem_ptr->length };
} }
std::string pem(pkey_t &pkey) { std::string
pem(pkey_t &pkey) {
bio_t bio { BIO_new(BIO_s_mem()) }; bio_t bio { BIO_new(BIO_s_mem()) };
PEM_write_bio_PrivateKey(bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr); PEM_write_bio_PrivateKey(bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr);
@@ -357,7 +375,8 @@ std::string pem(pkey_t &pkey) {
return { mem_ptr->data, mem_ptr->length }; return { mem_ptr->data, mem_ptr->length };
} }
std::string_view signature(const x509_t &x) { std::string_view
signature(const x509_t &x) {
// X509_ALGOR *_ = nullptr; // X509_ALGOR *_ = nullptr;
const ASN1_BIT_STRING *asn1 = nullptr; const ASN1_BIT_STRING *asn1 = nullptr;
@@ -366,7 +385,8 @@ std::string_view signature(const x509_t &x) {
return { (const char *) asn1->data, (std::size_t) asn1->length }; return { (const char *) asn1->data, (std::size_t) asn1->length };
} }
std::string rand(std::size_t bytes) { std::string
rand(std::size_t bytes) {
std::string r; std::string r;
r.resize(bytes); r.resize(bytes);
@@ -375,7 +395,8 @@ std::string rand(std::size_t bytes) {
return r; return r;
} }
std::vector<uint8_t> sign(const pkey_t &pkey, const std::string_view &data, const EVP_MD *md) { std::vector<uint8_t>
sign(const pkey_t &pkey, const std::string_view &data, const EVP_MD *md) {
md_ctx_t ctx { EVP_MD_CTX_create() }; md_ctx_t ctx { EVP_MD_CTX_create() };
if (EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, pkey.get()) != 1) { if (EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, pkey.get()) != 1) {
@@ -398,7 +419,8 @@ std::vector<uint8_t> sign(const pkey_t &pkey, const std::string_view &data, cons
return digest; return digest;
} }
creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits) { creds_t
gen_creds(const std::string_view &cn, std::uint32_t key_bits) {
x509_t x509 { X509_new() }; x509_t x509 { X509_new() };
pkey_ctx_t ctx { EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr) }; pkey_ctx_t ctx { EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr) };
pkey_t pkey; pkey_t pkey;
@@ -443,11 +465,13 @@ creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits) {
return { pem(x509), pem(pkey) }; return { pem(x509), pem(pkey) };
} }
std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_view &data) { std::vector<uint8_t>
sign256(const pkey_t &pkey, const std::string_view &data) {
return sign(pkey, data, EVP_sha256()); return sign(pkey, data, EVP_sha256());
} }
bool verify(const x509_t &x509, const std::string_view &data, const std::string_view &signature, const EVP_MD *md) { bool
verify(const x509_t &x509, const std::string_view &data, const std::string_view &signature, const EVP_MD *md) {
auto pkey = X509_get_pubkey(x509.get()); auto pkey = X509_get_pubkey(x509.get());
md_ctx_t ctx { EVP_MD_CTX_create() }; md_ctx_t ctx { EVP_MD_CTX_create() };
@@ -467,15 +491,18 @@ bool verify(const x509_t &x509, const std::string_view &data, const std::string_
return true; return true;
} }
bool verify256(const x509_t &x509, const std::string_view &data, const std::string_view &signature) { bool
verify256(const x509_t &x509, const std::string_view &data, const std::string_view &signature) {
return verify(x509, data, signature, EVP_sha256()); return verify(x509, data, signature, EVP_sha256());
} }
void md_ctx_destroy(EVP_MD_CTX *ctx) { void
md_ctx_destroy(EVP_MD_CTX *ctx) {
EVP_MD_CTX_destroy(ctx); EVP_MD_CTX_destroy(ctx);
} }
std::string rand_alphabet(std::size_t bytes, const std::string_view &alphabet) { std::string
rand_alphabet(std::size_t bytes, const std::string_view &alphabet) {
auto value = rand(bytes); auto value = rand(bytes);
for (std::size_t i = 0; i != value.size(); ++i) { for (std::size_t i = 0; i != value.size(); ++i) {

View File

@@ -18,7 +18,8 @@ struct creds_t {
}; };
constexpr std::size_t digest_size = 256; constexpr std::size_t digest_size = 256;
void md_ctx_destroy(EVP_MD_CTX *); void
md_ctx_destroy(EVP_MD_CTX *);
using sha256_t = std::array<std::uint8_t, SHA256_DIGEST_LENGTH>; using sha256_t = std::array<std::uint8_t, SHA256_DIGEST_LENGTH>;
@@ -33,33 +34,47 @@ using pkey_t = util::safe_ptr<EVP_PKEY, EVP_PKEY_free>;
using pkey_ctx_t = util::safe_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>; using pkey_ctx_t = util::safe_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
using bignum_t = util::safe_ptr<BIGNUM, BN_free>; using bignum_t = util::safe_ptr<BIGNUM, BN_free>;
sha256_t hash(const std::string_view &plaintext); sha256_t
hash(const std::string_view &plaintext);
aes_t gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin); aes_t
gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin);
x509_t x509(const std::string_view &x); x509_t
pkey_t pkey(const std::string_view &k); x509(const std::string_view &x);
std::string pem(x509_t &x509); pkey_t
std::string pem(pkey_t &pkey); pkey(const std::string_view &k);
std::string
pem(x509_t &x509);
std::string
pem(pkey_t &pkey);
std::vector<uint8_t> sign256(const pkey_t &pkey, const std::string_view &data); std::vector<uint8_t>
bool verify256(const x509_t &x509, const std::string_view &data, const std::string_view &signature); sign256(const pkey_t &pkey, const std::string_view &data);
bool
verify256(const x509_t &x509, const std::string_view &data, const std::string_view &signature);
creds_t gen_creds(const std::string_view &cn, std::uint32_t key_bits); creds_t
gen_creds(const std::string_view &cn, std::uint32_t key_bits);
std::string_view signature(const x509_t &x); std::string_view
signature(const x509_t &x);
std::string rand(std::size_t bytes); std::string
std::string rand_alphabet(std::size_t bytes, rand(std::size_t bytes);
std::string
rand_alphabet(std::size_t bytes,
const std::string_view &alphabet = std::string_view { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!%&()=-" }); const std::string_view &alphabet = std::string_view { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!%&()=-" });
class cert_chain_t { class cert_chain_t {
public: public:
KITTY_DECL_CONSTR(cert_chain_t) KITTY_DECL_CONSTR(cert_chain_t)
void add(x509_t &&cert); void
add(x509_t &&cert);
const char *verify(x509_t::element_type *cert); const char *
verify(x509_t::element_type *cert);
private: private:
std::vector<std::pair<x509_t, x509_store_t>> _certs; std::vector<std::pair<x509_t, x509_store_t>> _certs;
@@ -68,7 +83,8 @@ private:
namespace cipher { namespace cipher {
constexpr std::size_t tag_size = 16; constexpr std::size_t tag_size = 16;
constexpr std::size_t round_to_pkcs7_padded(std::size_t size) { constexpr std::size_t
round_to_pkcs7_padded(std::size_t size) {
return ((size + 15) / 16) * 16; return ((size + 15) / 16) * 16;
} }
@@ -86,19 +102,23 @@ class ecb_t : public cipher_t {
public: public:
ecb_t() = default; ecb_t() = default;
ecb_t(ecb_t &&) noexcept = default; ecb_t(ecb_t &&) noexcept = default;
ecb_t &operator=(ecb_t &&) noexcept = default; ecb_t &
operator=(ecb_t &&) noexcept = default;
ecb_t(const aes_t &key, bool padding = true); ecb_t(const aes_t &key, bool padding = true);
int encrypt(const std::string_view &plaintext, std::vector<std::uint8_t> &cipher); int
int decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext); encrypt(const std::string_view &plaintext, std::vector<std::uint8_t> &cipher);
int
decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext);
}; };
class gcm_t: public cipher_t { class gcm_t: public cipher_t {
public: public:
gcm_t() = default; gcm_t() = default;
gcm_t(gcm_t &&) noexcept = default; gcm_t(gcm_t &&) noexcept = default;
gcm_t &operator=(gcm_t &&) noexcept = default; gcm_t &
operator=(gcm_t &&) noexcept = default;
gcm_t(const crypto::aes_t &key, bool padding = true); gcm_t(const crypto::aes_t &key, bool padding = true);
@@ -108,16 +128,19 @@ public:
* return -1 on error * return -1 on error
* return bytes written on success * return bytes written on success
*/ */
int encrypt(const std::string_view &plaintext, std::uint8_t *tagged_cipher, aes_t *iv); int
encrypt(const std::string_view &plaintext, std::uint8_t *tagged_cipher, aes_t *iv);
int decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext, aes_t *iv); int
decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext, aes_t *iv);
}; };
class cbc_t: public cipher_t { class cbc_t: public cipher_t {
public: public:
cbc_t() = default; cbc_t() = default;
cbc_t(cbc_t &&) noexcept = default; cbc_t(cbc_t &&) noexcept = default;
cbc_t &operator=(cbc_t &&) noexcept = default; cbc_t &
operator=(cbc_t &&) noexcept = default;
cbc_t(const crypto::aes_t &key, bool padding = true); cbc_t(const crypto::aes_t &key, bool padding = true);
@@ -127,7 +150,8 @@ public:
* return -1 on error * return -1 on error
* return bytes written on success * return bytes written on success
*/ */
int encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_t *iv); int
encrypt(const std::string_view &plaintext, std::uint8_t *cipher, aes_t *iv);
}; };
} // namespace cipher } // namespace cipher
} // namespace crypto } // namespace crypto

View File

@@ -31,14 +31,17 @@ using namespace std::literals;
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace pt = boost::property_tree; namespace pt = boost::property_tree;
int reload_user_creds(const std::string &file); int
bool user_creds_exist(const std::string &file); reload_user_creds(const std::string &file);
bool
user_creds_exist(const std::string &file);
std::string unique_id; std::string unique_id;
net::net_e origin_pin_allowed; net::net_e origin_pin_allowed;
net::net_e origin_web_ui_allowed; net::net_e origin_web_ui_allowed;
int init() { int
init() {
bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE]; bool clean_slate = config::sunshine.flags[config::flag::FRESH_STATE];
origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed); origin_pin_allowed = net::from_enum_string(config::nvhttp.origin_pin_allowed);
origin_web_ui_allowed = net::from_enum_string(config::nvhttp.origin_web_ui_allowed); origin_web_ui_allowed = net::from_enum_string(config::nvhttp.origin_web_ui_allowed);
@@ -64,7 +67,8 @@ int init() {
return 0; return 0;
} }
int save_user_creds(const std::string &file, const std::string &username, const std::string &password, bool run_our_mouth) { int
save_user_creds(const std::string &file, const std::string &username, const std::string &password, bool run_our_mouth) {
pt::ptree outputTree; pt::ptree outputTree;
if (fs::exists(file)) { if (fs::exists(file)) {
@@ -93,7 +97,8 @@ int save_user_creds(const std::string &file, const std::string &username, const
return 0; return 0;
} }
bool user_creds_exist(const std::string &file) { bool
user_creds_exist(const std::string &file) {
if (!fs::exists(file)) { if (!fs::exists(file)) {
return false; return false;
} }
@@ -112,7 +117,8 @@ bool user_creds_exist(const std::string &file) {
return false; return false;
} }
int reload_user_creds(const std::string &file) { int
reload_user_creds(const std::string &file) {
pt::ptree inputTree; pt::ptree inputTree;
try { try {
pt::read_json(file, inputTree); pt::read_json(file, inputTree);
@@ -127,7 +133,8 @@ int reload_user_creds(const std::string &file) {
return 0; return 0;
} }
int create_creds(const std::string &pkey, const std::string &cert) { int
create_creds(const std::string &pkey, const std::string &cert) {
fs::path pkey_path = pkey; fs::path pkey_path = pkey;
fs::path cert_path = cert; fs::path cert_path = cert;
@@ -182,7 +189,8 @@ int create_creds(const std::string &pkey, const std::string &cert) {
return 0; return 0;
} }
bool download_file(const std::string &url, const std::string &file) { bool
download_file(const std::string &url, const std::string &file) {
CURL *curl = curl_easy_init(); CURL *curl = curl_easy_init();
if (!curl) { if (!curl) {
BOOST_LOG(error) << "Couldn't create CURL instance"; BOOST_LOG(error) << "Couldn't create CURL instance";
@@ -209,7 +217,8 @@ bool download_file(const std::string &url, const std::string &file) {
return result == CURLE_OK; return result == CURLE_OK;
} }
std::string url_escape(const std::string &url) { std::string
url_escape(const std::string &url) {
CURL *curl = curl_easy_init(); CURL *curl = curl_easy_init();
char *string = curl_easy_escape(curl, url.c_str(), url.length()); char *string = curl_easy_escape(curl, url.c_str(), url.length());
std::string result(string); std::string result(string);
@@ -218,7 +227,8 @@ std::string url_escape(const std::string &url) {
return result; return result;
} }
std::string url_get_host(const std::string &url) { std::string
url_get_host(const std::string &url) {
CURLU *curlu = curl_url(); CURLU *curlu = curl_url();
curl_url_set(curlu, CURLUPART_URL, url.c_str(), url.length()); curl_url_set(curlu, CURLUPART_URL, url.c_str(), url.length());
char *host; char *host;

View File

@@ -3,18 +3,25 @@
namespace http { namespace http {
int init(); int
int create_creds(const std::string &pkey, const std::string &cert); init();
int save_user_creds( int
create_creds(const std::string &pkey, const std::string &cert);
int
save_user_creds(
const std::string &file, const std::string &file,
const std::string &username, const std::string &username,
const std::string &password, const std::string &password,
bool run_our_mouth = false); bool run_our_mouth = false);
int reload_user_creds(const std::string &file); int
bool download_file(const std::string &url, const std::string &file); reload_user_creds(const std::string &file);
std::string url_escape(const std::string &url); bool
std::string url_get_host(const std::string &url); download_file(const std::string &url, const std::string &file);
std::string
url_escape(const std::string &url);
std::string
url_get_host(const std::string &url);
extern std::string unique_id; extern std::string unique_id;
extern net::net_e origin_pin_allowed; extern net::net_e origin_pin_allowed;

View File

@@ -41,7 +41,8 @@ enum class button_state_e {
}; };
template <std::size_t N> template <std::size_t N>
int alloc_id(std::bitset<N> &gamepad_mask) { int
alloc_id(std::bitset<N> &gamepad_mask) {
for (int x = 0; x < gamepad_mask.size(); ++x) { for (int x = 0; x < gamepad_mask.size(); ++x) {
if (!gamepad_mask[x]) { if (!gamepad_mask[x]) {
gamepad_mask[x] = true; gamepad_mask[x] = true;
@@ -53,7 +54,8 @@ int alloc_id(std::bitset<N> &gamepad_mask) {
} }
template <std::size_t N> template <std::size_t N>
void free_id(std::bitset<N> &gamepad_mask, int id) { void
free_id(std::bitset<N> &gamepad_mask, int id) {
gamepad_mask[id] = false; gamepad_mask[id] = false;
} }
@@ -64,14 +66,16 @@ static std::array<std::uint8_t, 5> mouse_press {};
static platf::input_t platf_input; static platf::input_t platf_input;
static std::bitset<platf::MAX_GAMEPADS> gamepadMask {}; static std::bitset<platf::MAX_GAMEPADS> gamepadMask {};
void free_gamepad(platf::input_t &platf_input, int id) { void
free_gamepad(platf::input_t &platf_input, int id) {
platf::gamepad(platf_input, id, platf::gamepad_state_t {}); platf::gamepad(platf_input, id, platf::gamepad_state_t {});
platf::free_gamepad(platf_input, id); platf::free_gamepad(platf_input, id);
free_id(gamepadMask, id); free_id(gamepadMask, id);
} }
struct gamepad_t { struct gamepad_t {
gamepad_t() : gamepad_state {}, back_timeout_id {}, id { -1 }, back_button_state { button_state_e::NONE } {} gamepad_t():
gamepad_state {}, back_timeout_id {}, id { -1 }, back_button_state { button_state_e::NONE } {}
~gamepad_t() { ~gamepad_t() {
if (id >= 0) { if (id >= 0) {
task_pool.push([id = this->id]() { task_pool.push([id = this->id]() {
@@ -105,8 +109,8 @@ struct input_t {
input_t( input_t(
safe::mail_raw_t::event_t<input::touch_port_t> touch_port_event, safe::mail_raw_t::event_t<input::touch_port_t> touch_port_event,
platf::rumble_queue_t rumble_queue) platf::rumble_queue_t rumble_queue):
: shortcutFlags {}, shortcutFlags {},
active_gamepad_state {}, active_gamepad_state {},
gamepads(MAX_GAMEPADS), gamepads(MAX_GAMEPADS),
touch_port_event { std::move(touch_port_event) }, touch_port_event { std::move(touch_port_event) },
@@ -135,7 +139,8 @@ struct input_t {
* On nothing * On nothing
* return 0 * return 0
*/ */
inline int apply_shortcut(short keyCode) { inline int
apply_shortcut(short keyCode) {
constexpr auto VK_F1 = 0x70; constexpr auto VK_F1 = 0x70;
constexpr auto VK_F13 = 0x7C; constexpr auto VK_F13 = 0x7C;
@@ -155,7 +160,8 @@ inline int apply_shortcut(short keyCode) {
return 0; return 0;
} }
void print(PNV_REL_MOUSE_MOVE_PACKET packet) { void
print(PNV_REL_MOUSE_MOVE_PACKET packet) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin relative mouse move packet--"sv << std::endl << "--begin relative mouse move packet--"sv << std::endl
<< "deltaX ["sv << util::endian::big(packet->deltaX) << ']' << std::endl << "deltaX ["sv << util::endian::big(packet->deltaX) << ']' << std::endl
@@ -163,7 +169,8 @@ void print(PNV_REL_MOUSE_MOVE_PACKET packet) {
<< "--end relative mouse move packet--"sv; << "--end relative mouse move packet--"sv;
} }
void print(PNV_ABS_MOUSE_MOVE_PACKET packet) { void
print(PNV_ABS_MOUSE_MOVE_PACKET packet) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin absolute mouse move packet--"sv << std::endl << "--begin absolute mouse move packet--"sv << std::endl
<< "x ["sv << util::endian::big(packet->x) << ']' << std::endl << "x ["sv << util::endian::big(packet->x) << ']' << std::endl
@@ -173,7 +180,8 @@ void print(PNV_ABS_MOUSE_MOVE_PACKET packet) {
<< "--end absolute mouse move packet--"sv; << "--end absolute mouse move packet--"sv;
} }
void print(PNV_MOUSE_BUTTON_PACKET packet) { void
print(PNV_MOUSE_BUTTON_PACKET packet) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin mouse button packet--"sv << std::endl << "--begin mouse button packet--"sv << std::endl
<< "action ["sv << util::hex(packet->header.magic).to_string_view() << ']' << std::endl << "action ["sv << util::hex(packet->header.magic).to_string_view() << ']' << std::endl
@@ -181,21 +189,24 @@ void print(PNV_MOUSE_BUTTON_PACKET packet) {
<< "--end mouse button packet--"sv; << "--end mouse button packet--"sv;
} }
void print(PNV_SCROLL_PACKET packet) { void
print(PNV_SCROLL_PACKET packet) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin mouse scroll packet--"sv << std::endl << "--begin mouse scroll packet--"sv << std::endl
<< "scrollAmt1 ["sv << util::endian::big(packet->scrollAmt1) << ']' << std::endl << "scrollAmt1 ["sv << util::endian::big(packet->scrollAmt1) << ']' << std::endl
<< "--end mouse scroll packet--"sv; << "--end mouse scroll packet--"sv;
} }
void print(PSS_HSCROLL_PACKET packet) { void
print(PSS_HSCROLL_PACKET packet) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin mouse hscroll packet--"sv << std::endl << "--begin mouse hscroll packet--"sv << std::endl
<< "scrollAmount ["sv << util::endian::big(packet->scrollAmount) << ']' << std::endl << "scrollAmount ["sv << util::endian::big(packet->scrollAmount) << ']' << std::endl
<< "--end mouse hscroll packet--"sv; << "--end mouse hscroll packet--"sv;
} }
void print(PNV_KEYBOARD_PACKET packet) { void
print(PNV_KEYBOARD_PACKET packet) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin keyboard packet--"sv << std::endl << "--begin keyboard packet--"sv << std::endl
<< "keyAction ["sv << util::hex(packet->header.magic).to_string_view() << ']' << std::endl << "keyAction ["sv << util::hex(packet->header.magic).to_string_view() << ']' << std::endl
@@ -205,7 +216,8 @@ void print(PNV_KEYBOARD_PACKET packet) {
<< "--end keyboard packet--"sv; << "--end keyboard packet--"sv;
} }
void print(PNV_UNICODE_PACKET packet) { void
print(PNV_UNICODE_PACKET packet) {
std::string text(packet->text, util::endian::big(packet->header.size) - sizeof(packet->header.magic)); std::string text(packet->text, util::endian::big(packet->header.size) - sizeof(packet->header.magic));
BOOST_LOG(debug) BOOST_LOG(debug)
<< "--begin unicode packet--"sv << std::endl << "--begin unicode packet--"sv << std::endl
@@ -213,7 +225,8 @@ void print(PNV_UNICODE_PACKET packet) {
<< "--end unicode packet--"sv; << "--end unicode packet--"sv;
} }
void print(PNV_MULTI_CONTROLLER_PACKET packet) { void
print(PNV_MULTI_CONTROLLER_PACKET packet) {
// Moonlight spams controller packet even when not necessary // Moonlight spams controller packet even when not necessary
BOOST_LOG(verbose) BOOST_LOG(verbose)
<< "--begin controller packet--"sv << std::endl << "--begin controller packet--"sv << std::endl
@@ -229,7 +242,8 @@ void print(PNV_MULTI_CONTROLLER_PACKET packet) {
<< "--end controller packet--"sv; << "--end controller packet--"sv;
} }
void print(void *payload) { void
print(void *payload) {
auto header = (PNV_INPUT_HEADER) payload; auto header = (PNV_INPUT_HEADER) payload;
switch (util::endian::little(header->magic)) { switch (util::endian::little(header->magic)) {
@@ -262,7 +276,8 @@ void print(void *payload) {
} }
} }
void passthrough(std::shared_ptr<input_t> &input, PNV_REL_MOUSE_MOVE_PACKET packet) { void
passthrough(std::shared_ptr<input_t> &input, PNV_REL_MOUSE_MOVE_PACKET packet) {
if (!config::input.mouse) { if (!config::input.mouse) {
return; return;
} }
@@ -271,7 +286,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_REL_MOUSE_MOVE_PACKET pack
platf::move_mouse(platf_input, util::endian::big(packet->deltaX), util::endian::big(packet->deltaY)); platf::move_mouse(platf_input, util::endian::big(packet->deltaX), util::endian::big(packet->deltaY));
} }
void passthrough(std::shared_ptr<input_t> &input, PNV_ABS_MOUSE_MOVE_PACKET packet) { void
passthrough(std::shared_ptr<input_t> &input, PNV_ABS_MOUSE_MOVE_PACKET packet) {
if (!config::input.mouse) { if (!config::input.mouse) {
return; return;
} }
@@ -320,7 +336,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_ABS_MOUSE_MOVE_PACKET pack
platf::abs_mouse(platf_input, abs_port, (x - offsetX) * touch_port.scalar_inv, (y - offsetY) * touch_port.scalar_inv); platf::abs_mouse(platf_input, abs_port, (x - offsetX) * touch_port.scalar_inv, (y - offsetY) * touch_port.scalar_inv);
} }
void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet) { void
passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet) {
if (!config::input.mouse) { if (!config::input.mouse) {
return; return;
} }
@@ -382,7 +399,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MOUSE_BUTTON_PACKET packet
platf::button_mouse(platf_input, button, release); platf::button_mouse(platf_input, button, release);
} }
short map_keycode(short keycode) { short
map_keycode(short keycode) {
auto it = config::input.keybindings.find(keycode); auto it = config::input.keybindings.find(keycode);
if (it != std::end(config::input.keybindings)) { if (it != std::end(config::input.keybindings)) {
return it->second; return it->second;
@@ -394,7 +412,8 @@ short map_keycode(short keycode) {
/** /**
* Update flags for keyboard shortcut combo's * Update flags for keyboard shortcut combo's
*/ */
inline void update_shortcutFlags(int *flags, short keyCode, bool release) { inline void
update_shortcutFlags(int *flags, short keyCode, bool release) {
switch (keyCode) { switch (keyCode) {
case VKEY_SHIFT: case VKEY_SHIFT:
case VKEY_LSHIFT: case VKEY_LSHIFT:
@@ -429,7 +448,8 @@ inline void update_shortcutFlags(int *flags, short keyCode, bool release) {
} }
} }
void repeat_key(short key_code) { void
repeat_key(short key_code) {
// If key no longer pressed, stop repeating // If key no longer pressed, stop repeating
if (!key_press[key_code]) { if (!key_press[key_code]) {
key_press_repeat_id = nullptr; key_press_repeat_id = nullptr;
@@ -441,7 +461,8 @@ void repeat_key(short key_code) {
key_press_repeat_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_period, key_code).task_id; key_press_repeat_id = task_pool.pushDelayed(repeat_key, config::input.key_repeat_period, key_code).task_id;
} }
void passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET packet) { void
passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET packet) {
if (!config::input.keyboard) { if (!config::input.keyboard) {
return; return;
} }
@@ -482,7 +503,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_KEYBOARD_PACKET packet) {
platf::keyboard(platf_input, map_keycode(keyCode), release); platf::keyboard(platf_input, map_keycode(keyCode), release);
} }
void passthrough(PNV_SCROLL_PACKET packet) { void
passthrough(PNV_SCROLL_PACKET packet) {
if (!config::input.mouse) { if (!config::input.mouse) {
return; return;
} }
@@ -490,7 +512,8 @@ void passthrough(PNV_SCROLL_PACKET packet) {
platf::scroll(platf_input, util::endian::big(packet->scrollAmt1)); platf::scroll(platf_input, util::endian::big(packet->scrollAmt1));
} }
void passthrough(PSS_HSCROLL_PACKET packet) { void
passthrough(PSS_HSCROLL_PACKET packet) {
if (!config::input.mouse) { if (!config::input.mouse) {
return; return;
} }
@@ -498,7 +521,8 @@ void passthrough(PSS_HSCROLL_PACKET packet) {
platf::hscroll(platf_input, util::endian::big(packet->scrollAmount)); platf::hscroll(platf_input, util::endian::big(packet->scrollAmount));
} }
void passthrough(PNV_UNICODE_PACKET packet) { void
passthrough(PNV_UNICODE_PACKET packet) {
if (!config::input.keyboard) { if (!config::input.keyboard) {
return; return;
} }
@@ -507,7 +531,8 @@ void passthrough(PNV_UNICODE_PACKET packet) {
platf::unicode(platf_input, packet->text, size); platf::unicode(platf_input, packet->text, size);
} }
int updateGamepads(std::vector<gamepad_t> &gamepads, std::int16_t old_state, std::int16_t new_state, const platf::rumble_queue_t &rumble_queue) { int
updateGamepads(std::vector<gamepad_t> &gamepads, std::int16_t old_state, std::int16_t new_state, const platf::rumble_queue_t &rumble_queue) {
auto xorGamepadMask = old_state ^ new_state; auto xorGamepadMask = old_state ^ new_state;
if (!xorGamepadMask) { if (!xorGamepadMask) {
return 0; return 0;
@@ -548,7 +573,8 @@ int updateGamepads(std::vector<gamepad_t> &gamepads, std::int16_t old_state, std
return 0; return 0;
} }
void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET packet) { void
passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET packet) {
if (!config::input.controller) { if (!config::input.controller) {
return; return;
} }
@@ -650,7 +676,8 @@ void passthrough(std::shared_ptr<input_t> &input, PNV_MULTI_CONTROLLER_PACKET pa
gamepad.gamepad_state = gamepad_state; gamepad.gamepad_state = gamepad_state;
} }
void passthrough_helper(std::shared_ptr<input_t> input, std::vector<std::uint8_t> &&input_data) { void
passthrough_helper(std::shared_ptr<input_t> input, std::vector<std::uint8_t> &&input_data) {
void *payload = input_data.data(); void *payload = input_data.data();
auto header = (PNV_INPUT_HEADER) payload; auto header = (PNV_INPUT_HEADER) payload;
@@ -684,11 +711,13 @@ void passthrough_helper(std::shared_ptr<input_t> input, std::vector<std::uint8_t
} }
} }
void passthrough(std::shared_ptr<input_t> &input, std::vector<std::uint8_t> &&input_data) { void
passthrough(std::shared_ptr<input_t> &input, std::vector<std::uint8_t> &&input_data) {
task_pool.push(passthrough_helper, input, move_by_copy_util::cmove(input_data)); task_pool.push(passthrough_helper, input, move_by_copy_util::cmove(input_data));
} }
void reset(std::shared_ptr<input_t> &input) { void
reset(std::shared_ptr<input_t> &input) {
task_pool.cancel(key_press_repeat_id); task_pool.cancel(key_press_repeat_id);
task_pool.cancel(input->mouse_left_button_timeout); task_pool.cancel(input->mouse_left_button_timeout);
@@ -715,13 +744,15 @@ public:
} }
}; };
[[nodiscard]] std::unique_ptr<platf::deinit_t> init() { [[nodiscard]] std::unique_ptr<platf::deinit_t>
init() {
platf_input = platf::input(); platf_input = platf::input();
return std::make_unique<deinit_t>(); return std::make_unique<deinit_t>();
} }
std::shared_ptr<input_t> alloc(safe::mail_t mail) { std::shared_ptr<input_t>
alloc(safe::mail_t mail) {
auto input = std::make_shared<input_t>( auto input = std::make_shared<input_t>(
mail->event<input::touch_port_t>(mail::touch_port), mail->event<input::touch_port_t>(mail::touch_port),
mail->queue<platf::rumble_t>(mail::rumble)); mail->queue<platf::rumble_t>(mail::rumble));

View File

@@ -11,14 +11,18 @@
namespace input { namespace input {
struct input_t; struct input_t;
void print(void *input); void
void reset(std::shared_ptr<input_t> &input); print(void *input);
void passthrough(std::shared_ptr<input_t> &input, std::vector<std::uint8_t> &&input_data); void
reset(std::shared_ptr<input_t> &input);
void
passthrough(std::shared_ptr<input_t> &input, std::vector<std::uint8_t> &&input_data);
[[nodiscard]] std::unique_ptr<platf::deinit_t>
init();
[[nodiscard]] std::unique_ptr<platf::deinit_t> init(); std::shared_ptr<input_t>
alloc(safe::mail_t mail);
std::shared_ptr<input_t> alloc(safe::mail_t mail);
struct touch_port_t: public platf::touch_port_t { struct touch_port_t: public platf::touch_port_t {
int env_width, env_height; int env_width, env_height;

View File

@@ -55,7 +55,8 @@ using text_sink = bl::sinks::asynchronous_sink<bl::sinks::text_ostream_backend>;
boost::shared_ptr<text_sink> sink; boost::shared_ptr<text_sink> sink;
struct NoDelete { struct NoDelete {
void operator()(void *) {} void
operator()(void *) {}
}; };
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int) BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)
@@ -69,7 +70,8 @@ BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", int)
* print_help("sunshine"); * print_help("sunshine");
* ``` * ```
*/ */
void print_help(const char *name) { void
print_help(const char *name) {
std::cout std::cout
<< "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl << "Usage: "sv << name << " [options] [/path/to/configuration_file] [--cmd]"sv << std::endl
<< " Any configurable option can be overwritten with: \"name=value\""sv << std::endl << " Any configurable option can be overwritten with: \"name=value\""sv << std::endl
@@ -90,20 +92,21 @@ void print_help(const char *name) {
} }
namespace help { namespace help {
int entry(const char *name, int argc, char *argv[]) { int
entry(const char *name, int argc, char *argv[]) {
print_help(name); print_help(name);
return 0; return 0;
} }
} // namespace help } // namespace help
namespace version { namespace version {
int entry(const char *name, int argc, char *argv[]) { int
entry(const char *name, int argc, char *argv[]) {
std::cout << PROJECT_NAME << " version: v" << PROJECT_VER << std::endl; std::cout << PROJECT_NAME << " version: v" << PROJECT_VER << std::endl;
return 0; return 0;
} }
} // namespace version } // namespace version
/** /**
* @brief Flush the log. * @brief Flush the log.
* *
@@ -112,24 +115,28 @@ int entry(const char *name, int argc, char *argv[]) {
* log_flush(); * log_flush();
* ``` * ```
*/ */
void log_flush() { void
log_flush() {
sink->flush(); sink->flush();
} }
std::map<int, std::function<void()>> signal_handlers; std::map<int, std::function<void()>> signal_handlers;
void on_signal_forwarder(int sig) { void
on_signal_forwarder(int sig) {
signal_handlers.at(sig)(); signal_handlers.at(sig)();
} }
template <class FN> template <class FN>
void on_signal(int sig, FN &&fn) { void
on_signal(int sig, FN &&fn) {
signal_handlers.emplace(sig, std::forward<FN>(fn)); signal_handlers.emplace(sig, std::forward<FN>(fn));
std::signal(sig, on_signal_forwarder); std::signal(sig, on_signal_forwarder);
} }
namespace gen_creds { namespace gen_creds {
int entry(const char *name, int argc, char *argv[]) { int
entry(const char *name, int argc, char *argv[]) {
if (argc < 2 || argv[0] == "help"sv || argv[1] == "help"sv) { if (argc < 2 || argv[0] == "help"sv || argv[1] == "help"sv) {
print_help(name); print_help(name);
return 0; return 0;
@@ -148,7 +155,8 @@ std::map<std::string_view, std::function<int(const char *name, int argc, char **
}; };
#ifdef _WIN32 #ifdef _WIN32
LRESULT CALLBACK SessionMonitorWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT CALLBACK
SessionMonitorWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) { switch (uMsg) {
case WM_ENDSESSION: { case WM_ENDSESSION: {
// Raise a SIGINT to trigger our cleanup logic and terminate ourselves // Raise a SIGINT to trigger our cleanup logic and terminate ourselves
@@ -176,7 +184,8 @@ LRESULT CALLBACK SessionMonitorWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, L
* main(1, const char* args[] = {"sunshine", nullptr}); * main(1, const char* args[] = {"sunshine", nullptr});
* ``` * ```
*/ */
int main(int argc, char *argv[]) { int
main(int argc, char *argv[]) {
task_pool_util::TaskPool::task_id_t force_shutdown = nullptr; task_pool_util::TaskPool::task_id_t force_shutdown = nullptr;
#ifdef _WIN32 #ifdef _WIN32
@@ -395,7 +404,8 @@ int main(int argc, char *argv[]) {
* std::string contents = read_file("path/to/file"); * std::string contents = read_file("path/to/file");
* ``` * ```
*/ */
std::string read_file(const char *path) { std::string
read_file(const char *path) {
if (!std::filesystem::exists(path)) { if (!std::filesystem::exists(path)) {
BOOST_LOG(debug) << "Missing file: " << path; BOOST_LOG(debug) << "Missing file: " << path;
return {}; return {};
@@ -425,7 +435,8 @@ std::string read_file(const char *path) {
* int write_status = write_file("path/to/file", "file contents"); * int write_status = write_file("path/to/file", "file contents");
* ``` * ```
*/ */
int write_file(const char *path, const std::string_view &contents) { int
write_file(const char *path, const std::string_view &contents) {
std::ofstream out(path); std::ofstream out(path);
if (!out.is_open()) { if (!out.is_open()) {
@@ -447,7 +458,8 @@ int write_file(const char *path, const std::string_view &contents) {
* std::uint16_t mapped_port = map_port(1); * std::uint16_t mapped_port = map_port(1);
* ``` * ```
*/ */
std::uint16_t map_port(int port) { std::uint16_t
map_port(int port) {
// TODO: Ensure port is in the range of 21-65535 // TODO: Ensure port is in the range of 21-65535
// TODO: Ensure port is not already in use by another application // TODO: Ensure port is not already in use by another application
return (std::uint16_t)((int) config::sunshine.port + port); return (std::uint16_t)((int) config::sunshine.port + port);

View File

@@ -28,19 +28,32 @@ extern boost::log::sources::severity_logger<int> error;
extern boost::log::sources::severity_logger<int> fatal; extern boost::log::sources::severity_logger<int> fatal;
// functions // functions
int main(int argc, char *argv[]); int
void log_flush(); main(int argc, char *argv[]);
void open_url(const std::string &url); void
void tray_open_ui_cb(struct tray_menu *item); log_flush();
void tray_donate_github_cb(struct tray_menu *item); void
void tray_donate_mee6_cb(struct tray_menu *item); open_url(const std::string &url);
void tray_donate_patreon_cb(struct tray_menu *item); void
void tray_donate_paypal_cb(struct tray_menu *item); tray_open_ui_cb(struct tray_menu *item);
void tray_quit_cb(struct tray_menu *item); void
void print_help(const char *name); tray_donate_github_cb(struct tray_menu *item);
std::string read_file(const char *path); void
int write_file(const char *path, const std::string_view &contents); tray_donate_mee6_cb(struct tray_menu *item);
std::uint16_t map_port(int port); void
tray_donate_patreon_cb(struct tray_menu *item);
void
tray_donate_paypal_cb(struct tray_menu *item);
void
tray_quit_cb(struct tray_menu *item);
void
print_help(const char *name);
std::string
read_file(const char *path);
int
write_file(const char *path, const std::string_view &contents);
std::uint16_t
map_port(int port);
// namespaces // namespaces
namespace mail { namespace mail {

View File

@@ -16,7 +16,8 @@ private:
move_type _to_move; move_type _to_move;
public: public:
explicit MoveByCopy(move_type &&to_move) : _to_move(std::move(to_move)) {} explicit MoveByCopy(move_type &&to_move):
_to_move(std::move(to_move)) {}
MoveByCopy(MoveByCopy &&other) = default; MoveByCopy(MoveByCopy &&other) = default;
@@ -24,9 +25,11 @@ public:
*this = other; *this = other;
} }
MoveByCopy &operator=(MoveByCopy &&other) = default; MoveByCopy &
operator=(MoveByCopy &&other) = default;
MoveByCopy &operator=(const MoveByCopy &other) { MoveByCopy &
operator=(const MoveByCopy &other) {
this->_to_move = std::move(const_cast<MoveByCopy &>(other)._to_move); this->_to_move = std::move(const_cast<MoveByCopy &>(other)._to_move);
return *this; return *this;
@@ -38,13 +41,15 @@ public:
}; };
template <class T> template <class T>
MoveByCopy<T> cmove(T &movable) { MoveByCopy<T>
cmove(T &movable) {
return MoveByCopy<T>(std::move(movable)); return MoveByCopy<T>(std::move(movable));
} }
// Do NOT use this unless you are absolutely certain the object to be moved is no longer used by the caller // Do NOT use this unless you are absolutely certain the object to be moved is no longer used by the caller
template <class T> template <class T>
MoveByCopy<T> const_cmove(const T &movable) { MoveByCopy<T>
const_cmove(const T &movable) {
return MoveByCopy<T>(std::move(const_cast<T &>(movable))); return MoveByCopy<T>(std::move(const_cast<T &>(movable)));
} }
} // namespace move_by_copy_util } // namespace move_by_copy_util

View File

@@ -7,7 +7,8 @@
using namespace std::literals; using namespace std::literals;
namespace net { namespace net {
// In the format "xxx.xxx.xxx.xxx/x" // In the format "xxx.xxx.xxx.xxx/x"
std::pair<std::uint32_t, std::uint32_t> ip_block(const std::string_view &ip); std::pair<std::uint32_t, std::uint32_t>
ip_block(const std::string_view &ip);
std::vector<std::pair<std::uint32_t, std::uint32_t>> pc_ips { std::vector<std::pair<std::uint32_t, std::uint32_t>> pc_ips {
ip_block("127.0.0.1/32"sv) ip_block("127.0.0.1/32"sv)
@@ -18,7 +19,8 @@ std::vector<std::tuple<std::uint32_t, std::uint32_t>> lan_ips {
ip_block("10.0.0.0/8"sv) ip_block("10.0.0.0/8"sv)
}; };
std::uint32_t ip(const std::string_view &ip_str) { std::uint32_t
ip(const std::string_view &ip_str) {
auto begin = std::begin(ip_str); auto begin = std::begin(ip_str);
auto end = std::end(ip_str); auto end = std::end(ip_str);
auto temp_end = std::find(begin, end, '.'); auto temp_end = std::find(begin, end, '.');
@@ -39,7 +41,8 @@ std::uint32_t ip(const std::string_view &ip_str) {
} }
// In the format "xxx.xxx.xxx.xxx/x" // In the format "xxx.xxx.xxx.xxx/x"
std::pair<std::uint32_t, std::uint32_t> ip_block(const std::string_view &ip_str) { std::pair<std::uint32_t, std::uint32_t>
ip_block(const std::string_view &ip_str) {
auto begin = std::begin(ip_str); auto begin = std::begin(ip_str);
auto end = std::find(begin, std::end(ip_str), '/'); auto end = std::find(begin, std::end(ip_str), '/');
@@ -50,7 +53,8 @@ std::pair<std::uint32_t, std::uint32_t> ip_block(const std::string_view &ip_str)
return { addr, addr + ((1 << bits) - 1) }; return { addr, addr + ((1 << bits) - 1) };
} }
net_e from_enum_string(const std::string_view &view) { net_e
from_enum_string(const std::string_view &view) {
if (view == "wan") { if (view == "wan") {
return WAN; return WAN;
} }
@@ -60,7 +64,8 @@ net_e from_enum_string(const std::string_view &view) {
return PC; return PC;
} }
net_e from_address(const std::string_view &view) { net_e
from_address(const std::string_view &view) {
auto addr = ip(view); auto addr = ip(view);
for (auto [ip_low, ip_high] : pc_ips) { for (auto [ip_low, ip_high] : pc_ips) {
@@ -78,7 +83,8 @@ net_e from_address(const std::string_view &view) {
return WAN; return WAN;
} }
std::string_view to_enum_string(net_e net) { std::string_view
to_enum_string(net_e net) {
switch (net) { switch (net) {
case PC: case PC:
return "pc"sv; return "pc"sv;
@@ -92,14 +98,16 @@ std::string_view to_enum_string(net_e net) {
return "wan"sv; return "wan"sv;
} }
host_t host_create(ENetAddress &addr, std::size_t peers, std::uint16_t port) { host_t
host_create(ENetAddress &addr, std::size_t peers, std::uint16_t port) {
enet_address_set_host(&addr, "0.0.0.0"); enet_address_set_host(&addr, "0.0.0.0");
enet_address_set_port(&addr, port); enet_address_set_port(&addr, port);
return host_t { enet_host_create(AF_INET, &addr, peers, 1, 0, 0) }; return host_t { enet_host_create(AF_INET, &addr, peers, 1, 0, 0) };
} }
void free_host(ENetHost *host) { void
free_host(ENetHost *host) {
std::for_each(host->peers, host->peers + host->peerCount, [](ENetPeer &peer_ref) { std::for_each(host->peers, host->peers + host->peerCount, [](ENetPeer &peer_ref) {
ENetPeer *peer = &peer_ref; ENetPeer *peer = &peer_ref;

View File

@@ -10,7 +10,8 @@
#include "utility.h" #include "utility.h"
namespace net { namespace net {
void free_host(ENetHost *host); void
free_host(ENetHost *host);
using host_t = util::safe_ptr<ENetHost, free_host>; using host_t = util::safe_ptr<ENetHost, free_host>;
using peer_t = ENetPeer *; using peer_t = ENetPeer *;
@@ -22,12 +23,16 @@ enum net_e : int {
WAN WAN
}; };
net_e from_enum_string(const std::string_view &view); net_e
std::string_view to_enum_string(net_e net); from_enum_string(const std::string_view &view);
std::string_view
to_enum_string(net_e net);
net_e from_address(const std::string_view &view); net_e
from_address(const std::string_view &view);
host_t host_create(ENetAddress &addr, std::size_t peers, std::uint16_t port); host_t
host_create(ENetAddress &addr, std::size_t peers, std::uint16_t port);
} // namespace net } // namespace net
#endif // SUNSHINE_NETWORK_H #endif // SUNSHINE_NETWORK_H

View File

@@ -38,14 +38,15 @@ namespace pt = boost::property_tree;
class SunshineHttpsServer: public SimpleWeb::Server<SimpleWeb::HTTPS> { class SunshineHttpsServer: public SimpleWeb::Server<SimpleWeb::HTTPS> {
public: public:
SunshineHttpsServer(const std::string &certification_file, const std::string &private_key_file) SunshineHttpsServer(const std::string &certification_file, const std::string &private_key_file):
: SimpleWeb::Server<SimpleWeb::HTTPS>::Server(certification_file, private_key_file) {} SimpleWeb::Server<SimpleWeb::HTTPS>::Server(certification_file, private_key_file) {}
std::function<int(SSL *)> verify; std::function<int(SSL *)> verify;
std::function<void(std::shared_ptr<Response>, std::shared_ptr<Request>)> on_verify_failed; std::function<void(std::shared_ptr<Response>, std::shared_ptr<Request>)> on_verify_failed;
protected: protected:
void after_bind() override { void
after_bind() override {
SimpleWeb::Server<SimpleWeb::HTTPS>::after_bind(); SimpleWeb::Server<SimpleWeb::HTTPS>::after_bind();
if (verify) { if (verify) {
@@ -58,7 +59,8 @@ protected:
} }
// This is Server<HTTPS>::accept() with SSL validation support added // This is Server<HTTPS>::accept() with SSL validation support added
void accept() override { void
accept() override {
auto connection = create_connection(*io_service, context); auto connection = create_connection(*io_service, context);
acceptor->async_accept(connection->socket->lowest_layer(), [this, connection](const SimpleWeb::error_code &ec) { acceptor->async_accept(connection->socket->lowest_layer(), [this, connection](const SimpleWeb::error_code &ec) {
@@ -147,7 +149,8 @@ enum class op_e {
REMOVE REMOVE
}; };
std::string get_arg(const args_t &args, const char *name) { std::string
get_arg(const args_t &args, const char *name) {
auto it = args.find(name); auto it = args.find(name);
if (it == std::end(args)) { if (it == std::end(args)) {
throw std::out_of_range(name); throw std::out_of_range(name);
@@ -155,7 +158,8 @@ std::string get_arg(const args_t &args, const char *name) {
return it->second; return it->second;
} }
void save_state() { void
save_state() {
pt::ptree root; pt::ptree root;
if (fs::exists(config::nvhttp.file_state)) { if (fs::exists(config::nvhttp.file_state)) {
@@ -197,7 +201,8 @@ void save_state() {
} }
} }
void load_state() { void
load_state() {
if (!fs::exists(config::nvhttp.file_state)) { if (!fs::exists(config::nvhttp.file_state)) {
BOOST_LOG(info) << "File "sv << config::nvhttp.file_state << " doesn't exist"sv; BOOST_LOG(info) << "File "sv << config::nvhttp.file_state << " doesn't exist"sv;
http::unique_id = uuid_util::uuid_t::generate().string(); http::unique_id = uuid_util::uuid_t::generate().string();
@@ -236,7 +241,8 @@ void load_state() {
} }
} }
void update_id_client(const std::string &uniqueID, std::string &&cert, op_e op) { void
update_id_client(const std::string &uniqueID, std::string &&cert, op_e op) {
switch (op) { switch (op) {
case op_e::ADD: { case op_e::ADD: {
auto &client = map_id_client[uniqueID]; auto &client = map_id_client[uniqueID];
@@ -253,7 +259,8 @@ void update_id_client(const std::string &uniqueID, std::string &&cert, op_e op)
} }
} }
rtsp_stream::launch_session_t make_launch_session(bool host_audio, const args_t &args) { rtsp_stream::launch_session_t
make_launch_session(bool host_audio, const args_t &args) {
rtsp_stream::launch_session_t launch_session; rtsp_stream::launch_session_t launch_session;
launch_session.host_audio = host_audio; launch_session.host_audio = host_audio;
@@ -267,7 +274,8 @@ rtsp_stream::launch_session_t make_launch_session(bool host_audio, const args_t
return launch_session; return launch_session;
} }
void getservercert(pair_session_t &sess, pt::ptree &tree, const std::string &pin) { void
getservercert(pair_session_t &sess, pt::ptree &tree, const std::string &pin) {
if (sess.async_insert_pin.salt.size() < 32) { if (sess.async_insert_pin.salt.size() < 32) {
tree.put("root.paired", 0); tree.put("root.paired", 0);
tree.put("root.<xmlattr>.status_code", 400); tree.put("root.<xmlattr>.status_code", 400);
@@ -285,7 +293,8 @@ void getservercert(pair_session_t &sess, pt::ptree &tree, const std::string &pin
tree.put("root.plaincert", util::hex_vec(conf_intern.servercert, true)); tree.put("root.plaincert", util::hex_vec(conf_intern.servercert, true));
tree.put("root.<xmlattr>.status_code", 200); tree.put("root.<xmlattr>.status_code", 200);
} }
void serverchallengeresp(pair_session_t &sess, pt::ptree &tree, const args_t &args) { void
serverchallengeresp(pair_session_t &sess, pt::ptree &tree, const args_t &args) {
auto encrypted_response = util::from_hex_vec(get_arg(args, "serverchallengeresp"), true); auto encrypted_response = util::from_hex_vec(get_arg(args, "serverchallengeresp"), true);
std::vector<uint8_t> decrypted; std::vector<uint8_t> decrypted;
@@ -305,7 +314,8 @@ void serverchallengeresp(pair_session_t &sess, pt::ptree &tree, const args_t &ar
tree.put("root.<xmlattr>.status_code", 200); tree.put("root.<xmlattr>.status_code", 200);
} }
void clientchallenge(pair_session_t &sess, pt::ptree &tree, const args_t &args) { void
clientchallenge(pair_session_t &sess, pt::ptree &tree, const args_t &args) {
auto challenge = util::from_hex_vec(get_arg(args, "clientchallenge"), true); auto challenge = util::from_hex_vec(get_arg(args, "clientchallenge"), true);
crypto::cipher::ecb_t cipher(*sess.cipher_key, false); crypto::cipher::ecb_t cipher(*sess.cipher_key, false);
@@ -340,7 +350,8 @@ void clientchallenge(pair_session_t &sess, pt::ptree &tree, const args_t &args)
tree.put("root.<xmlattr>.status_code", 200); tree.put("root.<xmlattr>.status_code", 200);
} }
void clientpairingsecret(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, pair_session_t &sess, pt::ptree &tree, const args_t &args) { void
clientpairingsecret(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, pair_session_t &sess, pt::ptree &tree, const args_t &args) {
auto &client = sess.client; auto &client = sess.client;
auto pairingsecret = util::from_hex_vec(get_arg(args, "clientpairingsecret"), true); auto pairingsecret = util::from_hex_vec(get_arg(args, "clientpairingsecret"), true);
@@ -401,7 +412,8 @@ struct tunnel<SimpleWeb::HTTP> {
}; };
template <class T> template <class T>
void print_req(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) { void
print_req(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
BOOST_LOG(debug) << "TUNNEL :: "sv << tunnel<T>::to_string; BOOST_LOG(debug) << "TUNNEL :: "sv << tunnel<T>::to_string;
BOOST_LOG(debug) << "METHOD :: "sv << request->method; BOOST_LOG(debug) << "METHOD :: "sv << request->method;
@@ -421,7 +433,8 @@ void print_req(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> reque
} }
template <class T> template <class T>
void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) { void
not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request); print_req<T>(request);
pt::ptree tree; pt::ptree tree;
@@ -440,7 +453,8 @@ void not_found(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> resp
} }
template <class T> template <class T>
void pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) { void
pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request); print_req<T>(request);
pt::ptree tree; pt::ptree tree;
@@ -520,7 +534,8 @@ void pair(std::shared_ptr<safe::queue_t<crypto::x509_t>> &add_cert, std::shared_
* bool pin_status = nvhttp::pin("1234"); * bool pin_status = nvhttp::pin("1234");
* ``` * ```
*/ */
bool pin(std::string pin) { bool
pin(std::string pin) {
pt::ptree tree; pt::ptree tree;
if (map_id_sess.empty()) { if (map_id_sess.empty()) {
return false; return false;
@@ -551,7 +566,8 @@ bool pin(std::string pin) {
} }
template <class T> template <class T>
void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) { void
pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request); print_req<T>(request);
response->close_connection_after_response = true; response->close_connection_after_response = true;
@@ -576,7 +592,8 @@ void pin(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response,
} }
template <class T> template <class T>
void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) { void
serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> response, std::shared_ptr<typename SimpleWeb::ServerBase<T>::Request> request) {
print_req<T>(request); print_req<T>(request);
int pair_status = 0; int pair_status = 0;
@@ -584,7 +601,6 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
auto args = request->parse_query_string(); auto args = request->parse_query_string();
auto clientID = args.find("uniqueid"s); auto clientID = args.find("uniqueid"s);
if (clientID != std::end(args)) { if (clientID != std::end(args)) {
if (auto it = map_id_client.find(clientID->second); it != std::end(map_id_client)) { if (auto it = map_id_client.find(clientID->second); it != std::end(map_id_client)) {
pair_status = 1; pair_status = 1;
@@ -659,7 +675,8 @@ void serverinfo(std::shared_ptr<typename SimpleWeb::ServerBase<T>::Response> res
response->close_connection_after_response = true; response->close_connection_after_response = true;
} }
void applist(resp_https_t response, req_https_t request) { void
applist(resp_https_t response, req_https_t request) {
print_req<SimpleWeb::HTTPS>(request); print_req<SimpleWeb::HTTPS>(request);
pt::ptree tree; pt::ptree tree;
@@ -703,7 +720,8 @@ void applist(resp_https_t response, req_https_t request) {
} }
} }
void launch(bool &host_audio, resp_https_t response, req_https_t request) { void
launch(bool &host_audio, resp_https_t response, req_https_t request) {
print_req<SimpleWeb::HTTPS>(request); print_req<SimpleWeb::HTTPS>(request);
pt::ptree tree; pt::ptree tree;
@@ -728,7 +746,6 @@ void launch(bool &host_audio, resp_https_t response, req_https_t request) {
args.find("rikeyid"s) == std::end(args) || args.find("rikeyid"s) == std::end(args) ||
args.find("localAudioPlayMode"s) == std::end(args) || args.find("localAudioPlayMode"s) == std::end(args) ||
args.find("appid"s) == std::end(args)) { args.find("appid"s) == std::end(args)) {
tree.put("root.resume", 0); tree.put("root.resume", 0);
tree.put("root.<xmlattr>.status_code", 400); tree.put("root.<xmlattr>.status_code", 400);
@@ -763,7 +780,8 @@ void launch(bool &host_audio, resp_https_t response, req_https_t request) {
tree.put("root.gamesession", 1); tree.put("root.gamesession", 1);
} }
void resume(bool &host_audio, resp_https_t response, req_https_t request) { void
resume(bool &host_audio, resp_https_t response, req_https_t request) {
print_req<SimpleWeb::HTTPS>(request); print_req<SimpleWeb::HTTPS>(request);
pt::ptree tree; pt::ptree tree;
@@ -796,7 +814,6 @@ void resume(bool &host_audio, resp_https_t response, req_https_t request) {
if ( if (
args.find("rikey"s) == std::end(args) || args.find("rikey"s) == std::end(args) ||
args.find("rikeyid"s) == std::end(args)) { args.find("rikeyid"s) == std::end(args)) {
tree.put("root.resume", 0); tree.put("root.resume", 0);
tree.put("root.<xmlattr>.status_code", 400); tree.put("root.<xmlattr>.status_code", 400);
@@ -810,7 +827,8 @@ void resume(bool &host_audio, resp_https_t response, req_https_t request) {
tree.put("root.resume", 1); tree.put("root.resume", 1);
} }
void cancel(resp_https_t response, req_https_t request) { void
cancel(resp_https_t response, req_https_t request) {
print_req<SimpleWeb::HTTPS>(request); print_req<SimpleWeb::HTTPS>(request);
pt::ptree tree; pt::ptree tree;
@@ -839,8 +857,8 @@ void cancel(resp_https_t response, req_https_t request) {
} }
} }
void
void appasset(resp_https_t response, req_https_t request) { appasset(resp_https_t response, req_https_t request) {
print_req<SimpleWeb::HTTPS>(request); print_req<SimpleWeb::HTTPS>(request);
auto args = request->parse_query_string(); auto args = request->parse_query_string();
@@ -861,7 +879,8 @@ void appasset(resp_https_t response, req_https_t request) {
* nvhttp::start(); * nvhttp::start();
* ``` * ```
*/ */
void start() { void
start() {
auto shutdown_event = mail::man->event<bool>(mail::shutdown); auto shutdown_event = mail::man->event<bool>(mail::shutdown);
auto port_http = map_port(PORT_HTTP); auto port_http = map_port(PORT_HTTP);
@@ -905,7 +924,6 @@ void start() {
auto fg = util::fail_guard([&]() { auto fg = util::fail_guard([&]() {
char subject_name[256]; char subject_name[256];
X509_NAME_oneline(X509_get_subject_name(x509), subject_name, sizeof(subject_name)); X509_NAME_oneline(X509_get_subject_name(x509), subject_name, sizeof(subject_name));
BOOST_LOG(debug) << subject_name << " -- "sv << (verified ? "verified"sv : "denied"sv); BOOST_LOG(debug) << subject_name << " -- "sv << (verified ? "verified"sv : "denied"sv);
@@ -1007,7 +1025,8 @@ void start() {
* nvhttp::erase_all_clients(); * nvhttp::erase_all_clients();
* ``` * ```
*/ */
void erase_all_clients() { void
erase_all_clients() {
map_id_client.clear(); map_id_client.clear();
save_state(); save_state();
} }

View File

@@ -39,9 +39,12 @@ constexpr auto PORT_HTTP = 0;
constexpr auto PORT_HTTPS = -5; constexpr auto PORT_HTTPS = -5;
// functions // functions
void start(); void
bool pin(std::string pin); start();
void erase_all_clients(); bool
pin(std::string pin);
void
erase_all_clients();
} // namespace nvhttp } // namespace nvhttp
#endif // SUNSHINE_NVHTTP_H #endif // SUNSHINE_NVHTTP_H

View File

@@ -69,8 +69,8 @@ constexpr std::uint16_t Y = 0x8000;
struct rumble_t { struct rumble_t {
KITTY_DEFAULT_CONSTR(rumble_t) KITTY_DEFAULT_CONSTR(rumble_t)
rumble_t(std::uint16_t id, std::uint16_t lowfreq, std::uint16_t highfreq) rumble_t(std::uint16_t id, std::uint16_t lowfreq, std::uint16_t highfreq):
: id { id }, lowfreq { lowfreq }, highfreq { highfreq } {} id { id }, lowfreq { lowfreq }, highfreq { highfreq } {}
std::uint16_t id; std::uint16_t id;
std::uint16_t lowfreq; std::uint16_t lowfreq;
@@ -130,7 +130,8 @@ enum class pix_fmt_e {
unknown unknown
}; };
inline std::string_view from_pix_fmt(pix_fmt_e pix_fmt) { inline std::string_view
from_pix_fmt(pix_fmt_e pix_fmt) {
using namespace std::literals; using namespace std::literals;
#define _CONVERT(x) \ #define _CONVERT(x) \
case pix_fmt_e::x: \ case pix_fmt_e::x: \
@@ -174,8 +175,10 @@ public:
img_t(img_t &&) = delete; img_t(img_t &&) = delete;
img_t(const img_t &) = delete; img_t(const img_t &) = delete;
img_t &operator=(img_t &&) = delete; img_t &
img_t &operator=(const img_t &) = delete; operator=(img_t &&) = delete;
img_t &
operator=(const img_t &) = delete;
std::uint8_t *data {}; std::uint8_t *data {};
std::int32_t width {}; std::int32_t width {};
@@ -204,29 +207,34 @@ struct hwdevice_t {
void *data {}; void *data {};
AVFrame *frame {}; AVFrame *frame {};
virtual int convert(platf::img_t &img) { virtual int
convert(platf::img_t &img) {
return -1; return -1;
} }
/** /**
* implementations must take ownership of 'frame' * implementations must take ownership of 'frame'
*/ */
virtual int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) { virtual int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) {
BOOST_LOG(error) << "Illegal call to hwdevice_t::set_frame(). Did you forget to override it?"; BOOST_LOG(error) << "Illegal call to hwdevice_t::set_frame(). Did you forget to override it?";
return -1; return -1;
}; };
virtual void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) {}; virtual void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) {};
/** /**
* Implementations may set parameters during initialization of the hwframes context * Implementations may set parameters during initialization of the hwframes context
*/ */
virtual void init_hwframes(AVHWFramesContext *frames) {}; virtual void
init_hwframes(AVHWFramesContext *frames) {};
/** /**
* Implementations may make modifications required before context derivation * Implementations may make modifications required before context derivation
*/ */
virtual int prepare_to_derive_context(int hw_device_type) { virtual int
prepare_to_derive_context(int hw_device_type) {
return 0; return 0;
}; };
@@ -255,7 +263,8 @@ public:
*/ */
using snapshot_cb_t = std::function<std::shared_ptr<img_t>(std::shared_ptr<img_t> &img, bool frame_captured)>; using snapshot_cb_t = std::function<std::shared_ptr<img_t>(std::shared_ptr<img_t> &img, bool frame_captured)>;
display_t() noexcept : offset_x { 0 }, offset_y { 0 } {} display_t() noexcept:
offset_x { 0 }, offset_y { 0 } {}
/** /**
* snapshot_cb --> the callback * snapshot_cb --> the callback
@@ -267,21 +276,27 @@ public:
* capture_e::error on error * capture_e::error on error
* capture_e::reinit when need of reinitialization * capture_e::reinit when need of reinitialization
*/ */
virtual capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) = 0; virtual capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) = 0;
virtual std::shared_ptr<img_t> alloc_img() = 0; virtual std::shared_ptr<img_t>
alloc_img() = 0;
virtual int dummy_img(img_t *img) = 0; virtual int
dummy_img(img_t *img) = 0;
virtual std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) { virtual std::shared_ptr<hwdevice_t>
make_hwdevice(pix_fmt_e pix_fmt) {
return std::make_shared<hwdevice_t>(); return std::make_shared<hwdevice_t>();
} }
virtual bool is_hdr() { virtual bool
is_hdr() {
return false; return false;
} }
virtual bool get_hdr_metadata(SS_HDR_METADATA &metadata) { virtual bool
get_hdr_metadata(SS_HDR_METADATA &metadata) {
std::memset(&metadata, 0, sizeof(metadata)); std::memset(&metadata, 0, sizeof(metadata));
return false; return false;
} }
@@ -297,34 +312,44 @@ public:
class mic_t { class mic_t {
public: public:
virtual capture_e sample(std::vector<std::int16_t> &frame_buffer) = 0; virtual capture_e
sample(std::vector<std::int16_t> &frame_buffer) = 0;
virtual ~mic_t() = default; virtual ~mic_t() = default;
}; };
class audio_control_t { class audio_control_t {
public: public:
virtual int set_sink(const std::string &sink) = 0; virtual int
set_sink(const std::string &sink) = 0;
virtual std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) = 0; virtual std::unique_ptr<mic_t>
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) = 0;
virtual std::optional<sink_t> sink_info() = 0; virtual std::optional<sink_t>
sink_info() = 0;
virtual ~audio_control_t() = default; virtual ~audio_control_t() = default;
}; };
void freeInput(void *); void
freeInput(void *);
using input_t = util::safe_ptr<void, freeInput>; using input_t = util::safe_ptr<void, freeInput>;
std::filesystem::path appdata(); std::filesystem::path
appdata();
std::string get_mac_address(const std::string_view &address); std::string
get_mac_address(const std::string_view &address);
std::string from_sockaddr(const sockaddr *const); std::string
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const); from_sockaddr(const sockaddr *const);
std::pair<std::uint16_t, std::string>
from_sockaddr_ex(const sockaddr *const);
std::unique_ptr<audio_control_t> audio_control(); std::unique_ptr<audio_control_t>
audio_control();
/** /**
* display_name --> The name of the monitor that SHOULD be displayed * display_name --> The name of the monitor that SHOULD be displayed
@@ -335,12 +360,15 @@ std::unique_ptr<audio_control_t> audio_control();
* *
* Returns display_t based on hwdevice_type * Returns display_t based on hwdevice_type
*/ */
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config); std::shared_ptr<display_t>
display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config);
// A list of names of displays accepted as display_name with the mem_type_e // A list of names of displays accepted as display_name with the mem_type_e
std::vector<std::string> display_names(mem_type_e hwdevice_type); std::vector<std::string>
display_names(mem_type_e hwdevice_type);
boost::process::child run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, boost::process::environment &env, FILE *file, std::error_code &ec, boost::process::group *group); boost::process::child
run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, boost::process::environment &env, FILE *file, std::error_code &ec, boost::process::group *group);
enum class thread_priority_e : int { enum class thread_priority_e : int {
low, low,
@@ -348,14 +376,19 @@ enum class thread_priority_e : int {
high, high,
critical critical
}; };
void adjust_thread_priority(thread_priority_e priority); void
adjust_thread_priority(thread_priority_e priority);
// Allow OS-specific actions to be taken to prepare for streaming // Allow OS-specific actions to be taken to prepare for streaming
void streaming_will_start(); void
void streaming_will_stop(); streaming_will_start();
void
streaming_will_stop();
bool restart_supported(); bool
bool restart(); restart_supported();
bool
restart();
struct batched_send_info_t { struct batched_send_info_t {
const char *buffer; const char *buffer;
@@ -366,37 +399,53 @@ struct batched_send_info_t {
boost::asio::ip::address &target_address; boost::asio::ip::address &target_address;
uint16_t target_port; uint16_t target_port;
}; };
bool send_batch(batched_send_info_t &send_info); bool
send_batch(batched_send_info_t &send_info);
enum class qos_data_type_e : int { enum class qos_data_type_e : int {
audio, audio,
video video
}; };
std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type); std::unique_ptr<deinit_t>
enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type);
input_t input(); input_t
void move_mouse(input_t &input, int deltaX, int deltaY); input();
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y); void
void button_mouse(input_t &input, int button, bool release); move_mouse(input_t &input, int deltaX, int deltaY);
void scroll(input_t &input, int distance); void
void hscroll(input_t &input, int distance); abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y);
void keyboard(input_t &input, uint16_t modcode, bool release); void
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state); button_mouse(input_t &input, int button, bool release);
void unicode(input_t &input, char *utf8, int size); void
scroll(input_t &input, int distance);
void
hscroll(input_t &input, int distance);
void
keyboard(input_t &input, uint16_t modcode, bool release);
void
gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
void
unicode(input_t &input, char *utf8, int size);
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue); int
void free_gamepad(input_t &input, int nr); alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue);
void
free_gamepad(input_t &input, int nr);
#define SERVICE_NAME "Sunshine" #define SERVICE_NAME "Sunshine"
#define SERVICE_TYPE "_nvstream._tcp" #define SERVICE_TYPE "_nvstream._tcp"
namespace publish { namespace publish {
[[nodiscard]] std::unique_ptr<deinit_t> start(); [[nodiscard]] std::unique_ptr<deinit_t>
start();
} }
[[nodiscard]] std::unique_ptr<deinit_t> init(); [[nodiscard]] std::unique_ptr<deinit_t>
init();
std::vector<std::string_view> &supported_gamepads(); std::vector<std::string_view> &
supported_gamepads();
} // namespace platf } // namespace platf
#endif //SUNSHINE_COMMON_H #endif //SUNSHINE_COMMON_H

View File

@@ -30,7 +30,8 @@ constexpr pa_channel_position_t position_mapping[] {
PA_CHANNEL_POSITION_SIDE_RIGHT, PA_CHANNEL_POSITION_SIDE_RIGHT,
}; };
std::string to_string(const char *name, const std::uint8_t *mapping, int channels) { std::string
to_string(const char *name, const std::uint8_t *mapping, int channels) {
std::stringstream ss; std::stringstream ss;
ss << "rate=48000 sink_name="sv << name << " format=s16le channels="sv << channels << " channel_map="sv; ss << "rate=48000 sink_name="sv << name << " format=s16le channels="sv << channels << " channel_map="sv;
@@ -50,7 +51,8 @@ std::string to_string(const char *name, const std::uint8_t *mapping, int channel
struct mic_attr_t: public mic_t { struct mic_attr_t: public mic_t {
util::safe_ptr<pa_simple, pa_simple_free> mic; util::safe_ptr<pa_simple, pa_simple_free> mic;
capture_e sample(std::vector<std::int16_t> &sample_buf) override { capture_e
sample(std::vector<std::int16_t> &sample_buf) override {
auto sample_size = sample_buf.size(); auto sample_size = sample_buf.size();
auto buf = sample_buf.data(); auto buf = sample_buf.data();
@@ -65,7 +67,8 @@ struct mic_attr_t : public mic_t {
} }
}; };
std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size, std::string source_name) { std::unique_ptr<mic_t>
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size, std::string source_name) {
auto mic = std::make_unique<mic_attr_t>(); auto mic = std::make_unique<mic_attr_t>();
pa_sample_spec ss { PA_SAMPLE_S16LE, sample_rate, (std::uint8_t) channels }; pa_sample_spec ss { PA_SAMPLE_S16LE, sample_rate, (std::uint8_t) channels };
@@ -113,7 +116,8 @@ template<class T>
using add_const_t = typename add_const_helper<std::is_pointer_v<T>, T>::type; using add_const_t = typename add_const_helper<std::is_pointer_v<T>, T>::type;
template <class T> template <class T>
void pa_free(T *p) { void
pa_free(T *p) {
pa_xfree(p); pa_xfree(p);
} }
using ctx_t = util::safe_ptr<pa_context, pa_context_unref>; using ctx_t = util::safe_ptr<pa_context, pa_context_unref>;
@@ -125,7 +129,8 @@ template<class T>
using cb_simple_t = std::function<void(ctx_t::pointer, add_const_t<T> i)>; using cb_simple_t = std::function<void(ctx_t::pointer, add_const_t<T> i)>;
template <class T> template <class T>
void cb(ctx_t::pointer ctx, add_const_t<T> i, void *userdata) { void
cb(ctx_t::pointer ctx, add_const_t<T> i, void *userdata) {
auto &f = *(cb_simple_t<T> *) userdata; auto &f = *(cb_simple_t<T> *) userdata;
// Cannot similarly filter on eol here. Unless reported otherwise assume // Cannot similarly filter on eol here. Unless reported otherwise assume
@@ -137,7 +142,8 @@ template<class T>
using cb_t = std::function<void(ctx_t::pointer, add_const_t<T> i, int eol)>; using cb_t = std::function<void(ctx_t::pointer, add_const_t<T> i, int eol)>;
template <class T> template <class T>
void cb(ctx_t::pointer ctx, add_const_t<T> i, int eol, void *userdata) { void
cb(ctx_t::pointer ctx, add_const_t<T> i, int eol, void *userdata) {
auto &f = *(cb_t<T> *) userdata; auto &f = *(cb_t<T> *) userdata;
// For some reason, pulseaudio calls this callback after disconnecting // For some reason, pulseaudio calls this callback after disconnecting
@@ -148,19 +154,22 @@ void cb(ctx_t::pointer ctx, add_const_t<T> i, int eol, void *userdata) {
f(ctx, i, eol); f(ctx, i, eol);
} }
void cb_i(ctx_t::pointer ctx, std::uint32_t i, void *userdata) { void
cb_i(ctx_t::pointer ctx, std::uint32_t i, void *userdata) {
auto alarm = (safe::alarm_raw_t<int> *) userdata; auto alarm = (safe::alarm_raw_t<int> *) userdata;
alarm->ring(i); alarm->ring(i);
} }
void ctx_state_cb(ctx_t::pointer ctx, void *userdata) { void
ctx_state_cb(ctx_t::pointer ctx, void *userdata) {
auto &f = *(std::function<void(ctx_t::pointer)> *) userdata; auto &f = *(std::function<void(ctx_t::pointer)> *) userdata;
f(ctx); f(ctx);
} }
void success_cb(ctx_t::pointer ctx, int status, void *userdata) { void
success_cb(ctx_t::pointer ctx, int status, void *userdata) {
assert(userdata != nullptr); assert(userdata != nullptr);
auto alarm = (safe::alarm_raw_t<int> *) userdata; auto alarm = (safe::alarm_raw_t<int> *) userdata;
@@ -189,7 +198,8 @@ public:
std::unique_ptr<std::function<void(ctx_t::pointer)>> events_cb; std::unique_ptr<std::function<void(ctx_t::pointer)>> events_cb;
std::thread worker; std::thread worker;
int init() { int
init() {
events = std::make_unique<safe::event_t<ctx_event_e>>(); events = std::make_unique<safe::event_t<ctx_event_e>>();
loop.reset(pa_mainloop_new()); loop.reset(pa_mainloop_new());
ctx.reset(pa_context_new(pa_mainloop_get_api(loop.get()), "sunshine")); ctx.reset(pa_context_new(pa_mainloop_get_api(loop.get()), "sunshine"));
@@ -245,7 +255,8 @@ public:
return 0; return 0;
} }
int load_null(const char *name, const std::uint8_t *channel_mapping, int channels) { int
load_null(const char *name, const std::uint8_t *channel_mapping, int channels) {
auto alarm = safe::make_alarm<int>(); auto alarm = safe::make_alarm<int>();
op_t op { op_t op {
@@ -261,7 +272,8 @@ public:
return *alarm->status(); return *alarm->status();
} }
int unload_null(std::uint32_t i) { int
unload_null(std::uint32_t i) {
if (i == PA_INVALID_INDEX) { if (i == PA_INVALID_INDEX) {
return 0; return 0;
} }
@@ -282,7 +294,8 @@ public:
return 0; return 0;
} }
std::optional<sink_t> sink_info() override { std::optional<sink_t>
sink_info() override {
constexpr auto stereo = "sink-sunshine-stereo"; constexpr auto stereo = "sink-sunshine-stereo";
constexpr auto surround51 = "sink-sunshine-surround51"; constexpr auto surround51 = "sink-sunshine-surround51";
constexpr auto surround71 = "sink-sunshine-surround71"; constexpr auto surround71 = "sink-sunshine-surround71";
@@ -382,7 +395,8 @@ public:
return std::make_optional(std::move(sink)); return std::make_optional(std::move(sink));
} }
std::string get_default_sink_name() { std::string
get_default_sink_name() {
std::string sink_name; std::string sink_name;
auto alarm = safe::make_alarm<int>(); auto alarm = safe::make_alarm<int>();
@@ -404,7 +418,8 @@ public:
return sink_name; return sink_name;
} }
std::string get_monitor_name(const std::string &sink_name) { std::string
get_monitor_name(const std::string &sink_name) {
std::string monitor_name; std::string monitor_name;
auto alarm = safe::make_alarm<int>(); auto alarm = safe::make_alarm<int>();
@@ -435,7 +450,8 @@ public:
return monitor_name; return monitor_name;
} }
std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override { std::unique_ptr<mic_t>
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override {
// Sink choice priority: // Sink choice priority:
// 1. Config sink // 1. Config sink
// 2. Last sink swapped to (Usually virtual in this case) // 2. Last sink swapped to (Usually virtual in this case)
@@ -450,7 +466,8 @@ public:
return ::platf::microphone(mapping, channels, sample_rate, frame_size, get_monitor_name(sink_name)); return ::platf::microphone(mapping, channels, sample_rate, frame_size, get_monitor_name(sink_name));
} }
int set_sink(const std::string &sink) override { int
set_sink(const std::string &sink) override {
auto alarm = safe::make_alarm<int>(); auto alarm = safe::make_alarm<int>();
BOOST_LOG(info) << "Setting default sink to: ["sv << sink << "]"sv; BOOST_LOG(info) << "Setting default sink to: ["sv << sink << "]"sv;
@@ -495,7 +512,8 @@ public:
}; };
} // namespace pa } // namespace pa
std::unique_ptr<audio_control_t> audio_control() { std::unique_ptr<audio_control_t>
audio_control() {
auto audio = std::make_unique<pa::server_t>(); auto audio = std::make_unique<pa::server_t>();
if (audio->init()) { if (audio->init()) {

View File

@@ -30,11 +30,13 @@ namespace cuda {
constexpr auto cudaDevAttrMaxThreadsPerBlock = (CUdevice_attribute) 1; constexpr auto cudaDevAttrMaxThreadsPerBlock = (CUdevice_attribute) 1;
constexpr auto cudaDevAttrMaxThreadsPerMultiProcessor = (CUdevice_attribute) 39; constexpr auto cudaDevAttrMaxThreadsPerMultiProcessor = (CUdevice_attribute) 39;
void pass_error(const std::string_view &sv, const char *name, const char *description) { void
pass_error(const std::string_view &sv, const char *name, const char *description) {
BOOST_LOG(error) << sv << name << ':' << description; BOOST_LOG(error) << sv << name << ':' << description;
} }
void cff(CudaFunctions *cf) { void
cff(CudaFunctions *cf) {
cuda_free_functions(&cf); cuda_free_functions(&cf);
} }
@@ -42,7 +44,8 @@ using cdf_t = util::safe_ptr<CudaFunctions, cff>;
static cdf_t cdf; static cdf_t cdf;
inline static int check(CUresult result, const std::string_view &sv) { inline static int
check(CUresult result, const std::string_view &sv) {
if (result != CUDA_SUCCESS) { if (result != CUDA_SUCCESS) {
const char *name; const char *name;
const char *description; const char *description;
@@ -57,7 +60,8 @@ inline static int check(CUresult result, const std::string_view &sv) {
return 0; return 0;
} }
void freeStream(CUstream stream) { void
freeStream(CUstream stream) {
CU_CHECK_IGNORE(cdf->cuStreamDestroy(stream), "Couldn't destroy cuda stream"); CU_CHECK_IGNORE(cdf->cuStreamDestroy(stream), "Couldn't destroy cuda stream");
} }
@@ -66,7 +70,8 @@ public:
tex_t tex; tex_t tex;
}; };
int init() { int
init() {
auto status = cuda_load_functions(&cdf, nullptr); auto status = cuda_load_functions(&cdf, nullptr);
if (status) { if (status) {
BOOST_LOG(error) << "Couldn't load cuda: "sv << status; BOOST_LOG(error) << "Couldn't load cuda: "sv << status;
@@ -81,7 +86,8 @@ int init() {
class cuda_t: public platf::hwdevice_t { class cuda_t: public platf::hwdevice_t {
public: public:
int init(int in_width, int in_height) { int
init(int in_width, int in_height) {
if (!cdf) { if (!cdf) {
BOOST_LOG(warning) << "cuda not initialized"sv; BOOST_LOG(warning) << "cuda not initialized"sv;
return -1; return -1;
@@ -95,7 +101,8 @@ public:
return 0; return 0;
} }
int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override { int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
this->hwframe.reset(frame); this->hwframe.reset(frame);
this->frame = frame; this->frame = frame;
@@ -133,7 +140,8 @@ public:
return 0; return 0;
} }
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override { void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override {
sws.set_colorspace(colorspace, color_range); sws.set_colorspace(colorspace, color_range);
auto tex = tex_t::make(height, width * 4); auto tex = tex_t::make(height, width * 4);
@@ -161,7 +169,8 @@ public:
sws.convert(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], tex->texture.linear, stream.get(), { frame->width, frame->height, 0, 0 }); sws.convert(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], tex->texture.linear, stream.get(), { frame->width, frame->height, 0, 0 });
} }
cudaTextureObject_t tex_obj(const tex_t &tex) const { cudaTextureObject_t
tex_obj(const tex_t &tex) const {
return linear_interpolation ? tex.texture.linear : tex.texture.point; return linear_interpolation ? tex.texture.linear : tex.texture.point;
} }
@@ -178,11 +187,13 @@ public:
class cuda_ram_t: public cuda_t { class cuda_ram_t: public cuda_t {
public: public:
int convert(platf::img_t &img) override { int
convert(platf::img_t &img) override {
return sws.load_ram(img, tex.array) || sws.convert(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], tex_obj(tex), stream.get()); return sws.load_ram(img, tex.array) || sws.convert(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], tex_obj(tex), stream.get());
} }
int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) { int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) {
if (cuda_t::set_frame(frame, hw_frames_ctx)) { if (cuda_t::set_frame(frame, hw_frames_ctx)) {
return -1; return -1;
} }
@@ -202,12 +213,14 @@ public:
class cuda_vram_t: public cuda_t { class cuda_vram_t: public cuda_t {
public: public:
int convert(platf::img_t &img) override { int
convert(platf::img_t &img) override {
return sws.convert(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], tex_obj(((img_t *) &img)->tex), stream.get()); return sws.convert(frame->data[0], frame->data[1], frame->linesize[0], frame->linesize[1], tex_obj(((img_t *) &img)->tex), stream.get());
} }
}; };
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram) { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(int width, int height, bool vram) {
if (init()) { if (init()) {
return nullptr; return nullptr;
} }
@@ -232,12 +245,14 @@ namespace nvfbc {
static PNVFBCCREATEINSTANCE createInstance {}; static PNVFBCCREATEINSTANCE createInstance {};
static NVFBC_API_FUNCTION_LIST func { NVFBC_VERSION }; static NVFBC_API_FUNCTION_LIST func { NVFBC_VERSION };
static constexpr inline NVFBC_BOOL nv_bool(bool b) { static constexpr inline NVFBC_BOOL
nv_bool(bool b) {
return b ? NVFBC_TRUE : NVFBC_FALSE; return b ? NVFBC_TRUE : NVFBC_FALSE;
} }
static void *handle { nullptr }; static void *handle { nullptr };
int init() { int
init() {
static bool funcs_loaded = false; static bool funcs_loaded = false;
if (funcs_loaded) return 0; if (funcs_loaded) return 0;
@@ -304,18 +319,21 @@ class handle_t {
public: public:
handle_t() = default; handle_t() = default;
handle_t(handle_t &&other) : handle_flags { other.handle_flags }, handle { other.handle } { handle_t(handle_t &&other):
handle_flags { other.handle_flags }, handle { other.handle } {
other.handle_flags.reset(); other.handle_flags.reset();
} }
handle_t &operator=(handle_t &&other) { handle_t &
operator=(handle_t &&other) {
std::swap(handle_flags, other.handle_flags); std::swap(handle_flags, other.handle_flags);
std::swap(handle, other.handle); std::swap(handle, other.handle);
return *this; return *this;
} }
static std::optional<handle_t> make() { static std::optional<handle_t>
make() {
NVFBC_CREATE_HANDLE_PARAMS params { NVFBC_CREATE_HANDLE_PARAMS_VER }; NVFBC_CREATE_HANDLE_PARAMS params { NVFBC_CREATE_HANDLE_PARAMS_VER };
handle_t handle; handle_t handle;
@@ -331,11 +349,13 @@ public:
return std::move(handle); return std::move(handle);
} }
const char *last_error() { const char *
last_error() {
return func.nvFBCGetLastErrorStr(handle); return func.nvFBCGetLastErrorStr(handle);
} }
std::optional<NVFBC_GET_STATUS_PARAMS> status() { std::optional<NVFBC_GET_STATUS_PARAMS>
status() {
NVFBC_GET_STATUS_PARAMS params { NVFBC_GET_STATUS_PARAMS_VER }; NVFBC_GET_STATUS_PARAMS params { NVFBC_GET_STATUS_PARAMS_VER };
auto status = func.nvFBCGetStatus(handle, &params); auto status = func.nvFBCGetStatus(handle, &params);
@@ -348,7 +368,8 @@ public:
return params; return params;
} }
int capture(NVFBC_CREATE_CAPTURE_SESSION_PARAMS &capture_params) { int
capture(NVFBC_CREATE_CAPTURE_SESSION_PARAMS &capture_params) {
if (func.nvFBCCreateCaptureSession(handle, &capture_params)) { if (func.nvFBCCreateCaptureSession(handle, &capture_params)) {
BOOST_LOG(error) << "Failed to start capture session: "sv << last_error(); BOOST_LOG(error) << "Failed to start capture session: "sv << last_error();
return -1; return -1;
@@ -368,7 +389,8 @@ public:
return 0; return 0;
} }
int stop() { int
stop() {
if (!handle_flags[SESSION_CAPTURE]) { if (!handle_flags[SESSION_CAPTURE]) {
return 0; return 0;
} }
@@ -386,7 +408,8 @@ public:
return 0; return 0;
} }
int reset() { int
reset() {
if (!handle_flags[SESSION_HANDLE]) { if (!handle_flags[SESSION_HANDLE]) {
return 0; return 0;
} }
@@ -415,7 +438,8 @@ public:
class display_t: public platf::display_t { class display_t: public platf::display_t {
public: public:
int init(const std::string_view &display_name, const ::video::config_t &config) { int
init(const std::string_view &display_name, const ::video::config_t &config) {
auto handle = handle_t::make(); auto handle = handle_t::make();
if (!handle) { if (!handle) {
return -1; return -1;
@@ -479,7 +503,8 @@ public:
return 0; return 0;
} }
platf::capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override { platf::capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
// Force display_t::capture to initialize handle_t::capture // Force display_t::capture to initialize handle_t::capture
@@ -522,7 +547,8 @@ public:
} }
// Reinitialize the capture session. // Reinitialize the capture session.
platf::capture_e reinit(bool cursor) { platf::capture_e
reinit(bool cursor) {
if (handle.stop()) { if (handle.stop()) {
return platf::capture_e::error; return platf::capture_e::error;
} }
@@ -591,7 +617,8 @@ public:
return platf::capture_e::ok; return platf::capture_e::ok;
} }
platf::capture_e snapshot(platf::img_t *img, std::chrono::milliseconds timeout, bool cursor) { platf::capture_e
snapshot(platf::img_t *img, std::chrono::milliseconds timeout, bool cursor) {
if (cursor != cursor_visible) { if (cursor != cursor_visible) {
auto status = reinit(cursor); auto status = reinit(cursor);
if (status != platf::capture_e::ok) { if (status != platf::capture_e::ok) {
@@ -626,11 +653,13 @@ public:
return platf::capture_e::ok; return platf::capture_e::ok;
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(platf::pix_fmt_e pix_fmt) override { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(platf::pix_fmt_e pix_fmt) override {
return ::cuda::make_hwdevice(width, height, true); return ::cuda::make_hwdevice(width, height, true);
} }
std::shared_ptr<platf::img_t> alloc_img() override { std::shared_ptr<platf::img_t>
alloc_img() override {
auto img = std::make_shared<cuda::img_t>(); auto img = std::make_shared<cuda::img_t>();
img->data = nullptr; img->data = nullptr;
@@ -649,7 +678,8 @@ public:
return img; return img;
}; };
int dummy_img(platf::img_t *) override { int
dummy_img(platf::img_t *) override {
return 0; return 0;
} }
@@ -664,7 +694,8 @@ public:
} // namespace cuda } // namespace cuda
namespace platf { namespace platf {
std::shared_ptr<display_t> nvfbc_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) { std::shared_ptr<display_t>
nvfbc_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
if (hwdevice_type != mem_type_e::cuda) { if (hwdevice_type != mem_type_e::cuda) {
BOOST_LOG(error) << "Could not initialize nvfbc display with the given hw device type"sv; BOOST_LOG(error) << "Could not initialize nvfbc display with the given hw device type"sv;
return nullptr; return nullptr;
@@ -679,7 +710,8 @@ std::shared_ptr<display_t> nvfbc_display(mem_type_e hwdevice_type, const std::st
return display; return display;
} }
std::vector<std::string> nvfbc_display_names() { std::vector<std::string>
nvfbc_display_names() {
if (cuda::init() || cuda::nvfbc::init()) { if (cuda::init() || cuda::nvfbc::init()) {
return {}; return {};
} }

View File

@@ -14,10 +14,13 @@ class img_t;
namespace cuda { namespace cuda {
namespace nvfbc { namespace nvfbc {
std::vector<std::string> display_names(); std::vector<std::string>
display_names();
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram); std::shared_ptr<platf::hwdevice_t>
int init(); make_hwdevice(int width, int height, bool vram);
int
init();
} // namespace cuda } // namespace cuda
typedef struct cudaArray *cudaArray_t; typedef struct cudaArray *cudaArray_t;
@@ -34,18 +37,21 @@ namespace cuda {
class freeCudaPtr_t { class freeCudaPtr_t {
public: public:
void operator()(void *ptr); void
operator()(void *ptr);
}; };
class freeCudaStream_t { class freeCudaStream_t {
public: public:
void operator()(cudaStream_t ptr); void
operator()(cudaStream_t ptr);
}; };
using ptr_t = std::unique_ptr<void, freeCudaPtr_t>; using ptr_t = std::unique_ptr<void, freeCudaPtr_t>;
using stream_t = std::unique_ptr<CUstream_st, freeCudaStream_t>; using stream_t = std::unique_ptr<CUstream_st, freeCudaStream_t>;
stream_t make_stream(int flags = 0); stream_t
make_stream(int flags = 0);
struct viewport_t { struct viewport_t {
int width, height; int width, height;
@@ -54,16 +60,19 @@ struct viewport_t {
class tex_t { class tex_t {
public: public:
static std::optional<tex_t> make(int height, int pitch); static std::optional<tex_t>
make(int height, int pitch);
tex_t(); tex_t();
tex_t(tex_t &&); tex_t(tex_t &&);
tex_t &operator=(tex_t &&other); tex_t &
operator=(tex_t &&other);
~tex_t(); ~tex_t();
int copy(std::uint8_t *src, int height, int pitch); int
copy(std::uint8_t *src, int height, int pitch);
cudaArray_t array; cudaArray_t array;
@@ -84,15 +93,20 @@ public:
* *
* pitch -- The size of a single row of pixels in bytes * pitch -- The size of a single row of pixels in bytes
*/ */
static std::optional<sws_t> make(int in_width, int in_height, int out_width, int out_height, int pitch); static std::optional<sws_t>
make(int in_width, int in_height, int out_width, int out_height, int pitch);
// Converts loaded image into a CUDevicePtr // Converts loaded image into a CUDevicePtr
int convert(std::uint8_t *Y, std::uint8_t *UV, std::uint32_t pitchY, std::uint32_t pitchUV, cudaTextureObject_t texture, stream_t::pointer stream); int
int convert(std::uint8_t *Y, std::uint8_t *UV, std::uint32_t pitchY, std::uint32_t pitchUV, cudaTextureObject_t texture, stream_t::pointer stream, const viewport_t &viewport); convert(std::uint8_t *Y, std::uint8_t *UV, std::uint32_t pitchY, std::uint32_t pitchUV, cudaTextureObject_t texture, stream_t::pointer stream);
int
convert(std::uint8_t *Y, std::uint8_t *UV, std::uint32_t pitchY, std::uint32_t pitchUV, cudaTextureObject_t texture, stream_t::pointer stream, const viewport_t &viewport);
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range); void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range);
int load_ram(platf::img_t &img, cudaArray_t array); int
load_ram(platf::img_t &img, cudaArray_t array);
ptr_t color_matrix; ptr_t color_matrix;

View File

@@ -23,7 +23,8 @@ using namespace std::literals;
namespace gl { namespace gl {
GladGLContext ctx; GladGLContext ctx;
void drain_errors(const std::string_view &prefix) { void
drain_errors(const std::string_view &prefix) {
GLenum err; GLenum err;
while ((err = ctx.GetError()) != GL_NO_ERROR) { while ((err = ctx.GetError()) != GL_NO_ERROR) {
BOOST_LOG(error) << "GL: "sv << prefix << ": ["sv << util::hex(err).to_string_view() << ']'; BOOST_LOG(error) << "GL: "sv << prefix << ": ["sv << util::hex(err).to_string_view() << ']';
@@ -36,7 +37,8 @@ tex_t::~tex_t() {
} }
} }
tex_t tex_t::make(std::size_t count) { tex_t
tex_t::make(std::size_t count) {
tex_t textures { count }; tex_t textures { count };
ctx.GenTextures(textures.size(), textures.begin()); ctx.GenTextures(textures.size(), textures.begin());
@@ -61,7 +63,8 @@ frame_buf_t::~frame_buf_t() {
} }
} }
frame_buf_t frame_buf_t::make(std::size_t count) { frame_buf_t
frame_buf_t::make(std::size_t count) {
frame_buf_t frame_buf { count }; frame_buf_t frame_buf { count };
ctx.GenFramebuffers(frame_buf.size(), frame_buf.begin()); ctx.GenFramebuffers(frame_buf.size(), frame_buf.begin());
@@ -69,14 +72,16 @@ frame_buf_t frame_buf_t::make(std::size_t count) {
return frame_buf; return frame_buf;
} }
void frame_buf_t::copy(int id, int texture, int offset_x, int offset_y, int width, int height) { void
frame_buf_t::copy(int id, int texture, int offset_x, int offset_y, int width, int height) {
gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, (*this)[id]); gl::ctx.BindFramebuffer(GL_FRAMEBUFFER, (*this)[id]);
gl::ctx.ReadBuffer(GL_COLOR_ATTACHMENT0 + id); gl::ctx.ReadBuffer(GL_COLOR_ATTACHMENT0 + id);
gl::ctx.BindTexture(GL_TEXTURE_2D, texture); gl::ctx.BindTexture(GL_TEXTURE_2D, texture);
gl::ctx.CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offset_x, offset_y, width, height); gl::ctx.CopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, offset_x, offset_y, width, height);
} }
std::string shader_t::err_str() { std::string
shader_t::err_str() {
int length; int length;
ctx.GetShaderiv(handle(), GL_INFO_LOG_LENGTH, &length); ctx.GetShaderiv(handle(), GL_INFO_LOG_LENGTH, &length);
@@ -90,7 +95,8 @@ std::string shader_t::err_str() {
return string; return string;
} }
util::Either<shader_t, std::string> shader_t::compile(const std::string_view &source, GLenum type) { util::Either<shader_t, std::string>
shader_t::compile(const std::string_view &source, GLenum type) {
shader_t shader; shader_t shader;
auto data = source.data(); auto data = source.data();
@@ -110,11 +116,13 @@ util::Either<shader_t, std::string> shader_t::compile(const std::string_view &so
return shader; return shader;
} }
GLuint shader_t::handle() const { GLuint
shader_t::handle() const {
return _shader.el; return _shader.el;
} }
buffer_t buffer_t::make(util::buffer_t<GLint> &&offsets, const char *block, const std::string_view &data) { buffer_t
buffer_t::make(util::buffer_t<GLint> &&offsets, const char *block, const std::string_view &data) {
buffer_t buffer; buffer_t buffer;
buffer._block = block; buffer._block = block;
buffer._size = data.size(); buffer._size = data.size();
@@ -127,20 +135,24 @@ buffer_t buffer_t::make(util::buffer_t<GLint> &&offsets, const char *block, cons
return buffer; return buffer;
} }
GLuint buffer_t::handle() const { GLuint
buffer_t::handle() const {
return _buffer.el; return _buffer.el;
} }
const char *buffer_t::block() const { const char *
buffer_t::block() const {
return _block; return _block;
} }
void buffer_t::update(const std::string_view &view, std::size_t offset) { void
buffer_t::update(const std::string_view &view, std::size_t offset) {
ctx.BindBuffer(GL_UNIFORM_BUFFER, handle()); ctx.BindBuffer(GL_UNIFORM_BUFFER, handle());
ctx.BufferSubData(GL_UNIFORM_BUFFER, offset, view.size(), (const void *) view.data()); ctx.BufferSubData(GL_UNIFORM_BUFFER, offset, view.size(), (const void *) view.data());
} }
void buffer_t::update(std::string_view *members, std::size_t count, std::size_t offset) { void
buffer_t::update(std::string_view *members, std::size_t count, std::size_t offset) {
util::buffer_t<std::uint8_t> buffer { _size }; util::buffer_t<std::uint8_t> buffer { _size };
for (int x = 0; x < count; ++x) { for (int x = 0; x < count; ++x) {
@@ -152,7 +164,8 @@ void buffer_t::update(std::string_view *members, std::size_t count, std::size_t
update(util::view(buffer.begin(), buffer.end()), offset); update(util::view(buffer.begin(), buffer.end()), offset);
} }
std::string program_t::err_str() { std::string
program_t::err_str() {
int length; int length;
ctx.GetProgramiv(handle(), GL_INFO_LOG_LENGTH, &length); ctx.GetProgramiv(handle(), GL_INFO_LOG_LENGTH, &length);
@@ -166,7 +179,8 @@ std::string program_t::err_str() {
return string; return string;
} }
util::Either<program_t, std::string> program_t::link(const shader_t &vert, const shader_t &frag) { util::Either<program_t, std::string>
program_t::link(const shader_t &vert, const shader_t &frag) {
program_t program; program_t program;
program._program.el = ctx.CreateProgram(); program._program.el = ctx.CreateProgram();
@@ -193,14 +207,16 @@ util::Either<program_t, std::string> program_t::link(const shader_t &vert, const
return program; return program;
} }
void program_t::bind(const buffer_t &buffer) { void
program_t::bind(const buffer_t &buffer) {
ctx.UseProgram(handle()); ctx.UseProgram(handle());
auto i = ctx.GetUniformBlockIndex(handle(), buffer.block()); auto i = ctx.GetUniformBlockIndex(handle(), buffer.block());
ctx.BindBufferBase(GL_UNIFORM_BUFFER, i, buffer.handle()); ctx.BindBufferBase(GL_UNIFORM_BUFFER, i, buffer.handle());
} }
std::optional<buffer_t> program_t::uniform(const char *block, std::pair<const char *, std::string_view> *members, std::size_t count) { std::optional<buffer_t>
program_t::uniform(const char *block, std::pair<const char *, std::string_view> *members, std::size_t count) {
auto i = ctx.GetUniformBlockIndex(handle(), block); auto i = ctx.GetUniformBlockIndex(handle(), block);
if (i == GL_INVALID_INDEX) { if (i == GL_INVALID_INDEX) {
BOOST_LOG(error) << "Couldn't find index of ["sv << block << ']'; BOOST_LOG(error) << "Couldn't find index of ["sv << block << ']';
@@ -248,7 +264,8 @@ std::optional<buffer_t> program_t::uniform(const char *block, std::pair<const ch
return buffer_t::make(std::move(offsets), block, std::string_view { (char *) buffer.begin(), buffer.size() }); return buffer_t::make(std::move(offsets), block, std::string_view { (char *) buffer.begin(), buffer.size() });
} }
GLuint program_t::handle() const { GLuint
program_t::handle() const {
return _program.el; return _program.el;
} }
@@ -258,7 +275,8 @@ namespace gbm {
device_destroy_fn device_destroy; device_destroy_fn device_destroy;
create_device_fn create_device; create_device_fn create_device;
int init() { int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -309,11 +327,13 @@ 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_LO_EXT = 0x3449;
constexpr auto EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT = 0x344A; constexpr auto EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT = 0x344A;
bool fail() { bool
fail() {
return eglGetError() != EGL_SUCCESS; return eglGetError() != EGL_SUCCESS;
} }
display_t make_display(std::variant<gbm::gbm_t::pointer, wl_display *, _XDisplay *> native_display) { display_t
make_display(std::variant<gbm::gbm_t::pointer, wl_display *, _XDisplay *> native_display) {
constexpr auto EGL_PLATFORM_GBM_MESA = 0x31D7; constexpr auto EGL_PLATFORM_GBM_MESA = 0x31D7;
constexpr auto EGL_PLATFORM_WAYLAND_KHR = 0x31D8; constexpr auto EGL_PLATFORM_WAYLAND_KHR = 0x31D8;
constexpr auto EGL_PLATFORM_X11_KHR = 0x31D5; constexpr auto EGL_PLATFORM_X11_KHR = 0x31D5;
@@ -378,7 +398,8 @@ display_t make_display(std::variant<gbm::gbm_t::pointer, wl_display *, _XDisplay
return display; return display;
} }
std::optional<ctx_t> make_ctx(display_t::pointer display) { std::optional<ctx_t>
make_ctx(display_t::pointer display) {
constexpr int conf_attr[] { constexpr int conf_attr[] {
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE
}; };
@@ -434,7 +455,8 @@ struct plane_attr_t {
EGLAttrib hi; EGLAttrib hi;
}; };
inline plane_attr_t get_plane(std::uint32_t plane_indice) { inline plane_attr_t
get_plane(std::uint32_t plane_indice) {
switch (plane_indice) { switch (plane_indice) {
case 0: case 0:
return { return {
@@ -474,7 +496,8 @@ inline plane_attr_t get_plane(std::uint32_t plane_indice) {
return {}; return {};
} }
std::optional<rgb_t> import_source(display_t::pointer egl_display, const surface_descriptor_t &xrgb) { std::optional<rgb_t>
import_source(display_t::pointer egl_display, const surface_descriptor_t &xrgb) {
EGLAttrib attribs[47]; EGLAttrib attribs[47];
int atti = 0; int atti = 0;
attribs[atti++] = EGL_WIDTH; attribs[atti++] = EGL_WIDTH;
@@ -531,7 +554,8 @@ std::optional<rgb_t> import_source(display_t::pointer egl_display, const surface
return rgb; return rgb;
} }
std::optional<nv12_t> import_target(display_t::pointer egl_display, std::array<file_t, nv12_img_t::num_fds> &&fds, const surface_descriptor_t &r8, const surface_descriptor_t &gr88) { std::optional<nv12_t>
import_target(display_t::pointer egl_display, std::array<file_t, nv12_img_t::num_fds> &&fds, const surface_descriptor_t &r8, const surface_descriptor_t &gr88) {
EGLAttrib img_attr_planes[2][13] { EGLAttrib img_attr_planes[2][13] {
{ EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_R8, { EGL_LINUX_DRM_FOURCC_EXT, DRM_FORMAT_R8,
EGL_WIDTH, r8.width, EGL_WIDTH, r8.width,
@@ -578,7 +602,8 @@ std::optional<nv12_t> import_target(display_t::pointer egl_display, std::array<f
return nv12; return nv12;
} }
void sws_t::set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) { void
sws_t::set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) {
video::color_t *color_p; video::color_t *color_p;
switch (colorspace) { switch (colorspace) {
case 5: // SWS_CS_SMPTE170M case 5: // SWS_CS_SMPTE170M
@@ -614,7 +639,8 @@ void sws_t::set_colorspace(std::uint32_t colorspace, std::uint32_t color_range)
program[1].bind(color_matrix); program[1].bind(color_matrix);
} }
std::optional<sws_t> sws_t::make(int in_width, int in_height, int out_width, int out_heigth, gl::tex_t &&tex) { std::optional<sws_t>
sws_t::make(int in_width, int in_height, int out_width, int out_heigth, gl::tex_t &&tex) {
sws_t sws; sws_t sws;
sws.serial = std::numeric_limits<std::uint64_t>::max(); sws.serial = std::numeric_limits<std::uint64_t>::max();
@@ -742,7 +768,8 @@ std::optional<sws_t> sws_t::make(int in_width, int in_height, int out_width, int
return std::move(sws); return std::move(sws);
} }
int sws_t::blank(gl::frame_buf_t &fb, int offsetX, int offsetY, int width, int height) { int
sws_t::blank(gl::frame_buf_t &fb, int offsetX, int offsetY, int width, int height) {
auto f = [&]() { auto f = [&]() {
std::swap(offsetX, this->offsetX); std::swap(offsetX, this->offsetX);
std::swap(offsetY, this->offsetY); std::swap(offsetY, this->offsetY);
@@ -756,7 +783,8 @@ int sws_t::blank(gl::frame_buf_t &fb, int offsetX, int offsetY, int width, int h
return convert(fb); return convert(fb);
} }
std::optional<sws_t> sws_t::make(int in_width, int in_height, int out_width, int out_heigth) { std::optional<sws_t>
sws_t::make(int in_width, int in_height, int out_width, int out_heigth) {
auto tex = gl::tex_t::make(2); auto tex = gl::tex_t::make(2);
gl::ctx.BindTexture(GL_TEXTURE_2D, tex[0]); gl::ctx.BindTexture(GL_TEXTURE_2D, tex[0]);
gl::ctx.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, in_width, in_height); gl::ctx.TexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, in_width, in_height);
@@ -764,14 +792,16 @@ std::optional<sws_t> sws_t::make(int in_width, int in_height, int out_width, int
return make(in_width, in_height, out_width, out_heigth, std::move(tex)); return make(in_width, in_height, out_width, out_heigth, std::move(tex));
} }
void sws_t::load_ram(platf::img_t &img) { void
sws_t::load_ram(platf::img_t &img) {
loaded_texture = tex[0]; loaded_texture = tex[0];
gl::ctx.BindTexture(GL_TEXTURE_2D, loaded_texture); gl::ctx.BindTexture(GL_TEXTURE_2D, loaded_texture);
gl::ctx.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, img.width, img.height, GL_BGRA, GL_UNSIGNED_BYTE, img.data); gl::ctx.TexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, img.width, img.height, GL_BGRA, GL_UNSIGNED_BYTE, img.data);
} }
void sws_t::load_vram(img_descriptor_t &img, int offset_x, int offset_y, int texture) { void
sws_t::load_vram(img_descriptor_t &img, int offset_x, int offset_y, int texture) {
// When only a sub-part of the image must be encoded... // When only a sub-part of the image must be encoded...
const bool copy = offset_x || offset_y || img.sd.width != in_width || img.sd.height != in_height; const bool copy = offset_x || offset_y || img.sd.width != in_width || img.sd.height != in_height;
if (copy) { if (copy) {
@@ -831,7 +861,8 @@ void sws_t::load_vram(img_descriptor_t &img, int offset_x, int offset_y, int tex
} }
} }
int sws_t::convert(gl::frame_buf_t &fb) { int
sws_t::convert(gl::frame_buf_t &fb) {
gl::ctx.BindTexture(GL_TEXTURE_2D, loaded_texture); gl::ctx.BindTexture(GL_TEXTURE_2D, loaded_texture);
GLenum attachments[] { GLenum attachments[] {
@@ -864,6 +895,7 @@ int sws_t::convert(gl::frame_buf_t &fb) {
} }
} // namespace egl } // namespace egl
void free_frame(AVFrame *frame) { void
free_frame(AVFrame *frame) {
av_frame_free(&frame); av_frame_free(&frame);
} }

View File

@@ -17,30 +17,35 @@
#define gl_drain_errors_helper(x) gl::drain_errors(x) #define gl_drain_errors_helper(x) gl::drain_errors(x)
#define gl_drain_errors gl_drain_errors_helper(__FILE__ ":" SUNSHINE_STRINGIFY(__LINE__)) #define gl_drain_errors gl_drain_errors_helper(__FILE__ ":" SUNSHINE_STRINGIFY(__LINE__))
extern "C" int close(int __fd); extern "C" int
close(int __fd);
// X11 Display // X11 Display
extern "C" struct _XDisplay; extern "C" struct _XDisplay;
struct AVFrame; struct AVFrame;
void free_frame(AVFrame *frame); void
free_frame(AVFrame *frame);
using frame_t = util::safe_ptr<AVFrame, free_frame>; using frame_t = util::safe_ptr<AVFrame, free_frame>;
namespace gl { namespace gl {
extern GladGLContext ctx; extern GladGLContext ctx;
void drain_errors(const std::string_view &prefix); void
drain_errors(const std::string_view &prefix);
class tex_t: public util::buffer_t<GLuint> { class tex_t: public util::buffer_t<GLuint> {
using util::buffer_t<GLuint>::buffer_t; using util::buffer_t<GLuint>::buffer_t;
public: public:
tex_t(tex_t &&) = default; tex_t(tex_t &&) = default;
tex_t &operator=(tex_t &&) = default; tex_t &
operator=(tex_t &&) = default;
~tex_t(); ~tex_t();
static tex_t make(std::size_t count); static tex_t
make(std::size_t count);
}; };
class frame_buf_t: public util::buffer_t<GLuint> { class frame_buf_t: public util::buffer_t<GLuint> {
@@ -48,13 +53,16 @@ class frame_buf_t : public util::buffer_t<GLuint> {
public: public:
frame_buf_t(frame_buf_t &&) = default; frame_buf_t(frame_buf_t &&) = default;
frame_buf_t &operator=(frame_buf_t &&) = default; frame_buf_t &
operator=(frame_buf_t &&) = default;
~frame_buf_t(); ~frame_buf_t();
static frame_buf_t make(std::size_t count); static frame_buf_t
make(std::size_t count);
inline void bind(std::nullptr_t, std::nullptr_t) { inline void
bind(std::nullptr_t, std::nullptr_t) {
int x = 0; int x = 0;
for (auto fb : (*this)) { for (auto fb : (*this)) {
ctx.BindFramebuffer(GL_FRAMEBUFFER, fb); ctx.BindFramebuffer(GL_FRAMEBUFFER, fb);
@@ -66,7 +74,8 @@ public:
} }
template <class It> template <class It>
void bind(It it_begin, It it_end) { void
bind(It it_begin, It it_end) {
using namespace std::literals; using namespace std::literals;
if (std::distance(it_begin, it_end) > size()) { if (std::distance(it_begin, it_end) > size()) {
BOOST_LOG(warning) << "To many elements to bind"sv; BOOST_LOG(warning) << "To many elements to bind"sv;
@@ -87,7 +96,8 @@ public:
/** /**
* Copies a part of the framebuffer to texture * Copies a part of the framebuffer to texture
*/ */
void copy(int id, int texture, int offset_x, int offset_y, int width, int height); void
copy(int id, int texture, int offset_x, int offset_y, int width, int height);
}; };
class shader_t { class shader_t {
@@ -98,11 +108,14 @@ class shader_t {
}); });
public: public:
std::string err_str(); std::string
err_str();
static util::Either<shader_t, std::string> compile(const std::string_view &source, GLenum type); static util::Either<shader_t, std::string>
compile(const std::string_view &source, GLenum type);
GLuint handle() const; GLuint
handle() const;
private: private:
shader_internal_t _shader; shader_internal_t _shader;
@@ -116,14 +129,19 @@ class buffer_t {
}); });
public: public:
static buffer_t make(util::buffer_t<GLint> &&offsets, const char *block, const std::string_view &data); static buffer_t
make(util::buffer_t<GLint> &&offsets, const char *block, const std::string_view &data);
GLuint handle() const; GLuint
handle() const;
const char *block() const; const char *
block() const;
void update(const std::string_view &view, std::size_t offset = 0); void
void update(std::string_view *members, std::size_t count, std::size_t offset = 0); update(const std::string_view &view, std::size_t offset = 0);
void
update(std::string_view *members, std::size_t count, std::size_t offset = 0);
private: private:
const char *_block; const char *_block;
@@ -143,15 +161,20 @@ class program_t {
}); });
public: public:
std::string err_str(); std::string
err_str();
static util::Either<program_t, std::string> link(const shader_t &vert, const shader_t &frag); static util::Either<program_t, std::string>
link(const shader_t &vert, const shader_t &frag);
void bind(const buffer_t &buffer); void
bind(const buffer_t &buffer);
std::optional<buffer_t> uniform(const char *block, std::pair<const char *, std::string_view> *members, std::size_t count); std::optional<buffer_t>
uniform(const char *block, std::pair<const char *, std::string_view> *members, std::size_t count);
GLuint handle() const; GLuint
handle() const;
private: private:
program_internal_t _program; program_internal_t _program;
@@ -168,7 +191,8 @@ extern create_device_fn create_device;
using gbm_t = util::dyn_safe_ptr<device, &device_destroy>; using gbm_t = util::dyn_safe_ptr<device, &device_destroy>;
int init(); int
init();
} // namespace gbm } // namespace gbm
@@ -230,14 +254,18 @@ struct surface_descriptor_t {
std::uint32_t offsets[4]; std::uint32_t offsets[4];
}; };
display_t make_display(std::variant<gbm::gbm_t::pointer, wl_display *, _XDisplay *> native_display); display_t
std::optional<ctx_t> make_ctx(display_t::pointer display); make_display(std::variant<gbm::gbm_t::pointer, wl_display *, _XDisplay *> native_display);
std::optional<ctx_t>
make_ctx(display_t::pointer display);
std::optional<rgb_t> import_source( std::optional<rgb_t>
import_source(
display_t::pointer egl_display, display_t::pointer egl_display,
const surface_descriptor_t &xrgb); const surface_descriptor_t &xrgb);
std::optional<nv12_t> import_target( std::optional<nv12_t>
import_target(
display_t::pointer egl_display, display_t::pointer egl_display,
std::array<file_t, nv12_img_t::num_fds> &&fds, std::array<file_t, nv12_img_t::num_fds> &&fds,
const surface_descriptor_t &r8, const surface_descriptor_t &gr88); const surface_descriptor_t &r8, const surface_descriptor_t &gr88);
@@ -258,7 +286,8 @@ public:
reset(); reset();
} }
void reset() { void
reset() {
for (auto x = 0; x < 4; ++x) { for (auto x = 0; x < 4; ++x) {
if (sd.fds[x] >= 0) { if (sd.fds[x] >= 0) {
close(sd.fds[x]); close(sd.fds[x]);
@@ -276,19 +305,26 @@ public:
class sws_t { class sws_t {
public: public:
static std::optional<sws_t> make(int in_width, int in_height, int out_width, int out_heigth, gl::tex_t &&tex); static std::optional<sws_t>
static std::optional<sws_t> make(int in_width, int in_height, int out_width, int out_heigth); make(int in_width, int in_height, int out_width, int out_heigth, gl::tex_t &&tex);
static std::optional<sws_t>
make(int in_width, int in_height, int out_width, int out_heigth);
// Convert the loaded image into the first two framebuffers // Convert the loaded image into the first two framebuffers
int convert(gl::frame_buf_t &fb); int
convert(gl::frame_buf_t &fb);
// Make an area of the image black // Make an area of the image black
int blank(gl::frame_buf_t &fb, int offsetX, int offsetY, int width, int height); int
blank(gl::frame_buf_t &fb, int offsetX, int offsetY, int width, int height);
void load_ram(platf::img_t &img); void
void load_vram(img_descriptor_t &img, int offset_x, int offset_y, int texture); load_ram(platf::img_t &img);
void
load_vram(img_descriptor_t &img, int offset_x, int offset_y, int texture);
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range); void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range);
// The first texture is the monitor image. // The first texture is the monitor image.
// The second texture is the cursor image // The second texture is the cursor image
@@ -313,7 +349,8 @@ public:
std::uint64_t serial; std::uint64_t serial;
}; };
bool fail(); bool
fail();
} // namespace egl } // namespace egl
#endif #endif

View File

@@ -54,7 +54,8 @@ _FN(FakeRelativeMotionEvent, int, (Display * dpy, int deltaX, int deltaY, unsign
_FN(FakeButtonEvent, int, (Display * dpy, unsigned int button, Bool is_press, unsigned long delay)); _FN(FakeButtonEvent, int, (Display * dpy, unsigned int button, Bool is_press, unsigned long delay));
_FN(FakeKeyEvent, int, (Display * dpy, unsigned int keycode, Bool is_press, unsigned long delay)); _FN(FakeKeyEvent, int, (Display * dpy, unsigned int keycode, Bool is_press, unsigned long delay));
static int init() { static int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -83,7 +84,8 @@ static int init() {
} }
} // namespace tst } // namespace tst
static int init() { static int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -144,7 +146,8 @@ constexpr auto UNKNOWN = 0;
* @brief Initializes the keycode constants for translating * @brief Initializes the keycode constants for translating
* moonlight keycodes to linux/X11 keycodes * moonlight keycodes to linux/X11 keycodes
*/ */
static constexpr std::array<keycode_t, 0xE3> init_keycodes() { static constexpr std::array<keycode_t, 0xE3>
init_keycodes() {
std::array<keycode_t, 0xE3> keycodes {}; std::array<keycode_t, 0xE3> keycodes {};
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
@@ -301,28 +304,32 @@ constexpr touch_port_t target_touch_port {
19200, 12000 19200, 12000
}; };
static std::pair<std::uint32_t, std::uint32_t> operator*(const std::pair<std::uint32_t, std::uint32_t> &l, int r) { static std::pair<std::uint32_t, std::uint32_t>
operator*(const std::pair<std::uint32_t, std::uint32_t> &l, int r) {
return { return {
l.first * r, l.first * r,
l.second * r, l.second * r,
}; };
} }
static std::pair<std::uint32_t, std::uint32_t> operator/(const std::pair<std::uint32_t, std::uint32_t> &l, int r) { static std::pair<std::uint32_t, std::uint32_t>
operator/(const std::pair<std::uint32_t, std::uint32_t> &l, int r) {
return { return {
l.first / r, l.first / r,
l.second / r, l.second / r,
}; };
} }
static std::pair<std::uint32_t, std::uint32_t> &operator+=(std::pair<std::uint32_t, std::uint32_t> &l, const std::pair<std::uint32_t, std::uint32_t> &r) { static std::pair<std::uint32_t, std::uint32_t> &
operator+=(std::pair<std::uint32_t, std::uint32_t> &l, const std::pair<std::uint32_t, std::uint32_t> &r) {
l.first += r.first; l.first += r.first;
l.second += r.second; l.second += r.second;
return l; return l;
} }
static inline void print(const ff_envelope &envelope) { static inline void
print(const ff_envelope &envelope) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "Envelope:"sv << std::endl << "Envelope:"sv << std::endl
<< " attack_length: " << envelope.attack_length << std::endl << " attack_length: " << envelope.attack_length << std::endl
@@ -331,21 +338,24 @@ static inline void print(const ff_envelope &envelope) {
<< " fade_level: " << envelope.fade_level; << " fade_level: " << envelope.fade_level;
} }
static inline void print(const ff_replay &replay) { static inline void
print(const ff_replay &replay) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "Replay:"sv << std::endl << "Replay:"sv << std::endl
<< " length: "sv << replay.length << std::endl << " length: "sv << replay.length << std::endl
<< " delay: "sv << replay.delay; << " delay: "sv << replay.delay;
} }
static inline void print(const ff_trigger &trigger) { static inline void
print(const ff_trigger &trigger) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "Trigger:"sv << std::endl << "Trigger:"sv << std::endl
<< " button: "sv << trigger.button << std::endl << " button: "sv << trigger.button << std::endl
<< " interval: "sv << trigger.interval; << " interval: "sv << trigger.interval;
} }
static inline void print(const ff_effect &effect) { static inline void
print(const ff_effect &effect) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< std::endl << std::endl
<< std::endl << std::endl
@@ -392,7 +402,6 @@ static inline void print(const ff_effect &effect) {
<< " weak_magnitude: " << effect.u.rumble.weak_magnitude; << " weak_magnitude: " << effect.u.rumble.weak_magnitude;
break; break;
case FF_SPRING: case FF_SPRING:
BOOST_LOG(debug) BOOST_LOG(debug)
<< "FF_SPRING:" << std::endl << "FF_SPRING:" << std::endl
@@ -439,21 +448,20 @@ class effect_t {
public: public:
KITTY_DEFAULT_CONSTR_MOVE(effect_t) KITTY_DEFAULT_CONSTR_MOVE(effect_t)
effect_t(int gamepadnr, uinput_t::pointer dev, rumble_queue_t &&q) effect_t(int gamepadnr, uinput_t::pointer dev, rumble_queue_t &&q):
: gamepadnr { gamepadnr }, dev { dev }, rumble_queue { std::move(q) }, gain { 0xFFFF }, id_to_data {} {} gamepadnr { gamepadnr }, dev { dev }, rumble_queue { std::move(q) }, gain { 0xFFFF }, id_to_data {} {}
class data_t { class data_t {
public: public:
KITTY_DEFAULT_CONSTR(data_t) KITTY_DEFAULT_CONSTR(data_t)
data_t(const ff_effect &effect) data_t(const ff_effect &effect):
: delay { effect.replay.delay }, delay { effect.replay.delay },
length { effect.replay.length }, length { effect.replay.length },
end_point { std::chrono::steady_clock::time_point::min() }, end_point { std::chrono::steady_clock::time_point::min() },
envelope {}, envelope {},
start {}, start {},
end {} { end {} {
switch (effect.type) { switch (effect.type) {
case FF_CONSTANT: case FF_CONSTANT:
start.weak = effect.u.constant.level; start.weak = effect.u.constant.level;
@@ -493,13 +501,15 @@ public:
} }
} }
std::uint32_t magnitude(std::chrono::milliseconds time_left, std::uint32_t start, std::uint32_t end) { std::uint32_t
magnitude(std::chrono::milliseconds time_left, std::uint32_t start, std::uint32_t end) {
auto rel = end - start; auto rel = end - start;
return start + (rel * time_left.count() / length.count()); return start + (rel * time_left.count() / length.count());
} }
std::pair<std::uint32_t, std::uint32_t> rumble(std::chrono::steady_clock::time_point tp) { std::pair<std::uint32_t, std::uint32_t>
rumble(std::chrono::steady_clock::time_point tp) {
if (end_point < tp) { if (end_point < tp) {
return {}; return {};
} }
@@ -534,11 +544,13 @@ public:
}; };
} }
void activate() { void
activate() {
end_point = std::chrono::steady_clock::now() + delay + length; end_point = std::chrono::steady_clock::now() + delay + length;
} }
void deactivate() { void
deactivate() {
end_point = std::chrono::steady_clock::time_point::min(); end_point = std::chrono::steady_clock::time_point::min();
} }
@@ -557,7 +569,8 @@ public:
} end; } end;
}; };
std::pair<std::uint32_t, std::uint32_t> rumble(std::chrono::steady_clock::time_point tp) { std::pair<std::uint32_t, std::uint32_t>
rumble(std::chrono::steady_clock::time_point tp) {
std::pair<std::uint32_t, std::uint32_t> weak_strong {}; std::pair<std::uint32_t, std::uint32_t> weak_strong {};
for (auto &[_, data] : id_to_data) { for (auto &[_, data] : id_to_data) {
weak_strong += data.rumble(tp); weak_strong += data.rumble(tp);
@@ -570,7 +583,8 @@ public:
return old_rumble; return old_rumble;
} }
void upload(const ff_effect &effect) { void
upload(const ff_effect &effect) {
print(effect); print(effect);
auto it = id_to_data.find(effect.id); auto it = id_to_data.find(effect.id);
@@ -586,7 +600,8 @@ public:
it->second = data; it->second = data;
} }
void activate(int id) { void
activate(int id) {
auto it = id_to_data.find(id); auto it = id_to_data.find(id);
if (it != std::end(id_to_data)) { if (it != std::end(id_to_data)) {
@@ -594,7 +609,8 @@ public:
} }
} }
void deactivate(int id) { void
deactivate(int id) {
auto it = id_to_data.find(id); auto it = id_to_data.find(id);
if (it != std::end(id_to_data)) { if (it != std::end(id_to_data)) {
@@ -602,7 +618,8 @@ public:
} }
} }
void erase(int id) { void
erase(int id) {
id_to_data.erase(id); id_to_data.erase(id);
BOOST_LOG(debug) << "Removed rumble effect id ["sv << id << ']'; BOOST_LOG(debug) << "Removed rumble effect id ["sv << id << ']';
} }
@@ -629,14 +646,17 @@ struct rumble_ctx_t {
safe::queue_t<mail_evdev_t> rumble_queue_queue; safe::queue_t<mail_evdev_t> rumble_queue_queue;
}; };
void broadcastRumble(safe::queue_t<mail_evdev_t> &ctx); void
int startRumble(rumble_ctx_t &ctx) { broadcastRumble(safe::queue_t<mail_evdev_t> &ctx);
int
startRumble(rumble_ctx_t &ctx) {
ctx.rumble_thread = std::thread { broadcastRumble, std::ref(ctx.rumble_queue_queue) }; ctx.rumble_thread = std::thread { broadcastRumble, std::ref(ctx.rumble_queue_queue) };
return 0; return 0;
} }
void stopRumble(rumble_ctx_t &ctx) { void
stopRumble(rumble_ctx_t &ctx) {
ctx.rumble_queue_queue.stop(); ctx.rumble_queue_queue.stop();
BOOST_LOG(debug) << "Waiting for Gamepad notifications to stop..."sv; BOOST_LOG(debug) << "Waiting for Gamepad notifications to stop..."sv;
@@ -648,7 +668,8 @@ static auto notifications = safe::make_shared<rumble_ctx_t>(startRumble, stopRum
struct input_raw_t { struct input_raw_t {
public: public:
void clear_touchscreen() { void
clear_touchscreen() {
std::filesystem::path touch_path { appdata() / "sunshine_touchscreen"sv }; std::filesystem::path touch_path { appdata() / "sunshine_touchscreen"sv };
if (std::filesystem::is_symlink(touch_path)) { if (std::filesystem::is_symlink(touch_path)) {
@@ -658,7 +679,8 @@ public:
touch_input.reset(); touch_input.reset();
} }
void clear_keyboard() { void
clear_keyboard() {
std::filesystem::path key_path { appdata() / "sunshine_keyboard"sv }; std::filesystem::path key_path { appdata() / "sunshine_keyboard"sv };
if (std::filesystem::is_symlink(key_path)) { if (std::filesystem::is_symlink(key_path)) {
@@ -668,7 +690,8 @@ public:
keyboard_input.reset(); keyboard_input.reset();
} }
void clear_mouse() { void
clear_mouse() {
std::filesystem::path mouse_path { appdata() / "sunshine_mouse"sv }; std::filesystem::path mouse_path { appdata() / "sunshine_mouse"sv };
if (std::filesystem::is_symlink(mouse_path)) { if (std::filesystem::is_symlink(mouse_path)) {
@@ -678,7 +701,8 @@ public:
mouse_input.reset(); mouse_input.reset();
} }
void clear_gamepad(int nr) { void
clear_gamepad(int nr) {
auto &[dev, _] = gamepads[nr]; auto &[dev, _] = gamepads[nr];
if (!dev) { if (!dev) {
@@ -700,7 +724,8 @@ public:
gamepads[nr] = std::make_pair(uinput_t {}, gamepad_state_t {}); gamepads[nr] = std::make_pair(uinput_t {}, gamepad_state_t {});
} }
int create_mouse() { int
create_mouse() {
int err = libevdev_uinput_create_from_device(mouse_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &mouse_input); int err = libevdev_uinput_create_from_device(mouse_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &mouse_input);
if (err) { if (err) {
@@ -713,7 +738,8 @@ public:
return 0; return 0;
} }
int create_touchscreen() { int
create_touchscreen() {
int err = libevdev_uinput_create_from_device(touch_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &touch_input); int err = libevdev_uinput_create_from_device(touch_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &touch_input);
if (err) { if (err) {
@@ -726,7 +752,8 @@ public:
return 0; return 0;
} }
int create_keyboard() { int
create_keyboard() {
int err = libevdev_uinput_create_from_device(keyboard_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &keyboard_input); int err = libevdev_uinput_create_from_device(keyboard_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &keyboard_input);
if (err) { if (err) {
@@ -739,7 +766,8 @@ public:
return 0; return 0;
} }
int alloc_gamepad(int nr, rumble_queue_t &&rumble_queue) { int
alloc_gamepad(int nr, rumble_queue_t &&rumble_queue) {
TUPLE_2D_REF(input, gamepad_state, gamepads[nr]); TUPLE_2D_REF(input, gamepad_state, gamepads[nr]);
int err = libevdev_uinput_create_from_device(gamepad_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &input); int err = libevdev_uinput_create_from_device(gamepad_dev.get(), LIBEVDEV_UINPUT_OPEN_MANAGED, &input);
@@ -775,7 +803,8 @@ public:
return 0; return 0;
} }
void clear() { void
clear() {
clear_touchscreen(); clear_touchscreen();
clear_keyboard(); clear_keyboard();
clear_mouse(); clear_mouse();
@@ -812,7 +841,8 @@ public:
#endif #endif
}; };
inline void rumbleIterate(std::vector<effect_t> &effects, std::vector<pollfd_t> &polls, std::chrono::milliseconds to) { inline void
rumbleIterate(std::vector<effect_t> &effects, std::vector<pollfd_t> &polls, std::chrono::milliseconds to) {
std::vector<pollfd> polls_recv; std::vector<pollfd> polls_recv;
polls_recv.reserve(polls.size()); polls_recv.reserve(polls.size());
for (auto &poll : polls) { for (auto &poll : polls) {
@@ -947,7 +977,8 @@ inline void rumbleIterate(std::vector<effect_t> &effects, std::vector<pollfd_t>
} }
} }
void broadcastRumble(safe::queue_t<mail_evdev_t> &rumble_queue_queue) { void
broadcastRumble(safe::queue_t<mail_evdev_t> &rumble_queue_queue) {
std::vector<effect_t> effects; std::vector<effect_t> effects;
std::vector<pollfd_t> polls; std::vector<pollfd_t> polls;
@@ -971,7 +1002,6 @@ void broadcastRumble(safe::queue_t<mail_evdev_t> &rumble_queue_queue) {
}); });
if (effect_it != std::end(effects)) { if (effect_it != std::end(effects)) {
auto poll_it = std::begin(polls) + (effect_it - std::begin(effects)); auto poll_it = std::begin(polls) + (effect_it - std::begin(effects));
polls.erase(poll_it); polls.erase(poll_it);
@@ -1027,7 +1057,8 @@ void broadcastRumble(safe::queue_t<mail_evdev_t> &rumble_queue_queue) {
* x_abs_mouse(input, 0, 0); * x_abs_mouse(input, 0, 0);
* ``` * ```
*/ */
static void x_abs_mouse(input_t &input, float x, float y) { static void
x_abs_mouse(input_t &input, float x, float y) {
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
Display *xdisplay = ((input_raw_t *) input.get())->display; Display *xdisplay = ((input_raw_t *) input.get())->display;
if (!xdisplay) { if (!xdisplay) {
@@ -1050,7 +1081,8 @@ static void x_abs_mouse(input_t &input, float x, float y) {
* abs_mouse(input, touch_port, 0, 0); * abs_mouse(input, touch_port, 0, 0);
* ``` * ```
*/ */
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { void
abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {
auto touchscreen = ((input_raw_t *) input.get())->touch_input.get(); auto touchscreen = ((input_raw_t *) input.get())->touch_input.get();
if (!touchscreen) { if (!touchscreen) {
x_abs_mouse(input, x, y); x_abs_mouse(input, x, y);
@@ -1079,7 +1111,8 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y)
* x_move_mouse(input, 10, 10); // Move mouse 10 pixels down and right * x_move_mouse(input, 10, 10); // Move mouse 10 pixels down and right
* ``` * ```
*/ */
static void x_move_mouse(input_t &input, int deltaX, int deltaY) { static void
x_move_mouse(input_t &input, int deltaX, int deltaY) {
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
Display *xdisplay = ((input_raw_t *) input.get())->display; Display *xdisplay = ((input_raw_t *) input.get())->display;
if (!xdisplay) { if (!xdisplay) {
@@ -1101,7 +1134,8 @@ static void x_move_mouse(input_t &input, int deltaX, int deltaY) {
* move_mouse(input, 10, 10); // Move mouse 10 pixels down and right * move_mouse(input, 10, 10); // Move mouse 10 pixels down and right
* ``` * ```
*/ */
void move_mouse(input_t &input, int deltaX, int deltaY) { void
move_mouse(input_t &input, int deltaX, int deltaY) {
auto mouse = ((input_raw_t *) input.get())->mouse_input.get(); auto mouse = ((input_raw_t *) input.get())->mouse_input.get();
if (!mouse) { if (!mouse) {
x_move_mouse(input, deltaX, deltaY); x_move_mouse(input, deltaX, deltaY);
@@ -1130,7 +1164,8 @@ void move_mouse(input_t &input, int deltaX, int deltaY) {
* x_button_mouse(input, 1, false); // Press left mouse button * x_button_mouse(input, 1, false); // Press left mouse button
* ``` * ```
*/ */
static void x_button_mouse(input_t &input, int button, bool release) { static void
x_button_mouse(input_t &input, int button, bool release) {
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
unsigned int x_button = 0; unsigned int x_button = 0;
switch (button) { switch (button) {
@@ -1172,7 +1207,8 @@ static void x_button_mouse(input_t &input, int button, bool release) {
* button_mouse(input, 1, false); // Press left mouse button * button_mouse(input, 1, false); // Press left mouse button
* ``` * ```
*/ */
void button_mouse(input_t &input, int button, bool release) { void
button_mouse(input_t &input, int button, bool release) {
auto mouse = ((input_raw_t *) input.get())->mouse_input.get(); auto mouse = ((input_raw_t *) input.get())->mouse_input.get();
if (!mouse) { if (!mouse) {
x_button_mouse(input, button, release); x_button_mouse(input, button, release);
@@ -1220,7 +1256,8 @@ void button_mouse(input_t &input, int button, bool release) {
* x_scroll(input, 10, 4, 5); * x_scroll(input, 10, 4, 5);
* ``` * ```
*/ */
static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { static void
x_scroll(input_t &input, int distance, int button_pos, int button_neg) {
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
Display *xdisplay = ((input_raw_t *) input.get())->display; Display *xdisplay = ((input_raw_t *) input.get())->display;
if (!xdisplay) { if (!xdisplay) {
@@ -1246,7 +1283,8 @@ static void x_scroll(input_t &input, int distance, int button_pos, int button_ne
* scroll(input, 1200); * scroll(input, 1200);
* ``` * ```
*/ */
void scroll(input_t &input, int high_res_distance) { void
scroll(input_t &input, int high_res_distance) {
int distance = high_res_distance / 120; int distance = high_res_distance / 120;
auto mouse = ((input_raw_t *) input.get())->mouse_input.get(); auto mouse = ((input_raw_t *) input.get())->mouse_input.get();
@@ -1270,7 +1308,8 @@ void scroll(input_t &input, int high_res_distance) {
* hscroll(input, 1200); * hscroll(input, 1200);
* ``` * ```
*/ */
void hscroll(input_t &input, int high_res_distance) { void
hscroll(input_t &input, int high_res_distance) {
int distance = high_res_distance / 120; int distance = high_res_distance / 120;
auto mouse = ((input_raw_t *) input.get())->mouse_input.get(); auto mouse = ((input_raw_t *) input.get())->mouse_input.get();
@@ -1284,7 +1323,8 @@ void hscroll(input_t &input, int high_res_distance) {
libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0);
} }
static keycode_t keysym(std::uint16_t modcode) { static keycode_t
keysym(std::uint16_t modcode) {
if (modcode <= keycodes.size()) { if (modcode <= keycodes.size()) {
return keycodes[modcode]; return keycodes[modcode];
} }
@@ -1303,7 +1343,8 @@ static keycode_t keysym(std::uint16_t modcode) {
* x_keyboard(input, 0x5A, false); // Press Z * x_keyboard(input, 0x5A, false); // Press Z
* ``` * ```
*/ */
static void x_keyboard(input_t &input, uint16_t modcode, bool release) { static void
x_keyboard(input_t &input, uint16_t modcode, bool release) {
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
auto keycode = keysym(modcode); auto keycode = keysym(modcode);
if (keycode.keysym == UNKNOWN) { if (keycode.keysym == UNKNOWN) {
@@ -1336,7 +1377,8 @@ static void x_keyboard(input_t &input, uint16_t modcode, bool release) {
* keyboard(input, 0x5A, false); // Press Z * keyboard(input, 0x5A, false); // Press Z
* ``` * ```
*/ */
void keyboard(input_t &input, uint16_t modcode, bool release) { void
keyboard(input_t &input, uint16_t modcode, bool release) {
auto keyboard = ((input_raw_t *) input.get())->keyboard_input.get(); auto keyboard = ((input_raw_t *) input.get())->keyboard_input.get();
if (!keyboard) { if (!keyboard) {
x_keyboard(input, modcode, release); x_keyboard(input, modcode, release);
@@ -1356,7 +1398,8 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
libevdev_uinput_write_event(keyboard, EV_SYN, SYN_REPORT, 0); libevdev_uinput_write_event(keyboard, EV_SYN, SYN_REPORT, 0);
} }
void keyboard_ev(libevdev_uinput *keyboard, int linux_code, int event_code = 1) { void
keyboard_ev(libevdev_uinput *keyboard, int linux_code, int event_code = 1) {
libevdev_uinput_write_event(keyboard, EV_KEY, linux_code, event_code); libevdev_uinput_write_event(keyboard, EV_KEY, linux_code, event_code);
libevdev_uinput_write_event(keyboard, EV_SYN, SYN_REPORT, 0); libevdev_uinput_write_event(keyboard, EV_SYN, SYN_REPORT, 0);
} }
@@ -1368,7 +1411,8 @@ void keyboard_ev(libevdev_uinput *keyboard, int linux_code, int event_code = 1)
* *
* adapted from: https://stackoverflow.com/a/7639754 * adapted from: https://stackoverflow.com/a/7639754
*/ */
std::string to_hex(const std::basic_string<char32_t> &str) { std::string
to_hex(const std::basic_string<char32_t> &str) {
std::stringstream ss; std::stringstream ss;
ss << std::hex << std::setfill('0'); ss << std::hex << std::setfill('0');
for (const auto &ch : str) { for (const auto &ch : str) {
@@ -1391,7 +1435,8 @@ std::string to_hex(const std::basic_string<char32_t> &str) {
* - then type: CTRL+SHIFT+U+1F471 * - then type: CTRL+SHIFT+U+1F471
* see the conversion at: https://www.compart.com/en/unicode/U+1F471 * see the conversion at: https://www.compart.com/en/unicode/U+1F471
*/ */
void unicode(input_t &input, char *utf8, int size) { void
unicode(input_t &input, char *utf8, int size) {
auto kb = ((input_raw_t *) input.get())->keyboard_input.get(); auto kb = ((input_raw_t *) input.get())->keyboard_input.get();
if (!kb) { if (!kb) {
return; return;
@@ -1429,18 +1474,20 @@ void unicode(input_t &input, char *utf8, int size) {
keyboard_ev(kb, KEY_LEFTCTRL, 0); keyboard_ev(kb, KEY_LEFTCTRL, 0);
} }
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) { int
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
return ((input_raw_t *) input.get())->alloc_gamepad(nr, std::move(rumble_queue)); return ((input_raw_t *) input.get())->alloc_gamepad(nr, std::move(rumble_queue));
} }
void free_gamepad(input_t &input, int nr) { void
free_gamepad(input_t &input, int nr) {
((input_raw_t *) input.get())->clear_gamepad(nr); ((input_raw_t *) input.get())->clear_gamepad(nr);
} }
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) { void
gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
TUPLE_2D_REF(uinput, gamepad_state_old, ((input_raw_t *) input.get())->gamepads[nr]); TUPLE_2D_REF(uinput, gamepad_state_old, ((input_raw_t *) input.get())->gamepads[nr]);
auto bf = gamepad_state.buttonFlags ^ gamepad_state_old.buttonFlags; auto bf = gamepad_state.buttonFlags ^ gamepad_state_old.buttonFlags;
auto bf_new = gamepad_state.buttonFlags; auto bf_new = gamepad_state.buttonFlags;
@@ -1507,7 +1554,8 @@ void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
* auto my_keyboard = keyboard(); * auto my_keyboard = keyboard();
* ``` * ```
*/ */
evdev_t keyboard() { evdev_t
keyboard() {
evdev_t dev { libevdev_new() }; evdev_t dev { libevdev_new() };
libevdev_set_uniq(dev.get(), "Sunshine Keyboard"); libevdev_set_uniq(dev.get(), "Sunshine Keyboard");
@@ -1535,7 +1583,8 @@ evdev_t keyboard() {
* auto my_mouse = mouse(); * auto my_mouse = mouse();
* ``` * ```
*/ */
evdev_t mouse() { evdev_t
mouse() {
evdev_t dev { libevdev_new() }; evdev_t dev { libevdev_new() };
libevdev_set_uniq(dev.get(), "Sunshine Mouse"); libevdev_set_uniq(dev.get(), "Sunshine Mouse");
@@ -1585,7 +1634,8 @@ evdev_t mouse() {
* auto my_touchscreen = touchscreen(); * auto my_touchscreen = touchscreen();
* ``` * ```
*/ */
evdev_t touchscreen() { evdev_t
touchscreen() {
evdev_t dev { libevdev_new() }; evdev_t dev { libevdev_new() };
libevdev_set_uniq(dev.get(), "Sunshine Touch"); libevdev_set_uniq(dev.get(), "Sunshine Touch");
@@ -1597,7 +1647,6 @@ evdev_t touchscreen() {
libevdev_enable_property(dev.get(), INPUT_PROP_DIRECT); libevdev_enable_property(dev.get(), INPUT_PROP_DIRECT);
libevdev_enable_event_type(dev.get(), EV_KEY); libevdev_enable_event_type(dev.get(), EV_KEY);
libevdev_enable_event_code(dev.get(), EV_KEY, BTN_TOUCH, nullptr); libevdev_enable_event_code(dev.get(), EV_KEY, BTN_TOUCH, nullptr);
libevdev_enable_event_code(dev.get(), EV_KEY, BTN_TOOL_PEN, nullptr); // Needed to be enabled for BTN_TOOL_FINGER to work. libevdev_enable_event_code(dev.get(), EV_KEY, BTN_TOOL_PEN, nullptr); // Needed to be enabled for BTN_TOOL_FINGER to work.
@@ -1635,7 +1684,8 @@ evdev_t touchscreen() {
* auto my_x360 = x360(); * auto my_x360 = x360();
* ``` * ```
*/ */
evdev_t x360() { evdev_t
x360() {
evdev_t dev { libevdev_new() }; evdev_t dev { libevdev_new() };
input_absinfo stick { input_absinfo stick {
@@ -1711,7 +1761,8 @@ evdev_t x360() {
* auto my_input = input(); * auto my_input = input();
* ``` * ```
*/ */
input_t input() { input_t
input() {
input_t result { new input_raw_t() }; input_t result { new input_raw_t() };
auto &gp = *(input_raw_t *) result.get(); auto &gp = *(input_raw_t *) result.get();
@@ -1749,12 +1800,14 @@ input_t input() {
return result; return result;
} }
void freeInput(void *p) { void
freeInput(void *p) {
auto *input = (input_raw_t *) p; auto *input = (input_raw_t *) p;
delete input; delete input;
} }
std::vector<std::string_view> &supported_gamepads() { std::vector<std::string_view> &
supported_gamepads() {
static std::vector<std::string_view> gamepads { "x360"sv }; static std::vector<std::string_view> gamepads { "x360"sv };
return gamepads; return gamepads;

View File

@@ -51,8 +51,8 @@ public:
class wrapper_fb { class wrapper_fb {
public: public:
wrapper_fb(drmModeFB *fb) wrapper_fb(drmModeFB *fb):
: fb { fb }, fb_id { fb->fb_id }, width { fb->width }, height { fb->height } { fb { fb }, fb_id { fb->fb_id }, width { fb->width }, height { fb->height } {
pixel_format = DRM_FORMAT_XRGB8888; pixel_format = DRM_FORMAT_XRGB8888;
modifier = DRM_FORMAT_MOD_INVALID; modifier = DRM_FORMAT_MOD_INVALID;
std::fill_n(handles, 4, 0); std::fill_n(handles, 4, 0);
@@ -62,8 +62,8 @@ public:
pitches[0] = fb->pitch; pitches[0] = fb->pitch;
} }
wrapper_fb(drmModeFB2 *fb2) wrapper_fb(drmModeFB2 *fb2):
: fb2 { fb2 }, fb_id { fb2->fb_id }, width { fb2->width }, height { fb2->height } { fb2 { fb2 }, fb_id { fb2->fb_id }, width { fb2->width }, height { fb2->height } {
pixel_format = fb2->pixel_format; pixel_format = fb2->pixel_format;
modifier = (fb2->flags & DRM_MODE_FB_MODIFIERS) ? fb2->modifier : DRM_FORMAT_MOD_INVALID; modifier = (fb2->flags & DRM_MODE_FB_MODIFIERS) ? fb2->modifier : DRM_FORMAT_MOD_INVALID;
@@ -107,7 +107,8 @@ using conn_type_count_t = std::map<std::uint32_t, std::uint32_t>;
static int env_width; static int env_width;
static int env_height; static int env_height;
std::string_view plane_type(std::uint64_t val) { std::string_view
plane_type(std::uint64_t val) {
switch (val) { switch (val) {
case DRM_PLANE_TYPE_OVERLAY: case DRM_PLANE_TYPE_OVERLAY:
return "DRM_PLANE_TYPE_OVERLAY"sv; return "DRM_PLANE_TYPE_OVERLAY"sv;
@@ -149,7 +150,8 @@ struct card_descriptor_t {
static std::vector<card_descriptor_t> card_descriptors; static std::vector<card_descriptor_t> card_descriptors;
static std::uint32_t from_view(const std::string_view &string) { static std::uint32_t
from_view(const std::string_view &string) {
#define _CONVERT(x, y) \ #define _CONVERT(x, y) \
if (string == x) return DRM_MODE_CONNECTOR_##y if (string == x) return DRM_MODE_CONNECTOR_##y
@@ -174,15 +176,16 @@ static std::uint32_t from_view(const std::string_view &string) {
class plane_it_t: public round_robin_util::it_wrap_t<plane_t::element_type, plane_it_t> { class plane_it_t: public round_robin_util::it_wrap_t<plane_t::element_type, plane_it_t> {
public: public:
plane_it_t(int fd, std::uint32_t *plane_p, std::uint32_t *end) plane_it_t(int fd, std::uint32_t *plane_p, std::uint32_t *end):
: fd { fd }, plane_p { plane_p }, end { end } { fd { fd }, plane_p { plane_p }, end { end } {
inc(); inc();
} }
plane_it_t(int fd, std::uint32_t *end) plane_it_t(int fd, std::uint32_t *end):
: fd { fd }, plane_p { end }, end { end } {} fd { fd }, plane_p { end }, end { end } {}
void inc() { void
inc() {
this->plane.reset(); this->plane.reset();
for (; plane_p != end; ++plane_p) { for (; plane_p != end; ++plane_p) {
@@ -204,11 +207,13 @@ public:
} }
} }
bool eq(const plane_it_t &other) const { bool
eq(const plane_it_t &other) const {
return plane_p == other.plane_p; return plane_p == other.plane_p;
} }
plane_t::pointer get() { plane_t::pointer
get() {
return plane.get(); return plane.get();
} }
@@ -223,7 +228,8 @@ class card_t {
public: public:
using connector_interal_t = util::safe_ptr<drmModeConnector, drmModeFreeConnector>; using connector_interal_t = util::safe_ptr<drmModeConnector, drmModeFreeConnector>;
int init(const char *path) { int
init(const char *path) {
cap_sys_admin admin; cap_sys_admin admin;
fd.el = open(path, O_RDWR); fd.el = open(path, O_RDWR);
@@ -250,7 +256,8 @@ public:
return 0; return 0;
} }
fb_t fb(plane_t::pointer plane) { fb_t
fb(plane_t::pointer plane) {
cap_sys_admin admin; cap_sys_admin admin;
auto fb2 = drmModeGetFB2(fd.el, plane->fb_id); auto fb2 = drmModeGetFB2(fd.el, plane->fb_id);
@@ -266,19 +273,23 @@ public:
return nullptr; return nullptr;
} }
crtc_t crtc(std::uint32_t id) { crtc_t
crtc(std::uint32_t id) {
return drmModeGetCrtc(fd.el, id); return drmModeGetCrtc(fd.el, id);
} }
encoder_t encoder(std::uint32_t id) { encoder_t
encoder(std::uint32_t id) {
return drmModeGetEncoder(fd.el, id); return drmModeGetEncoder(fd.el, id);
} }
res_t res() { res_t
res() {
return drmModeGetResources(fd.el); return drmModeGetResources(fd.el);
} }
bool is_cursor(std::uint32_t plane_id) { bool
is_cursor(std::uint32_t plane_id) {
auto props = plane_props(plane_id); auto props = plane_props(plane_id);
for (auto &[prop, val] : props) { for (auto &[prop, val] : props) {
if (prop->name == "type"sv) { if (prop->name == "type"sv) {
@@ -294,7 +305,8 @@ public:
return false; return false;
} }
std::uint32_t get_panel_orientation(std::uint32_t plane_id) { std::uint32_t
get_panel_orientation(std::uint32_t plane_id) {
auto props = plane_props(plane_id); auto props = plane_props(plane_id);
for (auto &[prop, val] : props) { for (auto &[prop, val] : props) {
if (prop->name == "rotation"sv) { if (prop->name == "rotation"sv) {
@@ -306,11 +318,13 @@ public:
return DRM_MODE_ROTATE_0; return DRM_MODE_ROTATE_0;
} }
connector_interal_t connector(std::uint32_t id) { connector_interal_t
connector(std::uint32_t id) {
return drmModeGetConnector(fd.el, id); return drmModeGetConnector(fd.el, id);
} }
std::vector<connector_t> monitors(conn_type_count_t &conn_type_count) { std::vector<connector_t>
monitors(conn_type_count_t &conn_type_count) {
auto resources = res(); auto resources = res();
if (!resources) { if (!resources) {
BOOST_LOG(error) << "Couldn't get connector resources"sv; BOOST_LOG(error) << "Couldn't get connector resources"sv;
@@ -343,7 +357,8 @@ public:
return monitors; return monitors;
} }
file_t handleFD(std::uint32_t handle) { file_t
handleFD(std::uint32_t handle) {
file_t fb_fd; file_t fb_fd;
auto status = drmPrimeHandleToFD(fd.el, handle, 0 /* flags */, &fb_fd.el); auto status = drmPrimeHandleToFD(fd.el, handle, 0 /* flags */, &fb_fd.el);
@@ -354,7 +369,8 @@ public:
return fb_fd; return fb_fd;
} }
std::vector<std::pair<prop_t, std::uint64_t>> props(std::uint32_t id, std::uint32_t type) { std::vector<std::pair<prop_t, std::uint64_t>>
props(std::uint32_t id, std::uint32_t type) {
obj_prop_t obj_prop = drmModeObjectGetProperties(fd.el, id, type); obj_prop_t obj_prop = drmModeObjectGetProperties(fd.el, id, type);
std::vector<std::pair<prop_t, std::uint64_t>> props; std::vector<std::pair<prop_t, std::uint64_t>> props;
@@ -367,40 +383,47 @@ public:
return props; return props;
} }
std::vector<std::pair<prop_t, std::uint64_t>> plane_props(std::uint32_t id) { std::vector<std::pair<prop_t, std::uint64_t>>
plane_props(std::uint32_t id) {
return props(id, DRM_MODE_OBJECT_PLANE); return props(id, DRM_MODE_OBJECT_PLANE);
} }
std::vector<std::pair<prop_t, std::uint64_t>> crtc_props(std::uint32_t id) { std::vector<std::pair<prop_t, std::uint64_t>>
crtc_props(std::uint32_t id) {
return props(id, DRM_MODE_OBJECT_CRTC); return props(id, DRM_MODE_OBJECT_CRTC);
} }
std::vector<std::pair<prop_t, std::uint64_t>> connector_props(std::uint32_t id) { std::vector<std::pair<prop_t, std::uint64_t>>
connector_props(std::uint32_t id) {
return props(id, DRM_MODE_OBJECT_CONNECTOR); return props(id, DRM_MODE_OBJECT_CONNECTOR);
} }
plane_t operator[](std::uint32_t index) { plane_t
operator[](std::uint32_t index) {
return drmModeGetPlane(fd.el, plane_res->planes[index]); return drmModeGetPlane(fd.el, plane_res->planes[index]);
} }
std::uint32_t count() { std::uint32_t
count() {
return plane_res->count_planes; return plane_res->count_planes;
} }
plane_it_t begin() const { plane_it_t
begin() const {
return plane_it_t { fd.el, plane_res->planes, plane_res->planes + plane_res->count_planes }; return plane_it_t { fd.el, plane_res->planes, plane_res->planes + plane_res->count_planes };
} }
plane_it_t end() const { plane_it_t
end() const {
return plane_it_t { fd.el, plane_res->planes + plane_res->count_planes }; return plane_it_t { fd.el, plane_res->planes + plane_res->count_planes };
} }
file_t fd; file_t fd;
plane_res_t plane_res; plane_res_t plane_res;
}; };
std::map<std::uint32_t, monitor_t> map_crtc_to_monitor(const std::vector<connector_t> &connectors) { std::map<std::uint32_t, monitor_t>
map_crtc_to_monitor(const std::vector<connector_t> &connectors) {
std::map<std::uint32_t, monitor_t> result; std::map<std::uint32_t, monitor_t> result;
for (auto &connector : connectors) { for (auto &connector : connectors) {
@@ -421,7 +444,8 @@ struct kms_img_t : public img_t {
} }
}; };
void print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer crtc) { void
print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer crtc) {
if (crtc) { if (crtc) {
BOOST_LOG(debug) << "crtc("sv << crtc->x << ", "sv << crtc->y << ')'; BOOST_LOG(debug) << "crtc("sv << crtc->x << ", "sv << crtc->y << ')';
BOOST_LOG(debug) << "crtc("sv << crtc->width << ", "sv << crtc->height << ')'; BOOST_LOG(debug) << "crtc("sv << crtc->width << ", "sv << crtc->height << ')';
@@ -455,9 +479,11 @@ void print(plane_t::pointer plane, fb_t::pointer fb, crtc_t::pointer crtc) {
class display_t: public platf::display_t { class display_t: public platf::display_t {
public: public:
display_t(mem_type_e mem_type) : platf::display_t(), mem_type { mem_type } {} display_t(mem_type_e mem_type):
platf::display_t(), mem_type { mem_type } {}
int init(const std::string &display_name, const ::video::config_t &config) { int
init(const std::string &display_name, const ::video::config_t &config) {
delay = std::chrono::nanoseconds { 1s } / config.framerate; delay = std::chrono::nanoseconds { 1s } / config.framerate;
int monitor_index = util::from_view(display_name); int monitor_index = util::from_view(display_name);
@@ -593,7 +619,8 @@ public:
return 0; return 0;
} }
inline capture_e refresh(file_t *file, egl::surface_descriptor_t *sd) { inline capture_e
refresh(file_t *file, egl::surface_descriptor_t *sd) {
plane_t plane = drmModeGetPlane(card.fd.el, plane_id); plane_t plane = drmModeGetPlane(card.fd.el, plane_id);
auto fb = card.fb(plane.get()); auto fb = card.fb(plane.get());
@@ -660,9 +687,11 @@ public:
class display_ram_t: public display_t { class display_ram_t: public display_t {
public: public:
display_ram_t(mem_type_e mem_type) : display_t(mem_type) {} display_ram_t(mem_type_e mem_type):
display_t(mem_type) {}
int init(const std::string &display_name, const ::video::config_t &config) { int
init(const std::string &display_name, const ::video::config_t &config) {
if (!gbm::create_device) { if (!gbm::create_device) {
BOOST_LOG(warning) << "libgbm not initialized"sv; BOOST_LOG(warning) << "libgbm not initialized"sv;
return -1; return -1;
@@ -693,7 +722,8 @@ public:
return 0; return 0;
} }
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override { capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while (img) { while (img) {
@@ -728,7 +758,8 @@ public:
return capture_e::ok; return capture_e::ok;
} }
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override { std::shared_ptr<hwdevice_t>
make_hwdevice(pix_fmt_e pix_fmt) override {
if (mem_type == mem_type_e::vaapi) { if (mem_type == mem_type_e::vaapi) {
return va::make_hwdevice(width, height, false); return va::make_hwdevice(width, height, false);
} }
@@ -736,7 +767,8 @@ public:
return std::make_shared<hwdevice_t>(); return std::make_shared<hwdevice_t>();
} }
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) { capture_e
snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
file_t fb_fd[4]; file_t fb_fd[4];
egl::surface_descriptor_t sd; egl::surface_descriptor_t sd;
@@ -770,7 +802,8 @@ public:
return capture_e::ok; return capture_e::ok;
} }
std::shared_ptr<img_t> alloc_img() override { std::shared_ptr<img_t>
alloc_img() override {
auto img = std::make_shared<kms_img_t>(); auto img = std::make_shared<kms_img_t>();
img->width = width; img->width = width;
img->height = height; img->height = height;
@@ -781,7 +814,8 @@ public:
return img; return img;
} }
int dummy_img(platf::img_t *img) override { int
dummy_img(platf::img_t *img) override {
return 0; return 0;
} }
@@ -792,9 +826,11 @@ public:
class display_vram_t: public display_t { class display_vram_t: public display_t {
public: public:
display_vram_t(mem_type_e mem_type) : display_t(mem_type) {} display_vram_t(mem_type_e mem_type):
display_t(mem_type) {}
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override { std::shared_ptr<hwdevice_t>
make_hwdevice(pix_fmt_e pix_fmt) override {
if (mem_type == mem_type_e::vaapi) { if (mem_type == mem_type_e::vaapi) {
return va::make_hwdevice(width, height, dup(card.fd.el), img_offset_x, img_offset_y, true); return va::make_hwdevice(width, height, dup(card.fd.el), img_offset_x, img_offset_y, true);
} }
@@ -803,7 +839,8 @@ public:
return nullptr; return nullptr;
} }
std::shared_ptr<img_t> alloc_img() override { std::shared_ptr<img_t>
alloc_img() override {
auto img = std::make_shared<egl::img_descriptor_t>(); auto img = std::make_shared<egl::img_descriptor_t>();
img->serial = std::numeric_limits<decltype(img->serial)>::max(); img->serial = std::numeric_limits<decltype(img->serial)>::max();
@@ -816,11 +853,13 @@ public:
return img; return img;
} }
int dummy_img(platf::img_t *img) override { int
dummy_img(platf::img_t *img) override {
return snapshot(img, 1s, false) != capture_e::ok; return snapshot(img, 1s, false) != capture_e::ok;
} }
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) { capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while (img) { while (img) {
@@ -855,7 +894,8 @@ public:
return capture_e::ok; return capture_e::ok;
} }
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds /* timeout */, bool cursor) { capture_e
snapshot(img_t *img_out_base, std::chrono::milliseconds /* timeout */, bool cursor) {
file_t fb_fd[4]; file_t fb_fd[4];
auto img = (egl::img_descriptor_t *) img_out_base; auto img = (egl::img_descriptor_t *) img_out_base;
@@ -888,7 +928,8 @@ public:
return capture_e::ok; return capture_e::ok;
} }
int init(const std::string &display_name, const ::video::config_t &config) { int
init(const std::string &display_name, const ::video::config_t &config) {
if (display_t::init(display_name, config)) { if (display_t::init(display_name, config)) {
return -1; return -1;
} }
@@ -908,7 +949,8 @@ public:
} // namespace kms } // namespace kms
std::shared_ptr<display_t> kms_display(mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) { std::shared_ptr<display_t>
kms_display(mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
if (hwdevice_type == mem_type_e::vaapi) { if (hwdevice_type == mem_type_e::vaapi) {
auto disp = std::make_shared<kms::display_vram_t>(hwdevice_type); auto disp = std::make_shared<kms::display_vram_t>(hwdevice_type);
@@ -928,7 +970,6 @@ std::shared_ptr<display_t> kms_display(mem_type_e hwdevice_type, const std::stri
return disp; return disp;
} }
/** /**
* On Wayland, it's not possible to determine the position of the monitor on the desktop with KMS. * On Wayland, it's not possible to determine the position of the monitor on the desktop with KMS.
* Wayland does allow applications to query attached monitors on the desktop, * Wayland does allow applications to query attached monitors on the desktop,
@@ -939,7 +980,8 @@ std::shared_ptr<display_t> kms_display(mem_type_e hwdevice_type, const std::stri
* *
* This is an ugly hack :( * This is an ugly hack :(
*/ */
void correlate_to_wayland(std::vector<kms::card_descriptor_t> &cds) { void
correlate_to_wayland(std::vector<kms::card_descriptor_t> &cds) {
auto monitors = wl::monitors(); auto monitors = wl::monitors();
for (auto &monitor : monitors) { for (auto &monitor : monitors) {
@@ -990,7 +1032,8 @@ void correlate_to_wayland(std::vector<kms::card_descriptor_t> &cds) {
} }
// A list of names of displays accepted as display_name // A list of names of displays accepted as display_name
std::vector<std::string> kms_display_names() { std::vector<std::string>
kms_display_names() {
int count = 0; int count = 0;
if (!fs::exists("/dev/dri")) { if (!fs::exists("/dev/dri")) {

View File

@@ -37,7 +37,8 @@ namespace bp = boost::process;
window_system_e window_system; window_system_e window_system;
namespace dyn { namespace dyn {
void *handle(const std::vector<const char *> &libs) { void *
handle(const std::vector<const char *> &libs) {
void *handle; void *handle;
for (auto lib : libs) { for (auto lib : libs) {
@@ -60,7 +61,8 @@ void *handle(const std::vector<const char *> &libs) {
return nullptr; return nullptr;
} }
int load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict) { int
load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict) {
int err = 0; int err = 0;
for (auto &func : funcs) { for (auto &func : funcs) {
TUPLE_2D_REF(fn, name, func); TUPLE_2D_REF(fn, name, func);
@@ -80,7 +82,8 @@ int load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &f
namespace platf { namespace platf {
using ifaddr_t = util::safe_ptr<ifaddrs, freeifaddrs>; using ifaddr_t = util::safe_ptr<ifaddrs, freeifaddrs>;
ifaddr_t get_ifaddrs() { ifaddr_t
get_ifaddrs() {
ifaddrs *p { nullptr }; ifaddrs *p { nullptr };
getifaddrs(&p); getifaddrs(&p);
@@ -88,7 +91,8 @@ ifaddr_t get_ifaddrs() {
return ifaddr_t { p }; return ifaddr_t { p };
} }
fs::path appdata() { fs::path
appdata() {
const char *homedir; const char *homedir;
if ((homedir = getenv("HOME")) == nullptr) { if ((homedir = getenv("HOME")) == nullptr) {
homedir = getpwuid(geteuid())->pw_dir; homedir = getpwuid(geteuid())->pw_dir;
@@ -97,7 +101,8 @@ fs::path appdata() {
return fs::path { homedir } / ".config/sunshine"sv; return fs::path { homedir } / ".config/sunshine"sv;
} }
std::string from_sockaddr(const sockaddr *const ip_addr) { std::string
from_sockaddr(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family; auto family = ip_addr->sa_family;
@@ -114,7 +119,8 @@ std::string from_sockaddr(const sockaddr *const ip_addr) {
return std::string { data }; return std::string { data };
} }
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_addr) { std::pair<std::uint16_t, std::string>
from_sockaddr_ex(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family; auto family = ip_addr->sa_family;
@@ -134,7 +140,8 @@ std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_
return { port, std::string { data } }; return { port, std::string { data } };
} }
std::string get_mac_address(const std::string_view &address) { std::string
get_mac_address(const std::string_view &address) {
auto ifaddrs = get_ifaddrs(); auto ifaddrs = get_ifaddrs();
for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) { for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) {
if (pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) { if (pos->ifa_addr && address == from_sockaddr(pos->ifa_addr)) {
@@ -151,7 +158,8 @@ std::string get_mac_address(const std::string_view &address) {
return "00:00:00:00:00:00"s; return "00:00:00:00:00:00"s;
} }
bp::child run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { bp::child
run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) {
BOOST_LOG(warning) << "run_unprivileged() is not yet implemented for this platform. The new process will run with Sunshine's permissions."sv; BOOST_LOG(warning) << "run_unprivileged() is not yet implemented for this platform. The new process will run with Sunshine's permissions."sv;
if (!group) { if (!group) {
if (!file) { if (!file) {
@@ -171,29 +179,35 @@ bp::child run_unprivileged(const std::string &cmd, boost::filesystem::path &work
} }
} }
void adjust_thread_priority(thread_priority_e priority) { void
adjust_thread_priority(thread_priority_e priority) {
// Unimplemented // Unimplemented
} }
void streaming_will_start() { void
streaming_will_start() {
// Nothing to do // Nothing to do
} }
void streaming_will_stop() { void
streaming_will_stop() {
// Nothing to do // Nothing to do
} }
bool restart_supported() { bool
restart_supported() {
// Restart not supported yet // Restart not supported yet
return false; return false;
} }
bool restart() { bool
restart() {
// Restart not supported yet // Restart not supported yet
return false; return false;
} }
bool send_batch(batched_send_info_t &send_info) { bool
send_batch(batched_send_info_t &send_info) {
auto sockfd = (int) send_info.native_socket; auto sockfd = (int) send_info.native_socket;
// Convert the target address into a sockaddr // Convert the target address into a sockaddr
@@ -349,7 +363,8 @@ bool send_batch(batched_send_info_t &send_info) {
class qos_t: public deinit_t { class qos_t: public deinit_t {
public: public:
qos_t(int sockfd, int level, int option) : sockfd(sockfd), level(level), option(option) {} qos_t(int sockfd, int level, int option):
sockfd(sockfd), level(level), option(option) {}
virtual ~qos_t() { virtual ~qos_t() {
int reset_val = -1; int reset_val = -1;
@@ -364,7 +379,8 @@ private:
int option; int option;
}; };
std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type) { std::unique_ptr<deinit_t>
enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type) {
int sockfd = (int) native_socket; int sockfd = (int) native_socket;
int level; int level;
@@ -423,42 +439,55 @@ enum source_e : std::size_t {
static std::bitset<source::MAX_FLAGS> sources; static std::bitset<source::MAX_FLAGS> sources;
#ifdef SUNSHINE_BUILD_CUDA #ifdef SUNSHINE_BUILD_CUDA
std::vector<std::string> nvfbc_display_names(); std::vector<std::string>
std::shared_ptr<display_t> nvfbc_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config); nvfbc_display_names();
std::shared_ptr<display_t>
nvfbc_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config);
bool verify_nvfbc() { bool
verify_nvfbc() {
return !nvfbc_display_names().empty(); return !nvfbc_display_names().empty();
} }
#endif #endif
#ifdef SUNSHINE_BUILD_WAYLAND #ifdef SUNSHINE_BUILD_WAYLAND
std::vector<std::string> wl_display_names(); std::vector<std::string>
std::shared_ptr<display_t> wl_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config); wl_display_names();
std::shared_ptr<display_t>
wl_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config);
bool verify_wl() { bool
verify_wl() {
return window_system == window_system_e::WAYLAND && !wl_display_names().empty(); return window_system == window_system_e::WAYLAND && !wl_display_names().empty();
} }
#endif #endif
#ifdef SUNSHINE_BUILD_DRM #ifdef SUNSHINE_BUILD_DRM
std::vector<std::string> kms_display_names(); std::vector<std::string>
std::shared_ptr<display_t> kms_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config); kms_display_names();
std::shared_ptr<display_t>
kms_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config);
bool verify_kms() { bool
verify_kms() {
return !kms_display_names().empty(); return !kms_display_names().empty();
} }
#endif #endif
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
std::vector<std::string> x11_display_names(); std::vector<std::string>
std::shared_ptr<display_t> x11_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config); x11_display_names();
std::shared_ptr<display_t>
x11_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config);
bool verify_x11() { bool
verify_x11() {
return window_system == window_system_e::X11 && !x11_display_names().empty(); return window_system == window_system_e::X11 && !x11_display_names().empty();
} }
#endif #endif
std::vector<std::string> display_names(mem_type_e hwdevice_type) { std::vector<std::string>
display_names(mem_type_e hwdevice_type) {
#ifdef SUNSHINE_BUILD_CUDA #ifdef SUNSHINE_BUILD_CUDA
// display using NvFBC only supports mem_type_e::cuda // display using NvFBC only supports mem_type_e::cuda
if (sources[source::NVFBC] && hwdevice_type == mem_type_e::cuda) return nvfbc_display_names(); if (sources[source::NVFBC] && hwdevice_type == mem_type_e::cuda) return nvfbc_display_names();
@@ -475,7 +504,8 @@ std::vector<std::string> display_names(mem_type_e hwdevice_type) {
return {}; return {};
} }
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) { std::shared_ptr<display_t>
display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
#ifdef SUNSHINE_BUILD_CUDA #ifdef SUNSHINE_BUILD_CUDA
if (sources[source::NVFBC] && hwdevice_type == mem_type_e::cuda) { if (sources[source::NVFBC] && hwdevice_type == mem_type_e::cuda) {
BOOST_LOG(info) << "Screencasting with NvFBC"sv; BOOST_LOG(info) << "Screencasting with NvFBC"sv;
@@ -504,7 +534,8 @@ std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &
return nullptr; return nullptr;
} }
std::unique_ptr<deinit_t> init() { std::unique_ptr<deinit_t>
init() {
// These are allowed to fail. // These are allowed to fail.
gbm::init(); gbm::init();
va::init(); va::init();

View File

@@ -23,8 +23,10 @@ extern window_system_e window_system;
namespace dyn { namespace dyn {
typedef void (*apiproc)(void); typedef void (*apiproc)(void);
int load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict = true); int
void *handle(const std::vector<const char *> &libs); load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict = true);
void *
handle(const std::vector<const char *> &libs);
} // namespace dyn } // namespace dyn

View File

@@ -195,8 +195,8 @@ simple_poll_quit_fn simple_poll_quit;
simple_poll_new_fn simple_poll_new; simple_poll_new_fn simple_poll_new;
simple_poll_free_fn simple_poll_free; simple_poll_free_fn simple_poll_free;
int
int init_common() { init_common() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -229,7 +229,8 @@ int init_common() {
return 0; return 0;
} }
int init_client() { int
init_client() {
if (init_common()) { if (init_common()) {
return -1; return -1;
} }
@@ -270,7 +271,8 @@ int init_client() {
namespace platf::publish { namespace platf::publish {
template <class T> template <class T>
void free(T *p) { void
free(T *p) {
avahi::free(p); avahi::free(p);
} }
@@ -286,9 +288,11 @@ client_t client;
ptr_t<char> name; ptr_t<char> name;
void create_services(avahi::Client *c); void
create_services(avahi::Client *c);
void entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, void *) { void
entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, void *) {
group = g; group = g;
switch (state) { switch (state) {
@@ -311,7 +315,8 @@ void entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, vo
} }
} }
void create_services(avahi::Client *c) { void
create_services(avahi::Client *c) {
int ret; int ret;
auto fg = util::fail_guard([]() { auto fg = util::fail_guard([]() {
@@ -366,7 +371,8 @@ void create_services(avahi::Client *c) {
fg.disable(); fg.disable();
} }
void client_callback(avahi::Client *c, avahi::ClientState state, void *) { void
client_callback(avahi::Client *c, avahi::ClientState state, void *) {
switch (state) { switch (state) {
case avahi::CLIENT_S_RUNNING: case avahi::CLIENT_S_RUNNING:
create_services(c); create_services(c);
@@ -388,7 +394,8 @@ class deinit_t : public ::platf::deinit_t {
public: public:
std::thread poll_thread; std::thread poll_thread;
deinit_t(std::thread poll_thread) : poll_thread { std::move(poll_thread) } {} deinit_t(std::thread poll_thread):
poll_thread { std::move(poll_thread) } {}
~deinit_t() override { ~deinit_t() override {
if (avahi::simple_poll_quit && poll) { if (avahi::simple_poll_quit && poll) {
@@ -401,7 +408,8 @@ public:
} }
}; };
[[nodiscard]] std::unique_ptr<::platf::deinit_t> start() { [[nodiscard]] std::unique_ptr<::platf::deinit_t>
start() {
if (avahi::init_client()) { if (avahi::init_client()) {
return nullptr; return nullptr;
} }

View File

@@ -9,7 +9,8 @@ extern "C" {
#if !VA_CHECK_VERSION(1, 9, 0) #if !VA_CHECK_VERSION(1, 9, 0)
/* vaSyncBuffer stub allows Sunshine built against libva <2.9.0 /* vaSyncBuffer stub allows Sunshine built against libva <2.9.0
to link against ffmpeg on libva 2.9.0 or later */ to link against ffmpeg on libva 2.9.0 or later */
VAStatus vaSyncBuffer( VAStatus
vaSyncBuffer(
VADisplay dpy, VADisplay dpy,
VABufferID buf_id, VABufferID buf_id,
uint64_t timeout_ns) { uint64_t timeout_ns) {
@@ -193,7 +194,6 @@ enum class entry_e {
ProtectedContent = 14, ProtectedContent = 14,
}; };
typedef VAStatus (*queryConfigEntrypoints_fn)(VADisplay dpy, profile_e profile, entry_e *entrypoint_list, int *num_entrypoints); typedef VAStatus (*queryConfigEntrypoints_fn)(VADisplay dpy, profile_e profile, entry_e *entrypoint_list, int *num_entrypoints);
typedef int (*maxNumEntrypoints_fn)(VADisplay dpy); typedef int (*maxNumEntrypoints_fn)(VADisplay dpy);
typedef VADisplay (*getDisplayDRM_fn)(int fd); typedef VADisplay (*getDisplayDRM_fn)(int fd);
@@ -222,7 +222,8 @@ static exportSurfaceHandle_fn exportSurfaceHandle;
using display_t = util::dyn_safe_ptr_v2<void, VAStatus, &terminate>; using display_t = util::dyn_safe_ptr_v2<void, VAStatus, &terminate>;
int init_main_va() { int
init_main_va() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -255,7 +256,8 @@ int init_main_va() {
return 0; return 0;
} }
int init() { int
init() {
if (init_main_va()) { if (init_main_va()) {
return -1; return -1;
} }
@@ -284,11 +286,13 @@ int init() {
return 0; return 0;
} }
int vaapi_make_hwdevice_ctx(platf::hwdevice_t *base, AVBufferRef **hw_device_buf); int
vaapi_make_hwdevice_ctx(platf::hwdevice_t *base, AVBufferRef **hw_device_buf);
class va_t: public platf::hwdevice_t { class va_t: public platf::hwdevice_t {
public: public:
int init(int in_width, int in_height, file_t &&render_device) { int
init(int in_width, int in_height, file_t &&render_device) {
file = std::move(render_device); file = std::move(render_device);
if (!va::initialize || !gbm::create_device) { if (!va::initialize || !gbm::create_device) {
@@ -324,7 +328,8 @@ public:
return 0; return 0;
} }
int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override { int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
this->hwframe.reset(frame); this->hwframe.reset(frame);
this->frame = frame; this->frame = frame;
@@ -345,7 +350,6 @@ public:
va::EXPORT_SURFACE_WRITE_ONLY | va::EXPORT_SURFACE_COMPOSED_LAYERS, va::EXPORT_SURFACE_WRITE_ONLY | va::EXPORT_SURFACE_COMPOSED_LAYERS,
&prime); &prime);
if (status) { if (status) {
BOOST_LOG(error) << "Couldn't export va surface handle: ["sv << (int) surface << "]: "sv << va::errorStr(status); BOOST_LOG(error) << "Couldn't export va surface handle: ["sv << (int) surface << "]: "sv << va::errorStr(status);
return -1; return -1;
@@ -390,7 +394,8 @@ public:
return 0; return 0;
} }
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override { void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override {
sws.set_colorspace(colorspace, color_range); sws.set_colorspace(colorspace, color_range);
} }
@@ -413,7 +418,8 @@ public:
class va_ram_t: public va_t { class va_ram_t: public va_t {
public: public:
int convert(platf::img_t &img) override { int
convert(platf::img_t &img) override {
sws.load_ram(img); sws.load_ram(img);
sws.convert(nv12->buf); sws.convert(nv12->buf);
@@ -423,7 +429,8 @@ public:
class va_vram_t: public va_t { class va_vram_t: public va_t {
public: public:
int convert(platf::img_t &img) override { int
convert(platf::img_t &img) override {
auto &descriptor = (egl::img_descriptor_t &) img; auto &descriptor = (egl::img_descriptor_t &) img;
if (descriptor.sequence > sequence) { if (descriptor.sequence > sequence) {
@@ -446,7 +453,8 @@ public:
return 0; return 0;
} }
int init(int in_width, int in_height, file_t &&render_device, int offset_x, int offset_y) { int
init(int in_width, int in_height, file_t &&render_device, int offset_x, int offset_y) {
if (va_t::init(in_width, in_height, std::move(render_device))) { if (va_t::init(in_width, in_height, std::move(render_device))) {
return -1; return -1;
} }
@@ -499,11 +507,13 @@ typedef struct AVVAAPIDeviceContext {
unsigned int driver_quirks; unsigned int driver_quirks;
} AVVAAPIDeviceContext; } AVVAAPIDeviceContext;
static void __log(void *level, const char *msg) { static void
__log(void *level, const char *msg) {
BOOST_LOG(*(boost::log::sources::severity_logger<int> *) level) << msg; BOOST_LOG(*(boost::log::sources::severity_logger<int> *) level) << msg;
} }
int vaapi_make_hwdevice_ctx(platf::hwdevice_t *base, AVBufferRef **hw_device_buf) { int
vaapi_make_hwdevice_ctx(platf::hwdevice_t *base, AVBufferRef **hw_device_buf) {
if (!va::initialize) { if (!va::initialize) {
BOOST_LOG(warning) << "libva not loaded"sv; BOOST_LOG(warning) << "libva not loaded"sv;
return -1; return -1;
@@ -565,7 +575,8 @@ int vaapi_make_hwdevice_ctx(platf::hwdevice_t *base, AVBufferRef **hw_device_buf
return 0; return 0;
} }
static bool query(display_t::pointer display, profile_e profile) { static bool
query(display_t::pointer display, profile_e profile) {
std::vector<entry_e> entrypoints; std::vector<entry_e> entrypoints;
entrypoints.resize(maxNumEntrypoints(display)); entrypoints.resize(maxNumEntrypoints(display));
@@ -586,7 +597,8 @@ static bool query(display_t::pointer display, profile_e profile) {
return false; return false;
} }
bool validate(int fd) { bool
validate(int fd) {
if (init()) { if (init()) {
return false; return false;
} }
@@ -625,7 +637,8 @@ bool validate(int fd) {
return true; return true;
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, bool vram) { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, bool vram) {
if (vram) { if (vram) {
auto egl = std::make_shared<va::va_vram_t>(); auto egl = std::make_shared<va::va_vram_t>();
if (egl->init(width, height, std::move(card), offset_x, offset_y)) { if (egl->init(width, height, std::move(card), offset_x, offset_y)) {
@@ -645,7 +658,8 @@ std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &
} }
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, int offset_x, int offset_y, bool vram) { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(int width, int height, int offset_x, int offset_y, bool vram) {
auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str(); auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str();
file_t file = open(render_device, O_RDWR); file_t file = open(render_device, O_RDWR);
@@ -659,7 +673,8 @@ std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, int offs
return make_hwdevice(width, height, std::move(file), offset_x, offset_y, vram); return make_hwdevice(width, height, std::move(file), offset_x, offset_y, vram);
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram) { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(int width, int height, bool vram) {
return make_hwdevice(width, height, 0, 0, vram); return make_hwdevice(width, height, 0, 0, vram);
} }
} // namespace va } // namespace va

View File

@@ -15,13 +15,18 @@ namespace va {
* offset_y --> Vertical offset of the image in the texture * offset_y --> Vertical offset of the image in the texture
* file_t card --> The file descriptor of the render device used for encoding * file_t card --> The file descriptor of the render device used for encoding
*/ */
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, bool vram); std::shared_ptr<platf::hwdevice_t>
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, int offset_x, int offset_y, bool vram); make_hwdevice(int width, int height, bool vram);
std::shared_ptr<platf::hwdevice_t> make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, bool vram); std::shared_ptr<platf::hwdevice_t>
make_hwdevice(int width, int height, int offset_x, int offset_y, bool vram);
std::shared_ptr<platf::hwdevice_t>
make_hwdevice(int width, int height, file_t &&card, int offset_x, int offset_y, bool vram);
// Ensure the render device pointed to by fd is capable of encoding h264 with the hevc_mode configured // Ensure the render device pointed to by fd is capable of encoding h264 with the hevc_mode configured
bool validate(int fd); bool
validate(int fd);
int init(); int
init();
} // namespace va } // namespace va
#endif #endif

View File

@@ -23,13 +23,15 @@ namespace wl {
// Helper to call C++ method from wayland C callback // Helper to call C++ method from wayland C callback
template <class T, class Method, Method m, class... Params> template <class T, class Method, Method m, class... Params>
static auto classCall(void *data, Params... params) -> decltype(((*reinterpret_cast<T *>(data)).*m)(params...)) { static auto
classCall(void *data, Params... params) -> decltype(((*reinterpret_cast<T *>(data)).*m)(params...)) {
return ((*reinterpret_cast<T *>(data)).*m)(params...); return ((*reinterpret_cast<T *>(data)).*m)(params...);
} }
#define CLASS_CALL(c, m) classCall<c, decltype(&c::m), &c::m> #define CLASS_CALL(c, m) classCall<c, decltype(&c::m), &c::m>
int display_t::init(const char *display_name) { int
display_t::init(const char *display_name) {
if (!display_name) { if (!display_name) {
display_name = std::getenv("WAYLAND_DISPLAY"); display_name = std::getenv("WAYLAND_DISPLAY");
} }
@@ -50,16 +52,18 @@ int display_t::init(const char *display_name) {
return 0; return 0;
} }
void display_t::roundtrip() { void
display_t::roundtrip() {
wl_display_roundtrip(display_internal.get()); wl_display_roundtrip(display_internal.get());
} }
wl_registry *display_t::registry() { wl_registry *
display_t::registry() {
return wl_display_get_registry(display_internal.get()); return wl_display_get_registry(display_internal.get());
} }
inline monitor_t::monitor_t(wl_output *output) inline monitor_t::monitor_t(wl_output *output):
: output { output }, listener { output { output }, listener {
&CLASS_CALL(monitor_t, xdg_position), &CLASS_CALL(monitor_t, xdg_position),
&CLASS_CALL(monitor_t, xdg_size), &CLASS_CALL(monitor_t, xdg_size),
&CLASS_CALL(monitor_t, xdg_done), &CLASS_CALL(monitor_t, xdg_done),
@@ -67,52 +71,62 @@ inline monitor_t::monitor_t(wl_output *output)
&CLASS_CALL(monitor_t, xdg_description) &CLASS_CALL(monitor_t, xdg_description)
} {} } {}
inline void monitor_t::xdg_name(zxdg_output_v1 *, const char *name) { inline void
monitor_t::xdg_name(zxdg_output_v1 *, const char *name) {
this->name = name; this->name = name;
BOOST_LOG(info) << "Name: "sv << this->name; BOOST_LOG(info) << "Name: "sv << this->name;
} }
void monitor_t::xdg_description(zxdg_output_v1 *, const char *description) { void
monitor_t::xdg_description(zxdg_output_v1 *, const char *description) {
this->description = description; this->description = description;
BOOST_LOG(info) << "Found monitor: "sv << this->description; BOOST_LOG(info) << "Found monitor: "sv << this->description;
} }
void monitor_t::xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y) { void
monitor_t::xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y) {
viewport.offset_x = x; viewport.offset_x = x;
viewport.offset_y = y; viewport.offset_y = y;
BOOST_LOG(info) << "Offset: "sv << x << 'x' << y; BOOST_LOG(info) << "Offset: "sv << x << 'x' << y;
} }
void monitor_t::xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height) { void
monitor_t::xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height) {
viewport.width = width; viewport.width = width;
viewport.height = height; viewport.height = height;
BOOST_LOG(info) << "Resolution: "sv << width << 'x' << height; BOOST_LOG(info) << "Resolution: "sv << width << 'x' << height;
} }
void monitor_t::xdg_done(zxdg_output_v1 *) { void
monitor_t::xdg_done(zxdg_output_v1 *) {
BOOST_LOG(info) << "All info about monitor ["sv << name << "] has been send"sv; BOOST_LOG(info) << "All info about monitor ["sv << name << "] has been send"sv;
} }
void monitor_t::listen(zxdg_output_manager_v1 *output_manager) { void
monitor_t::listen(zxdg_output_manager_v1 *output_manager) {
auto xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, output); auto xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, output);
zxdg_output_v1_add_listener(xdg_output, &listener, this); zxdg_output_v1_add_listener(xdg_output, &listener, this);
} }
interface_t::interface_t() noexcept interface_t::interface_t() noexcept
: output_manager { nullptr }, listener { :
output_manager { nullptr },
listener {
&CLASS_CALL(interface_t, add_interface), &CLASS_CALL(interface_t, add_interface),
&CLASS_CALL(interface_t, del_interface) &CLASS_CALL(interface_t, del_interface)
} {} } {}
void interface_t::listen(wl_registry *registry) { void
interface_t::listen(wl_registry *registry) {
wl_registry_add_listener(registry, &listener, this); wl_registry_add_listener(registry, &listener, this);
} }
void interface_t::add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version) { void
interface_t::add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version) {
BOOST_LOG(debug) << "Available interface: "sv << interface << '(' << id << ") version "sv << version; BOOST_LOG(debug) << "Available interface: "sv << interface << '(' << id << ") version "sv << version;
if (!std::strcmp(interface, wl_output_interface.name)) { if (!std::strcmp(interface, wl_output_interface.name)) {
@@ -135,12 +149,13 @@ void interface_t::add_interface(wl_registry *registry, std::uint32_t id, const c
} }
} }
void interface_t::del_interface(wl_registry *registry, uint32_t id) { void
interface_t::del_interface(wl_registry *registry, uint32_t id) {
BOOST_LOG(info) << "Delete: "sv << id; BOOST_LOG(info) << "Delete: "sv << id;
} }
dmabuf_t::dmabuf_t() dmabuf_t::dmabuf_t():
: status { READY }, frames {}, current_frame { &frames[0] }, listener { status { READY }, frames {}, current_frame { &frames[0] }, listener {
&CLASS_CALL(dmabuf_t, frame), &CLASS_CALL(dmabuf_t, frame),
&CLASS_CALL(dmabuf_t, object), &CLASS_CALL(dmabuf_t, object),
&CLASS_CALL(dmabuf_t, ready), &CLASS_CALL(dmabuf_t, ready),
@@ -148,7 +163,8 @@ dmabuf_t::dmabuf_t()
} { } {
} }
void dmabuf_t::listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor) { void
dmabuf_t::listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor) {
auto frame = zwlr_export_dmabuf_manager_v1_capture_output(dmabuf_manager, blend_cursor, output); auto frame = zwlr_export_dmabuf_manager_v1_capture_output(dmabuf_manager, blend_cursor, output);
zwlr_export_dmabuf_frame_v1_add_listener(frame, &listener, this); zwlr_export_dmabuf_frame_v1_add_listener(frame, &listener, this);
@@ -161,7 +177,8 @@ dmabuf_t::~dmabuf_t() {
} }
} }
void dmabuf_t::frame( void
dmabuf_t::frame(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t width, std::uint32_t height, std::uint32_t width, std::uint32_t height,
std::uint32_t x, std::uint32_t y, std::uint32_t x, std::uint32_t y,
@@ -177,7 +194,8 @@ void dmabuf_t::frame(
next_frame->sd.modifier = (((std::uint64_t) high) << 32) | low; next_frame->sd.modifier = (((std::uint64_t) high) << 32) | low;
} }
void dmabuf_t::object( void
dmabuf_t::object(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t index, std::uint32_t index,
std::int32_t fd, std::int32_t fd,
@@ -192,10 +210,10 @@ void dmabuf_t::object(
next_frame->sd.offsets[plane_index] = offset; next_frame->sd.offsets[plane_index] = offset;
} }
void dmabuf_t::ready( void
dmabuf_t::ready(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec) { std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec) {
zwlr_export_dmabuf_frame_v1_destroy(frame); zwlr_export_dmabuf_frame_v1_destroy(frame);
current_frame->destroy(); current_frame->destroy();
@@ -204,10 +222,10 @@ void dmabuf_t::ready(
status = READY; status = READY;
} }
void dmabuf_t::cancel( void
dmabuf_t::cancel(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t reason) { std::uint32_t reason) {
zwlr_export_dmabuf_frame_v1_destroy(frame); zwlr_export_dmabuf_frame_v1_destroy(frame);
auto next_frame = get_next_frame(); auto next_frame = get_next_frame();
@@ -216,7 +234,8 @@ void dmabuf_t::cancel(
status = REINIT; status = REINIT;
} }
void frame_t::destroy() { void
frame_t::destroy() {
for (auto x = 0; x < 4; ++x) { for (auto x = 0; x < 4; ++x) {
if (sd.fds[x] >= 0) { if (sd.fds[x] >= 0) {
close(sd.fds[x]); close(sd.fds[x]);
@@ -231,7 +250,8 @@ frame_t::frame_t() {
std::fill_n(sd.fds, 4, -1); std::fill_n(sd.fds, 4, -1);
}; };
std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name) { std::vector<std::unique_ptr<monitor_t>>
monitors(const char *display_name) {
display_t display; display_t display;
if (display.init(display_name)) { if (display.init(display_name)) {
@@ -257,13 +277,15 @@ std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name) {
return std::move(interface.monitors); return std::move(interface.monitors);
} }
static bool validate() { static bool
validate() {
display_t display; display_t display;
return display.init() == 0; return display.init() == 0;
} }
int init() { int
init() {
static bool validated = validate(); static bool validated = validate();
return !validated; return !validated;

View File

@@ -24,7 +24,8 @@ public:
frame_t(); frame_t();
egl::surface_descriptor_t sd; egl::surface_descriptor_t sd;
void destroy(); void
destroy();
}; };
class dmabuf_t { class dmabuf_t {
@@ -38,16 +39,20 @@ public:
dmabuf_t(dmabuf_t &&) = delete; dmabuf_t(dmabuf_t &&) = delete;
dmabuf_t(const dmabuf_t &) = delete; dmabuf_t(const dmabuf_t &) = delete;
dmabuf_t &operator=(const dmabuf_t &) = delete; dmabuf_t &
dmabuf_t &operator=(dmabuf_t &&) = delete; operator=(const dmabuf_t &) = delete;
dmabuf_t &
operator=(dmabuf_t &&) = delete;
dmabuf_t(); dmabuf_t();
void listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor = false); void
listen(zwlr_export_dmabuf_manager_v1 *dmabuf_manager, wl_output *output, bool blend_cursor = false);
~dmabuf_t(); ~dmabuf_t();
void frame( void
frame(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t width, std::uint32_t height, std::uint32_t width, std::uint32_t height,
std::uint32_t x, std::uint32_t y, std::uint32_t x, std::uint32_t y,
@@ -56,7 +61,8 @@ public:
std::uint32_t high, std::uint32_t low, std::uint32_t high, std::uint32_t low,
std::uint32_t obj_count); std::uint32_t obj_count);
void object( void
object(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t index, std::uint32_t index,
std::int32_t fd, std::int32_t fd,
@@ -65,15 +71,18 @@ public:
std::uint32_t stride, std::uint32_t stride,
std::uint32_t plane_index); std::uint32_t plane_index);
void ready( void
ready(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec); std::uint32_t tv_sec_hi, std::uint32_t tv_sec_lo, std::uint32_t tv_nsec);
void cancel( void
cancel(
zwlr_export_dmabuf_frame_v1 *frame, zwlr_export_dmabuf_frame_v1 *frame,
std::uint32_t reason); std::uint32_t reason);
inline frame_t *get_next_frame() { inline frame_t *
get_next_frame() {
return current_frame == &frames[0] ? &frames[1] : &frames[0]; return current_frame == &frames[0] ? &frames[1] : &frames[0];
} }
@@ -90,18 +99,26 @@ public:
monitor_t(monitor_t &&) = delete; monitor_t(monitor_t &&) = delete;
monitor_t(const monitor_t &) = delete; monitor_t(const monitor_t &) = delete;
monitor_t &operator=(const monitor_t &) = delete; monitor_t &
monitor_t &operator=(monitor_t &&) = delete; operator=(const monitor_t &) = delete;
monitor_t &
operator=(monitor_t &&) = delete;
monitor_t(wl_output *output); monitor_t(wl_output *output);
void xdg_name(zxdg_output_v1 *, const char *name); void
void xdg_description(zxdg_output_v1 *, const char *description); xdg_name(zxdg_output_v1 *, const char *name);
void xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y); void
void xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height); xdg_description(zxdg_output_v1 *, const char *description);
void xdg_done(zxdg_output_v1 *); void
xdg_position(zxdg_output_v1 *, std::int32_t x, std::int32_t y);
void
xdg_size(zxdg_output_v1 *, std::int32_t width, std::int32_t height);
void
xdg_done(zxdg_output_v1 *);
void listen(zxdg_output_manager_v1 *output_manager); void
listen(zxdg_output_manager_v1 *output_manager);
wl_output *output; wl_output *output;
@@ -129,25 +146,31 @@ public:
interface_t(interface_t &&) = delete; interface_t(interface_t &&) = delete;
interface_t(const interface_t &) = delete; interface_t(const interface_t &) = delete;
interface_t &operator=(const interface_t &) = delete; interface_t &
interface_t &operator=(interface_t &&) = delete; operator=(const interface_t &) = delete;
interface_t &
operator=(interface_t &&) = delete;
interface_t() noexcept; interface_t() noexcept;
void listen(wl_registry *registry); void
listen(wl_registry *registry);
std::vector<std::unique_ptr<monitor_t>> monitors; std::vector<std::unique_ptr<monitor_t>> monitors;
zwlr_export_dmabuf_manager_v1 *dmabuf_manager; zwlr_export_dmabuf_manager_v1 *dmabuf_manager;
zxdg_output_manager_v1 *output_manager; zxdg_output_manager_v1 *output_manager;
bool operator[](interface_e bit) const { bool
operator[](interface_e bit) const {
return interface[bit]; return interface[bit];
} }
private: private:
void add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version); void
void del_interface(wl_registry *registry, uint32_t id); add_interface(wl_registry *registry, std::uint32_t id, const char *interface, std::uint32_t version);
void
del_interface(wl_registry *registry, uint32_t id);
std::bitset<MAX_INTERFACES> interface; std::bitset<MAX_INTERFACES> interface;
@@ -160,16 +183,20 @@ public:
* Initialize display with display_name * Initialize display with display_name
* If display_name == nullptr -> display_name = std::getenv("WAYLAND_DISPLAY") * If display_name == nullptr -> display_name = std::getenv("WAYLAND_DISPLAY")
*/ */
int init(const char *display_name = nullptr); int
init(const char *display_name = nullptr);
// Roundtrip with Wayland connection // Roundtrip with Wayland connection
void roundtrip(); void
roundtrip();
// Get the registry associated with the display // Get the registry associated with the display
// No need to manually free the registry // No need to manually free the registry
wl_registry *registry(); wl_registry *
registry();
inline display_internal_t::pointer get() { inline display_internal_t::pointer
get() {
return display_internal.get(); return display_internal.get();
} }
@@ -177,9 +204,11 @@ private:
display_internal_t display_internal; display_internal_t display_internal;
}; };
std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name = nullptr); std::vector<std::unique_ptr<monitor_t>>
monitors(const char *display_name = nullptr);
int init(); int
init();
} // namespace wl } // namespace wl
#else #else
@@ -192,12 +221,15 @@ public:
monitor_t(monitor_t &&) = delete; monitor_t(monitor_t &&) = delete;
monitor_t(const monitor_t &) = delete; monitor_t(const monitor_t &) = delete;
monitor_t &operator=(const monitor_t &) = delete; monitor_t &
monitor_t &operator=(monitor_t &&) = delete; operator=(const monitor_t &) = delete;
monitor_t &
operator=(monitor_t &&) = delete;
monitor_t(wl_output *output); monitor_t(wl_output *output);
void listen(zxdg_output_manager_v1 *output_manager); void
listen(zxdg_output_manager_v1 *output_manager);
wl_output *output; wl_output *output;
@@ -207,9 +239,11 @@ public:
platf::touch_port_t viewport; platf::touch_port_t viewport;
}; };
inline std::vector<std::unique_ptr<monitor_t>> monitors(const char *display_name = nullptr) { return {}; } inline std::vector<std::unique_ptr<monitor_t>>
monitors(const char *display_name = nullptr) { return {}; }
inline int init() { return -1; } inline int
init() { return -1; }
} // namespace wl } // namespace wl
#endif #endif

View File

@@ -19,7 +19,8 @@ struct img_t : public platf::img_t {
class wlr_t: public platf::display_t { class wlr_t: public platf::display_t {
public: public:
int init(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) { int
init(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
delay = std::chrono::nanoseconds { 1s } / config.framerate; delay = std::chrono::nanoseconds { 1s } / config.framerate;
mem_type = hwdevice_type; mem_type = hwdevice_type;
@@ -73,11 +74,13 @@ public:
return 0; return 0;
} }
int dummy_img(platf::img_t *img) override { int
dummy_img(platf::img_t *img) override {
return 0; return 0;
} }
inline platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) { inline platf::capture_e
snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
auto to = std::chrono::steady_clock::now() + timeout; auto to = std::chrono::steady_clock::now() + timeout;
dmabuf.listen(interface.dmabuf_manager, output, cursor); dmabuf.listen(interface.dmabuf_manager, output, cursor);
@@ -95,7 +98,6 @@ public:
dmabuf.status == dmabuf_t::REINIT || dmabuf.status == dmabuf_t::REINIT ||
current_frame->sd.width != width || current_frame->sd.width != width ||
current_frame->sd.height != height) { current_frame->sd.height != height) {
return platf::capture_e::reinit; return platf::capture_e::reinit;
} }
@@ -115,7 +117,8 @@ public:
class wlr_ram_t: public wlr_t { class wlr_ram_t: public wlr_t {
public: public:
platf::capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override { platf::capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while (img) { while (img) {
@@ -149,7 +152,8 @@ public:
return platf::capture_e::ok; return platf::capture_e::ok;
} }
platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) { platf::capture_e
snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
auto status = wlr_t::snapshot(img_out_base, timeout, cursor); auto status = wlr_t::snapshot(img_out_base, timeout, cursor);
if (status != platf::capture_e::ok) { if (status != platf::capture_e::ok) {
return status; return status;
@@ -176,7 +180,8 @@ public:
return platf::capture_e::ok; return platf::capture_e::ok;
} }
int init(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) { int
init(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
if (wlr_t::init(hwdevice_type, display_name, config)) { if (wlr_t::init(hwdevice_type, display_name, config)) {
return -1; return -1;
} }
@@ -196,7 +201,8 @@ public:
return 0; return 0;
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(platf::pix_fmt_e pix_fmt) override { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(platf::pix_fmt_e pix_fmt) override {
if (mem_type == platf::mem_type_e::vaapi) { if (mem_type == platf::mem_type_e::vaapi) {
return va::make_hwdevice(width, height, false); return va::make_hwdevice(width, height, false);
} }
@@ -204,7 +210,8 @@ public:
return std::make_shared<platf::hwdevice_t>(); return std::make_shared<platf::hwdevice_t>();
} }
std::shared_ptr<platf::img_t> alloc_img() override { std::shared_ptr<platf::img_t>
alloc_img() override {
auto img = std::make_shared<img_t>(); auto img = std::make_shared<img_t>();
img->width = width; img->width = width;
img->height = height; img->height = height;
@@ -221,7 +228,8 @@ public:
class wlr_vram_t: public wlr_t { class wlr_vram_t: public wlr_t {
public: public:
platf::capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override { platf::capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<platf::img_t> img, bool *cursor) override {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while (img) { while (img) {
@@ -255,7 +263,8 @@ public:
return platf::capture_e::ok; return platf::capture_e::ok;
} }
platf::capture_e snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) { platf::capture_e
snapshot(platf::img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
auto status = wlr_t::snapshot(img_out_base, timeout, cursor); auto status = wlr_t::snapshot(img_out_base, timeout, cursor);
if (status != platf::capture_e::ok) { if (status != platf::capture_e::ok) {
return status; return status;
@@ -277,7 +286,8 @@ public:
return platf::capture_e::ok; return platf::capture_e::ok;
} }
std::shared_ptr<platf::img_t> alloc_img() override { std::shared_ptr<platf::img_t>
alloc_img() override {
auto img = std::make_shared<egl::img_descriptor_t>(); auto img = std::make_shared<egl::img_descriptor_t>();
img->sequence = 0; img->sequence = 0;
@@ -290,7 +300,8 @@ public:
return img; return img;
} }
std::shared_ptr<platf::hwdevice_t> make_hwdevice(platf::pix_fmt_e pix_fmt) override { std::shared_ptr<platf::hwdevice_t>
make_hwdevice(platf::pix_fmt_e pix_fmt) override {
if (mem_type == platf::mem_type_e::vaapi) { if (mem_type == platf::mem_type_e::vaapi) {
return va::make_hwdevice(width, height, 0, 0, true); return va::make_hwdevice(width, height, 0, 0, true);
} }
@@ -298,7 +309,8 @@ public:
return std::make_shared<platf::hwdevice_t>(); return std::make_shared<platf::hwdevice_t>();
} }
int dummy_img(platf::img_t *img) override { int
dummy_img(platf::img_t *img) override {
return snapshot(img, 1000ms, false) != platf::capture_e::ok; return snapshot(img, 1000ms, false) != platf::capture_e::ok;
} }
@@ -308,7 +320,8 @@ public:
} // namespace wl } // namespace wl
namespace platf { namespace platf {
std::shared_ptr<display_t> wl_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) { std::shared_ptr<display_t>
wl_display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
if (hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi && hwdevice_type != platf::mem_type_e::cuda) { if (hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi && hwdevice_type != platf::mem_type_e::cuda) {
BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv; BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
return nullptr; return nullptr;
@@ -331,7 +344,8 @@ std::shared_ptr<display_t> wl_display(mem_type_e hwdevice_type, const std::strin
return wlr; return wlr;
} }
std::vector<std::string> wl_display_names() { std::vector<std::string>
wl_display_names() {
std::vector<std::string> display_names; std::vector<std::string> display_names;
wl::display_t display; wl::display_t display;

View File

@@ -30,8 +30,10 @@
using namespace std::literals; using namespace std::literals;
namespace platf { namespace platf {
int load_xcb(); int
int load_x11(); load_xcb();
int
load_x11();
namespace x11 { namespace x11 {
#define _FN(x, ret, args) \ #define _FN(x, ret, args) \
@@ -66,7 +68,8 @@ _FN(FreeScreenResources, void, (XRRScreenResources * resources));
_FN(FreeOutputInfo, void, (XRROutputInfo * outputInfo)); _FN(FreeOutputInfo, void, (XRROutputInfo * outputInfo));
_FN(FreeCrtcInfo, void, (XRRCrtcInfo * crtcInfo)); _FN(FreeCrtcInfo, void, (XRRCrtcInfo * crtcInfo));
static int init() { static int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -100,7 +103,8 @@ static int init() {
namespace fix { namespace fix {
_FN(GetCursorImage, XFixesCursorImage *, (Display * dpy)); _FN(GetCursorImage, XFixesCursorImage *, (Display * dpy));
static int init() { static int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -126,7 +130,8 @@ static int init() {
} }
} // namespace fix } // namespace fix
static int init() { static int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -193,7 +198,8 @@ _FN(connect, xcb_connection_t *, (const char *displayname, int *screenp));
_FN(setup_roots_iterator, xcb_screen_iterator_t, (const xcb_setup_t *R)); _FN(setup_roots_iterator, xcb_screen_iterator_t, (const xcb_setup_t *R));
_FN(generate_id, std::uint32_t, (xcb_connection_t * c)); _FN(generate_id, std::uint32_t, (xcb_connection_t * c));
int init_shm() { int
init_shm() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -221,7 +227,8 @@ int init_shm() {
return 0; return 0;
} }
int init() { int
init() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -255,8 +262,10 @@ int init() {
#undef _FN #undef _FN
} // namespace xcb } // namespace xcb
void freeImage(XImage *); void
void freeX(XFixesCursorImage *); freeImage(XImage *);
void
freeX(XFixesCursorImage *);
using xcb_connect_t = util::dyn_safe_ptr<xcb_connection_t, &xcb::disconnect>; using xcb_connect_t = util::dyn_safe_ptr<xcb_connection_t, &xcb::disconnect>;
using xcb_img_t = util::c_ptr<xcb_shm_get_image_reply_t>; using xcb_img_t = util::c_ptr<xcb_shm_get_image_reply_t>;
@@ -270,9 +279,12 @@ using screen_res_t = util::dyn_safe_ptr<_XRRScreenResources, &x11::rr::FreeScre
class shm_id_t { class shm_id_t {
public: public:
shm_id_t() : id { -1 } {} shm_id_t():
shm_id_t(int id) : id { id } {} id { -1 } {}
shm_id_t(shm_id_t &&other) noexcept : id(other.id) { shm_id_t(int id):
id { id } {}
shm_id_t(shm_id_t &&other) noexcept:
id(other.id) {
other.id = -1; other.id = -1;
} }
@@ -287,10 +299,13 @@ public:
class shm_data_t { class shm_data_t {
public: public:
shm_data_t() : data { (void *)-1 } {} shm_data_t():
shm_data_t(void *data) : data { data } {} data { (void *) -1 } {}
shm_data_t(void *data):
data { data } {}
shm_data_t(shm_data_t &&other) noexcept : data(other.data) { shm_data_t(shm_data_t &&other) noexcept:
data(other.data) {
other.data = (void *) -1; other.data = (void *) -1;
} }
@@ -314,7 +329,8 @@ struct shm_img_t : public img_t {
} }
}; };
static void blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) { static void
blend_cursor(Display *display, img_t &img, int offsetX, int offsetY) {
xcursor_t overlay { x11::fix::GetCursorImage(display) }; xcursor_t overlay { x11::fix::GetCursorImage(display) };
if (!overlay) { if (!overlay) {
@@ -379,11 +395,13 @@ struct x11_attr_t : public display_t {
*/ */
// int env_width, env_height; // int env_width, env_height;
x11_attr_t(mem_type_e mem_type) : xdisplay { x11::OpenDisplay(nullptr) }, xwindow {}, xattr {}, mem_type { mem_type } { x11_attr_t(mem_type_e mem_type):
xdisplay { x11::OpenDisplay(nullptr) }, xwindow {}, xattr {}, mem_type { mem_type } {
x11::InitThreads(); x11::InitThreads();
} }
int init(const std::string &display_name, const ::video::config_t &config) { int
init(const std::string &display_name, const ::video::config_t &config) {
if (!xdisplay) { if (!xdisplay) {
BOOST_LOG(error) << "Could not open X11 display"sv; BOOST_LOG(error) << "Could not open X11 display"sv;
return -1; return -1;
@@ -452,11 +470,13 @@ struct x11_attr_t : public display_t {
/** /**
* Called when the display attributes should change. * Called when the display attributes should change.
*/ */
void refresh() { void
refresh() {
x11::GetWindowAttributes(xdisplay.get(), xwindow, &xattr); //Update xattr's x11::GetWindowAttributes(xdisplay.get(), xwindow, &xattr); //Update xattr's
} }
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override { capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while (img) { while (img) {
@@ -491,7 +511,8 @@ struct x11_attr_t : public display_t {
return capture_e::ok; return capture_e::ok;
} }
capture_e snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) { capture_e
snapshot(img_t *img_out_base, std::chrono::milliseconds timeout, bool cursor) {
refresh(); refresh();
//The whole X server changed, so we must reinit everything //The whole X server changed, so we must reinit everything
@@ -516,11 +537,13 @@ struct x11_attr_t : public display_t {
return capture_e::ok; return capture_e::ok;
} }
std::shared_ptr<img_t> alloc_img() override { std::shared_ptr<img_t>
alloc_img() override {
return std::make_shared<x11_img_t>(); return std::make_shared<x11_img_t>();
} }
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override { std::shared_ptr<hwdevice_t>
make_hwdevice(pix_fmt_e pix_fmt) override {
if (mem_type == mem_type_e::vaapi) { if (mem_type == mem_type_e::vaapi) {
return va::make_hwdevice(width, height, false); return va::make_hwdevice(width, height, false);
} }
@@ -534,7 +557,8 @@ struct x11_attr_t : public display_t {
return std::make_shared<hwdevice_t>(); return std::make_shared<hwdevice_t>();
} }
int dummy_img(img_t *img) override { int
dummy_img(img_t *img) override {
snapshot(img, 0s, true); snapshot(img, 0s, true);
return 0; return 0;
} }
@@ -552,13 +576,15 @@ struct shm_attr_t : public x11_attr_t {
task_pool_util::TaskPool::task_id_t refresh_task_id; task_pool_util::TaskPool::task_id_t refresh_task_id;
void delayed_refresh() { void
delayed_refresh() {
refresh(); refresh();
refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id; refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id;
} }
shm_attr_t(mem_type_e mem_type) : x11_attr_t(mem_type), shm_xdisplay { x11::OpenDisplay(nullptr) } { shm_attr_t(mem_type_e mem_type):
x11_attr_t(mem_type), shm_xdisplay { x11::OpenDisplay(nullptr) } {
refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id; refresh_task_id = task_pool.pushDelayed(&shm_attr_t::delayed_refresh, 2s, this).task_id;
} }
@@ -567,7 +593,8 @@ struct shm_attr_t : public x11_attr_t {
; ;
} }
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override { capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
while (img) { while (img) {
@@ -602,7 +629,8 @@ struct shm_attr_t : public x11_attr_t {
return capture_e::ok; return capture_e::ok;
} }
capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) { capture_e
snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor) {
//The whole X server changed, so we must reinit everything //The whole X server changed, so we must reinit everything
if (xattr.width != env_width || xattr.height != env_height) { if (xattr.width != env_width || xattr.height != env_height) {
BOOST_LOG(warning) << "X dimensions changed in SHM mode, request reinit"sv; BOOST_LOG(warning) << "X dimensions changed in SHM mode, request reinit"sv;
@@ -627,7 +655,8 @@ struct shm_attr_t : public x11_attr_t {
} }
} }
std::shared_ptr<img_t> alloc_img() override { std::shared_ptr<img_t>
alloc_img() override {
auto img = std::make_shared<shm_img_t>(); auto img = std::make_shared<shm_img_t>();
img->width = width; img->width = width;
img->height = height; img->height = height;
@@ -638,11 +667,13 @@ struct shm_attr_t : public x11_attr_t {
return img; return img;
} }
int dummy_img(platf::img_t *img) override { int
dummy_img(platf::img_t *img) override {
return 0; return 0;
} }
int init(const std::string &display_name, const ::video::config_t &config) { int
init(const std::string &display_name, const ::video::config_t &config) {
if (x11_attr_t::init(display_name, config)) { if (x11_attr_t::init(display_name, config)) {
return 1; return 1;
} }
@@ -681,12 +712,14 @@ struct shm_attr_t : public x11_attr_t {
return 0; return 0;
} }
std::uint32_t frame_size() { std::uint32_t
frame_size() {
return width * height * 4; return width * height * 4;
} }
}; };
std::shared_ptr<display_t> x11_display(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) { std::shared_ptr<display_t>
x11_display(platf::mem_type_e hwdevice_type, const std::string &display_name, const ::video::config_t &config) {
if (hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi && hwdevice_type != platf::mem_type_e::cuda) { if (hwdevice_type != platf::mem_type_e::system && hwdevice_type != platf::mem_type_e::vaapi && hwdevice_type != platf::mem_type_e::cuda) {
BOOST_LOG(error) << "Could not initialize x11 display with the given hw device type"sv; BOOST_LOG(error) << "Could not initialize x11 display with the given hw device type"sv;
return nullptr; return nullptr;
@@ -720,7 +753,8 @@ std::shared_ptr<display_t> x11_display(platf::mem_type_e hwdevice_type, const st
return x11_disp; return x11_disp;
} }
std::vector<std::string> x11_display_names() { std::vector<std::string>
x11_display_names() {
if (load_x11() || load_xcb()) { if (load_x11() || load_xcb()) {
BOOST_LOG(error) << "Couldn't init x11 libraries"sv; BOOST_LOG(error) << "Couldn't init x11 libraries"sv;
@@ -756,21 +790,25 @@ std::vector<std::string> x11_display_names() {
return names; return names;
} }
void freeImage(XImage *p) { void
freeImage(XImage *p) {
XDestroyImage(p); XDestroyImage(p);
} }
void freeX(XFixesCursorImage *p) { void
freeX(XFixesCursorImage *p) {
x11::Free(p); x11::Free(p);
} }
int load_xcb() { int
load_xcb() {
// This will be called once only // This will be called once only
static int xcb_status = xcb::init_shm() || xcb::init(); static int xcb_status = xcb::init_shm() || xcb::init();
return xcb_status; return xcb_status;
} }
int load_x11() { int
load_x11() {
// This will be called once only // This will be called once only
static int x11_status = static int x11_status =
window_system == window_system_e::NONE || window_system == window_system_e::NONE ||
@@ -780,7 +818,8 @@ int load_x11() {
} }
namespace x11 { namespace x11 {
std::optional<cursor_t> cursor_t::make() { std::optional<cursor_t>
cursor_t::make() {
if (load_x11()) { if (load_x11()) {
return std::nullopt; return std::nullopt;
} }
@@ -792,7 +831,8 @@ std::optional<cursor_t> cursor_t::make() {
return cursor; return cursor;
} }
void cursor_t::capture(egl::cursor_t &img) { void
cursor_t::capture(egl::cursor_t &img) {
auto display = (xdisplay_t::pointer) ctx.get(); auto display = (xdisplay_t::pointer) ctx.get();
xcursor_t xcursor = fix::GetCursorImage(display); xcursor_t xcursor = fix::GetCursorImage(display);
@@ -819,19 +859,23 @@ void cursor_t::capture(egl::cursor_t &img) {
img.serial = xcursor->cursor_serial; img.serial = xcursor->cursor_serial;
} }
void cursor_t::blend(img_t &img, int offsetX, int offsetY) { void
cursor_t::blend(img_t &img, int offsetX, int offsetY) {
blend_cursor((xdisplay_t::pointer) ctx.get(), img, offsetX, offsetY); blend_cursor((xdisplay_t::pointer) ctx.get(), img, offsetX, offsetY);
} }
xdisplay_t make_display() { xdisplay_t
make_display() {
return OpenDisplay(nullptr); return OpenDisplay(nullptr);
} }
void freeDisplay(_XDisplay *xdisplay) { void
freeDisplay(_XDisplay *xdisplay) {
CloseDisplay(xdisplay); CloseDisplay(xdisplay);
} }
void freeCursorCtx(cursor_ctx_t::pointer ctx) { void
freeCursorCtx(cursor_ctx_t::pointer ctx) {
CloseDisplay((xdisplay_t::pointer) ctx); CloseDisplay((xdisplay_t::pointer) ctx);
} }
} // namespace x11 } // namespace x11

View File

@@ -17,17 +17,21 @@ namespace platf::x11 {
#ifdef SUNSHINE_BUILD_X11 #ifdef SUNSHINE_BUILD_X11
struct cursor_ctx_raw_t; struct cursor_ctx_raw_t;
void freeCursorCtx(cursor_ctx_raw_t *ctx); void
void freeDisplay(_XDisplay *xdisplay); freeCursorCtx(cursor_ctx_raw_t *ctx);
void
freeDisplay(_XDisplay *xdisplay);
using cursor_ctx_t = util::safe_ptr<cursor_ctx_raw_t, freeCursorCtx>; using cursor_ctx_t = util::safe_ptr<cursor_ctx_raw_t, freeCursorCtx>;
using xdisplay_t = util::safe_ptr<_XDisplay, freeDisplay>; using xdisplay_t = util::safe_ptr<_XDisplay, freeDisplay>;
class cursor_t { class cursor_t {
public: public:
static std::optional<cursor_t> make(); static std::optional<cursor_t>
make();
void capture(egl::cursor_t &img); void
capture(egl::cursor_t &img);
/** /**
* Capture and blend the cursor into the image * Capture and blend the cursor into the image
@@ -35,25 +39,31 @@ public:
* img <-- destination image * img <-- destination image
* offsetX, offsetY <--- Top left corner of the virtual screen * offsetX, offsetY <--- Top left corner of the virtual screen
*/ */
void blend(img_t &img, int offsetX, int offsetY); void
blend(img_t &img, int offsetX, int offsetY);
cursor_ctx_t ctx; cursor_ctx_t ctx;
}; };
xdisplay_t make_display(); xdisplay_t
make_display();
#else #else
// It's never something different from nullptr // It's never something different from nullptr
util::safe_ptr<_XDisplay, std::default_delete<_XDisplay>>; util::safe_ptr<_XDisplay, std::default_delete<_XDisplay>>;
class cursor_t { class cursor_t {
public: public:
static std::optional<cursor_t> make() { return std::nullopt; } static std::optional<cursor_t>
make() { return std::nullopt; }
void capture(egl::cursor_t &) {} void
void blend(img_t &, int, int) {} capture(egl::cursor_t &) {}
void
blend(img_t &, int, int) {}
}; };
xdisplay_t make_display() { return nullptr; } xdisplay_t
make_display() { return nullptr; }
#endif #endif
} // namespace platf::x11 } // namespace platf::x11

View File

@@ -3,7 +3,6 @@
@implementation AVAudio @implementation AVAudio
+ (NSArray<AVCaptureDevice *> *)microphones { + (NSArray<AVCaptureDevice *> *)microphones {
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:((NSOperatingSystemVersion) { 10, 15, 0 })]) { if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:((NSOperatingSystemVersion) { 10, 15, 0 })]) {
// This will generate a warning about AVCaptureDeviceDiscoverySession being // This will generate a warning about AVCaptureDeviceDiscoverySession being
// unavailable before macOS 10.15, but we have a guard to prevent it from // unavailable before macOS 10.15, but we have a guard to prevent it from

View File

@@ -3,7 +3,6 @@
#import <AVFoundation/AVFoundation.h> #import <AVFoundation/AVFoundation.h>
struct CaptureSession { struct CaptureSession {
AVCaptureVideoDataOutput *output; AVCaptureVideoDataOutput *output;
NSCondition *captureStopped; NSCondition *captureStopped;

View File

@@ -163,7 +163,6 @@
- (void)captureOutput:(AVCaptureOutput *)captureOutput - (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection { fromConnection:(AVCaptureConnection *)connection {
FrameCallbackBlock callback = [self.captureCallbacks objectForKey:connection]; FrameCallbackBlock callback = [self.captureCallbacks objectForKey:connection];
if (callback != nil) { if (callback != nil) {

View File

@@ -36,7 +36,8 @@ struct av_display_t : public display_t {
[av_capture release]; [av_capture release];
} }
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override { capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override {
__block auto img_next = std::move(img); __block auto img_next = std::move(img);
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) { auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
@@ -76,11 +77,13 @@ struct av_display_t : public display_t {
return capture_e::ok; return capture_e::ok;
} }
std::shared_ptr<img_t> alloc_img() override { std::shared_ptr<img_t>
alloc_img() override {
return std::make_shared<av_img_t>(); return std::make_shared<av_img_t>();
} }
std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override { std::shared_ptr<hwdevice_t>
make_hwdevice(pix_fmt_e pix_fmt) override {
if (pix_fmt == pix_fmt_e::yuv420p) { if (pix_fmt == pix_fmt_e::yuv420p) {
av_capture.pixelFormat = kCVPixelFormatType_32BGRA; av_capture.pixelFormat = kCVPixelFormatType_32BGRA;
@@ -99,7 +102,8 @@ struct av_display_t : public display_t {
} }
} }
int dummy_img(img_t *img) override { int
dummy_img(img_t *img) override {
auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) { auto signal = [av_capture capture:^(CMSampleBufferRef sampleBuffer) {
auto av_img = (av_img_t *) img; auto av_img = (av_img_t *) img;
@@ -143,16 +147,19 @@ struct av_display_t : public display_t {
* width --> the intended capture width * width --> the intended capture width
* height --> the intended capture height * height --> the intended capture height
*/ */
static void setResolution(void *display, int width, int height) { static void
setResolution(void *display, int width, int height) {
[static_cast<AVVideo *>(display) setFrameWidth:width frameHeight:height]; [static_cast<AVVideo *>(display) setFrameWidth:width frameHeight:height];
} }
static void setPixelFormat(void *display, OSType pixelFormat) { static void
setPixelFormat(void *display, OSType pixelFormat) {
static_cast<AVVideo *>(display).pixelFormat = pixelFormat; static_cast<AVVideo *>(display).pixelFormat = pixelFormat;
} }
}; };
std::shared_ptr<display_t> display(platf::mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) { std::shared_ptr<display_t>
display(platf::mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
if (hwdevice_type != platf::mem_type_e::system) { if (hwdevice_type != platf::mem_type_e::system) {
BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv; BOOST_LOG(error) << "Could not initialize display with the given hw device type."sv;
return nullptr; return nullptr;
@@ -186,7 +193,8 @@ std::shared_ptr<display_t> display(platf::mem_type_e hwdevice_type, const std::s
return display; return display;
} }
std::vector<std::string> display_names(mem_type_e hwdevice_type) { std::vector<std::string>
display_names(mem_type_e hwdevice_type) {
__block std::vector<std::string> display_names; __block std::vector<std::string> display_names;
auto display_array = [AVVideo displayNames]; auto display_array = [AVVideo displayNames];

View File

@@ -36,7 +36,8 @@ struct KeyCodeMap {
}; };
// Customized less operator for using std::lower_bound() on a KeyCodeMap array. // Customized less operator for using std::lower_bound() on a KeyCodeMap array.
bool operator<(const KeyCodeMap &a, const KeyCodeMap &b) { bool
operator<(const KeyCodeMap &a, const KeyCodeMap &b) {
return a.win_keycode < b.win_keycode; return a.win_keycode < b.win_keycode;
} }
@@ -212,7 +213,8 @@ const KeyCodeMap kKeyCodesMap[] = {
}; };
// clang-format on // clang-format on
int keysym(int keycode) { int
keysym(int keycode) {
KeyCodeMap key_map; KeyCodeMap key_map;
key_map.win_keycode = keycode; key_map.win_keycode = keycode;
@@ -227,7 +229,8 @@ int keysym(int keycode) {
return temp_map->mac_keycode; return temp_map->mac_keycode;
} }
void keyboard(input_t &input, uint16_t modcode, bool release) { void
keyboard(input_t &input, uint16_t modcode, bool release) {
auto key = keysym(modcode); auto key = keysym(modcode);
BOOST_LOG(debug) << "got keycode: 0x"sv << std::hex << modcode << ", translated to: 0x" << std::hex << key << ", release:" << release; BOOST_LOG(debug) << "got keycode: 0x"sv << std::hex << modcode << ", translated to: 0x" << std::hex << key << ", release:" << release;
@@ -243,7 +246,6 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
key == kVK_Command || key == kVK_RightCommand || key == kVK_Command || key == kVK_RightCommand ||
key == kVK_Option || key == kVK_RightOption || key == kVK_Option || key == kVK_RightOption ||
key == kVK_Control || key == kVK_RightControl) { key == kVK_Control || key == kVK_RightControl) {
CGEventFlags mask; CGEventFlags mask;
switch (key) { switch (key) {
@@ -277,29 +279,35 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
CGEventPost(kCGHIDEventTap, event); CGEventPost(kCGHIDEventTap, event);
} }
void unicode(input_t &input, char *utf8, int size) { void
unicode(input_t &input, char *utf8, int size) {
BOOST_LOG(info) << "unicode: Unicode input not yet implemented for MacOS."sv; BOOST_LOG(info) << "unicode: Unicode input not yet implemented for MacOS."sv;
} }
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) { int
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
BOOST_LOG(info) << "alloc_gamepad: Gamepad not yet implemented for MacOS."sv; BOOST_LOG(info) << "alloc_gamepad: Gamepad not yet implemented for MacOS."sv;
return -1; return -1;
} }
void free_gamepad(input_t &input, int nr) { void
free_gamepad(input_t &input, int nr) {
BOOST_LOG(info) << "free_gamepad: Gamepad not yet implemented for MacOS."sv; BOOST_LOG(info) << "free_gamepad: Gamepad not yet implemented for MacOS."sv;
} }
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) { void
gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
BOOST_LOG(info) << "gamepad: Gamepad not yet implemented for MacOS."sv; BOOST_LOG(info) << "gamepad: Gamepad not yet implemented for MacOS."sv;
} }
// returns current mouse location: // returns current mouse location:
inline CGPoint get_mouse_loc(input_t &input) { inline CGPoint
get_mouse_loc(input_t &input) {
return CGEventGetLocation(((macos_input_t *) input.get())->mouse_event); return CGEventGetLocation(((macos_input_t *) input.get())->mouse_event);
} }
void post_mouse(input_t &input, CGMouseButton button, CGEventType type, CGPoint location, int click_count) { void
post_mouse(input_t &input, CGMouseButton button, CGEventType type, CGPoint location, int click_count) {
BOOST_LOG(debug) << "mouse_event: "sv << button << ", type: "sv << type << ", location:"sv << location.x << ":"sv << location.y << " click_count: "sv << click_count; BOOST_LOG(debug) << "mouse_event: "sv << button << ", type: "sv << type << ", location:"sv << location.x << ":"sv << location.y << " click_count: "sv << click_count;
auto macos_input = (macos_input_t *) input.get(); auto macos_input = (macos_input_t *) input.get();
@@ -328,7 +336,8 @@ void post_mouse(input_t &input, CGMouseButton button, CGEventType type, CGPoint
CGWarpMouseCursorPosition(location); CGWarpMouseCursorPosition(location);
} }
inline CGEventType event_type_mouse(input_t &input) { inline CGEventType
event_type_mouse(input_t &input) {
auto macos_input = ((macos_input_t *) input.get()); auto macos_input = ((macos_input_t *) input.get());
if (macos_input->mouse_down[0]) { if (macos_input->mouse_down[0]) {
@@ -345,7 +354,8 @@ inline CGEventType event_type_mouse(input_t &input) {
} }
} }
void move_mouse(input_t &input, int deltaX, int deltaY) { void
move_mouse(input_t &input, int deltaX, int deltaY) {
auto current = get_mouse_loc(input); auto current = get_mouse_loc(input);
CGPoint location = CGPointMake(current.x + deltaX, current.y + deltaY); CGPoint location = CGPointMake(current.x + deltaX, current.y + deltaY);
@@ -353,7 +363,8 @@ void move_mouse(input_t &input, int deltaX, int deltaY) {
post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0); post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0);
} }
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { void
abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {
auto scaling = ((macos_input_t *) input.get())->displayScaling; auto scaling = ((macos_input_t *) input.get())->displayScaling;
CGPoint location = CGPointMake(x * scaling, y * scaling); CGPoint location = CGPointMake(x * scaling, y * scaling);
@@ -361,7 +372,8 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y)
post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0); post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0);
} }
uint64_t time_diff(uint64_t start) { uint64_t
time_diff(uint64_t start) {
uint64_t elapsed; uint64_t elapsed;
Nanoseconds elapsedNano; Nanoseconds elapsedNano;
@@ -371,7 +383,8 @@ uint64_t time_diff(uint64_t start) {
return *(uint64_t *) &elapsedNano; return *(uint64_t *) &elapsedNano;
} }
void button_mouse(input_t &input, int button, bool release) { void
button_mouse(input_t &input, int button, bool release) {
CGMouseButton mac_button; CGMouseButton mac_button;
CGEventType event; CGEventType event;
@@ -408,7 +421,8 @@ void button_mouse(input_t &input, int button, bool release) {
mouse->last_mouse_event[mac_button][release] = mach_absolute_time(); mouse->last_mouse_event[mac_button][release] = mach_absolute_time();
} }
void scroll(input_t &input, int high_res_distance) { void
scroll(input_t &input, int high_res_distance) {
CGEventRef upEvent = CGEventCreateScrollWheelEvent( CGEventRef upEvent = CGEventCreateScrollWheelEvent(
NULL, NULL,
kCGScrollEventUnitLine, kCGScrollEventUnitLine,
@@ -417,11 +431,13 @@ void scroll(input_t &input, int high_res_distance) {
CFRelease(upEvent); CFRelease(upEvent);
} }
void hscroll(input_t &input, int high_res_distance) { void
hscroll(input_t &input, int high_res_distance) {
// Unimplemented // Unimplemented
} }
input_t input() { input_t
input() {
input_t result { new macos_input_t() }; input_t result { new macos_input_t() };
auto macos_input = (macos_input_t *) result.get(); auto macos_input = (macos_input_t *) result.get();
@@ -455,7 +471,8 @@ input_t input() {
return result; return result;
} }
void freeInput(void *p) { void
freeInput(void *p) {
auto *input = (macos_input_t *) p; auto *input = (macos_input_t *) p;
CFRelease(input->source); CFRelease(input->source);
@@ -465,7 +482,8 @@ void freeInput(void *p) {
delete input; delete input;
} }
std::vector<std::string_view> &supported_gamepads() { std::vector<std::string_view> &
supported_gamepads() {
static std::vector<std::string_view> gamepads { ""sv }; static std::vector<std::string_view> gamepads { ""sv };
return gamepads; return gamepads;

View File

@@ -14,7 +14,8 @@ struct av_mic_t : public mic_t {
[av_audio_capture release]; [av_audio_capture release];
} }
capture_e sample(std::vector<std::int16_t> &sample_in) override { capture_e
sample(std::vector<std::int16_t> &sample_in) override {
auto sample_size = sample_in.size(); auto sample_size = sample_in.size();
uint32_t length = 0; uint32_t length = 0;
@@ -40,12 +41,14 @@ struct macos_audio_control_t : public audio_control_t {
AVCaptureDevice *audio_capture_device; AVCaptureDevice *audio_capture_device;
public: public:
int set_sink(const std::string &sink) override { int
set_sink(const std::string &sink) override {
BOOST_LOG(warning) << "audio_control_t::set_sink() unimplemented: "sv << sink; BOOST_LOG(warning) << "audio_control_t::set_sink() unimplemented: "sv << sink;
return 0; return 0;
} }
std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override { std::unique_ptr<mic_t>
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override {
auto mic = std::make_unique<av_mic_t>(); auto mic = std::make_unique<av_mic_t>();
const char *audio_sink = ""; const char *audio_sink = "";
@@ -74,14 +77,16 @@ public:
return mic; return mic;
} }
std::optional<sink_t> sink_info() override { std::optional<sink_t>
sink_info() override {
sink_t sink; sink_t sink;
return sink; return sink;
} }
}; };
std::unique_ptr<audio_control_t> audio_control() { std::unique_ptr<audio_control_t>
audio_control() {
return std::make_unique<macos_audio_control_t>(); return std::make_unique<macos_audio_control_t>();
} }
} // namespace platf } // namespace platf

View File

@@ -8,8 +8,10 @@
namespace dyn { namespace dyn {
typedef void (*apiproc)(void); typedef void (*apiproc)(void);
int load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict = true); int
void *handle(const std::vector<const char *> &libs); load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict = true);
void *
handle(const std::vector<const char *> &libs);
} // namespace dyn } // namespace dyn

View File

@@ -23,11 +23,14 @@ namespace platf {
#if __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 // __MAC_11_0 #if __MAC_OS_X_VERSION_MAX_ALLOWED < 110000 // __MAC_11_0
// If they're not in the SDK then we can use our own function definitions. // If they're not in the SDK then we can use our own function definitions.
// Need to use weak import so that this will link in macOS 10.14 and earlier // Need to use weak import so that this will link in macOS 10.14 and earlier
extern "C" bool CGPreflightScreenCaptureAccess(void) __attribute__((weak_import)); extern "C" bool
extern "C" bool CGRequestScreenCaptureAccess(void) __attribute__((weak_import)); CGPreflightScreenCaptureAccess(void) __attribute__((weak_import));
extern "C" bool
CGRequestScreenCaptureAccess(void) __attribute__((weak_import));
#endif #endif
std::unique_ptr<deinit_t> init() { std::unique_ptr<deinit_t>
init() {
// This will generate a warning about CGPreflightScreenCaptureAccess and // This will generate a warning about CGPreflightScreenCaptureAccess and
// CGRequestScreenCaptureAccess being unavailable before macOS 10.15, but // CGRequestScreenCaptureAccess being unavailable before macOS 10.15, but
// we have a guard to prevent it from being called on those earlier systems. // we have a guard to prevent it from being called on those earlier systems.
@@ -55,7 +58,8 @@ std::unique_ptr<deinit_t> init() {
return std::make_unique<deinit_t>(); return std::make_unique<deinit_t>();
} }
fs::path appdata() { fs::path
appdata() {
const char *homedir; const char *homedir;
if ((homedir = getenv("HOME")) == nullptr) { if ((homedir = getenv("HOME")) == nullptr) {
homedir = getpwuid(geteuid())->pw_dir; homedir = getpwuid(geteuid())->pw_dir;
@@ -66,7 +70,8 @@ fs::path appdata() {
using ifaddr_t = util::safe_ptr<ifaddrs, freeifaddrs>; using ifaddr_t = util::safe_ptr<ifaddrs, freeifaddrs>;
ifaddr_t get_ifaddrs() { ifaddr_t
get_ifaddrs() {
ifaddrs *p { nullptr }; ifaddrs *p { nullptr };
getifaddrs(&p); getifaddrs(&p);
@@ -74,7 +79,8 @@ ifaddr_t get_ifaddrs() {
return ifaddr_t { p }; return ifaddr_t { p };
} }
std::string from_sockaddr(const sockaddr *const ip_addr) { std::string
from_sockaddr(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family; auto family = ip_addr->sa_family;
@@ -91,7 +97,8 @@ std::string from_sockaddr(const sockaddr *const ip_addr) {
return std::string { data }; return std::string { data };
} }
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_addr) { std::pair<std::uint16_t, std::string>
from_sockaddr_ex(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family; auto family = ip_addr->sa_family;
@@ -111,7 +118,8 @@ std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_
return { port, std::string { data } }; return { port, std::string { data } };
} }
std::string get_mac_address(const std::string_view &address) { std::string
get_mac_address(const std::string_view &address) {
auto ifaddrs = get_ifaddrs(); auto ifaddrs = get_ifaddrs();
for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) { for (auto pos = ifaddrs.get(); pos != nullptr; pos = pos->ifa_next) {
@@ -149,7 +157,8 @@ std::string get_mac_address(const std::string_view &address) {
return "00:00:00:00:00:00"s; return "00:00:00:00:00:00"s;
} }
bp::child run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { bp::child
run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) {
BOOST_LOG(warning) << "run_unprivileged() is not yet implemented for this platform. The new process will run with Sunshine's permissions."sv; BOOST_LOG(warning) << "run_unprivileged() is not yet implemented for this platform. The new process will run with Sunshine's permissions."sv;
if (!group) { if (!group) {
if (!file) { if (!file) {
@@ -169,34 +178,41 @@ bp::child run_unprivileged(const std::string &cmd, boost::filesystem::path &work
} }
} }
void adjust_thread_priority(thread_priority_e priority) { void
adjust_thread_priority(thread_priority_e priority) {
// Unimplemented // Unimplemented
} }
void streaming_will_start() { void
streaming_will_start() {
// Nothing to do // Nothing to do
} }
void streaming_will_stop() { void
streaming_will_stop() {
// Nothing to do // Nothing to do
} }
bool restart_supported() { bool
restart_supported() {
// Restart not supported yet // Restart not supported yet
return false; return false;
} }
bool restart() { bool
restart() {
// Restart not supported yet // Restart not supported yet
return false; return false;
} }
bool send_batch(batched_send_info_t &send_info) { bool
send_batch(batched_send_info_t &send_info) {
// Fall back to unbatched send calls // Fall back to unbatched send calls
return false; return false;
} }
std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type) { std::unique_ptr<deinit_t>
enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type) {
// Unimplemented // Unimplemented
// //
// NB: When implementing, remember to consider that some routes can drop DSCP-tagged packets completely! // NB: When implementing, remember to consider that some routes can drop DSCP-tagged packets completely!
@@ -206,7 +222,8 @@ std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, boost::asio
} // namespace platf } // namespace platf
namespace dyn { namespace dyn {
void *handle(const std::vector<const char *> &libs) { void *
handle(const std::vector<const char *> &libs) {
void *handle; void *handle;
for (auto lib : libs) { for (auto lib : libs) {
@@ -229,7 +246,8 @@ void *handle(const std::vector<const char *> &libs) {
return nullptr; return nullptr;
} }
int load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict) { int
load(void *handle, const std::vector<std::tuple<apiproc *, const char *>> &funcs, bool strict) {
int err = 0; int err = 0;
for (auto &func : funcs) { for (auto &func : funcs) {
TUPLE_2D_REF(fn, name, func); TUPLE_2D_REF(fn, name, func);

View File

@@ -9,13 +9,15 @@ extern "C" {
namespace platf { namespace platf {
void free_frame(AVFrame *frame) { void
free_frame(AVFrame *frame) {
av_frame_free(&frame); av_frame_free(&frame);
} }
util::safe_ptr<AVFrame, free_frame> av_frame; util::safe_ptr<AVFrame, free_frame> av_frame;
int nv12_zero_device::convert(platf::img_t &img) { int
nv12_zero_device::convert(platf::img_t &img) {
av_frame_make_writable(av_frame.get()); av_frame_make_writable(av_frame.get());
av_img_t *av_img = (av_img_t *) &img; av_img_t *av_img = (av_img_t *) &img;
@@ -53,7 +55,8 @@ int nv12_zero_device::convert(platf::img_t &img) {
return result > 0 ? 0 : -1; return result > 0 ? 0 : -1;
} }
int nv12_zero_device::set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) { int
nv12_zero_device::set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) {
this->frame = frame; this->frame = frame;
av_frame.reset(frame); av_frame.reset(frame);
@@ -63,10 +66,12 @@ int nv12_zero_device::set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) {
return 0; return 0;
} }
void nv12_zero_device::set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) { void
nv12_zero_device::set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) {
} }
int nv12_zero_device::init(void *display, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn) { int
nv12_zero_device::init(void *display, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn) {
pixel_format_fn(display, '420v'); pixel_format_fn(display, '420v');
this->display = display; this->display = display;

View File

@@ -17,11 +17,15 @@ public:
resolution_fn_t resolution_fn; resolution_fn_t resolution_fn;
using pixel_format_fn_t = std::function<void(void *display, int pixelFormat)>; using pixel_format_fn_t = std::function<void(void *display, int pixelFormat)>;
int init(void *display, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn); int
init(void *display, resolution_fn_t resolution_fn, pixel_format_fn_t pixel_format_fn);
int convert(img_t &img); int
int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx); convert(img_t &img);
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range); int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx);
void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range);
}; };
} // namespace platf } // namespace platf

View File

@@ -195,8 +195,8 @@ simple_poll_quit_fn simple_poll_quit;
simple_poll_new_fn simple_poll_new; simple_poll_new_fn simple_poll_new;
simple_poll_free_fn simple_poll_free; simple_poll_free_fn simple_poll_free;
int
int init_common() { init_common() {
static void *handle { nullptr }; static void *handle { nullptr };
static bool funcs_loaded = false; static bool funcs_loaded = false;
@@ -229,7 +229,8 @@ int init_common() {
return 0; return 0;
} }
int init_client() { int
init_client() {
if (init_common()) { if (init_common()) {
return -1; return -1;
} }
@@ -270,7 +271,8 @@ int init_client() {
namespace platf::publish { namespace platf::publish {
template <class T> template <class T>
void free(T *p) { void
free(T *p) {
avahi::free(p); avahi::free(p);
} }
@@ -286,9 +288,11 @@ client_t client;
ptr_t<char> name; ptr_t<char> name;
void create_services(avahi::Client *c); void
create_services(avahi::Client *c);
void entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, void *) { void
entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, void *) {
group = g; group = g;
switch (state) { switch (state) {
@@ -311,7 +315,8 @@ void entry_group_callback(avahi::EntryGroup *g, avahi::EntryGroupState state, vo
} }
} }
void create_services(avahi::Client *c) { void
create_services(avahi::Client *c) {
int ret; int ret;
auto fg = util::fail_guard([]() { auto fg = util::fail_guard([]() {
@@ -366,7 +371,8 @@ void create_services(avahi::Client *c) {
fg.disable(); fg.disable();
} }
void client_callback(avahi::Client *c, avahi::ClientState state, void *) { void
client_callback(avahi::Client *c, avahi::ClientState state, void *) {
switch (state) { switch (state) {
case avahi::CLIENT_S_RUNNING: case avahi::CLIENT_S_RUNNING:
create_services(c); create_services(c);
@@ -388,7 +394,8 @@ class deinit_t : public ::platf::deinit_t {
public: public:
std::thread poll_thread; std::thread poll_thread;
deinit_t(std::thread poll_thread) : poll_thread { std::move(poll_thread) } {} deinit_t(std::thread poll_thread):
poll_thread { std::move(poll_thread) } {}
~deinit_t() override { ~deinit_t() override {
if (avahi::simple_poll_quit && poll) { if (avahi::simple_poll_quit && poll) {
@@ -401,7 +408,8 @@ public:
} }
}; };
[[nodiscard]] std::unique_ptr<::platf::deinit_t> start() { [[nodiscard]] std::unique_ptr<::platf::deinit_t>
start() {
if (avahi::init_client()) { if (avahi::init_client()) {
return nullptr; return nullptr;
} }

View File

@@ -6,7 +6,6 @@
// http://eretik.omegahg.com/ // http://eretik.omegahg.com/
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#pragma once #pragma once
#ifdef __MINGW32__ #ifdef __MINGW32__
@@ -39,11 +38,13 @@ class DECLSPEC_UUID("870af99c-171d-4f9e-af0d-e63df40c2bc9") CPolicyConfigClient;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
interface IPolicyConfig: public IUnknown { interface IPolicyConfig: public IUnknown {
public: public:
virtual HRESULT GetMixFormat( virtual HRESULT
GetMixFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX **); WAVEFORMATEX **);
virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE
GetDeviceFormat(
PCWSTR, PCWSTR,
INT, INT,
WAVEFORMATEX **); WAVEFORMATEX **);
@@ -51,7 +52,8 @@ public:
virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE ResetDeviceFormat(
PCWSTR); PCWSTR);
virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE
SetDeviceFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX *, WAVEFORMATEX *,
WAVEFORMATEX *); WAVEFORMATEX *);
@@ -66,25 +68,30 @@ public:
PCWSTR, PCWSTR,
PINT64); PINT64);
virtual HRESULT STDMETHODCALLTYPE GetShareMode( virtual HRESULT STDMETHODCALLTYPE
GetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); struct DeviceShareMode *);
virtual HRESULT STDMETHODCALLTYPE SetShareMode( virtual HRESULT STDMETHODCALLTYPE
SetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); struct DeviceShareMode *);
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( virtual HRESULT STDMETHODCALLTYPE
GetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( virtual HRESULT STDMETHODCALLTYPE
SetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( virtual HRESULT STDMETHODCALLTYPE
SetDefaultEndpoint(
PCWSTR wszDeviceId, PCWSTR wszDeviceId,
ERole eRole); ERole eRole);
@@ -110,16 +117,19 @@ class DECLSPEC_UUID("294935CE-F637-4E7C-A41B-AB255460B862") CPolicyConfigVistaCl
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
interface IPolicyConfigVista: public IUnknown { interface IPolicyConfigVista: public IUnknown {
public: public:
virtual HRESULT GetMixFormat( virtual HRESULT
GetMixFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX **); // not available on Windows 7, use method from IPolicyConfig WAVEFORMATEX **); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE
GetDeviceFormat(
PCWSTR, PCWSTR,
INT, INT,
WAVEFORMATEX **); WAVEFORMATEX **);
virtual HRESULT STDMETHODCALLTYPE SetDeviceFormat( virtual HRESULT STDMETHODCALLTYPE
SetDeviceFormat(
PCWSTR, PCWSTR,
WAVEFORMATEX *, WAVEFORMATEX *,
WAVEFORMATEX *); WAVEFORMATEX *);
@@ -134,25 +144,30 @@ public:
PCWSTR, PCWSTR,
PINT64); // not available on Windows 7, use method from IPolicyConfig PINT64); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetShareMode( virtual HRESULT STDMETHODCALLTYPE
GetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE SetShareMode( virtual HRESULT STDMETHODCALLTYPE
SetShareMode(
PCWSTR, PCWSTR,
struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig struct DeviceShareMode *); // not available on Windows 7, use method from IPolicyConfig
virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( virtual HRESULT STDMETHODCALLTYPE
GetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetPropertyValue( virtual HRESULT STDMETHODCALLTYPE
SetPropertyValue(
PCWSTR, PCWSTR,
const PROPERTYKEY &, const PROPERTYKEY &,
PROPVARIANT *); PROPVARIANT *);
virtual HRESULT STDMETHODCALLTYPE SetDefaultEndpoint( virtual HRESULT STDMETHODCALLTYPE
SetDefaultEndpoint(
PCWSTR wszDeviceId, PCWSTR wszDeviceId,
ERole eRole); ERole eRole);

View File

@@ -37,12 +37,14 @@ namespace platf::audio {
constexpr auto SAMPLE_RATE = 48000; constexpr auto SAMPLE_RATE = 48000;
template <class T> template <class T>
void Release(T *p) { void
Release(T *p) {
p->Release(); p->Release();
} }
template <class T> template <class T>
void co_task_free(T *p) { void
co_task_free(T *p) {
CoTaskMemFree((LPVOID) p); CoTaskMemFree((LPVOID) p);
} }
@@ -138,7 +140,8 @@ static format_t surround_51_side_speakers {
SPEAKER_SIDE_RIGHT, SPEAKER_SIDE_RIGHT,
}; };
WAVEFORMATEXTENSIBLE create_wave_format(const format_t &format) { WAVEFORMATEXTENSIBLE
create_wave_format(const format_t &format) {
WAVEFORMATEXTENSIBLE wave_format; WAVEFORMATEXTENSIBLE wave_format;
wave_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; wave_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
@@ -156,7 +159,8 @@ WAVEFORMATEXTENSIBLE create_wave_format(const format_t &format) {
return wave_format; return wave_format;
} }
int set_wave_format(audio::wave_format_t &wave_format, const format_t &format) { int
set_wave_format(audio::wave_format_t &wave_format, const format_t &format) {
wave_format->nSamplesPerSec = SAMPLE_RATE; wave_format->nSamplesPerSec = SAMPLE_RATE;
wave_format->wBitsPerSample = 16; wave_format->wBitsPerSample = 16;
@@ -184,7 +188,8 @@ int set_wave_format(audio::wave_format_t &wave_format, const format_t &format) {
return 0; return 0;
} }
audio_client_t make_audio_client(device_t &device, const format_t &format) { audio_client_t
make_audio_client(device_t &device, const format_t &format) {
audio_client_t audio_client; audio_client_t audio_client;
auto status = device->Activate( auto status = device->Activate(
IID_IAudioClient, IID_IAudioClient,
@@ -216,11 +221,13 @@ audio_client_t make_audio_client(device_t &device, const format_t &format) {
return audio_client; return audio_client;
} }
const wchar_t *no_null(const wchar_t *str) { const wchar_t *
no_null(const wchar_t *str) {
return str ? str : L"Unknown"; return str ? str : L"Unknown";
} }
bool validate_device(device_t &device) { bool
validate_device(device_t &device) {
bool valid = false; bool valid = false;
// Check for any valid format // Check for any valid format
@@ -237,7 +244,8 @@ bool validate_device(device_t &device) {
return valid; return valid;
} }
device_t default_device(device_enum_t &device_enum) { device_t
default_device(device_enum_t &device_enum) {
device_t device; device_t device;
HRESULT status; HRESULT status;
status = device_enum->GetDefaultAudioEndpoint( status = device_enum->GetDefaultAudioEndpoint(
@@ -245,7 +253,6 @@ device_t default_device(device_enum_t &device_enum) {
eConsole, eConsole,
&device); &device);
if (FAILED(status)) { if (FAILED(status)) {
BOOST_LOG(error) << "Couldn't create audio Device [0x"sv << util::hex(status).to_string_view() << ']'; BOOST_LOG(error) << "Couldn't create audio Device [0x"sv << util::hex(status).to_string_view() << ']';
@@ -257,7 +264,8 @@ device_t default_device(device_enum_t &device_enum) {
class mic_wasapi_t: public mic_t { class mic_wasapi_t: public mic_t {
public: public:
capture_e sample(std::vector<std::int16_t> &sample_out) override { capture_e
sample(std::vector<std::int16_t> &sample_out) override {
auto sample_size = sample_out.size(); auto sample_size = sample_out.size();
// Refill the sample buffer if needed // Refill the sample buffer if needed
@@ -278,8 +286,8 @@ public:
return capture_e::ok; return capture_e::ok;
} }
int
int init(std::uint32_t sample_rate, std::uint32_t frame_size, std::uint32_t channels_out) { init(std::uint32_t sample_rate, std::uint32_t frame_size, std::uint32_t channels_out) {
audio_event.reset(CreateEventA(nullptr, FALSE, FALSE, nullptr)); audio_event.reset(CreateEventA(nullptr, FALSE, FALSE, nullptr));
if (!audio_event) { if (!audio_event) {
BOOST_LOG(error) << "Couldn't create Event handle"sv; BOOST_LOG(error) << "Couldn't create Event handle"sv;
@@ -375,7 +383,8 @@ public:
} }
private: private:
capture_e _fill_buffer() { capture_e
_fill_buffer() {
HRESULT status; HRESULT status;
// Total number of samples // Total number of samples
@@ -465,7 +474,8 @@ public:
class audio_control_t: public ::platf::audio_control_t { class audio_control_t: public ::platf::audio_control_t {
public: public:
std::optional<sink_t> sink_info() override { std::optional<sink_t>
sink_info() override {
auto virtual_adapter_name = L"Steam Streaming Speakers"sv; auto virtual_adapter_name = L"Steam Streaming Speakers"sv;
sink_t sink; sink_t sink;
@@ -553,7 +563,8 @@ public:
return sink; return sink;
} }
std::unique_ptr<mic_t> microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override { std::unique_ptr<mic_t>
microphone(const std::uint8_t *mapping, int channels, std::uint32_t sample_rate, std::uint32_t frame_size) override {
auto mic = std::make_unique<mic_wasapi_t>(); auto mic = std::make_unique<mic_wasapi_t>();
if (mic->init(sample_rate, frame_size, channels)) { if (mic->init(sample_rate, frame_size, channels)) {
@@ -571,7 +582,8 @@ public:
* virtual-(format name) * virtual-(format name)
* If it doesn't contain that prefix, then the format will not be changed * If it doesn't contain that prefix, then the format will not be changed
*/ */
std::optional<std::wstring> set_format(const std::string &sink) { std::optional<std::wstring>
set_format(const std::string &sink) {
std::string_view sv { sink.c_str(), sink.size() }; std::string_view sv { sink.c_str(), sink.size() };
format_t::type_e type = format_t::none; format_t::type_e type = format_t::none;
@@ -628,7 +640,8 @@ public:
return std::make_optional(std::move(wstring_device_id)); return std::make_optional(std::move(wstring_device_id));
} }
int set_sink(const std::string &sink) override { int
set_sink(const std::string &sink) override {
auto wstring_device_id = set_format(sink); auto wstring_device_id = set_format(sink);
if (!wstring_device_id) { if (!wstring_device_id) {
return -1; return -1;
@@ -647,7 +660,8 @@ public:
return failure; return failure;
} }
int init() { int
init() {
auto status = CoCreateInstance( auto status = CoCreateInstance(
CLSID_CPolicyConfigClient, CLSID_CPolicyConfigClient,
nullptr, nullptr,
@@ -674,10 +688,12 @@ namespace platf {
// It's not big enough to justify it's own source file :/ // It's not big enough to justify it's own source file :/
namespace dxgi { namespace dxgi {
int init(); int
init();
} }
std::unique_ptr<audio_control_t> audio_control() { std::unique_ptr<audio_control_t>
audio_control() {
auto control = std::make_unique<audio::audio_control_t>(); auto control = std::make_unique<audio::audio_control_t>();
if (control->init()) { if (control->init()) {
@@ -687,7 +703,8 @@ std::unique_ptr<audio_control_t> audio_control() {
return control; return control;
} }
std::unique_ptr<deinit_t> init() { std::unique_ptr<deinit_t>
init() {
if (dxgi::init()) { if (dxgi::init()) {
return nullptr; return nullptr;
} }

View File

@@ -23,7 +23,8 @@ extern const char *format_str[];
auto constexpr D3D11_CREATE_DEVICE_FLAGS = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; auto constexpr D3D11_CREATE_DEVICE_FLAGS = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
template <class T> template <class T>
void Release(T *dxgi) { void
Release(T *dxgi) {
dxgi->Release(); dxgi->Release();
} }
@@ -78,15 +79,18 @@ struct cursor_t {
class gpu_cursor_t { class gpu_cursor_t {
public: public:
gpu_cursor_t() : cursor_view { 0, 0, 0, 0, 0.0f, 1.0f } {}; gpu_cursor_t():
void set_pos(LONG rel_x, LONG rel_y, bool visible) { cursor_view { 0, 0, 0, 0, 0.0f, 1.0f } {};
void
set_pos(LONG rel_x, LONG rel_y, bool visible) {
cursor_view.TopLeftX = rel_x; cursor_view.TopLeftX = rel_x;
cursor_view.TopLeftY = rel_y; cursor_view.TopLeftY = rel_y;
this->visible = visible; this->visible = visible;
} }
void set_texture(LONG width, LONG height, texture2d_t &&texture) { void
set_texture(LONG width, LONG height, texture2d_t &&texture) {
cursor_view.Width = width; cursor_view.Width = width;
cursor_view.Height = height; cursor_view.Height = height;
@@ -107,17 +111,22 @@ public:
bool has_frame {}; bool has_frame {};
bool use_dwmflush {}; bool use_dwmflush {};
capture_e next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p); capture_e
capture_e reset(dup_t::pointer dup_p = dup_t::pointer()); next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p);
capture_e release_frame(); capture_e
reset(dup_t::pointer dup_p = dup_t::pointer());
capture_e
release_frame();
~duplication_t(); ~duplication_t();
}; };
class display_base_t: public display_t { class display_base_t: public display_t {
public: public:
int init(const ::video::config_t &config, const std::string &display_name); int
capture_e capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override; init(const ::video::config_t &config, const std::string &display_name);
capture_e
capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<img_t> img, bool *cursor) override;
std::chrono::nanoseconds delay; std::chrono::nanoseconds delay;
@@ -142,34 +151,50 @@ public:
typedef NTSTATUS WINAPI (*PD3DKMTSetProcessSchedulingPriorityClass)(HANDLE, D3DKMT_SCHEDULINGPRIORITYCLASS); typedef NTSTATUS WINAPI (*PD3DKMTSetProcessSchedulingPriorityClass)(HANDLE, D3DKMT_SCHEDULINGPRIORITYCLASS);
virtual bool is_hdr() override; virtual bool
virtual bool get_hdr_metadata(SS_HDR_METADATA &metadata) override; is_hdr() override;
virtual bool
get_hdr_metadata(SS_HDR_METADATA &metadata) override;
protected: protected:
int get_pixel_pitch() { int
get_pixel_pitch() {
return (capture_format == DXGI_FORMAT_R16G16B16A16_FLOAT) ? 8 : 4; return (capture_format == DXGI_FORMAT_R16G16B16A16_FLOAT) ? 8 : 4;
} }
const char *dxgi_format_to_string(DXGI_FORMAT format); const char *
const char *colorspace_to_string(DXGI_COLOR_SPACE_TYPE type); dxgi_format_to_string(DXGI_FORMAT format);
const char *
colorspace_to_string(DXGI_COLOR_SPACE_TYPE type);
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) = 0; virtual capture_e
virtual int complete_img(img_t *img, bool dummy) = 0; snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) = 0;
virtual std::vector<DXGI_FORMAT> get_supported_sdr_capture_formats() = 0; virtual int
virtual std::vector<DXGI_FORMAT> get_supported_hdr_capture_formats() = 0; complete_img(img_t *img, bool dummy) = 0;
virtual std::vector<DXGI_FORMAT>
get_supported_sdr_capture_formats() = 0;
virtual std::vector<DXGI_FORMAT>
get_supported_hdr_capture_formats() = 0;
}; };
class display_ram_t: public display_base_t { class display_ram_t: public display_base_t {
public: public:
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override; virtual capture_e
snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override;
std::shared_ptr<img_t> alloc_img() override; std::shared_ptr<img_t>
int dummy_img(img_t *img) override; alloc_img() override;
int complete_img(img_t *img, bool dummy) override; int
std::vector<DXGI_FORMAT> get_supported_sdr_capture_formats() override; dummy_img(img_t *img) override;
std::vector<DXGI_FORMAT> get_supported_hdr_capture_formats() override; int
complete_img(img_t *img, bool dummy) override;
std::vector<DXGI_FORMAT>
get_supported_sdr_capture_formats() override;
std::vector<DXGI_FORMAT>
get_supported_hdr_capture_formats() override;
int init(const ::video::config_t &config, const std::string &display_name); int
init(const ::video::config_t &config, const std::string &display_name);
cursor_t cursor; cursor_t cursor;
D3D11_MAPPED_SUBRESOURCE img_info; D3D11_MAPPED_SUBRESOURCE img_info;
@@ -178,17 +203,25 @@ public:
class display_vram_t: public display_base_t, public std::enable_shared_from_this<display_vram_t> { class display_vram_t: public display_base_t, public std::enable_shared_from_this<display_vram_t> {
public: public:
virtual capture_e snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override; virtual capture_e
snapshot(img_t *img, std::chrono::milliseconds timeout, bool cursor_visible) override;
std::shared_ptr<img_t> alloc_img() override; std::shared_ptr<img_t>
int dummy_img(img_t *img_base) override; alloc_img() override;
int complete_img(img_t *img_base, bool dummy) override; int
std::vector<DXGI_FORMAT> get_supported_sdr_capture_formats() override; dummy_img(img_t *img_base) override;
std::vector<DXGI_FORMAT> get_supported_hdr_capture_formats() override; int
complete_img(img_t *img_base, bool dummy) override;
std::vector<DXGI_FORMAT>
get_supported_sdr_capture_formats() override;
std::vector<DXGI_FORMAT>
get_supported_hdr_capture_formats() override;
int init(const ::video::config_t &config, const std::string &display_name); int
init(const ::video::config_t &config, const std::string &display_name);
std::shared_ptr<platf::hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) override; std::shared_ptr<platf::hwdevice_t>
make_hwdevice(pix_fmt_e pix_fmt) override;
sampler_state_t sampler_linear; sampler_state_t sampler_linear;

View File

@@ -25,7 +25,8 @@ using namespace std::literals;
namespace platf::dxgi { namespace platf::dxgi {
namespace bp = boost::process; namespace bp = boost::process;
capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p) { capture_e
duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p) {
auto capture_status = release_frame(); auto capture_status = release_frame();
if (capture_status != capture_e::ok) { if (capture_status != capture_e::ok) {
return capture_status; return capture_status;
@@ -53,7 +54,8 @@ capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::ch
} }
} }
capture_e duplication_t::reset(dup_t::pointer dup_p) { capture_e
duplication_t::reset(dup_t::pointer dup_p) {
auto capture_status = release_frame(); auto capture_status = release_frame();
dup.reset(dup_p); dup.reset(dup_p);
@@ -61,7 +63,8 @@ capture_e duplication_t::reset(dup_t::pointer dup_p) {
return capture_status; return capture_status;
} }
capture_e duplication_t::release_frame() { capture_e
duplication_t::release_frame() {
if (!has_frame) { if (!has_frame) {
return capture_e::ok; return capture_e::ok;
} }
@@ -88,7 +91,8 @@ duplication_t::~duplication_t() {
release_frame(); release_frame();
} }
capture_e display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) { capture_e
display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<::platf::img_t> img, bool *cursor) {
auto next_frame = std::chrono::steady_clock::now(); auto next_frame = std::chrono::steady_clock::now();
// Use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if supported (Windows 10 1809+) // Use CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if supported (Windows 10 1809+)
@@ -151,7 +155,8 @@ capture_e display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<:
return capture_e::ok; return capture_e::ok;
} }
bool set_gpu_preference_on_self(int preference) { bool
set_gpu_preference_on_self(int preference) {
// The GPU preferences key uses app path as the value name. // The GPU preferences key uses app path as the value name.
WCHAR sunshine_path[MAX_PATH]; WCHAR sunshine_path[MAX_PATH];
GetModuleFileNameW(NULL, sunshine_path, ARRAYSIZE(sunshine_path)); GetModuleFileNameW(NULL, sunshine_path, ARRAYSIZE(sunshine_path));
@@ -184,7 +189,8 @@ bool set_gpu_preference_on_self(int preference) {
// (even if you try sneaky stuff like passing the ID3D11Device for the iGPU and the // (even if you try sneaky stuff like passing the ID3D11Device for the iGPU and the
// virtual DXGIOutput from the dGPU). Because the GPU preference is once-per-process, // virtual DXGIOutput from the dGPU). Because the GPU preference is once-per-process,
// we spawn a helper tool to probe for us before we set our own GPU preference. // we spawn a helper tool to probe for us before we set our own GPU preference.
bool probe_for_gpu_preference(const std::string &display_name) { bool
probe_for_gpu_preference(const std::string &display_name) {
// If we've already been through here, there's nothing to do this time. // If we've already been through here, there's nothing to do this time.
static bool set_gpu_preference = false; static bool set_gpu_preference = false;
if (set_gpu_preference) { if (set_gpu_preference) {
@@ -235,7 +241,8 @@ bool probe_for_gpu_preference(const std::string &display_name) {
return false; return false;
} }
bool test_dxgi_duplication(adapter_t &adapter, output_t &output) { bool
test_dxgi_duplication(adapter_t &adapter, output_t &output) {
D3D_FEATURE_LEVEL featureLevels[] { D3D_FEATURE_LEVEL featureLevels[] {
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_0,
@@ -283,7 +290,8 @@ bool test_dxgi_duplication(adapter_t &adapter, output_t &output) {
return false; return false;
} }
int display_base_t::init(const ::video::config_t &config, const std::string &display_name) { int
display_base_t::init(const ::video::config_t &config, const std::string &display_name) {
std::once_flag windows_cpp_once_flag; std::once_flag windows_cpp_once_flag;
std::call_once(windows_cpp_once_flag, []() { std::call_once(windows_cpp_once_flag, []() {
@@ -588,7 +596,8 @@ int display_base_t::init(const ::video::config_t &config, const std::string &dis
return 0; return 0;
} }
bool display_base_t::is_hdr() { bool
display_base_t::is_hdr() {
dxgi::output6_t output6 {}; dxgi::output6_t output6 {};
auto status = output->QueryInterface(IID_IDXGIOutput6, (void **) &output6); auto status = output->QueryInterface(IID_IDXGIOutput6, (void **) &output6);
@@ -603,7 +612,8 @@ bool display_base_t::is_hdr() {
return desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; return desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
} }
bool display_base_t::get_hdr_metadata(SS_HDR_METADATA &metadata) { bool
display_base_t::get_hdr_metadata(SS_HDR_METADATA &metadata) {
dxgi::output6_t output6 {}; dxgi::output6_t output6 {};
std::memset(&metadata, 0, sizeof(metadata)); std::memset(&metadata, 0, sizeof(metadata));
@@ -781,11 +791,13 @@ const char *format_str[] = {
"DXGI_FORMAT_V408" "DXGI_FORMAT_V408"
}; };
const char *display_base_t::dxgi_format_to_string(DXGI_FORMAT format) { const char *
display_base_t::dxgi_format_to_string(DXGI_FORMAT format) {
return format_str[format]; return format_str[format];
} }
const char *display_base_t::colorspace_to_string(DXGI_COLOR_SPACE_TYPE type) { const char *
display_base_t::colorspace_to_string(DXGI_COLOR_SPACE_TYPE type) {
const char *type_str[] = { const char *type_str[] = {
"DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709", "DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709",
"DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709", "DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709",
@@ -825,7 +837,8 @@ const char *display_base_t::colorspace_to_string(DXGI_COLOR_SPACE_TYPE type) {
} // namespace platf::dxgi } // namespace platf::dxgi
namespace platf { namespace platf {
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) { std::shared_ptr<display_t>
display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
if (hwdevice_type == mem_type_e::dxgi) { if (hwdevice_type == mem_type_e::dxgi) {
auto disp = std::make_shared<dxgi::display_vram_t>(); auto disp = std::make_shared<dxgi::display_vram_t>();
@@ -844,7 +857,8 @@ std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &
return nullptr; return nullptr;
} }
std::vector<std::string> display_names(mem_type_e) { std::vector<std::string>
display_names(mem_type_e) {
std::vector<std::string> display_names; std::vector<std::string> display_names;
HRESULT status; HRESULT status;

View File

@@ -13,7 +13,8 @@ struct img_t : public ::platf::img_t {
} }
}; };
void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) { void
blend_cursor_monochrome(const cursor_t &cursor, img_t &img) {
int height = cursor.shape_info.Height / 2; int height = cursor.shape_info.Height / 2;
int width = cursor.shape_info.Width; int width = cursor.shape_info.Width;
int pitch = cursor.shape_info.Pitch; int pitch = cursor.shape_info.Pitch;
@@ -75,7 +76,8 @@ void blend_cursor_monochrome(const cursor_t &cursor, img_t &img) {
} }
} }
void apply_color_alpha(int *img_pixel_p, int cursor_pixel) { void
apply_color_alpha(int *img_pixel_p, int cursor_pixel) {
auto colors_out = (std::uint8_t *) &cursor_pixel; auto colors_out = (std::uint8_t *) &cursor_pixel;
auto colors_in = (std::uint8_t *) img_pixel_p; auto colors_in = (std::uint8_t *) img_pixel_p;
@@ -91,7 +93,8 @@ void apply_color_alpha(int *img_pixel_p, int cursor_pixel) {
} }
} }
void apply_color_masked(int *img_pixel_p, int cursor_pixel) { void
apply_color_masked(int *img_pixel_p, int cursor_pixel) {
//TODO: When use of IDXGIOutput5 is implemented, support different color formats //TODO: When use of IDXGIOutput5 is implemented, support different color formats
auto alpha = ((std::uint8_t *) &cursor_pixel)[3]; auto alpha = ((std::uint8_t *) &cursor_pixel)[3];
if (alpha == 0xFF) { if (alpha == 0xFF) {
@@ -102,7 +105,8 @@ void apply_color_masked(int *img_pixel_p, int cursor_pixel) {
} }
} }
void blend_cursor_color(const cursor_t &cursor, img_t &img, const bool masked) { void
blend_cursor_color(const cursor_t &cursor, img_t &img, const bool masked) {
int height = cursor.shape_info.Height; int height = cursor.shape_info.Height;
int width = cursor.shape_info.Width; int width = cursor.shape_info.Width;
int pitch = cursor.shape_info.Pitch; int pitch = cursor.shape_info.Pitch;
@@ -149,7 +153,8 @@ void blend_cursor_color(const cursor_t &cursor, img_t &img, const bool masked) {
} }
} }
void blend_cursor(const cursor_t &cursor, img_t &img) { void
blend_cursor(const cursor_t &cursor, img_t &img) {
switch (cursor.shape_info.Type) { switch (cursor.shape_info.Type) {
case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR: case DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR:
blend_cursor_color(cursor, img, false); blend_cursor_color(cursor, img, false);
@@ -165,7 +170,8 @@ void blend_cursor(const cursor_t &cursor, img_t &img) {
} }
} }
capture_e display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) { capture_e
display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) {
auto img = (img_t *) img_base; auto img = (img_t *) img_base;
HRESULT status; HRESULT status;
@@ -301,7 +307,8 @@ capture_e display_ram_t::snapshot(::platf::img_t *img_base, std::chrono::millise
return capture_e::ok; return capture_e::ok;
} }
std::shared_ptr<platf::img_t> display_ram_t::alloc_img() { std::shared_ptr<platf::img_t>
display_ram_t::alloc_img() {
auto img = std::make_shared<img_t>(); auto img = std::make_shared<img_t>();
// Initialize fields that are format-independent // Initialize fields that are format-independent
@@ -311,7 +318,8 @@ std::shared_ptr<platf::img_t> display_ram_t::alloc_img() {
return img; return img;
} }
int display_ram_t::complete_img(platf::img_t *img, bool dummy) { int
display_ram_t::complete_img(platf::img_t *img, bool dummy) {
// If this is not a dummy image, we must know the format by now // If this is not a dummy image, we must know the format by now
if (!dummy && capture_format == DXGI_FORMAT_UNKNOWN) { if (!dummy && capture_format == DXGI_FORMAT_UNKNOWN) {
BOOST_LOG(error) << "display_ram_t::complete_img() called with unknown capture format!"; BOOST_LOG(error) << "display_ram_t::complete_img() called with unknown capture format!";
@@ -339,7 +347,8 @@ int display_ram_t::complete_img(platf::img_t *img, bool dummy) {
return 0; return 0;
} }
int display_ram_t::dummy_img(platf::img_t *img) { int
display_ram_t::dummy_img(platf::img_t *img) {
if (complete_img(img, true)) { if (complete_img(img, true)) {
return -1; return -1;
} }
@@ -348,16 +357,19 @@ int display_ram_t::dummy_img(platf::img_t *img) {
return 0; return 0;
} }
std::vector<DXGI_FORMAT> display_ram_t::get_supported_sdr_capture_formats() { std::vector<DXGI_FORMAT>
display_ram_t::get_supported_sdr_capture_formats() {
return { DXGI_FORMAT_B8G8R8A8_UNORM }; return { DXGI_FORMAT_B8G8R8A8_UNORM };
} }
std::vector<DXGI_FORMAT> display_ram_t::get_supported_hdr_capture_formats() { std::vector<DXGI_FORMAT>
display_ram_t::get_supported_hdr_capture_formats() {
// HDR is unsupported // HDR is unsupported
return {}; return {};
} }
int display_ram_t::init(const ::video::config_t &config, const std::string &display_name) { int
display_ram_t::init(const ::video::config_t &config, const std::string &display_name) {
if (display_base_t::init(config, display_name)) { if (display_base_t::init(config, display_name)) {
return -1; return -1;
} }

View File

@@ -14,13 +14,13 @@ extern "C" {
#include "src/main.h" #include "src/main.h"
#include "src/video.h" #include "src/video.h"
#define SUNSHINE_SHADERS_DIR SUNSHINE_ASSETS_DIR "/shaders/directx" #define SUNSHINE_SHADERS_DIR SUNSHINE_ASSETS_DIR "/shaders/directx"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;
} }
static void free_frame(AVFrame *frame) { static void
free_frame(AVFrame *frame) {
av_frame_free(&frame); av_frame_free(&frame);
} }
@@ -29,7 +29,8 @@ using frame_t = util::safe_ptr<AVFrame, free_frame>;
namespace platf::dxgi { namespace platf::dxgi {
template <class T> template <class T>
buf_t make_buffer(device_t::pointer device, const T &t) { buf_t
make_buffer(device_t::pointer device, const T &t) {
static_assert(sizeof(T) % 16 == 0, "Buffer needs to be aligned on a 16-byte alignment"); static_assert(sizeof(T) % 16 == 0, "Buffer needs to be aligned on a 16-byte alignment");
D3D11_BUFFER_DESC buffer_desc { D3D11_BUFFER_DESC buffer_desc {
@@ -52,7 +53,8 @@ buf_t make_buffer(device_t::pointer device, const T &t) {
return buf_t { buf_p }; return buf_t { buf_p };
} }
blend_t make_blend(device_t::pointer device, bool enable, bool invert) { blend_t
make_blend(device_t::pointer device, bool enable, bool invert) {
D3D11_BLEND_DESC bdesc {}; D3D11_BLEND_DESC bdesc {};
auto &rt = bdesc.RenderTarget[0]; auto &rt = bdesc.RenderTarget[0];
rt.BlendEnable = enable; rt.BlendEnable = enable;
@@ -121,7 +123,8 @@ struct img_d3d_t : public platf::img_t {
}; };
}; };
util::buffer_t<std::uint8_t> make_cursor_xor_image(const util::buffer_t<std::uint8_t> &img_data, DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info) { util::buffer_t<std::uint8_t>
make_cursor_xor_image(const util::buffer_t<std::uint8_t> &img_data, DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info) {
constexpr std::uint32_t inverted = 0xFFFFFFFF; constexpr std::uint32_t inverted = 0xFFFFFFFF;
constexpr std::uint32_t transparent = 0; constexpr std::uint32_t transparent = 0;
@@ -191,7 +194,8 @@ util::buffer_t<std::uint8_t> make_cursor_xor_image(const util::buffer_t<std::uin
return cursor_img; return cursor_img;
} }
util::buffer_t<std::uint8_t> make_cursor_alpha_image(const util::buffer_t<std::uint8_t> &img_data, DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info) { util::buffer_t<std::uint8_t>
make_cursor_alpha_image(const util::buffer_t<std::uint8_t> &img_data, DXGI_OUTDUPL_POINTER_SHAPE_INFO shape_info) {
constexpr std::uint32_t black = 0xFF000000; constexpr std::uint32_t black = 0xFF000000;
constexpr std::uint32_t white = 0xFFFFFFFF; constexpr std::uint32_t white = 0xFFFFFFFF;
constexpr std::uint32_t transparent = 0; constexpr std::uint32_t transparent = 0;
@@ -265,7 +269,8 @@ util::buffer_t<std::uint8_t> make_cursor_alpha_image(const util::buffer_t<std::u
return cursor_img; return cursor_img;
} }
blob_t compile_shader(LPCSTR file, LPCSTR entrypoint, LPCSTR shader_model) { blob_t
compile_shader(LPCSTR file, LPCSTR entrypoint, LPCSTR shader_model) {
blob_t::pointer msg_p = nullptr; blob_t::pointer msg_p = nullptr;
blob_t::pointer compiled_p; blob_t::pointer compiled_p;
@@ -292,17 +297,20 @@ blob_t compile_shader(LPCSTR file, LPCSTR entrypoint, LPCSTR shader_model) {
return blob_t { compiled_p }; return blob_t { compiled_p };
} }
blob_t compile_pixel_shader(LPCSTR file) { blob_t
compile_pixel_shader(LPCSTR file) {
return compile_shader(file, "main_ps", "ps_5_0"); return compile_shader(file, "main_ps", "ps_5_0");
} }
blob_t compile_vertex_shader(LPCSTR file) { blob_t
compile_vertex_shader(LPCSTR file) {
return compile_shader(file, "main_vs", "vs_5_0"); return compile_shader(file, "main_vs", "vs_5_0");
} }
class hwdevice_t: public platf::hwdevice_t { class hwdevice_t: public platf::hwdevice_t {
public: public:
int convert(platf::img_t &img_base) override { int
convert(platf::img_t &img_base) override {
auto &img = (img_d3d_t &) img_base; auto &img = (img_d3d_t &) img_base;
auto &img_ctx = img_ctx_map[img.id]; auto &img_ctx = img_ctx_map[img.id];
@@ -341,7 +349,8 @@ public:
return 0; return 0;
} }
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override { void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override {
switch (colorspace) { switch (colorspace) {
case 5: // SWS_CS_SMPTE170M case 5: // SWS_CS_SMPTE170M
color_p = &::video::colors[0]; color_p = &::video::colors[0];
@@ -373,7 +382,8 @@ public:
this->color_matrix = std::move(color_matrix); this->color_matrix = std::move(color_matrix);
} }
void init_hwframes(AVHWFramesContext *frames) override { void
init_hwframes(AVHWFramesContext *frames) override {
// We may be called with a QSV or D3D11VA context // We may be called with a QSV or D3D11VA context
if (frames->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { if (frames->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
auto d3d11_frames = (AVD3D11VAFramesContext *) frames->hwctx; auto d3d11_frames = (AVD3D11VAFramesContext *) frames->hwctx;
@@ -387,7 +397,8 @@ public:
frames->initial_pool_size = 1; frames->initial_pool_size = 1;
} }
int prepare_to_derive_context(int hw_device_type) override { int
prepare_to_derive_context(int hw_device_type) override {
// QuickSync requires our device to be multithread-protected // QuickSync requires our device to be multithread-protected
if (hw_device_type == AV_HWDEVICE_TYPE_QSV) { if (hw_device_type == AV_HWDEVICE_TYPE_QSV) {
multithread_t mt; multithread_t mt;
@@ -404,7 +415,8 @@ public:
return 0; return 0;
} }
int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override { int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
this->hwframe.reset(frame); this->hwframe.reset(frame);
this->frame = frame; this->frame = frame;
@@ -498,10 +510,10 @@ public:
return 0; return 0;
} }
int init( int
init(
std::shared_ptr<platf::display_t> display, adapter_t::pointer adapter_p, std::shared_ptr<platf::display_t> display, adapter_t::pointer adapter_p,
pix_fmt_e pix_fmt) { pix_fmt_e pix_fmt) {
D3D_FEATURE_LEVEL featureLevels[] { D3D_FEATURE_LEVEL featureLevels[] {
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_0,
@@ -642,7 +654,8 @@ private:
shader_res_t encoder_input_res; shader_res_t encoder_input_res;
keyed_mutex_t encoder_mutex; keyed_mutex_t encoder_mutex;
void reset() { void
reset() {
capture_texture_p = nullptr; capture_texture_p = nullptr;
encoder_texture.reset(); encoder_texture.reset();
encoder_input_res.reset(); encoder_input_res.reset();
@@ -650,7 +663,8 @@ private:
} }
}; };
int initialize_image_context(const img_d3d_t &img, encoder_img_ctx_t &img_ctx) { int
initialize_image_context(const img_d3d_t &img, encoder_img_ctx_t &img_ctx) {
// If we've already opened the shared texture, we're done // If we've already opened the shared texture, we're done
if (img_ctx.encoder_texture && img.capture_texture.get() == img_ctx.capture_texture_p) { if (img_ctx.encoder_texture && img.capture_texture.get() == img_ctx.capture_texture_p) {
return 0; return 0;
@@ -733,7 +747,8 @@ public:
device_ctx_t device_ctx; device_ctx_t device_ctx;
}; };
bool set_cursor_texture(device_t::pointer device, gpu_cursor_t &cursor, util::buffer_t<std::uint8_t> &&cursor_img, DXGI_OUTDUPL_POINTER_SHAPE_INFO &shape_info) { bool
set_cursor_texture(device_t::pointer device, gpu_cursor_t &cursor, util::buffer_t<std::uint8_t> &&cursor_img, DXGI_OUTDUPL_POINTER_SHAPE_INFO &shape_info) {
// This cursor image may not be used // This cursor image may not be used
if (cursor_img.size() == 0) { if (cursor_img.size() == 0) {
cursor.input_res.reset(); cursor.input_res.reset();
@@ -777,7 +792,8 @@ bool set_cursor_texture(device_t::pointer device, gpu_cursor_t &cursor, util::bu
return true; return true;
} }
capture_e display_vram_t::snapshot(platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) { capture_e
display_vram_t::snapshot(platf::img_t *img_base, std::chrono::milliseconds timeout, bool cursor_visible) {
auto img = (img_d3d_t *) img_base; auto img = (img_d3d_t *) img_base;
HRESULT status; HRESULT status;
@@ -965,7 +981,8 @@ capture_e display_vram_t::snapshot(platf::img_t *img_base, std::chrono::millisec
return capture_e::ok; return capture_e::ok;
} }
int display_vram_t::init(const ::video::config_t &config, const std::string &display_name) { int
display_vram_t::init(const ::video::config_t &config, const std::string &display_name) {
if (display_base_t::init(config, display_name)) { if (display_base_t::init(config, display_name)) {
return -1; return -1;
} }
@@ -1034,7 +1051,8 @@ int display_vram_t::init(const ::video::config_t &config, const std::string &dis
return 0; return 0;
} }
std::shared_ptr<platf::img_t> display_vram_t::alloc_img() { std::shared_ptr<platf::img_t>
display_vram_t::alloc_img() {
auto img = std::make_shared<img_d3d_t>(); auto img = std::make_shared<img_d3d_t>();
// Initialize format-independent fields // Initialize format-independent fields
@@ -1047,7 +1065,8 @@ std::shared_ptr<platf::img_t> display_vram_t::alloc_img() {
} }
// This cannot use ID3D11DeviceContext because it can be called concurrently by the encoding thread // This cannot use ID3D11DeviceContext because it can be called concurrently by the encoding thread
int display_vram_t::complete_img(platf::img_t *img_base, bool dummy) { int
display_vram_t::complete_img(platf::img_t *img_base, bool dummy) {
auto img = (img_d3d_t *) img_base; auto img = (img_d3d_t *) img_base;
// If this already has a capture texture and it's not switching dummy state, nothing to do // If this already has a capture texture and it's not switching dummy state, nothing to do
@@ -1134,15 +1153,18 @@ int display_vram_t::complete_img(platf::img_t *img_base, bool dummy) {
} }
// This cannot use ID3D11DeviceContext because it can be called concurrently by the encoding thread // This cannot use ID3D11DeviceContext because it can be called concurrently by the encoding thread
int display_vram_t::dummy_img(platf::img_t *img_base) { int
display_vram_t::dummy_img(platf::img_t *img_base) {
return complete_img(img_base, true); return complete_img(img_base, true);
} }
std::vector<DXGI_FORMAT> display_vram_t::get_supported_sdr_capture_formats() { std::vector<DXGI_FORMAT>
display_vram_t::get_supported_sdr_capture_formats() {
return { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM }; return { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM };
} }
std::vector<DXGI_FORMAT> display_vram_t::get_supported_hdr_capture_formats() { std::vector<DXGI_FORMAT>
display_vram_t::get_supported_hdr_capture_formats() {
return { return {
// scRGB FP16 is the desired format for HDR content. This will also handle // scRGB FP16 is the desired format for HDR content. This will also handle
// 10-bit SDR displays with the increased precision of FP16 vs 8-bit UNORMs. // 10-bit SDR displays with the increased precision of FP16 vs 8-bit UNORMs.
@@ -1164,7 +1186,8 @@ std::vector<DXGI_FORMAT> display_vram_t::get_supported_hdr_capture_formats() {
}; };
} }
std::shared_ptr<platf::hwdevice_t> display_vram_t::make_hwdevice(pix_fmt_e pix_fmt) { std::shared_ptr<platf::hwdevice_t>
display_vram_t::make_hwdevice(pix_fmt_e pix_fmt) {
if (pix_fmt != platf::pix_fmt_e::nv12 && pix_fmt != platf::pix_fmt_e::p010) { if (pix_fmt != platf::pix_fmt_e::nv12 && pix_fmt != platf::pix_fmt_e::p010) {
BOOST_LOG(error) << "display_vram_t doesn't support pixel format ["sv << from_pix_fmt(pix_fmt) << ']'; BOOST_LOG(error) << "display_vram_t doesn't support pixel format ["sv << from_pix_fmt(pix_fmt) << ']';
@@ -1185,7 +1208,8 @@ std::shared_ptr<platf::hwdevice_t> display_vram_t::make_hwdevice(pix_fmt_e pix_f
return hwdevice; return hwdevice;
} }
int init() { int
init() {
BOOST_LOG(info) << "Compiling shaders..."sv; BOOST_LOG(info) << "Compiling shaders..."sv;
scene_vs_hlsl = compile_vertex_shader(SUNSHINE_SHADERS_DIR "/SceneVS.hlsl"); scene_vs_hlsl = compile_vertex_shader(SUNSHINE_SHADERS_DIR "/SceneVS.hlsl");
if (!scene_vs_hlsl) { if (!scene_vs_hlsl) {

View File

@@ -22,7 +22,8 @@ constexpr touch_port_t target_touch_port {
using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>; using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>;
using target_t = util::safe_ptr<_VIGEM_TARGET_T, vigem_target_free>; using target_t = util::safe_ptr<_VIGEM_TARGET_T, vigem_target_free>;
static VIGEM_TARGET_TYPE map(const std::string_view &gp) { static VIGEM_TARGET_TYPE
map(const std::string_view &gp) {
if (gp == "x360"sv) { if (gp == "x360"sv) {
return Xbox360Wired; return Xbox360Wired;
} }
@@ -30,14 +31,16 @@ static VIGEM_TARGET_TYPE map(const std::string_view &gp) {
return DualShock4Wired; return DualShock4Wired;
} }
void CALLBACK x360_notify( void CALLBACK
x360_notify(
client_t::pointer client, client_t::pointer client,
target_t::pointer target, target_t::pointer target,
std::uint8_t largeMotor, std::uint8_t smallMotor, std::uint8_t largeMotor, std::uint8_t smallMotor,
std::uint8_t /* led_number */, std::uint8_t /* led_number */,
void *userdata); void *userdata);
void CALLBACK ds4_notify( void CALLBACK
ds4_notify(
client_t::pointer client, client_t::pointer client,
target_t::pointer target, target_t::pointer target,
std::uint8_t largeMotor, std::uint8_t smallMotor, std::uint8_t largeMotor, std::uint8_t smallMotor,
@@ -46,7 +49,8 @@ void CALLBACK ds4_notify(
class vigem_t { class vigem_t {
public: public:
int init() { int
init() {
VIGEM_ERROR status; VIGEM_ERROR status;
client.reset(vigem_alloc()); client.reset(vigem_alloc());
@@ -63,7 +67,8 @@ public:
return 0; return 0;
} }
int alloc_gamepad_interal(int nr, rumble_queue_t &rumble_queue, VIGEM_TARGET_TYPE gp_type) { int
alloc_gamepad_interal(int nr, rumble_queue_t &rumble_queue, VIGEM_TARGET_TYPE gp_type) {
auto &[rumble, gp] = gamepads[nr]; auto &[rumble, gp] = gamepads[nr];
assert(!gp); assert(!gp);
@@ -97,7 +102,8 @@ public:
return 0; return 0;
} }
void free_target(int nr) { void
free_target(int nr) {
auto &[_, gp] = gamepads[nr]; auto &[_, gp] = gamepads[nr];
if (gp && vigem_target_is_attached(gp.get())) { if (gp && vigem_target_is_attached(gp.get())) {
@@ -110,7 +116,8 @@ public:
gp.reset(); gp.reset();
} }
void rumble(target_t::pointer target, std::uint8_t smallMotor, std::uint8_t largeMotor) { void
rumble(target_t::pointer target, std::uint8_t smallMotor, std::uint8_t largeMotor) {
for (int x = 0; x < gamepads.size(); ++x) { for (int x = 0; x < gamepads.size(); ++x) {
auto &[rumble_queue, gp] = gamepads[x]; auto &[rumble_queue, gp] = gamepads[x];
@@ -142,13 +149,13 @@ public:
client_t client; client_t client;
}; };
void CALLBACK x360_notify( void CALLBACK
x360_notify(
client_t::pointer client, client_t::pointer client,
target_t::pointer target, target_t::pointer target,
std::uint8_t largeMotor, std::uint8_t smallMotor, std::uint8_t largeMotor, std::uint8_t smallMotor,
std::uint8_t /* led_number */, std::uint8_t /* led_number */,
void *userdata) { void *userdata) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "largeMotor: "sv << (int) largeMotor << std::endl << "largeMotor: "sv << (int) largeMotor << std::endl
<< "smallMotor: "sv << (int) smallMotor; << "smallMotor: "sv << (int) smallMotor;
@@ -156,13 +163,13 @@ void CALLBACK x360_notify(
task_pool.push(&vigem_t::rumble, (vigem_t *) userdata, target, smallMotor, largeMotor); task_pool.push(&vigem_t::rumble, (vigem_t *) userdata, target, smallMotor, largeMotor);
} }
void CALLBACK ds4_notify( void CALLBACK
ds4_notify(
client_t::pointer client, client_t::pointer client,
target_t::pointer target, target_t::pointer target,
std::uint8_t largeMotor, std::uint8_t smallMotor, std::uint8_t largeMotor, std::uint8_t smallMotor,
DS4_LIGHTBAR_COLOR /* led_color */, DS4_LIGHTBAR_COLOR /* led_color */,
void *userdata) { void *userdata) {
BOOST_LOG(debug) BOOST_LOG(debug)
<< "largeMotor: "sv << (int) largeMotor << std::endl << "largeMotor: "sv << (int) largeMotor << std::endl
<< "smallMotor: "sv << (int) smallMotor; << "smallMotor: "sv << (int) smallMotor;
@@ -180,7 +187,8 @@ struct input_raw_t {
HKL active_layout; HKL active_layout;
}; };
input_t input() { input_t
input() {
input_t result { new input_raw_t {} }; input_t result { new input_raw_t {} };
auto &raw = *(input_raw_t *) result.get(); auto &raw = *(input_raw_t *) result.get();
@@ -208,7 +216,8 @@ input_t input() {
return result; return result;
} }
void send_input(INPUT &i) { void
send_input(INPUT &i) {
retry: retry:
auto send = SendInput(1, &i, sizeof(INPUT)); auto send = SendInput(1, &i, sizeof(INPUT));
if (send != 1) { if (send != 1) {
@@ -221,7 +230,8 @@ retry:
} }
} }
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { void
abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {
INPUT i {}; INPUT i {};
i.type = INPUT_MOUSE; i.type = INPUT_MOUSE;
@@ -243,7 +253,8 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y)
send_input(i); send_input(i);
} }
void move_mouse(input_t &input, int deltaX, int deltaY) { void
move_mouse(input_t &input, int deltaX, int deltaY) {
INPUT i {}; INPUT i {};
i.type = INPUT_MOUSE; i.type = INPUT_MOUSE;
@@ -256,7 +267,8 @@ void move_mouse(input_t &input, int deltaX, int deltaY) {
send_input(i); send_input(i);
} }
void button_mouse(input_t &input, int button, bool release) { void
button_mouse(input_t &input, int button, bool release) {
constexpr auto KEY_STATE_DOWN = (SHORT) 0x8000; constexpr auto KEY_STATE_DOWN = (SHORT) 0x8000;
INPUT i {}; INPUT i {};
@@ -299,7 +311,8 @@ void button_mouse(input_t &input, int button, bool release) {
send_input(i); send_input(i);
} }
void scroll(input_t &input, int distance) { void
scroll(input_t &input, int distance) {
INPUT i {}; INPUT i {};
i.type = INPUT_MOUSE; i.type = INPUT_MOUSE;
@@ -311,7 +324,8 @@ void scroll(input_t &input, int distance) {
send_input(i); send_input(i);
} }
void hscroll(input_t &input, int distance) { void
hscroll(input_t &input, int distance) {
INPUT i {}; INPUT i {};
i.type = INPUT_MOUSE; i.type = INPUT_MOUSE;
@@ -323,7 +337,8 @@ void hscroll(input_t &input, int distance) {
send_input(i); send_input(i);
} }
void keyboard(input_t &input, uint16_t modcode, bool release) { void
keyboard(input_t &input, uint16_t modcode, bool release) {
auto raw = (input_raw_t *) input.get(); auto raw = (input_raw_t *) input.get();
INPUT i {}; INPUT i {};
@@ -372,7 +387,8 @@ void keyboard(input_t &input, uint16_t modcode, bool release) {
send_input(i); send_input(i);
} }
void unicode(input_t &input, char *utf8, int size) { void
unicode(input_t &input, char *utf8, int size) {
// We can do no worse than one UTF-16 character per byte of UTF-8 // We can do no worse than one UTF-16 character per byte of UTF-8
WCHAR wide[size]; WCHAR wide[size];
@@ -400,7 +416,8 @@ void unicode(input_t &input, char *utf8, int size) {
} }
} }
int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) { int
alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
auto raw = (input_raw_t *) input.get(); auto raw = (input_raw_t *) input.get();
if (!raw->vigem) { if (!raw->vigem) {
@@ -410,7 +427,8 @@ int alloc_gamepad(input_t &input, int nr, rumble_queue_t rumble_queue) {
return raw->vigem->alloc_gamepad_interal(nr, rumble_queue, map(config::input.gamepad)); return raw->vigem->alloc_gamepad_interal(nr, rumble_queue, map(config::input.gamepad));
} }
void free_gamepad(input_t &input, int nr) { void
free_gamepad(input_t &input, int nr) {
auto raw = (input_raw_t *) input.get(); auto raw = (input_raw_t *) input.get();
if (!raw->vigem) { if (!raw->vigem) {
@@ -420,13 +438,15 @@ void free_gamepad(input_t &input, int nr) {
raw->vigem->free_target(nr); raw->vigem->free_target(nr);
} }
static VIGEM_ERROR x360_update(client_t::pointer client, target_t::pointer gp, const gamepad_state_t &gamepad_state) { static VIGEM_ERROR
x360_update(client_t::pointer client, target_t::pointer gp, const gamepad_state_t &gamepad_state) {
auto &xusb = *(PXUSB_REPORT) &gamepad_state; auto &xusb = *(PXUSB_REPORT) &gamepad_state;
return vigem_target_x360_update(client, gp, xusb); return vigem_target_x360_update(client, gp, xusb);
} }
static DS4_DPAD_DIRECTIONS ds4_dpad(const gamepad_state_t &gamepad_state) { static DS4_DPAD_DIRECTIONS
ds4_dpad(const gamepad_state_t &gamepad_state) {
auto flags = gamepad_state.buttonFlags; auto flags = gamepad_state.buttonFlags;
if (flags & DPAD_UP) { if (flags & DPAD_UP) {
if (flags & DPAD_RIGHT) { if (flags & DPAD_RIGHT) {
@@ -463,7 +483,8 @@ static DS4_DPAD_DIRECTIONS ds4_dpad(const gamepad_state_t &gamepad_state) {
return DS4_BUTTON_DPAD_NONE; return DS4_BUTTON_DPAD_NONE;
} }
static DS4_BUTTONS ds4_buttons(const gamepad_state_t &gamepad_state) { static DS4_BUTTONS
ds4_buttons(const gamepad_state_t &gamepad_state) {
int buttons {}; int buttons {};
auto flags = gamepad_state.buttonFlags; auto flags = gamepad_state.buttonFlags;
@@ -485,7 +506,8 @@ static DS4_BUTTONS ds4_buttons(const gamepad_state_t &gamepad_state) {
return (DS4_BUTTONS) buttons; return (DS4_BUTTONS) buttons;
} }
static DS4_SPECIAL_BUTTONS ds4_special_buttons(const gamepad_state_t &gamepad_state) { static DS4_SPECIAL_BUTTONS
ds4_special_buttons(const gamepad_state_t &gamepad_state) {
int buttons {}; int buttons {};
if (gamepad_state.buttonFlags & BACK) buttons |= DS4_SPECIAL_BUTTON_TOUCHPAD; if (gamepad_state.buttonFlags & BACK) buttons |= DS4_SPECIAL_BUTTON_TOUCHPAD;
@@ -494,17 +516,20 @@ static DS4_SPECIAL_BUTTONS ds4_special_buttons(const gamepad_state_t &gamepad_st
return (DS4_SPECIAL_BUTTONS) buttons; return (DS4_SPECIAL_BUTTONS) buttons;
} }
static std::uint8_t to_ds4_triggerX(std::int16_t v) { static std::uint8_t
to_ds4_triggerX(std::int16_t v) {
return (v + std::numeric_limits<std::uint16_t>::max() / 2 + 1) / 257; return (v + std::numeric_limits<std::uint16_t>::max() / 2 + 1) / 257;
} }
static std::uint8_t to_ds4_triggerY(std::int16_t v) { static std::uint8_t
to_ds4_triggerY(std::int16_t v) {
auto new_v = -((std::numeric_limits<std::uint16_t>::max() / 2 + v - 1)) / 257; auto new_v = -((std::numeric_limits<std::uint16_t>::max() / 2 + v - 1)) / 257;
return new_v == 0 ? 0xFF : (std::uint8_t) new_v; return new_v == 0 ? 0xFF : (std::uint8_t) new_v;
} }
static VIGEM_ERROR ds4_update(client_t::pointer client, target_t::pointer gp, const gamepad_state_t &gamepad_state) { static VIGEM_ERROR
ds4_update(client_t::pointer client, target_t::pointer gp, const gamepad_state_t &gamepad_state) {
DS4_REPORT report; DS4_REPORT report;
DS4_REPORT_INIT(&report); DS4_REPORT_INIT(&report);
@@ -524,8 +549,8 @@ static VIGEM_ERROR ds4_update(client_t::pointer client, target_t::pointer gp, co
return vigem_target_ds4_update(client, gp, report); return vigem_target_ds4_update(client, gp, report);
} }
void
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) { gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
auto vigem = ((input_raw_t *) input.get())->vigem; auto vigem = ((input_raw_t *) input.get())->vigem;
// If there is no gamepad support // If there is no gamepad support
@@ -549,13 +574,15 @@ void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
} }
} }
void freeInput(void *p) { void
freeInput(void *p) {
auto input = (input_raw_t *) p; auto input = (input_raw_t *) p;
delete input; delete input;
} }
std::vector<std::string_view> &supported_gamepads() { std::vector<std::string_view> &
supported_gamepads() {
// ds4 == ps4 // ds4 == ps4
static std::vector<std::string_view> gps { static std::vector<std::string_view> gps {
"x360"sv, "ds4"sv, "ps4"sv "x360"sv, "ds4"sv, "ps4"sv

View File

@@ -63,13 +63,15 @@ decltype(WlanFreeMemory) *fn_WlanFreeMemory = nullptr;
decltype(WlanEnumInterfaces) *fn_WlanEnumInterfaces = nullptr; decltype(WlanEnumInterfaces) *fn_WlanEnumInterfaces = nullptr;
decltype(WlanSetInterface) *fn_WlanSetInterface = nullptr; decltype(WlanSetInterface) *fn_WlanSetInterface = nullptr;
std::filesystem::path appdata() { std::filesystem::path
appdata() {
WCHAR sunshine_path[MAX_PATH]; WCHAR sunshine_path[MAX_PATH];
GetModuleFileNameW(NULL, sunshine_path, _countof(sunshine_path)); GetModuleFileNameW(NULL, sunshine_path, _countof(sunshine_path));
return std::filesystem::path { sunshine_path }.remove_filename() / L"config"sv; return std::filesystem::path { sunshine_path }.remove_filename() / L"config"sv;
} }
std::string from_sockaddr(const sockaddr *const socket_address) { std::string
from_sockaddr(const sockaddr *const socket_address) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = socket_address->sa_family; auto family = socket_address->sa_family;
@@ -84,7 +86,8 @@ std::string from_sockaddr(const sockaddr *const socket_address) {
return std::string { data }; return std::string { data };
} }
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_addr) { std::pair<std::uint16_t, std::string>
from_sockaddr_ex(const sockaddr *const ip_addr) {
char data[INET6_ADDRSTRLEN]; char data[INET6_ADDRSTRLEN];
auto family = ip_addr->sa_family; auto family = ip_addr->sa_family;
@@ -102,7 +105,8 @@ std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const ip_
return { port, std::string { data } }; return { port, std::string { data } };
} }
adapteraddrs_t get_adapteraddrs() { adapteraddrs_t
get_adapteraddrs() {
adapteraddrs_t info { nullptr }; adapteraddrs_t info { nullptr };
ULONG size = 0; ULONG size = 0;
@@ -113,7 +117,8 @@ adapteraddrs_t get_adapteraddrs() {
return info; return info;
} }
std::string get_mac_address(const std::string_view &address) { std::string
get_mac_address(const std::string_view &address) {
adapteraddrs_t info = get_adapteraddrs(); adapteraddrs_t info = get_adapteraddrs();
for (auto adapter_pos = info.get(); adapter_pos != nullptr; adapter_pos = adapter_pos->Next) { for (auto adapter_pos = info.get(); adapter_pos != nullptr; adapter_pos = adapter_pos->Next) {
for (auto addr_pos = adapter_pos->FirstUnicastAddress; addr_pos != nullptr; addr_pos = addr_pos->Next) { for (auto addr_pos = adapter_pos->FirstUnicastAddress; addr_pos != nullptr; addr_pos = addr_pos->Next) {
@@ -134,7 +139,8 @@ std::string get_mac_address(const std::string_view &address) {
return "00:00:00:00:00:00"s; return "00:00:00:00:00:00"s;
} }
HDESK syncThreadDesktop() { HDESK
syncThreadDesktop() {
auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL); auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
if (!hDesk) { if (!hDesk) {
auto err = GetLastError(); auto err = GetLastError();
@@ -153,7 +159,8 @@ HDESK syncThreadDesktop() {
return hDesk; return hDesk;
} }
void print_status(const std::string_view &prefix, HRESULT status) { void
print_status(const std::string_view &prefix, HRESULT status) {
char err_string[1024]; char err_string[1024];
DWORD bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, DWORD bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
@@ -167,7 +174,8 @@ void print_status(const std::string_view &prefix, HRESULT status) {
BOOST_LOG(error) << prefix << ": "sv << std::string_view { err_string, bytes }; BOOST_LOG(error) << prefix << ": "sv << std::string_view { err_string, bytes };
} }
std::wstring utf8_to_wide_string(const std::string &str) { std::wstring
utf8_to_wide_string(const std::string &str) {
// Determine the size required for the destination string // Determine the size required for the destination string
int chars = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(), NULL, 0); int chars = MultiByteToWideChar(CP_UTF8, 0, str.data(), str.length(), NULL, 0);
@@ -179,7 +187,8 @@ std::wstring utf8_to_wide_string(const std::string &str) {
return std::wstring(buffer, chars); return std::wstring(buffer, chars);
} }
std::string wide_to_utf8_string(const std::wstring &str) { std::string
wide_to_utf8_string(const std::wstring &str) {
// Determine the size required for the destination string // Determine the size required for the destination string
int bytes = WideCharToMultiByte(CP_UTF8, 0, str.data(), str.length(), NULL, 0, NULL, NULL); int bytes = WideCharToMultiByte(CP_UTF8, 0, str.data(), str.length(), NULL, 0, NULL, NULL);
@@ -191,7 +200,8 @@ std::string wide_to_utf8_string(const std::wstring &str) {
return std::string(buffer, bytes); return std::string(buffer, bytes);
} }
HANDLE duplicate_shell_token() { HANDLE
duplicate_shell_token() {
// Get the shell window (will usually be owned by explorer.exe) // Get the shell window (will usually be owned by explorer.exe)
HWND shell_window = GetShellWindow(); HWND shell_window = GetShellWindow();
if (!shell_window) { if (!shell_window) {
@@ -229,7 +239,8 @@ HANDLE duplicate_shell_token() {
return new_token; return new_token;
} }
PTOKEN_USER get_token_user(HANDLE token) { PTOKEN_USER
get_token_user(HANDLE token) {
DWORD return_length; DWORD return_length;
if (GetTokenInformation(token, TokenUser, NULL, 0, &return_length) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { if (GetTokenInformation(token, TokenUser, NULL, 0, &return_length) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
auto winerr = GetLastError(); auto winerr = GetLastError();
@@ -252,11 +263,13 @@ PTOKEN_USER get_token_user(HANDLE token) {
return user; return user;
} }
void free_token_user(PTOKEN_USER user) { void
free_token_user(PTOKEN_USER user) {
HeapFree(GetProcessHeap(), 0, user); HeapFree(GetProcessHeap(), 0, user);
} }
bool is_token_same_user_as_process(HANDLE other_token) { bool
is_token_same_user_as_process(HANDLE other_token) {
HANDLE process_token; HANDLE process_token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token)) { if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &process_token)) {
auto winerr = GetLastError(); auto winerr = GetLastError();
@@ -284,7 +297,8 @@ bool is_token_same_user_as_process(HANDLE other_token) {
return ret; return ret;
} }
bool merge_user_environment_block(bp::environment &env, HANDLE shell_token) { bool
merge_user_environment_block(bp::environment &env, HANDLE shell_token) {
// Get the target user's environment block // Get the target user's environment block
PVOID env_block; PVOID env_block;
if (!CreateEnvironmentBlock(&env_block, shell_token, FALSE)) { if (!CreateEnvironmentBlock(&env_block, shell_token, FALSE)) {
@@ -321,12 +335,14 @@ bool merge_user_environment_block(bp::environment &env, HANDLE shell_token) {
} }
// Note: This does NOT append a null terminator // Note: This does NOT append a null terminator
void append_string_to_environment_block(wchar_t *env_block, int &offset, const std::wstring &wstr) { void
append_string_to_environment_block(wchar_t *env_block, int &offset, const std::wstring &wstr) {
std::memcpy(&env_block[offset], wstr.data(), wstr.length() * sizeof(wchar_t)); std::memcpy(&env_block[offset], wstr.data(), wstr.length() * sizeof(wchar_t));
offset += wstr.length(); offset += wstr.length();
} }
std::wstring create_environment_block(bp::environment &env) { std::wstring
create_environment_block(bp::environment &env) {
int size = 0; int size = 0;
for (const auto &entry : env) { for (const auto &entry : env) {
auto name = entry.get_name(); auto name = entry.get_name();
@@ -355,7 +371,8 @@ std::wstring create_environment_block(bp::environment &env) {
return std::wstring(env_block, offset); return std::wstring(env_block, offset);
} }
LPPROC_THREAD_ATTRIBUTE_LIST allocate_proc_thread_attr_list(DWORD attribute_count) { LPPROC_THREAD_ATTRIBUTE_LIST
allocate_proc_thread_attr_list(DWORD attribute_count) {
SIZE_T size; SIZE_T size;
InitializeProcThreadAttributeList(NULL, attribute_count, 0, &size); InitializeProcThreadAttributeList(NULL, attribute_count, 0, &size);
@@ -372,12 +389,14 @@ LPPROC_THREAD_ATTRIBUTE_LIST allocate_proc_thread_attr_list(DWORD attribute_coun
return list; return list;
} }
void free_proc_thread_attr_list(LPPROC_THREAD_ATTRIBUTE_LIST list) { void
free_proc_thread_attr_list(LPPROC_THREAD_ATTRIBUTE_LIST list) {
DeleteProcThreadAttributeList(list); DeleteProcThreadAttributeList(list);
HeapFree(GetProcessHeap(), 0, list); HeapFree(GetProcessHeap(), 0, list);
} }
bp::child run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) { bp::child
run_unprivileged(const std::string &cmd, boost::filesystem::path &working_dir, bp::environment &env, FILE *file, std::error_code &ec, bp::group *group) {
HANDLE shell_token = duplicate_shell_token(); HANDLE shell_token = duplicate_shell_token();
if (!shell_token) { if (!shell_token) {
// This can happen if the shell has crashed. Fail the launch rather than risking launching with // This can happen if the shell has crashed. Fail the launch rather than risking launching with
@@ -542,7 +561,8 @@ bp::child run_unprivileged(const std::string &cmd, boost::filesystem::path &work
} }
} }
void adjust_thread_priority(thread_priority_e priority) { void
adjust_thread_priority(thread_priority_e priority) {
int win32_priority; int win32_priority;
switch (priority) { switch (priority) {
@@ -569,7 +589,8 @@ void adjust_thread_priority(thread_priority_e priority) {
} }
} }
void streaming_will_start() { void
streaming_will_start() {
static std::once_flag load_wlanapi_once_flag; static std::once_flag load_wlanapi_once_flag;
std::call_once(load_wlanapi_once_flag, []() { std::call_once(load_wlanapi_once_flag, []() {
// wlanapi.dll is not installed by default on Windows Server, so we load it dynamically // wlanapi.dll is not installed by default on Windows Server, so we load it dynamically
@@ -671,7 +692,8 @@ void streaming_will_start() {
} }
} }
void streaming_will_stop() { void
streaming_will_stop() {
// Demote ourselves back to normal priority class // Demote ourselves back to normal priority class
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
@@ -697,19 +719,22 @@ void streaming_will_stop() {
} }
} }
bool restart_supported() { bool
restart_supported() {
// Restart is supported if we're running from the service // Restart is supported if we're running from the service
return (GetConsoleWindow() == NULL); return (GetConsoleWindow() == NULL);
} }
bool restart() { bool
restart() {
// Raise SIGINT to trigger the graceful exit logic. The service will // Raise SIGINT to trigger the graceful exit logic. The service will
// restart us in a few seconds. // restart us in a few seconds.
std::raise(SIGINT); std::raise(SIGINT);
return true; return true;
} }
SOCKADDR_IN to_sockaddr(boost::asio::ip::address_v4 address, uint16_t port) { SOCKADDR_IN
to_sockaddr(boost::asio::ip::address_v4 address, uint16_t port) {
SOCKADDR_IN saddr_v4 = {}; SOCKADDR_IN saddr_v4 = {};
saddr_v4.sin_family = AF_INET; saddr_v4.sin_family = AF_INET;
@@ -721,7 +746,8 @@ SOCKADDR_IN to_sockaddr(boost::asio::ip::address_v4 address, uint16_t port) {
return saddr_v4; return saddr_v4;
} }
SOCKADDR_IN6 to_sockaddr(boost::asio::ip::address_v6 address, uint16_t port) { SOCKADDR_IN6
to_sockaddr(boost::asio::ip::address_v6 address, uint16_t port) {
SOCKADDR_IN6 saddr_v6 = {}; SOCKADDR_IN6 saddr_v6 = {};
saddr_v6.sin6_family = AF_INET6; saddr_v6.sin6_family = AF_INET6;
@@ -736,7 +762,8 @@ SOCKADDR_IN6 to_sockaddr(boost::asio::ip::address_v6 address, uint16_t port) {
// Use UDP segmentation offload if it is supported by the OS. If the NIC is capable, this will use // Use UDP segmentation offload if it is supported by the OS. If the NIC is capable, this will use
// hardware acceleration to reduce CPU usage. Support for USO was introduced in Windows 10 20H1. // hardware acceleration to reduce CPU usage. Support for USO was introduced in Windows 10 20H1.
bool send_batch(batched_send_info_t &send_info) { bool
send_batch(batched_send_info_t &send_info) {
WSAMSG msg; WSAMSG msg;
// Convert the target address into a SOCKADDR // Convert the target address into a SOCKADDR
@@ -784,7 +811,8 @@ bool send_batch(batched_send_info_t &send_info) {
class qos_t: public deinit_t { class qos_t: public deinit_t {
public: public:
qos_t(QOS_FLOWID flow_id) : flow_id(flow_id) {} qos_t(QOS_FLOWID flow_id):
flow_id(flow_id) {}
virtual ~qos_t() { virtual ~qos_t() {
if (!fn_QOSRemoveSocketFromFlow(qos_handle, (SOCKET) NULL, flow_id, 0)) { if (!fn_QOSRemoveSocketFromFlow(qos_handle, (SOCKET) NULL, flow_id, 0)) {
@@ -797,7 +825,8 @@ private:
QOS_FLOWID flow_id; QOS_FLOWID flow_id;
}; };
std::unique_ptr<deinit_t> enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type) { std::unique_ptr<deinit_t>
enable_socket_qos(uintptr_t native_socket, boost::asio::ip::address &address, uint16_t port, qos_data_type_e data_type) {
SOCKADDR_IN saddr_v4; SOCKADDR_IN saddr_v4;
SOCKADDR_IN6 saddr_v6; SOCKADDR_IN6 saddr_v6;
PSOCKADDR dest_addr; PSOCKADDR dest_addr;

View File

@@ -6,8 +6,10 @@
#include <winnt.h> #include <winnt.h>
namespace platf { namespace platf {
void print_status(const std::string_view &prefix, HRESULT status); void
HDESK syncThreadDesktop(); print_status(const std::string_view &prefix, HRESULT status);
HDESK
syncThreadDesktop();
} // namespace platf } // namespace platf
#endif #endif

View File

@@ -59,7 +59,8 @@ typedef struct _DNS_SERVICE_INSTANCE {
} DNS_SERVICE_INSTANCE, *PDNS_SERVICE_INSTANCE; } DNS_SERVICE_INSTANCE, *PDNS_SERVICE_INSTANCE;
#endif #endif
typedef VOID WINAPI DNS_SERVICE_REGISTER_COMPLETE( typedef VOID WINAPI
DNS_SERVICE_REGISTER_COMPLETE(
_In_ DWORD Status, _In_ DWORD Status,
_In_ PVOID pQueryContext, _In_ PVOID pQueryContext,
_In_ PDNS_SERVICE_INSTANCE pInstance); _In_ PDNS_SERVICE_INSTANCE pInstance);
@@ -88,7 +89,8 @@ _FN(_DnsServiceRegister, DWORD, (_In_ PDNS_SERVICE_REGISTER_REQUEST pRequest, _I
} /* extern "C" */ } /* extern "C" */
namespace platf::publish { namespace platf::publish {
VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) { VOID WINAPI
register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) {
auto alarm = (safe::alarm_t<PDNS_SERVICE_INSTANCE>::element_type *) pQueryContext; auto alarm = (safe::alarm_t<PDNS_SERVICE_INSTANCE>::element_type *) pQueryContext;
if (status) { if (status) {
@@ -98,7 +100,8 @@ VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE
alarm->ring(pInstance); alarm->ring(pInstance);
} }
static int service(bool enable, PDNS_SERVICE_INSTANCE &existing_instance) { static int
service(bool enable, PDNS_SERVICE_INSTANCE &existing_instance) {
auto alarm = safe::make_alarm<PDNS_SERVICE_INSTANCE>(); auto alarm = safe::make_alarm<PDNS_SERVICE_INSTANCE>();
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter; std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> converter;
@@ -154,7 +157,8 @@ static int service(bool enable, PDNS_SERVICE_INSTANCE &existing_instance) {
class mdns_registration_t: public ::platf::deinit_t { class mdns_registration_t: public ::platf::deinit_t {
public: public:
mdns_registration_t() : existing_instance(nullptr) { mdns_registration_t():
existing_instance(nullptr) {
if (service(true, existing_instance)) { if (service(true, existing_instance)) {
BOOST_LOG(error) << "Unable to register Sunshine mDNS service"sv; BOOST_LOG(error) << "Unable to register Sunshine mDNS service"sv;
return; return;
@@ -178,7 +182,8 @@ private:
PDNS_SERVICE_INSTANCE existing_instance; PDNS_SERVICE_INSTANCE existing_instance;
}; };
int load_funcs(HMODULE handle) { int
load_funcs(HMODULE handle) {
auto fg = util::fail_guard([handle]() { auto fg = util::fail_guard([handle]() {
FreeLibrary(handle); FreeLibrary(handle);
}); });
@@ -196,7 +201,8 @@ int load_funcs(HMODULE handle) {
return 0; return 0;
} }
std::unique_ptr<::platf::deinit_t> start() { std::unique_ptr<::platf::deinit_t>
start() {
HMODULE handle = LoadLibrary("dnsapi.dll"); HMODULE handle = LoadLibrary("dnsapi.dll");
if (!handle || load_funcs(handle)) { if (!handle || load_funcs(handle)) {

View File

@@ -38,7 +38,8 @@ namespace pt = boost::property_tree;
proc_t proc; proc_t proc;
void process_end(bp::child &proc, bp::group &proc_handle) { void
process_end(bp::child &proc, bp::group &proc_handle) {
if (!proc.running()) { if (!proc.running()) {
return; return;
} }
@@ -50,7 +51,8 @@ void process_end(bp::child &proc, bp::group &proc_handle) {
proc.wait(); proc.wait();
} }
boost::filesystem::path find_working_directory(const std::string &cmd, bp::environment &env) { boost::filesystem::path
find_working_directory(const std::string &cmd, bp::environment &env) {
// Parse the raw command string into parts to get the actual command portion // Parse the raw command string into parts to get the actual command portion
#ifdef _WIN32 #ifdef _WIN32
auto parts = boost::program_options::split_winmain(cmd); auto parts = boost::program_options::split_winmain(cmd);
@@ -80,7 +82,8 @@ boost::filesystem::path find_working_directory(const std::string &cmd, bp::envir
return cmd_path.parent_path(); return cmd_path.parent_path();
} }
int proc_t::execute(int app_id) { int
proc_t::execute(int app_id) {
// Ensure starting from a clean slate // Ensure starting from a clean slate
terminate(); terminate();
@@ -179,7 +182,8 @@ int proc_t::execute(int app_id) {
return 0; return 0;
} }
int proc_t::running() { int
proc_t::running() {
if (placebo || _process.running()) { if (placebo || _process.running()) {
return _app_id; return _app_id;
} }
@@ -192,7 +196,8 @@ int proc_t::running() {
return 0; return 0;
} }
void proc_t::terminate() { void
proc_t::terminate() {
std::error_code ec; std::error_code ec;
// Ensure child process is terminated // Ensure child process is terminated
@@ -230,10 +235,12 @@ void proc_t::terminate() {
_pipe.reset(); _pipe.reset();
} }
const std::vector<ctx_t> &proc_t::get_apps() const { const std::vector<ctx_t> &
proc_t::get_apps() const {
return _apps; return _apps;
} }
std::vector<ctx_t> &proc_t::get_apps() { std::vector<ctx_t> &
proc_t::get_apps() {
return _apps; return _apps;
} }
@@ -241,7 +248,8 @@ std::vector<ctx_t> &proc_t::get_apps() {
// Returns image from assets directory if found there. // Returns image from assets directory if found there.
// Returns default image if image configuration is not set. // Returns default image if image configuration is not set.
// Returns http content-type header compatible image type. // Returns http content-type header compatible image type.
std::string proc_t::get_app_image(int app_id) { std::string
proc_t::get_app_image(int app_id) {
auto iter = std::find_if(_apps.begin(), _apps.end(), [&app_id](const auto app) { auto iter = std::find_if(_apps.begin(), _apps.end(), [&app_id](const auto app) {
return app.id == std::to_string(app_id); return app.id == std::to_string(app_id);
}); });
@@ -254,7 +262,8 @@ proc_t::~proc_t() {
terminate(); terminate();
} }
std::string_view::iterator find_match(std::string_view::iterator begin, std::string_view::iterator end) { std::string_view::iterator
find_match(std::string_view::iterator begin, std::string_view::iterator end) {
int stack = 0; int stack = 0;
--begin; --begin;
@@ -275,7 +284,8 @@ std::string_view::iterator find_match(std::string_view::iterator begin, std::str
return begin; return begin;
} }
std::string parse_env_val(bp::native_environment &env, const std::string_view &val_raw) { std::string
parse_env_val(bp::native_environment &env, const std::string_view &val_raw) {
auto pos = std::begin(val_raw); auto pos = std::begin(val_raw);
auto dollar = std::find(pos, std::end(val_raw), '$'); auto dollar = std::find(pos, std::end(val_raw), '$');
@@ -329,7 +339,8 @@ std::string parse_env_val(bp::native_environment &env, const std::string_view &v
return ss.str(); return ss.str();
} }
std::string validate_app_image_path(std::string app_image_path) { std::string
validate_app_image_path(std::string app_image_path) {
if (app_image_path.empty()) { if (app_image_path.empty()) {
return DEFAULT_APP_IMAGE_PATH; return DEFAULT_APP_IMAGE_PATH;
} }
@@ -366,7 +377,8 @@ std::string validate_app_image_path(std::string app_image_path) {
return app_image_path; return app_image_path;
} }
std::optional<std::string> calculate_sha256(const std::string &filename) { std::optional<std::string>
calculate_sha256(const std::string &filename) {
crypto::md_ctx_t ctx { EVP_MD_CTX_create() }; crypto::md_ctx_t ctx { EVP_MD_CTX_create() };
if (!ctx) { if (!ctx) {
return std::nullopt; return std::nullopt;
@@ -401,13 +413,15 @@ std::optional<std::string> calculate_sha256(const std::string &filename) {
return ss.str(); return ss.str();
} }
uint32_t calculate_crc32(const std::string &input) { uint32_t
calculate_crc32(const std::string &input) {
boost::crc_32_type result; boost::crc_32_type result;
result.process_bytes(input.data(), input.length()); result.process_bytes(input.data(), input.length());
return result.checksum(); return result.checksum();
} }
std::tuple<std::string, std::string> calculate_app_id(const std::string &app_name, std::string app_image_path, int index) { std::tuple<std::string, std::string>
calculate_app_id(const std::string &app_name, std::string app_image_path, int index) {
// Generate id by hashing name with image data if present // Generate id by hashing name with image data if present
std::vector<std::string> to_hash; std::vector<std::string> to_hash;
to_hash.push_back(app_name); to_hash.push_back(app_name);
@@ -437,7 +451,8 @@ std::tuple<std::string, std::string> calculate_app_id(const std::string &app_nam
return std::make_tuple(id_no_index, id_with_index); return std::make_tuple(id_no_index, id_with_index);
} }
std::optional<proc::proc_t> parse(const std::string &file_name) { std::optional<proc::proc_t>
parse(const std::string &file_name) {
pt::ptree tree; pt::ptree tree;
try { try {
@@ -550,7 +565,8 @@ std::optional<proc::proc_t> parse(const std::string &file_name) {
return std::nullopt; return std::nullopt;
} }
void refresh(const std::string &file_name) { void
refresh(const std::string &file_name) {
auto proc_opt = proc::parse(file_name); auto proc_opt = proc::parse(file_name);
if (proc_opt) { if (proc_opt) {

View File

@@ -56,24 +56,31 @@ public:
proc_t( proc_t(
boost::process::environment &&env, boost::process::environment &&env,
std::vector<ctx_t> &&apps) : _app_id(0), std::vector<ctx_t> &&apps):
_app_id(0),
_env(std::move(env)), _env(std::move(env)),
_apps(std::move(apps)) {} _apps(std::move(apps)) {}
int execute(int app_id); int
execute(int app_id);
/** /**
* @return _app_id if a process is running, otherwise returns 0 * @return _app_id if a process is running, otherwise returns 0
*/ */
int running(); int
running();
~proc_t(); ~proc_t();
const std::vector<ctx_t> &get_apps() const; const std::vector<ctx_t> &
std::vector<ctx_t> &get_apps(); get_apps() const;
std::string get_app_image(int app_id); std::vector<ctx_t> &
get_apps();
std::string
get_app_image(int app_id);
void terminate(); void
terminate();
private: private:
int _app_id; int _app_id;
@@ -97,11 +104,15 @@ private:
* Calculate a stable id based on name and image data * Calculate a stable id based on name and image data
* @return tuple of id calculated without index (for use if no collision) and one with * @return tuple of id calculated without index (for use if no collision) and one with
*/ */
std::tuple<std::string, std::string> calculate_app_id(const std::string &app_name, std::string app_image_path, int index); std::tuple<std::string, std::string>
calculate_app_id(const std::string &app_name, std::string app_image_path, int index);
std::string validate_app_image_path(std::string app_image_path); std::string
void refresh(const std::string &file_name); validate_app_image_path(std::string app_image_path);
std::optional<proc::proc_t> parse(const std::string &file_name); void
refresh(const std::string &file_name);
std::optional<proc::proc_t>
parse(const std::string &file_name);
extern proc_t proc; extern proc_t proc;
} // namespace proc } // namespace proc

View File

@@ -16,7 +16,8 @@ public:
typedef T iterator; typedef T iterator;
typedef std::ptrdiff_t diff_t; typedef std::ptrdiff_t diff_t;
iterator operator+=(diff_t step) { iterator
operator+=(diff_t step) {
while (step-- > 0) { while (step-- > 0) {
++_this(); ++_this();
} }
@@ -24,7 +25,8 @@ public:
return _this(); return _this();
} }
iterator operator-=(diff_t step) { iterator
operator-=(diff_t step) {
while (step-- > 0) { while (step-- > 0) {
--_this(); --_this();
} }
@@ -32,19 +34,22 @@ public:
return _this(); return _this();
} }
iterator operator+(diff_t step) { iterator
operator+(diff_t step) {
iterator new_ = _this(); iterator new_ = _this();
return new_ += step; return new_ += step;
} }
iterator operator-(diff_t step) { iterator
operator-(diff_t step) {
iterator new_ = _this(); iterator new_ = _this();
return new_ -= step; return new_ -= step;
} }
diff_t operator-(iterator first) { diff_t
operator-(iterator first) {
diff_t step = 0; diff_t step = 0;
while (first != _this()) { while (first != _this()) {
++step; ++step;
@@ -54,16 +59,19 @@ public:
return step; return step;
} }
iterator operator++() { iterator
operator++() {
_this().inc(); _this().inc();
return _this(); return _this();
} }
iterator operator--() { iterator
operator--() {
_this().dec(); _this().dec();
return _this(); return _this();
} }
iterator operator++(int) { iterator
operator++(int) {
iterator new_ = _this(); iterator new_ = _this();
++_this(); ++_this();
@@ -71,7 +79,8 @@ public:
return new_; return new_;
} }
iterator operator--(int) { iterator
operator--(int) {
iterator new_ = _this(); iterator new_ = _this();
--_this(); --_this();
@@ -79,34 +88,46 @@ public:
return new_; return new_;
} }
reference operator*() { return *_this().get(); } reference
const reference operator*() const { return *_this().get(); } operator*() { return *_this().get(); }
const reference
operator*() const { return *_this().get(); }
pointer operator->() { return &*_this(); } pointer
const pointer operator->() const { return &*_this(); } operator->() { return &*_this(); }
const pointer
operator->() const { return &*_this(); }
bool operator!=(const iterator &other) const { bool
operator!=(const iterator &other) const {
return !(_this() == other); return !(_this() == other);
} }
bool operator<(const iterator &other) const { bool
operator<(const iterator &other) const {
return !(_this() >= other); return !(_this() >= other);
} }
bool operator>=(const iterator &other) const { bool
operator>=(const iterator &other) const {
return _this() == other || _this() > other; return _this() == other || _this() > other;
} }
bool operator<=(const iterator &other) const { bool
operator<=(const iterator &other) const {
return _this() == other || _this() < other; return _this() == other || _this() < other;
} }
bool operator==(const iterator &other) const { return _this().eq(other); }; bool
bool operator>(const iterator &other) const { return _this().gt(other); } operator==(const iterator &other) const { return _this().eq(other); };
bool
operator>(const iterator &other) const { return _this().gt(other); }
private: private:
iterator &_this() { return *static_cast<iterator *>(this); } iterator &
const iterator &_this() const { return *static_cast<const iterator *>(this); } _this() { return *static_cast<iterator *>(this); }
const iterator &
_this() const { return *static_cast<const iterator *>(this); }
}; };
template <class V, class It> template <class V, class It>
@@ -115,9 +136,11 @@ public:
using iterator = It; using iterator = It;
using pointer = V *; using pointer = V *;
round_robin_t(iterator begin, iterator end) : _begin(begin), _end(end), _pos(begin) {} round_robin_t(iterator begin, iterator end):
_begin(begin), _end(end), _pos(begin) {}
void inc() { void
inc() {
++_pos; ++_pos;
if (_pos == _end) { if (_pos == _end) {
@@ -125,7 +148,8 @@ public:
} }
} }
void dec() { void
dec() {
if (_pos == _begin) { if (_pos == _begin) {
_pos = _end; _pos = _end;
} }
@@ -133,11 +157,13 @@ public:
--_pos; --_pos;
} }
bool eq(const round_robin_t &other) const { bool
eq(const round_robin_t &other) const {
return *_pos == *other._pos; return *_pos == *other._pos;
} }
pointer get() const { pointer
get() const {
return &*_pos; return &*_pos;
} }
@@ -149,7 +175,8 @@ private:
}; };
template <class V, class It> template <class V, class It>
round_robin_t<V, It> make_round_robin(It begin, It end) { round_robin_t<V, It>
make_round_robin(It begin, It end) {
return round_robin_t<V, It>(begin, end); return round_robin_t<V, It>(begin, end);
} }
} // namespace round_robin_util } // namespace round_robin_util

View File

@@ -30,7 +30,8 @@ using asio::ip::udp;
using namespace std::literals; using namespace std::literals;
namespace rtsp_stream { namespace rtsp_stream {
void free_msg(PRTSP_MESSAGE msg) { void
free_msg(PRTSP_MESSAGE msg) {
freeMessage(msg); freeMessage(msg);
delete msg; delete msg;
@@ -41,16 +42,20 @@ class rtsp_server_t;
using msg_t = util::safe_ptr<RTSP_MESSAGE, free_msg>; using msg_t = util::safe_ptr<RTSP_MESSAGE, free_msg>;
using cmd_func_t = std::function<void(rtsp_server_t *server, tcp::socket &, msg_t &&)>; using cmd_func_t = std::function<void(rtsp_server_t *server, tcp::socket &, msg_t &&)>;
void print_msg(PRTSP_MESSAGE msg); void
void cmd_not_found(tcp::socket &sock, msg_t &&req); print_msg(PRTSP_MESSAGE msg);
void respond(tcp::socket &sock, POPTION_ITEM options, int statuscode, const char *status_msg, int seqn, const std::string_view &payload); void
cmd_not_found(tcp::socket &sock, msg_t &&req);
void
respond(tcp::socket &sock, POPTION_ITEM options, int statuscode, const char *status_msg, int seqn, const std::string_view &payload);
class socket_t: public std::enable_shared_from_this<socket_t> { class socket_t: public std::enable_shared_from_this<socket_t> {
public: public:
socket_t(boost::asio::io_service &ios, std::function<void(tcp::socket &sock, msg_t &&)> &&handle_data_fn) socket_t(boost::asio::io_service &ios, std::function<void(tcp::socket &sock, msg_t &&)> &&handle_data_fn):
: handle_data_fn { std::move(handle_data_fn) }, sock { ios } {} handle_data_fn { std::move(handle_data_fn) }, sock { ios } {}
void read() { void
read() {
if (begin == std::end(msg_buf)) { if (begin == std::end(msg_buf)) {
BOOST_LOG(error) << "RTSP: read(): Exceeded maximum rtsp packet size: "sv << msg_buf.size(); BOOST_LOG(error) << "RTSP: read(): Exceeded maximum rtsp packet size: "sv << msg_buf.size();
@@ -69,7 +74,8 @@ public:
boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::bytes_transferred));
} }
void read_payload() { void
read_payload() {
if (begin == std::end(msg_buf)) { if (begin == std::end(msg_buf)) {
BOOST_LOG(error) << "RTSP: read_payload(): Exceeded maximum rtsp packet size: "sv << msg_buf.size(); BOOST_LOG(error) << "RTSP: read_payload(): Exceeded maximum rtsp packet size: "sv << msg_buf.size();
@@ -88,7 +94,8 @@ public:
boost::asio::placeholders::bytes_transferred)); boost::asio::placeholders::bytes_transferred));
} }
static void handle_payload(std::shared_ptr<socket_t> &socket, const boost::system::error_code &ec, std::size_t bytes) { static void
handle_payload(std::shared_ptr<socket_t> &socket, const boost::system::error_code &ec, std::size_t bytes) {
BOOST_LOG(debug) << "handle_payload(): Handle read of size: "sv << bytes << " bytes"sv; BOOST_LOG(debug) << "handle_payload(): Handle read of size: "sv << bytes << " bytes"sv;
auto sock_close = util::fail_guard([&socket]() { auto sock_close = util::fail_guard([&socket]() {
@@ -150,7 +157,8 @@ public:
socket->begin = end; socket->begin = end;
} }
static void handle_read(std::shared_ptr<socket_t> &socket, const boost::system::error_code &ec, std::size_t bytes) { static void
handle_read(std::shared_ptr<socket_t> &socket, const boost::system::error_code &ec, std::size_t bytes) {
BOOST_LOG(debug) << "handle_read(): Handle read of size: "sv << bytes << " bytes"sv; BOOST_LOG(debug) << "handle_read(): Handle read of size: "sv << bytes << " bytes"sv;
if (ec) { if (ec) {
@@ -192,7 +200,8 @@ public:
handle_payload(socket, ec, buf_size); handle_payload(socket, ec, buf_size);
} }
void handle_data(msg_t &&req) { void
handle_data(msg_t &&req) {
handle_data_fn(sock, std::move(req)); handle_data_fn(sock, std::move(req));
} }
@@ -212,7 +221,8 @@ public:
clear(); clear();
} }
int bind(std::uint16_t port, boost::system::error_code &ec) { int
bind(std::uint16_t port, boost::system::error_code &ec) {
{ {
auto lg = _session_slots.lock(); auto lg = _session_slots.lock();
@@ -249,11 +259,13 @@ public:
} }
template <class T, class X> template <class T, class X>
void iterate(std::chrono::duration<T, X> timeout) { void
iterate(std::chrono::duration<T, X> timeout) {
ios.run_one_for(timeout); ios.run_one_for(timeout);
} }
void handle_msg(tcp::socket &sock, msg_t &&req) { void
handle_msg(tcp::socket &sock, msg_t &&req) {
auto func = _map_cmd_cb.find(req->message.request.command); auto func = _map_cmd_cb.find(req->message.request.command);
if (func != std::end(_map_cmd_cb)) { if (func != std::end(_map_cmd_cb)) {
func->second(this, sock, std::move(req)); func->second(this, sock, std::move(req));
@@ -265,7 +277,8 @@ public:
sock.shutdown(boost::asio::socket_base::shutdown_type::shutdown_both); sock.shutdown(boost::asio::socket_base::shutdown_type::shutdown_both);
} }
void handle_accept(const boost::system::error_code &ec) { void
handle_accept(const boost::system::error_code &ec) {
if (ec) { if (ec) {
BOOST_LOG(error) << "Couldn't accept incoming connections: "sv << ec.message(); BOOST_LOG(error) << "Couldn't accept incoming connections: "sv << ec.message();
@@ -286,11 +299,13 @@ public:
}); });
} }
void map(const std::string_view &type, cmd_func_t cb) { void
map(const std::string_view &type, cmd_func_t cb) {
_map_cmd_cb.emplace(type, std::move(cb)); _map_cmd_cb.emplace(type, std::move(cb));
} }
void session_raise(rtsp_stream::launch_session_t launch_session) { void
session_raise(rtsp_stream::launch_session_t launch_session) {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
// If a launch event is still pending, don't overwrite it. // If a launch event is still pending, don't overwrite it.
@@ -303,13 +318,15 @@ public:
launch_event.raise(launch_session); launch_event.raise(launch_session);
} }
int session_count() const { int
session_count() const {
return config::stream.channels - _slot_count; return config::stream.channels - _slot_count;
} }
safe::event_t<rtsp_stream::launch_session_t> launch_event; safe::event_t<rtsp_stream::launch_session_t> launch_event;
void clear(bool all = true) { void
clear(bool all = true) {
// if a launch event timed out --> Remove it. // if a launch event timed out --> Remove it.
if (raised_timeout < std::chrono::steady_clock::now()) { if (raised_timeout < std::chrono::steady_clock::now()) {
auto discarded = launch_event.pop(0s); auto discarded = launch_event.pop(0s);
@@ -336,7 +353,8 @@ public:
} }
} }
void clear(std::shared_ptr<stream::session_t> *session_p) { void
clear(std::shared_ptr<stream::session_t> *session_p) {
auto lg = _session_slots.lock(); auto lg = _session_slots.lock();
session_p->reset(); session_p->reset();
@@ -344,7 +362,8 @@ public:
++_slot_count; ++_slot_count;
} }
std::shared_ptr<stream::session_t> *accept(std::shared_ptr<stream::session_t> &session) { std::shared_ptr<stream::session_t> *
accept(std::shared_ptr<stream::session_t> &session) {
auto lg = _session_slots.lock(); auto lg = _session_slots.lock();
for (auto &slot : *_session_slots) { for (auto &slot : *_session_slots) {
@@ -373,18 +392,21 @@ private:
rtsp_server_t server {}; rtsp_server_t server {};
void launch_session_raise(rtsp_stream::launch_session_t launch_session) { void
launch_session_raise(rtsp_stream::launch_session_t launch_session) {
server.session_raise(launch_session); server.session_raise(launch_session);
} }
int session_count() { int
session_count() {
// Ensure session_count is up-to-date // Ensure session_count is up-to-date
server.clear(false); server.clear(false);
return server.session_count(); return server.session_count();
} }
int send(tcp::socket &sock, const std::string_view &sv) { int
send(tcp::socket &sock, const std::string_view &sv) {
std::size_t bytes_send = 0; std::size_t bytes_send = 0;
while (bytes_send != sv.size()) { while (bytes_send != sv.size()) {
@@ -400,7 +422,8 @@ int send(tcp::socket &sock, const std::string_view &sv) {
return 0; return 0;
} }
void respond(tcp::socket &sock, msg_t &resp) { void
respond(tcp::socket &sock, msg_t &resp) {
auto payload = std::make_pair(resp->payload, resp->payloadLength); auto payload = std::make_pair(resp->payload, resp->payloadLength);
// Restore response message for proper destruction // Restore response message for proper destruction
@@ -429,18 +452,21 @@ void respond(tcp::socket &sock, msg_t &resp) {
send(sock, std::string_view { payload.first, (std::size_t) payload.second }); send(sock, std::string_view { payload.first, (std::size_t) payload.second });
} }
void respond(tcp::socket &sock, POPTION_ITEM options, int statuscode, const char *status_msg, int seqn, const std::string_view &payload) { void
respond(tcp::socket &sock, POPTION_ITEM options, int statuscode, const char *status_msg, int seqn, const std::string_view &payload) {
msg_t resp { new msg_t::element_type }; msg_t resp { new msg_t::element_type };
createRtspResponse(resp.get(), nullptr, 0, const_cast<char *>("RTSP/1.0"), statuscode, const_cast<char *>(status_msg), seqn, options, const_cast<char *>(payload.data()), (int) payload.size()); createRtspResponse(resp.get(), nullptr, 0, const_cast<char *>("RTSP/1.0"), statuscode, const_cast<char *>(status_msg), seqn, options, const_cast<char *>(payload.data()), (int) payload.size());
respond(sock, resp); respond(sock, resp);
} }
void cmd_not_found(tcp::socket &sock, msg_t &&req) { void
cmd_not_found(tcp::socket &sock, msg_t &&req) {
respond(sock, nullptr, 404, "NOT FOUND", req->sequenceNumber, {}); respond(sock, nullptr, 404, "NOT FOUND", req->sequenceNumber, {});
} }
void cmd_option(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) { void
cmd_option(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
OPTION_ITEM option {}; OPTION_ITEM option {};
// I know these string literals will not be modified // I know these string literals will not be modified
@@ -452,7 +478,8 @@ void cmd_option(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
respond(sock, &option, 200, "OK", req->sequenceNumber, {}); respond(sock, &option, 200, "OK", req->sequenceNumber, {});
} }
void cmd_describe(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) { void
cmd_describe(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
OPTION_ITEM option {}; OPTION_ITEM option {};
// I know these string literals will not be modified // I know these string literals will not be modified
@@ -496,7 +523,8 @@ void cmd_describe(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
respond(sock, &option, 200, "OK", req->sequenceNumber, ss.str()); respond(sock, &option, 200, "OK", req->sequenceNumber, ss.str());
} }
void cmd_setup(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) { void
cmd_setup(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
OPTION_ITEM options[3] {}; OPTION_ITEM options[3] {};
auto &seqn = options[0]; auto &seqn = options[0];
@@ -542,11 +570,11 @@ void cmd_setup(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
port_option.option = const_cast<char *>("Transport"); port_option.option = const_cast<char *>("Transport");
port_option.content = port_value.data(); port_option.content = port_value.data();
respond(sock, &seqn, 200, "OK", req->sequenceNumber, {}); respond(sock, &seqn, 200, "OK", req->sequenceNumber, {});
} }
void cmd_announce(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) { void
cmd_announce(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
OPTION_ITEM option {}; OPTION_ITEM option {};
// I know these string literals will not be modified // I know these string literals will not be modified
@@ -645,7 +673,6 @@ void cmd_announce(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
config.monitor.dynamicRange = util::from_view(args.at("x-nv-video[0].dynamicRangeMode"sv)); config.monitor.dynamicRange = util::from_view(args.at("x-nv-video[0].dynamicRangeMode"sv));
} }
catch (std::out_of_range &) { catch (std::out_of_range &) {
respond(sock, &option, 400, "BAD REQUEST", req->sequenceNumber, {}); respond(sock, &option, 400, "BAD REQUEST", req->sequenceNumber, {});
return; return;
} }
@@ -691,7 +718,8 @@ void cmd_announce(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
respond(sock, &option, 200, "OK", req->sequenceNumber, {}); respond(sock, &option, 200, "OK", req->sequenceNumber, {});
} }
void cmd_play(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) { void
cmd_play(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
OPTION_ITEM option {}; OPTION_ITEM option {};
// I know these string literals will not be modified // I know these string literals will not be modified
@@ -703,7 +731,8 @@ void cmd_play(rtsp_server_t *server, tcp::socket &sock, msg_t &&req) {
respond(sock, &option, 200, "OK", req->sequenceNumber, {}); respond(sock, &option, 200, "OK", req->sequenceNumber, {});
} }
void rtpThread() { void
rtpThread() {
auto shutdown_event = mail::man->event<bool>(mail::shutdown); auto shutdown_event = mail::man->event<bool>(mail::shutdown);
auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown); auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
@@ -737,7 +766,8 @@ void rtpThread() {
server.clear(); server.clear();
} }
void print_msg(PRTSP_MESSAGE msg) { void
print_msg(PRTSP_MESSAGE msg) {
std::string_view type = msg->type == TYPE_RESPONSE ? "RESPONSE"sv : "REQUEST"sv; std::string_view type = msg->type == TYPE_RESPONSE ? "RESPONSE"sv : "REQUEST"sv;
std::string_view payload { msg->payload, (size_t) msg->payloadLength }; std::string_view payload { msg->payload, (size_t) msg->payloadLength };

View File

@@ -18,10 +18,13 @@ struct launch_session_t {
bool host_audio; bool host_audio;
}; };
void launch_session_raise(launch_session_t launch_session); void
int session_count(); launch_session_raise(launch_session_t launch_session);
int
session_count();
void rtpThread(); void
rtpThread();
} // namespace rtsp_stream } // namespace rtsp_stream

View File

@@ -68,7 +68,8 @@ enum class socket_e : int {
#pragma pack(push, 1) #pragma pack(push, 1)
struct video_short_frame_header_t { struct video_short_frame_header_t {
uint8_t *payload() { uint8_t *
payload() {
return (uint8_t *) (this + 1); return (uint8_t *) (this + 1);
} }
@@ -90,7 +91,8 @@ static_assert(
"Short frame header must be 8 bytes"); "Short frame header must be 8 bytes");
struct video_packet_raw_t { struct video_packet_raw_t {
uint8_t *payload() { uint8_t *
payload() {
return (uint8_t *) (this + 1); return (uint8_t *) (this + 1);
} }
@@ -101,7 +103,8 @@ struct video_packet_raw_t {
}; };
struct audio_packet_raw_t { struct audio_packet_raw_t {
uint8_t *payload() { uint8_t *
payload() {
return (uint8_t *) (this + 1); return (uint8_t *) (this + 1);
} }
@@ -112,7 +115,8 @@ struct control_header_v2 {
std::uint16_t type; std::uint16_t type;
std::uint16_t payloadLength; std::uint16_t payloadLength;
uint8_t *payload() { uint8_t *
payload() {
return (uint8_t *) (this + 1); return (uint8_t *) (this + 1);
} }
}; };
@@ -149,14 +153,16 @@ typedef struct control_encrypted_t {
// seq is accepted as an arbitrary value in Moonlight // seq is accepted as an arbitrary value in Moonlight
std::uint32_t seq; // Monotonically increasing sequence number (used as IV for AES-GCM) std::uint32_t seq; // Monotonically increasing sequence number (used as IV for AES-GCM)
uint8_t *payload() { uint8_t *
payload() {
return (uint8_t *) (this + 1); return (uint8_t *) (this + 1);
} }
// encrypted control_header_v2 and payload data follow // encrypted control_header_v2 and payload data follow
} *control_encrypted_p; } *control_encrypted_p;
struct audio_fec_packet_raw_t { struct audio_fec_packet_raw_t {
uint8_t *payload() { uint8_t *
payload() {
return (uint8_t *) (this + 1); return (uint8_t *) (this + 1);
} }
@@ -166,7 +172,8 @@ struct audio_fec_packet_raw_t {
#pragma pack(pop) #pragma pack(pop)
constexpr std::size_t round_to_pkcs7_padded(std::size_t size) { constexpr std::size_t
round_to_pkcs7_padded(std::size_t size) {
return ((size + 15) / 16) * 16; return ((size + 15) / 16) * 16;
} }
constexpr std::size_t MAX_AUDIO_PACKET_SIZE = 1400; constexpr std::size_t MAX_AUDIO_PACKET_SIZE = 1400;
@@ -182,7 +189,8 @@ using message_queue_queue_t = std::shared_ptr<safe::queue_t<std::tuple<socket_e,
// return bytes written on success // return bytes written on success
// return -1 on error // return -1 on error
static inline int encode_audio(int featureSet, const audio::buffer_t &plaintext, audio_packet_t &destination, std::uint32_t avRiKeyIv, crypto::cipher::cbc_t &cbc) { static inline int
encode_audio(int featureSet, const audio::buffer_t &plaintext, audio_packet_t &destination, std::uint32_t avRiKeyIv, crypto::cipher::cbc_t &cbc) {
// If encryption isn't enabled // If encryption isn't enabled
if (!(featureSet & 0x20)) { if (!(featureSet & 0x20)) {
std::copy(std::begin(plaintext), std::end(plaintext), destination->payload()); std::copy(std::begin(plaintext), std::end(plaintext), destination->payload());
@@ -195,7 +203,8 @@ static inline int encode_audio(int featureSet, const audio::buffer_t &plaintext,
return cbc.encrypt(std::string_view { (char *) std::begin(plaintext), plaintext.size() }, destination->payload(), &iv); return cbc.encrypt(std::string_view { (char *) std::begin(plaintext), plaintext.size() }, destination->payload(), &iv);
} }
static inline void while_starting_do_nothing(std::atomic<session::state_e> &state) { static inline void
while_starting_do_nothing(std::atomic<session::state_e> &state) {
while (state.load(std::memory_order_acquire) == session::state_e::STARTING) { while (state.load(std::memory_order_acquire) == session::state_e::STARTING) {
std::this_thread::sleep_for(1ms); std::this_thread::sleep_for(1ms);
} }
@@ -203,13 +212,15 @@ static inline void while_starting_do_nothing(std::atomic<session::state_e> &stat
class control_server_t { class control_server_t {
public: public:
int bind(std::uint16_t port) { int
bind(std::uint16_t port) {
_host = net::host_create(_addr, config::stream.channels, port); _host = net::host_create(_addr, config::stream.channels, port);
return !(bool) _host; return !(bool) _host;
} }
void emplace_addr_to_session(const std::string &addr, session_t &session) { void
emplace_addr_to_session(const std::string &addr, session_t &session) {
auto lg = _map_addr_session.lock(); auto lg = _map_addr_session.lock();
_map_addr_session->emplace(addr, std::make_pair(0u, &session)); _map_addr_session->emplace(addr, std::make_pair(0u, &session));
@@ -218,22 +229,27 @@ public:
// Get session associated with address. // Get session associated with address.
// If none are found, try to find a session not yet claimed. (It will be marked by a port of value 0 // If none are found, try to find a session not yet claimed. (It will be marked by a port of value 0
// If none of those are found, return nullptr // If none of those are found, return nullptr
session_t *get_session(const net::peer_t peer); session_t *
get_session(const net::peer_t peer);
// Circular dependency: // Circular dependency:
// iterate refers to session // iterate refers to session
// session refers to broadcast_ctx_t // session refers to broadcast_ctx_t
// broadcast_ctx_t refers to control_server_t // broadcast_ctx_t refers to control_server_t
// Therefore, iterate is implemented further down the source file // Therefore, iterate is implemented further down the source file
void iterate(std::chrono::milliseconds timeout); void
iterate(std::chrono::milliseconds timeout);
void call(std::uint16_t type, session_t *session, const std::string_view &payload); void
call(std::uint16_t type, session_t *session, const std::string_view &payload);
void map(uint16_t type, std::function<void(session_t *, const std::string_view &)> cb) { void
map(uint16_t type, std::function<void(session_t *, const std::string_view &)> cb) {
_map_type_cb.emplace(type, std::move(cb)); _map_type_cb.emplace(type, std::move(cb));
} }
int send(const std::string_view &payload, net::peer_t peer) { int
send(const std::string_view &payload, net::peer_t peer) {
auto packet = enet_packet_create(payload.data(), payload.size(), ENET_PACKET_FLAG_RELIABLE); auto packet = enet_packet_create(payload.data(), payload.size(), ENET_PACKET_FLAG_RELIABLE);
if (enet_peer_send(peer, 0, packet)) { if (enet_peer_send(peer, 0, packet)) {
enet_packet_destroy(packet); enet_packet_destroy(packet);
@@ -244,7 +260,8 @@ public:
return 0; return 0;
} }
void flush() { void
flush() {
enet_host_flush(_host.get()); enet_host_flush(_host.get());
} }
@@ -341,12 +358,12 @@ struct session_t {
* returns string_view pointing to payload data * returns string_view pointing to payload data
*/ */
template <std::size_t max_payload_size> template <std::size_t max_payload_size>
static inline std::string_view encode_control(session_t *session, const std::string_view &plaintext, std::array<std::uint8_t, max_payload_size> &tagged_cipher) { static inline std::string_view
encode_control(session_t *session, const std::string_view &plaintext, std::array<std::uint8_t, max_payload_size> &tagged_cipher) {
static_assert( static_assert(
max_payload_size >= sizeof(control_encrypted_t) + sizeof(crypto::cipher::tag_size), max_payload_size >= sizeof(control_encrypted_t) + sizeof(crypto::cipher::tag_size),
"max_payload_size >= sizeof(control_encrypted_t) + sizeof(crypto::cipher::tag_size)"); "max_payload_size >= sizeof(control_encrypted_t) + sizeof(crypto::cipher::tag_size)");
if (session->config.controlProtocolType != 13) { if (session->config.controlProtocolType != 13) {
return plaintext; return plaintext;
} }
@@ -372,13 +389,15 @@ static inline std::string_view encode_control(session_t *session, const std::str
return std::string_view { (char *) tagged_cipher.data(), packet_length + sizeof(control_encrypted_t) - sizeof(control_encrypted_t::seq) }; return std::string_view { (char *) tagged_cipher.data(), packet_length + sizeof(control_encrypted_t) - sizeof(control_encrypted_t::seq) };
} }
int start_broadcast(broadcast_ctx_t &ctx); int
void end_broadcast(broadcast_ctx_t &ctx); start_broadcast(broadcast_ctx_t &ctx);
void
end_broadcast(broadcast_ctx_t &ctx);
static auto broadcast = safe::make_shared<broadcast_ctx_t>(start_broadcast, end_broadcast); static auto broadcast = safe::make_shared<broadcast_ctx_t>(start_broadcast, end_broadcast);
session_t *control_server_t::get_session(const net::peer_t peer) { session_t *
control_server_t::get_session(const net::peer_t peer) {
TUPLE_2D(port, addr_string, platf::from_sockaddr_ex((sockaddr *) &peer->address.address)); TUPLE_2D(port, addr_string, platf::from_sockaddr_ex((sockaddr *) &peer->address.address));
auto lg = _map_addr_session.lock(); auto lg = _map_addr_session.lock();
@@ -408,7 +427,8 @@ session_t *control_server_t::get_session(const net::peer_t peer) {
return nullptr; return nullptr;
} }
void control_server_t::call(std::uint16_t type, session_t *session, const std::string_view &payload) { void
control_server_t::call(std::uint16_t type, session_t *session, const std::string_view &payload) {
auto cb = _map_type_cb.find(type); auto cb = _map_type_cb.find(type);
if (cb == std::end(_map_type_cb)) { if (cb == std::end(_map_type_cb)) {
BOOST_LOG(debug) BOOST_LOG(debug)
@@ -422,7 +442,8 @@ void control_server_t::call(std::uint16_t type, session_t *session, const std::s
} }
} }
void control_server_t::iterate(std::chrono::milliseconds timeout) { void
control_server_t::iterate(std::chrono::milliseconds timeout) {
ENetEvent event; ENetEvent event;
auto res = enet_host_service(_host.get(), &event, timeout.count()); auto res = enet_host_service(_host.get(), &event, timeout.count());
@@ -473,20 +494,24 @@ struct fec_t {
size_t blocksize; size_t blocksize;
util::buffer_t<char> shards; util::buffer_t<char> shards;
char *data(size_t el) { char *
data(size_t el) {
return &shards[el * blocksize]; return &shards[el * blocksize];
} }
std::string_view operator[](size_t el) const { std::string_view
operator[](size_t el) const {
return { &shards[el * blocksize], blocksize }; return { &shards[el * blocksize], blocksize };
} }
size_t size() const { size_t
size() const {
return nr_shards; return nr_shards;
} }
}; };
static fec_t encode(const std::string_view &payload, size_t blocksize, size_t fecpercentage, size_t minparityshards) { static fec_t
encode(const std::string_view &payload, size_t blocksize, size_t fecpercentage, size_t minparityshards) {
auto payload_size = payload.size(); auto payload_size = payload.size();
auto pad = payload_size % blocksize != 0; auto pad = payload_size % blocksize != 0;
@@ -542,7 +567,8 @@ static fec_t encode(const std::string_view &payload, size_t blocksize, size_t fe
} // namespace fec } // namespace fec
template <class F> template <class F>
std::vector<uint8_t> insert(uint64_t insert_size, uint64_t slice_size, const std::string_view &data, F &&f) { std::vector<uint8_t>
insert(uint64_t insert_size, uint64_t slice_size, const std::string_view &data, F &&f) {
auto pad = data.size() % slice_size != 0; auto pad = data.size() % slice_size != 0;
auto elements = data.size() / slice_size + (pad ? 1 : 0); auto elements = data.size() / slice_size + (pad ? 1 : 0);
@@ -569,7 +595,8 @@ std::vector<uint8_t> insert(uint64_t insert_size, uint64_t slice_size, const std
return result; return result;
} }
std::vector<uint8_t> replace(const std::string_view &original, const std::string_view &old, const std::string_view &_new) { std::vector<uint8_t>
replace(const std::string_view &original, const std::string_view &old, const std::string_view &_new) {
std::vector<uint8_t> replaced; std::vector<uint8_t> replaced;
auto begin = std::begin(original); auto begin = std::begin(original);
@@ -585,7 +612,8 @@ std::vector<uint8_t> replace(const std::string_view &original, const std::string
return replaced; return replaced;
} }
int send_rumble(session_t *session, std::uint16_t id, std::uint16_t lowfreq, std::uint16_t highfreq) { int
send_rumble(session_t *session, std::uint16_t id, std::uint16_t lowfreq, std::uint16_t highfreq) {
if (!session->control.peer) { if (!session->control.peer) {
BOOST_LOG(warning) << "Couldn't send rumble data, still waiting for PING from Moonlight"sv; BOOST_LOG(warning) << "Couldn't send rumble data, still waiting for PING from Moonlight"sv;
// Still waiting for PING from Moonlight // Still waiting for PING from Moonlight
@@ -619,7 +647,8 @@ int send_rumble(session_t *session, std::uint16_t id, std::uint16_t lowfreq, std
return 0; return 0;
} }
int send_hdr_mode(session_t *session, video::hdr_info_t hdr_info) { int
send_hdr_mode(session_t *session, video::hdr_info_t hdr_info) {
if (!session->control.peer) { if (!session->control.peer) {
BOOST_LOG(warning) << "Couldn't send HDR mode, still waiting for PING from Moonlight"sv; BOOST_LOG(warning) << "Couldn't send HDR mode, still waiting for PING from Moonlight"sv;
// Still waiting for PING from Moonlight // Still waiting for PING from Moonlight
@@ -649,7 +678,8 @@ int send_hdr_mode(session_t *session, video::hdr_info_t hdr_info) {
return 0; return 0;
} }
void controlBroadcastThread(control_server_t *server) { void
controlBroadcastThread(control_server_t *server) {
server->map(packetTypes[IDX_PERIODIC_PING], [](session_t *session, const std::string_view &payload) { server->map(packetTypes[IDX_PERIODIC_PING], [](session_t *session, const std::string_view &payload) {
BOOST_LOG(verbose) << "type [IDX_START_A]"sv; BOOST_LOG(verbose) << "type [IDX_START_A]"sv;
}); });
@@ -874,7 +904,8 @@ void controlBroadcastThread(control_server_t *server) {
server->flush(); server->flush();
} }
void recvThread(broadcast_ctx_t &ctx) { void
recvThread(broadcast_ctx_t &ctx) {
std::map<asio::ip::address, message_queue_t> peer_to_video_session; std::map<asio::ip::address, message_queue_t> peer_to_video_session;
std::map<asio::ip::address, message_queue_t> peer_to_audio_session; std::map<asio::ip::address, message_queue_t> peer_to_audio_session;
@@ -926,7 +957,6 @@ void recvThread(broadcast_ctx_t &ctx) {
auto type_str = buf_elem ? "AUDIO"sv : "VIDEO"sv; auto type_str = buf_elem ? "AUDIO"sv : "VIDEO"sv;
BOOST_LOG(verbose) << "Recv: "sv << peer.address().to_string() << ':' << peer.port() << " :: " << type_str; BOOST_LOG(verbose) << "Recv: "sv << peer.address().to_string() << ':' << peer.port() << " :: " << type_str;
populate_peer_to_session(); populate_peer_to_session();
// No data, yet no error // No data, yet no error
@@ -958,7 +988,8 @@ void recvThread(broadcast_ctx_t &ctx) {
} }
} }
void videoBroadcastThread(udp::socket &sock) { void
videoBroadcastThread(udp::socket &sock) {
auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown); auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
auto packets = mail::man->queue<video::packet_t>(mail::video_packets); auto packets = mail::man->queue<video::packet_t>(mail::video_packets);
auto timebase = boost::posix_time::microsec_clock::universal_time(); auto timebase = boost::posix_time::microsec_clock::universal_time();
@@ -1135,7 +1166,8 @@ void videoBroadcastThread(udp::socket &sock) {
shutdown_event->raise(true); shutdown_event->raise(true);
} }
void audioBroadcastThread(udp::socket &sock) { void
audioBroadcastThread(udp::socket &sock) {
auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown); auto shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
auto packets = mail::man->queue<audio::packet_t>(mail::audio_packets); auto packets = mail::man->queue<audio::packet_t>(mail::audio_packets);
@@ -1192,7 +1224,6 @@ void audioBroadcastThread(udp::socket &sock) {
try { try {
sock.send_to(asio::buffer((char *) audio_packet.get(), sizeof(audio_packet_raw_t) + bytes), session->audio.peer); sock.send_to(asio::buffer((char *) audio_packet.get(), sizeof(audio_packet_raw_t) + bytes), session->audio.peer);
BOOST_LOG(verbose) << "Audio ["sv << sequenceNumber << "] :: send..."sv; BOOST_LOG(verbose) << "Audio ["sv << sequenceNumber << "] :: send..."sv;
auto &fec_packet = session->audio.fec_packet; auto &fec_packet = session->audio.fec_packet;
@@ -1224,7 +1255,8 @@ void audioBroadcastThread(udp::socket &sock) {
shutdown_event->raise(true); shutdown_event->raise(true);
} }
int start_broadcast(broadcast_ctx_t &ctx) { int
start_broadcast(broadcast_ctx_t &ctx) {
auto control_port = map_port(CONTROL_PORT); auto control_port = map_port(CONTROL_PORT);
auto video_port = map_port(VIDEO_STREAM_PORT); auto video_port = map_port(VIDEO_STREAM_PORT);
auto audio_port = map_port(AUDIO_STREAM_PORT); auto audio_port = map_port(AUDIO_STREAM_PORT);
@@ -1275,7 +1307,8 @@ int start_broadcast(broadcast_ctx_t &ctx) {
return 0; return 0;
} }
void end_broadcast(broadcast_ctx_t &ctx) { void
end_broadcast(broadcast_ctx_t &ctx) {
auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown); auto broadcast_shutdown_event = mail::man->event<bool>(mail::broadcast_shutdown);
broadcast_shutdown_event->raise(true); broadcast_shutdown_event->raise(true);
@@ -1309,7 +1342,8 @@ void end_broadcast(broadcast_ctx_t &ctx) {
broadcast_shutdown_event->reset(); broadcast_shutdown_event->reset();
} }
int recv_ping(decltype(broadcast)::ptr_t ref, socket_e type, udp::endpoint &peer, std::chrono::milliseconds timeout) { int
recv_ping(decltype(broadcast)::ptr_t ref, socket_e type, udp::endpoint &peer, std::chrono::milliseconds timeout) {
auto constexpr ping = "PING"sv; auto constexpr ping = "PING"sv;
auto messages = std::make_shared<message_queue_t::element_type>(30); auto messages = std::make_shared<message_queue_t::element_type>(30);
@@ -1378,7 +1412,8 @@ int recv_ping(decltype(broadcast)::ptr_t ref, socket_e type, udp::endpoint &peer
return -1; return -1;
} }
void videoThread(session_t *session) { void
videoThread(session_t *session) {
auto fg = util::fail_guard([&]() { auto fg = util::fail_guard([&]() {
session::stop(*session); session::stop(*session);
}); });
@@ -1402,7 +1437,8 @@ void videoThread(session_t *session) {
video::capture(session->mail, session->config.monitor, session); video::capture(session->mail, session->config.monitor, session);
} }
void audioThread(session_t *session) { void
audioThread(session_t *session) {
auto fg = util::fail_guard([&]() { auto fg = util::fail_guard([&]() {
session::stop(*session); session::stop(*session);
}); });
@@ -1429,11 +1465,13 @@ void audioThread(session_t *session) {
namespace session { namespace session {
std::atomic_uint running_sessions; std::atomic_uint running_sessions;
state_e state(session_t &session) { state_e
state(session_t &session) {
return session.state.load(std::memory_order_relaxed); return session.state.load(std::memory_order_relaxed);
} }
void stop(session_t &session) { void
stop(session_t &session) {
while_starting_do_nothing(session.state); while_starting_do_nothing(session.state);
auto expected = state_e::RUNNING; auto expected = state_e::RUNNING;
auto already_stopping = !session.state.compare_exchange_strong(expected, state_e::STOPPING); auto already_stopping = !session.state.compare_exchange_strong(expected, state_e::STOPPING);
@@ -1444,7 +1482,8 @@ void stop(session_t &session) {
session.shutdown_event->raise(true); session.shutdown_event->raise(true);
} }
void join(session_t &session) { void
join(session_t &session) {
// Current Nvidia drivers have a bug where NVENC can deadlock the encoder thread with hardware-accelerated // Current Nvidia drivers have a bug where NVENC can deadlock the encoder thread with hardware-accelerated
// GPU scheduling enabled. If this happens, we will terminate ourselves and the service can restart. // GPU scheduling enabled. If this happens, we will terminate ourselves and the service can restart.
// The alternative is that Sunshine can never start another session until it's manually restarted. // The alternative is that Sunshine can never start another session until it's manually restarted.
@@ -1512,7 +1551,8 @@ void join(session_t &session) {
BOOST_LOG(debug) << "Session ended"sv; BOOST_LOG(debug) << "Session ended"sv;
} }
int start(session_t &session, const std::string &addr_string) { int
start(session_t &session, const std::string &addr_string) {
session.input = input::alloc(session.mail); session.input = input::alloc(session.mail);
session.broadcast_ref = broadcast.ref(); session.broadcast_ref = broadcast.ref();
@@ -1539,7 +1579,6 @@ int start(session_t &session, const std::string &addr_string) {
connections->emplace_back(addr_string, 0); connections->emplace_back(addr_string, 0);
} }
session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout; session.pingTimeout = std::chrono::steady_clock::now() + config::stream.ping_timeout;
session.audioThread = std::thread { audioThread, &session }; session.audioThread = std::thread { audioThread, &session };
@@ -1555,7 +1594,8 @@ int start(session_t &session, const std::string &addr_string) {
return 0; return 0;
} }
std::shared_ptr<session_t> alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv) { std::shared_ptr<session_t>
alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv) {
auto session = std::make_shared<session_t>(); auto session = std::make_shared<session_t>();
auto mail = std::make_shared<safe::mail_raw_t>(); auto mail = std::make_shared<safe::mail_raw_t>();

View File

@@ -37,11 +37,16 @@ enum class state_e : int {
RUNNING, RUNNING,
}; };
std::shared_ptr<session_t> alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv); std::shared_ptr<session_t>
int start(session_t &session, const std::string &addr_string); alloc(config_t &config, crypto::aes_t &gcm_key, crypto::aes_t &iv);
void stop(session_t &session); int
void join(session_t &session); start(session_t &session, const std::string &addr_string);
state_e state(session_t &session); void
stop(session_t &session);
void
join(session_t &session);
state_e
state(session_t &session);
} // namespace session } // namespace session
} // namespace stream } // namespace stream

View File

@@ -15,14 +15,17 @@ public:
using value_t = T; using value_t = T;
using mutex_t = M; using mutex_t = M;
std::lock_guard<mutex_t> lock() { std::lock_guard<mutex_t>
lock() {
return std::lock_guard { _lock }; return std::lock_guard { _lock };
} }
template <class... Args> template <class... Args>
sync_t(Args &&...args) : raw { std::forward<Args>(args)... } {} sync_t(Args &&...args):
raw { std::forward<Args>(args)... } {}
sync_t &operator=(sync_t &&other) noexcept { sync_t &
operator=(sync_t &&other) noexcept {
std::lock(_lock, other._lock); std::lock(_lock, other._lock);
raw = std::move(other.raw); raw = std::move(other.raw);
@@ -33,7 +36,8 @@ public:
return *this; return *this;
} }
sync_t &operator=(sync_t &other) noexcept { sync_t &
operator=(sync_t &other) noexcept {
std::lock(_lock, other._lock); std::lock(_lock, other._lock);
raw = other.raw; raw = other.raw;
@@ -45,7 +49,8 @@ public:
} }
template <class V> template <class V>
sync_t &operator=(V &&val) { sync_t &
operator=(V &&val) {
auto lg = lock(); auto lg = lock();
raw = val; raw = val;
@@ -53,7 +58,8 @@ public:
return *this; return *this;
} }
sync_t &operator=(const value_t &val) noexcept { sync_t &
operator=(const value_t &val) noexcept {
auto lg = lock(); auto lg = lock();
raw = val; raw = val;
@@ -61,7 +67,8 @@ public:
return *this; return *this;
} }
sync_t &operator=(value_t &&val) noexcept { sync_t &
operator=(value_t &&val) noexcept {
auto lg = lock(); auto lg = lock();
raw = std::move(val); raw = std::move(val);
@@ -69,15 +76,18 @@ public:
return *this; return *this;
} }
value_t *operator->() { value_t *
operator->() {
return &raw; return &raw;
} }
value_t &operator*() { value_t &
operator*() {
return raw; return raw;
} }
const value_t &operator*() const { const value_t &
operator*() const {
return raw; return raw;
} }
@@ -89,5 +99,4 @@ private:
} // namespace sync_util } // namespace sync_util
#endif // SUNSHINE_SYNC_H #endif // SUNSHINE_SYNC_H

View File

@@ -37,7 +37,8 @@ namespace system_tray {
* @brief Open a url in the default web browser. * @brief Open a url in the default web browser.
* @param url The url to open. * @param url The url to open.
*/ */
void open_url(const std::string &url) { void
open_url(const std::string &url) {
boost::filesystem::path working_dir; boost::filesystem::path working_dir;
// if windows // if windows
@@ -70,7 +71,8 @@ void open_url(const std::string &url) {
* @brief Callback for opening the UI from the system tray. * @brief Callback for opening the UI from the system tray.
* @param item The tray menu item. * @param item The tray menu item.
*/ */
void tray_open_ui_cb(struct tray_menu *item) { void
tray_open_ui_cb(struct tray_menu *item) {
BOOST_LOG(info) << "Opening UI from system tray"sv; BOOST_LOG(info) << "Opening UI from system tray"sv;
// create the url with the port // create the url with the port
@@ -84,7 +86,8 @@ void tray_open_ui_cb(struct tray_menu *item) {
* @brief Callback for opening GitHub Sponsors from the system tray. * @brief Callback for opening GitHub Sponsors from the system tray.
* @param item The tray menu item. * @param item The tray menu item.
*/ */
void tray_donate_github_cb(struct tray_menu *item) { void
tray_donate_github_cb(struct tray_menu *item) {
open_url("https://github.com/sponsors/LizardByte"); open_url("https://github.com/sponsors/LizardByte");
} }
@@ -92,7 +95,8 @@ void tray_donate_github_cb(struct tray_menu *item) {
* @brief Callback for opening MEE6 donation from the system tray. * @brief Callback for opening MEE6 donation from the system tray.
* @param item The tray menu item. * @param item The tray menu item.
*/ */
void tray_donate_mee6_cb(struct tray_menu *item) { void
tray_donate_mee6_cb(struct tray_menu *item) {
open_url("https://mee6.xyz/m/804382334370578482"); open_url("https://mee6.xyz/m/804382334370578482");
} }
@@ -100,7 +104,8 @@ void tray_donate_mee6_cb(struct tray_menu *item) {
* @brief Callback for opening Patreon from the system tray. * @brief Callback for opening Patreon from the system tray.
* @param item The tray menu item. * @param item The tray menu item.
*/ */
void tray_donate_patreon_cb(struct tray_menu *item) { void
tray_donate_patreon_cb(struct tray_menu *item) {
open_url("https://www.patreon.com/LizardByte"); open_url("https://www.patreon.com/LizardByte");
} }
@@ -108,7 +113,8 @@ void tray_donate_patreon_cb(struct tray_menu *item) {
* @brief Callback for opening PayPal donation from the system tray. * @brief Callback for opening PayPal donation from the system tray.
* @param item The tray menu item. * @param item The tray menu item.
*/ */
void tray_donate_paypal_cb(struct tray_menu *item) { void
tray_donate_paypal_cb(struct tray_menu *item) {
open_url("https://www.paypal.com/paypalme/ReenigneArcher"); open_url("https://www.paypal.com/paypalme/ReenigneArcher");
} }
@@ -116,7 +122,8 @@ void tray_donate_paypal_cb(struct tray_menu *item) {
* @brief Callback for exiting Sunshine from the system tray. * @brief Callback for exiting Sunshine from the system tray.
* @param item The tray menu item. * @param item The tray menu item.
*/ */
void tray_quit_cb(struct tray_menu *item) { void
tray_quit_cb(struct tray_menu *item) {
BOOST_LOG(info) << "Quiting from system tray"sv; BOOST_LOG(info) << "Quiting from system tray"sv;
std::raise(SIGINT); std::raise(SIGINT);
@@ -146,13 +153,13 @@ static struct tray tray = {
{ .text = nullptr } }, { .text = nullptr } },
}; };
/** /**
* @brief Create the system tray. * @brief Create the system tray.
* @details This function has an endless loop, so it should be run in a separate thread. * @details This function has an endless loop, so it should be run in a separate thread.
* @return 1 if the system tray failed to create, otherwise 0 once the tray has been terminated. * @return 1 if the system tray failed to create, otherwise 0 once the tray has been terminated.
*/ */
int system_tray() { int
system_tray() {
if (tray_init(&tray) < 0) { if (tray_init(&tray) < 0) {
BOOST_LOG(warning) << "Failed to create system tray"sv; BOOST_LOG(warning) << "Failed to create system tray"sv;
return 1; return 1;
@@ -172,7 +179,8 @@ int system_tray() {
* @brief Run the system tray with platform specific options. * @brief Run the system tray with platform specific options.
* @note macOS requires that UI elements be created on the main thread, so the system tray is not implemented for macOS. * @note macOS requires that UI elements be created on the main thread, so the system tray is not implemented for macOS.
*/ */
void run_tray() { void
run_tray() {
// create the system tray // create the system tray
#if defined(__APPLE__) || defined(__MACH__) #if defined(__APPLE__) || defined(__MACH__)
// macOS requires that UI elements be created on the main thread // macOS requires that UI elements be created on the main thread
@@ -194,7 +202,8 @@ void run_tray() {
* @brief Exit the system tray. * @brief Exit the system tray.
* @return 0 after exiting the system tray. * @return 0 after exiting the system tray.
*/ */
int end_tray() { int
end_tray() {
tray_exit(); tray_exit();
return 0; return 0;
} }

View File

@@ -7,17 +7,27 @@
// system_tray namespace // system_tray namespace
namespace system_tray { namespace system_tray {
void open_url(const std::string &url); void
void tray_open_ui_cb(struct tray_menu *item); open_url(const std::string &url);
void tray_donate_github_cb(struct tray_menu *item); void
void tray_donate_mee6_cb(struct tray_menu *item); tray_open_ui_cb(struct tray_menu *item);
void tray_donate_patreon_cb(struct tray_menu *item); void
void tray_donate_paypal_cb(struct tray_menu *item); tray_donate_github_cb(struct tray_menu *item);
void tray_quit_cb(struct tray_menu *item); void
tray_donate_mee6_cb(struct tray_menu *item);
void
tray_donate_patreon_cb(struct tray_menu *item);
void
tray_donate_paypal_cb(struct tray_menu *item);
void
tray_quit_cb(struct tray_menu *item);
int system_tray(); int
int run_tray(); system_tray();
int end_tray(); int
run_tray();
int
end_tray();
} // namespace system_tray } // namespace system_tray
#endif #endif

View File

@@ -21,7 +21,8 @@ public:
inline virtual ~_ImplBase() = default; inline virtual ~_ImplBase() = default;
virtual void run() = 0; virtual void
run() = 0;
}; };
template <class Function> template <class Function>
@@ -29,9 +30,11 @@ class _Impl : public _ImplBase {
Function _func; Function _func;
public: public:
_Impl(Function &&f) : _func(std::forward<Function>(f)) {} _Impl(Function &&f):
_func(std::forward<Function>(f)) {}
void run() override { void
run() override {
_func(); _func();
} }
}; };
@@ -41,7 +44,6 @@ public:
typedef std::unique_ptr<_ImplBase> __task; typedef std::unique_ptr<_ImplBase> __task;
typedef _ImplBase *task_id_t; typedef _ImplBase *task_id_t;
typedef std::chrono::steady_clock::time_point __time_point; typedef std::chrono::steady_clock::time_point __time_point;
template <class R> template <class R>
@@ -50,7 +52,8 @@ public:
task_id_t task_id; task_id_t task_id;
std::future<R> future; std::future<R> future;
timer_task_t(task_id_t task_id, std::future<R> &future) : task_id { task_id }, future { std::move(future) } {} timer_task_t(task_id_t task_id, std::future<R> &future):
task_id { task_id }, future { std::move(future) } {}
}; };
protected: protected:
@@ -60,9 +63,11 @@ protected:
public: public:
TaskPool() = default; TaskPool() = default;
TaskPool(TaskPool &&other) noexcept : _tasks { std::move(other._tasks) }, _timer_tasks { std::move(other._timer_tasks) } {} TaskPool(TaskPool &&other) noexcept:
_tasks { std::move(other._tasks) }, _timer_tasks { std::move(other._timer_tasks) } {}
TaskPool &operator=(TaskPool &&other) noexcept { TaskPool &
operator=(TaskPool &&other) noexcept {
std::swap(_tasks, other._tasks); std::swap(_tasks, other._tasks);
std::swap(_timer_tasks, other._timer_tasks); std::swap(_timer_tasks, other._timer_tasks);
@@ -70,7 +75,8 @@ public:
} }
template <class Function, class... Args> template <class Function, class... Args>
auto push(Function &&newTask, Args &&...args) { auto
push(Function &&newTask, Args &&...args) {
static_assert(std::is_invocable_v<Function, Args &&...>, "arguments don't match the function"); static_assert(std::is_invocable_v<Function, Args &&...>, "arguments don't match the function");
using __return = std::invoke_result_t<Function, Args &&...>; using __return = std::invoke_result_t<Function, Args &&...>;
@@ -90,7 +96,8 @@ public:
return future; return future;
} }
void pushDelayed(std::pair<__time_point, __task> &&task) { void
pushDelayed(std::pair<__time_point, __task> &&task) {
std::lock_guard lg(_task_mutex); std::lock_guard lg(_task_mutex);
auto it = _timer_tasks.cbegin(); auto it = _timer_tasks.cbegin();
@@ -107,7 +114,8 @@ public:
* @return an id to potentially delay the task * @return an id to potentially delay the task
*/ */
template <class Function, class X, class Y, class... Args> template <class Function, class X, class Y, class... Args>
auto pushDelayed(Function &&newTask, std::chrono::duration<X, Y> duration, Args &&...args) { auto
pushDelayed(Function &&newTask, std::chrono::duration<X, Y> duration, Args &&...args) {
static_assert(std::is_invocable_v<Function, Args &&...>, "arguments don't match the function"); static_assert(std::is_invocable_v<Function, Args &&...>, "arguments don't match the function");
using __return = std::invoke_result_t<Function, Args &&...>; using __return = std::invoke_result_t<Function, Args &&...>;
@@ -141,7 +149,8 @@ public:
* @param duration The delay before executing the task * @param duration The delay before executing the task
*/ */
template <class X, class Y> template <class X, class Y>
void delay(task_id_t task_id, std::chrono::duration<X, Y> duration) { void
delay(task_id_t task_id, std::chrono::duration<X, Y> duration) {
std::lock_guard<std::mutex> lg(_task_mutex); std::lock_guard<std::mutex> lg(_task_mutex);
auto it = _timer_tasks.begin(); auto it = _timer_tasks.begin();
@@ -171,7 +180,8 @@ public:
} }
} }
bool cancel(task_id_t task_id) { bool
cancel(task_id_t task_id) {
std::lock_guard lg(_task_mutex); std::lock_guard lg(_task_mutex);
auto it = _timer_tasks.begin(); auto it = _timer_tasks.begin();
@@ -188,7 +198,8 @@ public:
return false; return false;
} }
std::optional<std::pair<__time_point, __task>> pop(task_id_t task_id) { std::optional<std::pair<__time_point, __task>>
pop(task_id_t task_id) {
std::lock_guard lg(_task_mutex); std::lock_guard lg(_task_mutex);
auto pos = std::find_if(std::begin(_timer_tasks), std::end(_timer_tasks), [&task_id](const auto &t) { return t.second.get() == task_id; }); auto pos = std::find_if(std::begin(_timer_tasks), std::end(_timer_tasks), [&task_id](const auto &t) { return t.second.get() == task_id; });
@@ -200,7 +211,8 @@ public:
return std::move(*pos); return std::move(*pos);
} }
std::optional<__task> pop() { std::optional<__task>
pop() {
std::lock_guard lg(_task_mutex); std::lock_guard lg(_task_mutex);
if (!_tasks.empty()) { if (!_tasks.empty()) {
@@ -219,13 +231,15 @@ public:
return std::nullopt; return std::nullopt;
} }
bool ready() { bool
ready() {
std::lock_guard<std::mutex> lg(_task_mutex); std::lock_guard<std::mutex> lg(_task_mutex);
return !_tasks.empty() || (!_timer_tasks.empty() && std::get<0>(_timer_tasks.back()) <= std::chrono::steady_clock::now()); return !_tasks.empty() || (!_timer_tasks.empty() && std::get<0>(_timer_tasks.back()) <= std::chrono::steady_clock::now());
} }
std::optional<__time_point> next() { std::optional<__time_point>
next() {
std::lock_guard<std::mutex> lg(_task_mutex); std::lock_guard<std::mutex> lg(_task_mutex);
if (_timer_tasks.empty()) { if (_timer_tasks.empty()) {
@@ -237,7 +251,8 @@ public:
private: private:
template <class Function> template <class Function>
std::unique_ptr<_ImplBase> toRunnable(Function &&f) { std::unique_ptr<_ImplBase>
toRunnable(Function &&f) {
return std::make_unique<_Impl<Function>>(std::forward<Function &&>(f)); return std::make_unique<_Impl<Function>>(std::forward<Function &&>(f));
} }
}; };

View File

@@ -22,9 +22,11 @@ private:
bool _continue; bool _continue;
public: public:
ThreadPool() : _continue { false } {} ThreadPool():
_continue { false } {}
explicit ThreadPool(int threads) : _thread(threads), _continue { true } { explicit ThreadPool(int threads):
_thread(threads), _continue { true } {
for (auto &t : _thread) { for (auto &t : _thread) {
t = std::thread(&ThreadPool::_main, this); t = std::thread(&ThreadPool::_main, this);
} }
@@ -38,7 +40,8 @@ public:
} }
template <class Function, class... Args> template <class Function, class... Args>
auto push(Function &&newTask, Args &&...args) { auto
push(Function &&newTask, Args &&...args) {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
auto future = TaskPool::push(std::forward<Function>(newTask), std::forward<Args>(args)...); auto future = TaskPool::push(std::forward<Function>(newTask), std::forward<Args>(args)...);
@@ -46,14 +49,16 @@ public:
return future; return future;
} }
void pushDelayed(std::pair<__time_point, __task> &&task) { void
pushDelayed(std::pair<__time_point, __task> &&task) {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
TaskPool::pushDelayed(std::move(task)); TaskPool::pushDelayed(std::move(task));
} }
template <class Function, class X, class Y, class... Args> template <class Function, class X, class Y, class... Args>
auto pushDelayed(Function &&newTask, std::chrono::duration<X, Y> duration, Args &&...args) { auto
pushDelayed(Function &&newTask, std::chrono::duration<X, Y> duration, Args &&...args) {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
auto future = TaskPool::pushDelayed(std::forward<Function>(newTask), duration, std::forward<Args>(args)...); auto future = TaskPool::pushDelayed(std::forward<Function>(newTask), duration, std::forward<Args>(args)...);
@@ -62,7 +67,8 @@ public:
return future; return future;
} }
void start(int threads) { void
start(int threads) {
_continue = true; _continue = true;
_thread.resize(threads); _thread.resize(threads);
@@ -72,21 +78,24 @@ public:
} }
} }
void stop() { void
stop() {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
_continue = false; _continue = false;
_cv.notify_all(); _cv.notify_all();
} }
void join() { void
join() {
for (auto &t : _thread) { for (auto &t : _thread) {
t.join(); t.join();
} }
} }
public: public:
void _main() { void
_main() {
while (_continue) { while (_continue) {
if (auto task = this->pop()) { if (auto task = this->pop()) {
(*task)->run(); (*task)->run();

View File

@@ -19,7 +19,8 @@ public:
using status_t = util::optional_t<T>; using status_t = util::optional_t<T>;
template <class... Args> template <class... Args>
void raise(Args &&...args) { void
raise(Args &&...args) {
std::lock_guard lg { _lock }; std::lock_guard lg { _lock };
if (!_continue) { if (!_continue) {
return; return;
@@ -36,7 +37,8 @@ public:
} }
// pop and view shoud not be used interchangeably // pop and view shoud not be used interchangeably
status_t pop() { status_t
pop() {
std::unique_lock ul { _lock }; std::unique_lock ul { _lock };
if (!_continue) { if (!_continue) {
@@ -58,7 +60,8 @@ public:
// pop and view shoud not be used interchangeably // pop and view shoud not be used interchangeably
template <class Rep, class Period> template <class Rep, class Period>
status_t pop(std::chrono::duration<Rep, Period> delay) { status_t
pop(std::chrono::duration<Rep, Period> delay) {
std::unique_lock ul { _lock }; std::unique_lock ul { _lock };
if (!_continue) { if (!_continue) {
@@ -77,7 +80,8 @@ public:
} }
// pop and view shoud not be used interchangeably // pop and view shoud not be used interchangeably
const status_t &view() { const status_t &
view() {
std::unique_lock ul { _lock }; std::unique_lock ul { _lock };
if (!_continue) { if (!_continue) {
@@ -95,11 +99,13 @@ public:
return _status; return _status;
} }
bool peek() { bool
peek() {
return _continue && (bool) _status; return _continue && (bool) _status;
} }
void stop() { void
stop() {
std::lock_guard lg { _lock }; std::lock_guard lg { _lock };
_continue = false; _continue = false;
@@ -107,7 +113,8 @@ public:
_cv.notify_all(); _cv.notify_all();
} }
void reset() { void
reset() {
std::lock_guard lg { _lock }; std::lock_guard lg { _lock };
_continue = true; _continue = true;
@@ -115,7 +122,8 @@ public:
_status = util::false_v<status_t>; _status = util::false_v<status_t>;
} }
[[nodiscard]] bool running() const { [[nodiscard]] bool
running() const {
return _continue; return _continue;
} }
@@ -132,16 +140,19 @@ class alarm_raw_t {
public: public:
using status_t = util::optional_t<T>; using status_t = util::optional_t<T>;
alarm_raw_t() : _status { util::false_v<status_t> } {} alarm_raw_t():
_status { util::false_v<status_t> } {}
void ring(const status_t &status) { void
ring(const status_t &status) {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
_status = status; _status = status;
_cv.notify_one(); _cv.notify_one();
} }
void ring(status_t &&status) { void
ring(status_t &&status) {
std::lock_guard lg(_lock); std::lock_guard lg(_lock);
_status = std::move(status); _status = std::move(status);
@@ -149,53 +160,62 @@ public:
} }
template <class Rep, class Period> template <class Rep, class Period>
auto wait_for(const std::chrono::duration<Rep, Period> &rel_time) { auto
wait_for(const std::chrono::duration<Rep, Period> &rel_time) {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
return _cv.wait_for(ul, rel_time, [this]() { return (bool) status(); }); return _cv.wait_for(ul, rel_time, [this]() { return (bool) status(); });
} }
template <class Rep, class Period, class Pred> template <class Rep, class Period, class Pred>
auto wait_for(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) { auto
wait_for(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
return _cv.wait_for(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); }); return _cv.wait_for(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); });
} }
template <class Rep, class Period> template <class Rep, class Period>
auto wait_until(const std::chrono::duration<Rep, Period> &rel_time) { auto
wait_until(const std::chrono::duration<Rep, Period> &rel_time) {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
return _cv.wait_until(ul, rel_time, [this]() { return (bool) status(); }); return _cv.wait_until(ul, rel_time, [this]() { return (bool) status(); });
} }
template <class Rep, class Period, class Pred> template <class Rep, class Period, class Pred>
auto wait_until(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) { auto
wait_until(const std::chrono::duration<Rep, Period> &rel_time, Pred &&pred) {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
return _cv.wait_until(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); }); return _cv.wait_until(ul, rel_time, [this, &pred]() { return (bool) status() || pred(); });
} }
auto wait() { auto
wait() {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
_cv.wait(ul, [this]() { return (bool) status(); }); _cv.wait(ul, [this]() { return (bool) status(); });
} }
template <class Pred> template <class Pred>
auto wait(Pred &&pred) { auto
wait(Pred &&pred) {
std::unique_lock ul(_lock); std::unique_lock ul(_lock);
_cv.wait(ul, [this, &pred]() { return (bool) status() || pred(); }); _cv.wait(ul, [this, &pred]() { return (bool) status() || pred(); });
} }
const status_t &status() const { const status_t &
status() const {
return _status; return _status;
} }
status_t &status() { status_t &
status() {
return _status; return _status;
} }
void reset() { void
reset() {
_status = status_t {}; _status = status_t {};
} }
@@ -210,7 +230,8 @@ template<class T>
using alarm_t = std::shared_ptr<alarm_raw_t<T>>; using alarm_t = std::shared_ptr<alarm_raw_t<T>>;
template <class T> template <class T>
alarm_t<T> make_alarm() { alarm_t<T>
make_alarm() {
return std::make_shared<alarm_raw_t<T>>(); return std::make_shared<alarm_raw_t<T>>();
} }
@@ -219,10 +240,12 @@ class queue_t {
public: public:
using status_t = util::optional_t<T>; using status_t = util::optional_t<T>;
queue_t(std::uint32_t max_elements = 32) : _max_elements { max_elements } {} queue_t(std::uint32_t max_elements = 32):
_max_elements { max_elements } {}
template <class... Args> template <class... Args>
void raise(Args &&...args) { void
raise(Args &&...args) {
std::lock_guard ul { _lock }; std::lock_guard ul { _lock };
if (!_continue) { if (!_continue) {
@@ -238,12 +261,14 @@ public:
_cv.notify_all(); _cv.notify_all();
} }
bool peek() { bool
peek() {
return _continue && !_queue.empty(); return _continue && !_queue.empty();
} }
template <class Rep, class Period> template <class Rep, class Period>
status_t pop(std::chrono::duration<Rep, Period> delay) { status_t
pop(std::chrono::duration<Rep, Period> delay) {
std::unique_lock ul { _lock }; std::unique_lock ul { _lock };
if (!_continue) { if (!_continue) {
@@ -262,7 +287,8 @@ public:
return val; return val;
} }
status_t pop() { status_t
pop() {
std::unique_lock ul { _lock }; std::unique_lock ul { _lock };
if (!_continue) { if (!_continue) {
@@ -283,11 +309,13 @@ public:
return val; return val;
} }
std::vector<T> &unsafe() { std::vector<T> &
unsafe() {
return _queue; return _queue;
} }
void stop() { void
stop() {
std::lock_guard lg { _lock }; std::lock_guard lg { _lock };
_continue = false; _continue = false;
@@ -295,7 +323,8 @@ public:
_cv.notify_all(); _cv.notify_all();
} }
[[nodiscard]] bool running() const { [[nodiscard]] bool
running() const {
return _continue; return _continue;
} }
@@ -320,14 +349,18 @@ public:
struct ptr_t { struct ptr_t {
shared_t *owner; shared_t *owner;
ptr_t() : owner { nullptr } {} ptr_t():
explicit ptr_t(shared_t *owner) : owner { owner } {} owner { nullptr } {}
explicit ptr_t(shared_t *owner):
owner { owner } {}
ptr_t(ptr_t &&ptr) noexcept : owner { ptr.owner } { ptr_t(ptr_t &&ptr) noexcept:
owner { ptr.owner } {
ptr.owner = nullptr; ptr.owner = nullptr;
} }
ptr_t(const ptr_t &ptr) noexcept : owner { ptr.owner } { ptr_t(const ptr_t &ptr) noexcept:
owner { ptr.owner } {
if (!owner) { if (!owner) {
return; return;
} }
@@ -336,7 +369,8 @@ public:
tmp.owner = nullptr; tmp.owner = nullptr;
} }
ptr_t &operator=(const ptr_t &ptr) noexcept { ptr_t &
operator=(const ptr_t &ptr) noexcept {
if (!ptr.owner) { if (!ptr.owner) {
release(); release();
@@ -346,7 +380,8 @@ public:
return *this = std::move(*ptr.owner->ref()); return *this = std::move(*ptr.owner->ref());
} }
ptr_t &operator=(ptr_t &&ptr) noexcept { ptr_t &
operator=(ptr_t &&ptr) noexcept {
if (owner) { if (owner) {
release(); release();
} }
@@ -366,7 +401,8 @@ public:
return owner != nullptr; return owner != nullptr;
} }
void release() { void
release() {
std::lock_guard lg { owner->_lock }; std::lock_guard lg { owner->_lock };
if (!--owner->_count) { if (!--owner->_count) {
@@ -377,18 +413,22 @@ public:
owner = nullptr; owner = nullptr;
} }
element_type *get() const { element_type *
get() const {
return reinterpret_cast<element_type *>(owner->_object_buf.data()); return reinterpret_cast<element_type *>(owner->_object_buf.data());
} }
element_type *operator->() { element_type *
operator->() {
return reinterpret_cast<element_type *>(owner->_object_buf.data()); return reinterpret_cast<element_type *>(owner->_object_buf.data());
} }
}; };
template <class FC, class FD> template <class FC, class FD>
shared_t(FC &&fc, FD &&fd) : _construct { std::forward<FC>(fc) }, _destruct { std::forward<FD>(fd) } {} shared_t(FC &&fc, FD &&fd):
[[nodiscard]] ptr_t ref() { _construct { std::forward<FC>(fc) }, _destruct { std::forward<FD>(fd) } {}
[[nodiscard]] ptr_t
ref() {
std::lock_guard lg { _lock }; std::lock_guard lg { _lock };
if (!_count) { if (!_count) {
@@ -414,7 +454,8 @@ private:
}; };
template <class T, class F_Construct, class F_Destruct> template <class T, class F_Construct, class F_Destruct>
auto make_shared(F_Construct &&fc, F_Destruct &&fd) { auto
make_shared(F_Construct &&fc, F_Destruct &&fd) {
return shared_t<T> { return shared_t<T> {
std::forward<F_Construct>(fc), std::forward<F_Destruct>(fd) std::forward<F_Construct>(fc), std::forward<F_Destruct>(fd)
}; };
@@ -425,12 +466,14 @@ using signal_t = event_t<bool>;
class mail_raw_t; class mail_raw_t;
using mail_t = std::shared_ptr<mail_raw_t>; using mail_t = std::shared_ptr<mail_raw_t>;
void cleanup(mail_raw_t *); void
cleanup(mail_raw_t *);
template <class T> template <class T>
class post_t: public T { class post_t: public T {
public: public:
template <class... Args> template <class... Args>
post_t(mail_t mail, Args &&...args) : T(std::forward<Args>(args)...), mail { std::move(mail) } {} post_t(mail_t mail, Args &&...args):
T(std::forward<Args>(args)...), mail { std::move(mail) } {}
mail_t mail; mail_t mail;
@@ -440,7 +483,8 @@ public:
}; };
template <class T> template <class T>
inline auto lock(const std::weak_ptr<void> &wp) { inline auto
lock(const std::weak_ptr<void> &wp) {
return std::reinterpret_pointer_cast<typename T::element_type>(wp.lock()); return std::reinterpret_pointer_cast<typename T::element_type>(wp.lock());
} }
@@ -453,7 +497,8 @@ public:
using queue_t = std::shared_ptr<post_t<queue_t<T>>>; using queue_t = std::shared_ptr<post_t<queue_t<T>>>;
template <class T> template <class T>
event_t<T> event(const std::string_view &id) { event_t<T>
event(const std::string_view &id) {
std::lock_guard lg { mutex }; std::lock_guard lg { mutex };
auto it = id_to_post.find(id); auto it = id_to_post.find(id);
@@ -468,7 +513,8 @@ public:
} }
template <class T> template <class T>
queue_t<T> queue(const std::string_view &id) { queue_t<T>
queue(const std::string_view &id) {
std::lock_guard lg { mutex }; std::lock_guard lg { mutex };
auto it = id_to_post.find(id); auto it = id_to_post.find(id);
@@ -482,7 +528,8 @@ public:
return post; return post;
} }
void cleanup() { void
cleanup() {
std::lock_guard lg { mutex }; std::lock_guard lg { mutex };
for (auto it = std::begin(id_to_post); it != std::end(id_to_post); ++it) { for (auto it = std::begin(id_to_post); it != std::end(id_to_post); ++it) {
@@ -501,7 +548,8 @@ public:
std::map<std::string, std::weak_ptr<void>, std::less<>> id_to_post; std::map<std::string, std::weak_ptr<void>, std::less<>> id_to_post;
}; };
inline void cleanup(mail_raw_t *mail) { inline void
cleanup(mail_raw_t *mail) {
mail->cleanup(); mail->cleanup();
} }
} // namespace safe } // namespace safe

View File

@@ -35,12 +35,12 @@ struct mapping_t {
bool tcp; bool tcp;
}; };
void unmap( void
unmap(
const urls_t &urls, const urls_t &urls,
const IGDdatas &data, const IGDdatas &data,
std::vector<mapping_t>::const_reverse_iterator begin, std::vector<mapping_t>::const_reverse_iterator begin,
std::vector<mapping_t>::const_reverse_iterator end) { std::vector<mapping_t>::const_reverse_iterator end) {
BOOST_LOG(debug) << "Unmapping UPNP ports"sv; BOOST_LOG(debug) << "Unmapping UPNP ports"sv;
for (auto it = begin; it != end; ++it) { for (auto it = begin; it != end; ++it) {
@@ -61,8 +61,8 @@ void unmap(
class deinit_t: public platf::deinit_t { class deinit_t: public platf::deinit_t {
public: public:
using iter_t = std::vector<mapping_t>::const_reverse_iterator; using iter_t = std::vector<mapping_t>::const_reverse_iterator;
deinit_t(urls_t &&urls, IGDdatas data, std::vector<mapping_t> &&mapping) deinit_t(urls_t &&urls, IGDdatas data, std::vector<mapping_t> &&mapping):
: urls { std::move(urls) }, data { data }, mapping { std::move(mapping) } {} urls { std::move(urls) }, data { data }, mapping { std::move(mapping) } {}
~deinit_t() { ~deinit_t() {
BOOST_LOG(info) << "Unmapping UPNP ports..."sv; BOOST_LOG(info) << "Unmapping UPNP ports..."sv;
@@ -75,7 +75,8 @@ public:
std::vector<mapping_t> mapping; std::vector<mapping_t> mapping;
}; };
static std::string_view status_string(int status) { static std::string_view
status_string(int status) {
switch (status) { switch (status) {
case 0: case 0:
return "No IGD device found"sv; return "No IGD device found"sv;
@@ -90,7 +91,8 @@ static std::string_view status_string(int status) {
return "Unknown status"sv; return "Unknown status"sv;
} }
std::unique_ptr<platf::deinit_t> start() { std::unique_ptr<platf::deinit_t>
start() {
if (!config::sunshine.flags[config::flag::UPNP]) { if (!config::sunshine.flags[config::flag::UPNP]) {
return nullptr; return nullptr;
} }

View File

@@ -4,7 +4,8 @@
#include "platform/common.h" #include "platform/common.h"
namespace upnp { namespace upnp {
[[nodiscard]] std::unique_ptr<platf::deinit_t> start(); [[nodiscard]] std::unique_ptr<platf::deinit_t>
start();
} }
#endif #endif

View File

@@ -40,16 +40,21 @@ struct argument_type<T(U)> {
other.el = element_type { init_val }; \ other.el = element_type { init_val }; \
} \ } \
\ \
move_t &operator=(const move_t &) = delete; \ move_t & \
operator=(const move_t &) = delete; \
\ \
move_t &operator=(move_t &&other) { \ move_t & \
operator=(move_t &&other) { \
std::swap(el, other.el); \ std::swap(el, other.el); \
return *this; \ return *this; \
} \ } \
element_type *operator->() { return &el; } \ element_type * \
const element_type *operator->() const { return &el; } \ operator->() { return &el; } \
const element_type * \
operator->() const { return &el; } \
\ \
inline element_type release() { \ inline element_type \
release() { \
element_type val = std::move(el); \ element_type val = std::move(el); \
el = element_type { init_val }; \ el = element_type { init_val }; \
return val; \ return val; \
@@ -146,8 +151,10 @@ template<class T>
class FailGuard { class FailGuard {
public: public:
FailGuard() = delete; FailGuard() = delete;
FailGuard(T &&f) noexcept : _func { std::forward<T>(f) } {} FailGuard(T &&f) noexcept:
FailGuard(FailGuard &&other) noexcept : _func { std::move(other._func) } { _func { std::forward<T>(f) } {}
FailGuard(FailGuard &&other) noexcept:
_func { std::move(other._func) } {
this->failure = other.failure; this->failure = other.failure;
other.failure = false; other.failure = false;
@@ -155,8 +162,10 @@ public:
FailGuard(const FailGuard &) = delete; FailGuard(const FailGuard &) = delete;
FailGuard &operator=(const FailGuard &) = delete; FailGuard &
FailGuard &operator=(FailGuard &&other) = delete; operator=(const FailGuard &) = delete;
FailGuard &
operator=(FailGuard &&other) = delete;
~FailGuard() noexcept { ~FailGuard() noexcept {
if (failure) { if (failure) {
@@ -164,7 +173,8 @@ public:
} }
} }
void disable() { failure = false; } void
disable() { failure = false; }
bool failure { true }; bool failure { true };
private: private:
@@ -172,12 +182,14 @@ private:
}; };
template <class T> template <class T>
[[nodiscard]] auto fail_guard(T &&f) { [[nodiscard]] auto
fail_guard(T &&f) {
return FailGuard<T> { std::forward<T>(f) }; return FailGuard<T> { std::forward<T>(f) };
} }
template <class T> template <class T>
void append_struct(std::vector<uint8_t> &buf, const T &_struct) { void
append_struct(std::vector<uint8_t> &buf, const T &_struct) {
constexpr size_t data_len = sizeof(_struct); constexpr size_t data_len = sizeof(_struct);
buf.reserve(data_len); buf.reserve(data_len);
@@ -219,34 +231,43 @@ public:
} }
} }
char *begin() { return _hex; } char *
char *end() { return _hex + sizeof(elem_type) * 2; } begin() { return _hex; }
char *
end() { return _hex + sizeof(elem_type) * 2; }
const char *begin() const { return _hex; } const char *
const char *end() const { return _hex + sizeof(elem_type) * 2; } begin() const { return _hex; }
const char *
end() const { return _hex + sizeof(elem_type) * 2; }
const char *cbegin() const { return _hex; } const char *
const char *cend() const { return _hex + sizeof(elem_type) * 2; } cbegin() const { return _hex; }
const char *
cend() const { return _hex + sizeof(elem_type) * 2; }
std::string to_string() const { std::string
to_string() const {
return { begin(), end() }; return { begin(), end() };
} }
std::string_view to_string_view() const { std::string_view
to_string_view() const {
return { begin(), sizeof(elem_type) * 2 }; return { begin(), sizeof(elem_type) * 2 };
} }
}; };
template <class T> template <class T>
Hex<T> hex(const T &elem, bool rev = false) { Hex<T>
hex(const T &elem, bool rev = false) {
return Hex<T>(elem, rev); return Hex<T>(elem, rev);
} }
template <class It> template <class It>
std::string hex_vec(It begin, It end, bool rev = false) { std::string
hex_vec(It begin, It end, bool rev = false) {
auto str_size = 2 * std::distance(begin, end); auto str_size = 2 * std::distance(begin, end);
std::string hex; std::string hex;
hex.resize(str_size); hex.resize(str_size);
@@ -268,17 +289,18 @@ std::string hex_vec(It begin, It end, bool rev = false) {
} }
} }
return hex; return hex;
} }
template <class C> template <class C>
std::string hex_vec(C &&c, bool rev = false) { std::string
hex_vec(C &&c, bool rev = false) {
return hex_vec(std::begin(c), std::end(c), rev); return hex_vec(std::begin(c), std::end(c), rev);
} }
template <class T> template <class T>
T from_hex(const std::string_view &hex, bool rev = false) { T
from_hex(const std::string_view &hex, bool rev = false) {
std::uint8_t buf[sizeof(T)]; std::uint8_t buf[sizeof(T)];
static char constexpr shift_bit = 'a' - 'A'; static char constexpr shift_bit = 'a' - 'A';
@@ -329,7 +351,8 @@ T from_hex(const std::string_view &hex, bool rev = false) {
return *reinterpret_cast<T *>(buf); return *reinterpret_cast<T *>(buf);
} }
inline std::string from_hex_vec(const std::string &hex, bool rev = false) { inline std::string
from_hex_vec(const std::string &hex, bool rev = false) {
std::string buf; std::string buf;
static char constexpr shift_bit = 'a' - 'A'; static char constexpr shift_bit = 'a' - 'A';
@@ -381,7 +404,8 @@ template<class T>
class hash { class hash {
public: public:
using value_type = T; using value_type = T;
std::size_t operator()(const value_type &value) const { std::size_t
operator()(const value_type &value) const {
const auto *p = reinterpret_cast<const char *>(&value); const auto *p = reinterpret_cast<const char *>(&value);
return std::hash<std::string_view> {}(std::string_view { p, sizeof(value_type) }); return std::hash<std::string_view> {}(std::string_view { p, sizeof(value_type) });
@@ -389,16 +413,19 @@ public:
}; };
template <class T> template <class T>
auto enm(const T &val) -> const std::underlying_type_t<T> & { auto
enm(const T &val) -> const std::underlying_type_t<T> & {
return *reinterpret_cast<const std::underlying_type_t<T> *>(&val); return *reinterpret_cast<const std::underlying_type_t<T> *>(&val);
} }
template <class T> template <class T>
auto enm(T &val) -> std::underlying_type_t<T> & { auto
enm(T &val) -> std::underlying_type_t<T> & {
return *reinterpret_cast<std::underlying_type_t<T> *>(&val); return *reinterpret_cast<std::underlying_type_t<T> *>(&val);
} }
inline std::int64_t from_chars(const char *begin, const char *end) { inline std::int64_t
from_chars(const char *begin, const char *end) {
if (begin == end) { if (begin == end) {
return 0; return 0;
} }
@@ -414,7 +441,8 @@ inline std::int64_t from_chars(const char *begin, const char *end) {
return *begin != '-' ? res + (std::int64_t)(*begin - '0') * mul : -res; return *begin != '-' ? res + (std::int64_t)(*begin - '0') * mul : -res;
} }
inline std::int64_t from_view(const std::string_view &number) { inline std::int64_t
from_view(const std::string_view &number) {
return from_chars(std::begin(number), std::end(number)); return from_chars(std::begin(number), std::end(number));
} }
@@ -423,26 +451,32 @@ class Either : public std::variant<std::monostate, X, Y> {
public: public:
using std::variant<std::monostate, X, Y>::variant; using std::variant<std::monostate, X, Y>::variant;
constexpr bool has_left() const { constexpr bool
has_left() const {
return std::holds_alternative<X>(*this); return std::holds_alternative<X>(*this);
} }
constexpr bool has_right() const { constexpr bool
has_right() const {
return std::holds_alternative<Y>(*this); return std::holds_alternative<Y>(*this);
} }
X &left() { X &
left() {
return std::get<X>(*this); return std::get<X>(*this);
} }
Y &right() { Y &
right() {
return std::get<Y>(*this); return std::get<Y>(*this);
} }
const X &left() const { const X &
left() const {
return std::get<X>(*this); return std::get<X>(*this);
} }
const Y &right() const { const Y &
right() const {
return std::get<Y>(*this); return std::get<Y>(*this);
} }
}; };
@@ -455,29 +489,36 @@ public:
using pointer = element_type *; using pointer = element_type *;
using deleter_type = D; using deleter_type = D;
constexpr uniq_ptr() noexcept : _p { nullptr } {} constexpr uniq_ptr() noexcept:
constexpr uniq_ptr(std::nullptr_t) noexcept : _p { nullptr } {} _p { nullptr } {}
constexpr uniq_ptr(std::nullptr_t) noexcept:
_p { nullptr } {}
uniq_ptr(const uniq_ptr &other) noexcept = delete; uniq_ptr(const uniq_ptr &other) noexcept = delete;
uniq_ptr &operator=(const uniq_ptr &other) noexcept = delete; uniq_ptr &
operator=(const uniq_ptr &other) noexcept = delete;
template <class V> template <class V>
uniq_ptr(V *p) noexcept : _p { p } { uniq_ptr(V *p) noexcept:
_p { p } {
static_assert(std::is_same_v<element_type, void> || std::is_same_v<element_type, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V"); static_assert(std::is_same_v<element_type, void> || std::is_same_v<element_type, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V");
} }
template <class V> template <class V>
uniq_ptr(std::unique_ptr<V, deleter_type> &&uniq) noexcept : _p { uniq.release() } { uniq_ptr(std::unique_ptr<V, deleter_type> &&uniq) noexcept:
_p { uniq.release() } {
static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V"); static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V");
} }
template <class V> template <class V>
uniq_ptr(uniq_ptr<V, deleter_type> &&other) noexcept : _p { other.release() } { uniq_ptr(uniq_ptr<V, deleter_type> &&other) noexcept:
_p { other.release() } {
static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V"); static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V");
} }
template <class V> template <class V>
uniq_ptr &operator=(uniq_ptr<V, deleter_type> &&other) noexcept { uniq_ptr &
operator=(uniq_ptr<V, deleter_type> &&other) noexcept {
static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V"); static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V");
reset(other.release()); reset(other.release());
@@ -485,7 +526,8 @@ public:
} }
template <class V> template <class V>
uniq_ptr &operator=(std::unique_ptr<V, deleter_type> &&uniq) noexcept { uniq_ptr &
operator=(std::unique_ptr<V, deleter_type> &&uniq) noexcept {
static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V"); static_assert(std::is_same_v<element_type, void> || std::is_same_v<T, V> || std::is_base_of_v<element_type, V>, "element_type must be base class of V");
reset(uniq.release()); reset(uniq.release());
@@ -497,7 +539,8 @@ public:
reset(); reset();
} }
void reset(pointer p = pointer()) { void
reset(pointer p = pointer()) {
if (_p) { if (_p) {
_deleter(_p); _deleter(_p);
} }
@@ -505,45 +548,56 @@ public:
_p = p; _p = p;
} }
pointer release() { pointer
release() {
auto tmp = _p; auto tmp = _p;
_p = nullptr; _p = nullptr;
return tmp; return tmp;
} }
pointer get() { pointer
get() {
return _p; return _p;
} }
const pointer get() const { const pointer
get() const {
return _p; return _p;
} }
const std::add_lvalue_reference_t<element_type> operator*() const { const std::add_lvalue_reference_t<element_type>
operator*() const {
return *_p; return *_p;
} }
std::add_lvalue_reference_t<element_type> operator*() { std::add_lvalue_reference_t<element_type>
operator*() {
return *_p; return *_p;
} }
const pointer operator->() const { const pointer
operator->() const {
return _p; return _p;
} }
pointer operator->() { pointer
operator->() {
return _p; return _p;
} }
pointer *operator&() const { pointer *
operator&() const {
return &_p; return &_p;
} }
pointer *operator&() { pointer *
operator&() {
return &_p; return &_p;
} }
deleter_type &get_deleter() { deleter_type &
get_deleter() {
return _deleter; return _deleter;
} }
const deleter_type &get_deleter() const { const deleter_type &
get_deleter() const {
return _deleter; return _deleter;
} }
@@ -557,52 +611,62 @@ protected:
}; };
template <class T1, class D1, class T2, class D2> template <class T1, class D1, class T2, class D2>
bool operator==(const uniq_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) { bool
operator==(const uniq_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) {
return x.get() == y.get(); return x.get() == y.get();
} }
template <class T1, class D1, class T2, class D2> template <class T1, class D1, class T2, class D2>
bool operator!=(const uniq_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) { bool
operator!=(const uniq_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) {
return x.get() != y.get(); return x.get() != y.get();
} }
template <class T1, class D1, class T2, class D2> template <class T1, class D1, class T2, class D2>
bool operator==(const std::unique_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) { bool
operator==(const std::unique_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) {
return x.get() == y.get(); return x.get() == y.get();
} }
template <class T1, class D1, class T2, class D2> template <class T1, class D1, class T2, class D2>
bool operator!=(const std::unique_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) { bool
operator!=(const std::unique_ptr<T1, D1> &x, const uniq_ptr<T2, D2> &y) {
return x.get() != y.get(); return x.get() != y.get();
} }
template <class T1, class D1, class T2, class D2> template <class T1, class D1, class T2, class D2>
bool operator==(const uniq_ptr<T1, D1> &x, const std::unique_ptr<T1, D1> &y) { bool
operator==(const uniq_ptr<T1, D1> &x, const std::unique_ptr<T1, D1> &y) {
return x.get() == y.get(); return x.get() == y.get();
} }
template <class T1, class D1, class T2, class D2> template <class T1, class D1, class T2, class D2>
bool operator!=(const uniq_ptr<T1, D1> &x, const std::unique_ptr<T1, D1> &y) { bool
operator!=(const uniq_ptr<T1, D1> &x, const std::unique_ptr<T1, D1> &y) {
return x.get() != y.get(); return x.get() != y.get();
} }
template <class T, class D> template <class T, class D>
bool operator==(const uniq_ptr<T, D> &x, std::nullptr_t) { bool
operator==(const uniq_ptr<T, D> &x, std::nullptr_t) {
return !(bool) x; return !(bool) x;
} }
template <class T, class D> template <class T, class D>
bool operator!=(const uniq_ptr<T, D> &x, std::nullptr_t) { bool
operator!=(const uniq_ptr<T, D> &x, std::nullptr_t) {
return (bool) x; return (bool) x;
} }
template <class T, class D> template <class T, class D>
bool operator==(std::nullptr_t, const uniq_ptr<T, D> &y) { bool
operator==(std::nullptr_t, const uniq_ptr<T, D> &y) {
return !(bool) y; return !(bool) y;
} }
template <class T, class D> template <class T, class D>
bool operator!=(std::nullptr_t, const uniq_ptr<T, D> &y) { bool
operator!=(std::nullptr_t, const uniq_ptr<T, D> &y) {
return (bool) y; return (bool) y;
} }
@@ -610,7 +674,8 @@ template<class P>
using shared_t = std::shared_ptr<typename P::element_type>; using shared_t = std::shared_ptr<typename P::element_type>;
template <class P, class T> template <class P, class T>
shared_t<P> make_shared(T *pointer) { shared_t<P>
make_shared(T *pointer) {
return shared_t<P>(reinterpret_cast<typename P::pointer>(pointer), typename P::deleter_type()); return shared_t<P>(reinterpret_cast<typename P::pointer>(pointer), typename P::deleter_type());
} }
@@ -621,14 +686,19 @@ public:
using pointer = element_type *; using pointer = element_type *;
using reference = element_type &; using reference = element_type &;
wrap_ptr() : _own_ptr { false }, _p { nullptr } {} wrap_ptr():
wrap_ptr(pointer p) : _own_ptr { false }, _p { p } {} _own_ptr { false }, _p { nullptr } {}
wrap_ptr(std::unique_ptr<element_type> &&uniq_p) : _own_ptr { true }, _p { uniq_p.release() } {} wrap_ptr(pointer p):
wrap_ptr(wrap_ptr &&other) : _own_ptr { other._own_ptr }, _p { other._p } { _own_ptr { false }, _p { p } {}
wrap_ptr(std::unique_ptr<element_type> &&uniq_p):
_own_ptr { true }, _p { uniq_p.release() } {}
wrap_ptr(wrap_ptr &&other):
_own_ptr { other._own_ptr }, _p { other._p } {
other._own_ptr = false; other._own_ptr = false;
} }
wrap_ptr &operator=(wrap_ptr &&other) noexcept { wrap_ptr &
operator=(wrap_ptr &&other) noexcept {
if (_own_ptr) { if (_own_ptr) {
delete _p; delete _p;
} }
@@ -642,7 +712,8 @@ public:
} }
template <class V> template <class V>
wrap_ptr &operator=(std::unique_ptr<V> &&uniq_ptr) { wrap_ptr &
operator=(std::unique_ptr<V> &&uniq_ptr) {
static_assert(std::is_base_of_v<element_type, V>, "element_type must be base class of V"); static_assert(std::is_base_of_v<element_type, V>, "element_type must be base class of V");
_own_ptr = true; _own_ptr = true;
_p = uniq_ptr.release(); _p = uniq_ptr.release();
@@ -650,7 +721,8 @@ public:
return *this; return *this;
} }
wrap_ptr &operator=(pointer p) { wrap_ptr &
operator=(pointer p) {
if (_own_ptr) { if (_own_ptr) {
delete _p; delete _p;
} }
@@ -669,16 +741,20 @@ public:
_own_ptr = false; _own_ptr = false;
} }
const reference operator*() const { const reference
operator*() const {
return *_p; return *_p;
} }
reference operator*() { reference
operator*() {
return *_p; return *_p;
} }
const pointer operator->() const { const pointer
operator->() const {
return _p; return _p;
} }
pointer operator->() { pointer
operator->() {
return _p; return _p;
} }
@@ -723,54 +799,68 @@ using optional_t = either_t<
template <class T> template <class T>
class buffer_t { class buffer_t {
public: public:
buffer_t() : _els { 0 } {}; buffer_t():
buffer_t(buffer_t &&o) noexcept : _els { o._els }, _buf { std::move(o._buf) } { _els { 0 } {};
buffer_t(buffer_t &&o) noexcept:
_els { o._els }, _buf { std::move(o._buf) } {
o._els = 0; o._els = 0;
} }
buffer_t(const buffer_t &o) : _els { o._els }, _buf { std::make_unique<T[]>(_els) } { buffer_t(const buffer_t &o):
_els { o._els }, _buf { std::make_unique<T[]>(_els) } {
std::copy(o.begin(), o.end(), begin()); std::copy(o.begin(), o.end(), begin());
} }
buffer_t &operator=(buffer_t &&o) noexcept { buffer_t &
operator=(buffer_t &&o) noexcept {
std::swap(_els, o._els); std::swap(_els, o._els);
std::swap(_buf, o._buf); std::swap(_buf, o._buf);
return *this; return *this;
}; };
explicit buffer_t(size_t elements) : _els { elements }, _buf { std::make_unique<T[]>(elements) } {} explicit buffer_t(size_t elements):
explicit buffer_t(size_t elements, const T &t) : _els { elements }, _buf { std::make_unique<T[]>(elements) } { _els { elements }, _buf { std::make_unique<T[]>(elements) } {}
explicit buffer_t(size_t elements, const T &t):
_els { elements }, _buf { std::make_unique<T[]>(elements) } {
std::fill_n(_buf.get(), elements, t); std::fill_n(_buf.get(), elements, t);
} }
T &operator[](size_t el) { T &
operator[](size_t el) {
return _buf[el]; return _buf[el];
} }
const T &operator[](size_t el) const { const T &
operator[](size_t el) const {
return _buf[el]; return _buf[el];
} }
size_t size() const { size_t
size() const {
return _els; return _els;
} }
void fake_resize(std::size_t els) { void
fake_resize(std::size_t els) {
_els = els; _els = els;
} }
T *begin() { T *
begin() {
return _buf.get(); return _buf.get();
} }
const T *begin() const { const T *
begin() const {
return _buf.get(); return _buf.get();
} }
T *end() { T *
end() {
return _buf.get() + _els; return _buf.get() + _els;
} }
const T *end() const { const T *
end() const {
return _buf.get() + _els; return _buf.get() + _els;
} }
@@ -780,7 +870,8 @@ private:
}; };
template <class T> template <class T>
T either(std::optional<T> &&l, T &&r) { T
either(std::optional<T> &&l, T &&r) {
if (l) { if (l) {
return std::move(*l); return std::move(*l);
} }
@@ -797,7 +888,8 @@ template<class T, class ReturnType, typename Function<ReturnType, T>::type funct
struct Destroy { struct Destroy {
typedef T pointer; typedef T pointer;
void operator()(pointer p) { void
operator()(pointer p) {
function(p); function(p);
} }
}; };
@@ -810,12 +902,14 @@ template<class T, class ReturnType, typename Function<ReturnType, T *>::type fun
using safe_ptr_v2 = uniq_ptr<T, Destroy<T *, ReturnType, function>>; using safe_ptr_v2 = uniq_ptr<T, Destroy<T *, ReturnType, function>>;
template <class T> template <class T>
void c_free(T *p) { void
c_free(T *p) {
free(p); free(p);
} }
template <class T, class ReturnType, ReturnType (**function)(T *)> template <class T, class ReturnType, ReturnType (**function)(T *)>
void dynamic(T *p) { void
dynamic(T *p) {
(*function)(p); (*function)(p);
} }
@@ -829,12 +923,14 @@ template<class T>
using c_ptr = safe_ptr<T, c_free<T>>; using c_ptr = safe_ptr<T, c_free<T>>;
template <class It> template <class It>
std::string_view view(It begin, It end) { std::string_view
view(It begin, It end) {
return std::string_view { (const char *) begin, (std::size_t)(end - begin) }; return std::string_view { (const char *) begin, (std::size_t)(end - begin) };
} }
template <class T> template <class T>
std::string_view view(const T &data) { std::string_view
view(const T &data) {
return std::string_view((const char *) &data, sizeof(T)); return std::string_view((const char *) &data, sizeof(T));
} }
@@ -872,7 +968,8 @@ struct endian_helper {};
template <class T> template <class T>
struct endian_helper<T, std::enable_if_t< struct endian_helper<T, std::enable_if_t<
!(instantiation_of_v<std::optional, T>)>> { !(instantiation_of_v<std::optional, T>)>> {
static inline T big(T x) { static inline T
big(T x) {
if constexpr (endianness<T>::little) { if constexpr (endianness<T>::little) {
uint8_t *data = reinterpret_cast<uint8_t *>(&x); uint8_t *data = reinterpret_cast<uint8_t *>(&x);
@@ -882,7 +979,8 @@ struct endian_helper<T, std::enable_if_t<
return x; return x;
} }
static inline T little(T x) { static inline T
little(T x) {
if constexpr (endianness<T>::big) { if constexpr (endianness<T>::big) {
uint8_t *data = reinterpret_cast<uint8_t *>(&x); uint8_t *data = reinterpret_cast<uint8_t *>(&x);
@@ -896,7 +994,8 @@ struct endian_helper<T, std::enable_if_t<
template <class T> template <class T>
struct endian_helper<T, std::enable_if_t< struct endian_helper<T, std::enable_if_t<
instantiation_of_v<std::optional, T>>> { instantiation_of_v<std::optional, T>>> {
static inline T little(T x) { static inline T
little(T x) {
if (!x) return x; if (!x) return x;
if constexpr (endianness<T>::big) { if constexpr (endianness<T>::big) {
@@ -908,8 +1007,8 @@ struct endian_helper<T, std::enable_if_t<
return x; return x;
} }
static inline T
static inline T big(T x) { big(T x) {
if (!x) return x; if (!x) return x;
if constexpr (endianness<T>::little) { if constexpr (endianness<T>::little) {
@@ -923,10 +1022,12 @@ struct endian_helper<T, std::enable_if_t<
}; };
template <class T> template <class T>
inline auto little(T x) { return endian_helper<T>::little(x); } inline auto
little(T x) { return endian_helper<T>::little(x); }
template <class T> template <class T>
inline auto big(T x) { return endian_helper<T>::big(x); } inline auto
big(T x) { return endian_helper<T>::big(x); }
} // namespace endian } // namespace endian
} // namespace util } // namespace util
#endif #endif

View File

@@ -12,7 +12,8 @@ union uuid_t {
std::uint32_t b32[4]; std::uint32_t b32[4];
std::uint64_t b64[2]; std::uint64_t b64[2];
static uuid_t generate(std::default_random_engine &engine) { static uuid_t
generate(std::default_random_engine &engine) {
std::uniform_int_distribution<std::uint8_t> dist(0, std::numeric_limits<std::uint8_t>::max()); std::uniform_int_distribution<std::uint8_t> dist(0, std::numeric_limits<std::uint8_t>::max());
uuid_t buf; uuid_t buf;
@@ -26,7 +27,8 @@ union uuid_t {
return buf; return buf;
} }
static uuid_t generate() { static uuid_t
generate() {
std::random_device r; std::random_device r;
std::default_random_engine engine { r() }; std::default_random_engine engine { r() };
@@ -34,7 +36,8 @@ union uuid_t {
return generate(engine); return generate(engine);
} }
[[nodiscard]] std::string string() const { [[nodiscard]] std::string
string() const {
std::string result; std::string result;
result.reserve(sizeof(uuid_t) * 2 + 4); result.reserve(sizeof(uuid_t) * 2 + 4);
@@ -61,15 +64,18 @@ union uuid_t {
return result; return result;
} }
constexpr bool operator==(const uuid_t &other) const { constexpr bool
operator==(const uuid_t &other) const {
return b64[0] == other.b64[0] && b64[1] == other.b64[1]; return b64[0] == other.b64[0] && b64[1] == other.b64[1];
} }
constexpr bool operator<(const uuid_t &other) const { constexpr bool
operator<(const uuid_t &other) const {
return (b64[0] < other.b64[0] || (b64[0] == other.b64[0] && b64[1] < other.b64[1])); return (b64[0] < other.b64[0] || (b64[0] == other.b64[0] && b64[1] < other.b64[1]));
} }
constexpr bool operator>(const uuid_t &other) const { constexpr bool
operator>(const uuid_t &other) const {
return (b64[0] > other.b64[0] || (b64[0] == other.b64[0] && b64[1] > other.b64[1])); return (b64[0] > other.b64[0] || (b64[0] == other.b64[0] && b64[1] > other.b64[1]));
} }
}; };

View File

@@ -30,15 +30,18 @@ namespace video {
constexpr auto hevc_nalu = "\000\000\000\001("sv; constexpr auto hevc_nalu = "\000\000\000\001("sv;
constexpr auto h264_nalu = "\000\000\000\001e"sv; constexpr auto h264_nalu = "\000\000\000\001e"sv;
void free_ctx(AVCodecContext *ctx) { void
free_ctx(AVCodecContext *ctx) {
avcodec_free_context(&ctx); avcodec_free_context(&ctx);
} }
void free_frame(AVFrame *frame) { void
free_frame(AVFrame *frame) {
av_frame_free(&frame); av_frame_free(&frame);
} }
void free_buffer(AVBufferRef *ref) { void
free_buffer(AVBufferRef *ref) {
av_buffer_unref(&ref); av_buffer_unref(&ref);
} }
@@ -78,19 +81,25 @@ enum class profile_hevc_e : int {
}; };
} // namespace qsv } // namespace qsv
platf::mem_type_e
map_base_dev_type(AVHWDeviceType type);
platf::pix_fmt_e
map_pix_fmt(AVPixelFormat fmt);
platf::mem_type_e map_base_dev_type(AVHWDeviceType type); util::Either<buffer_t, int>
platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt); dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
util::Either<buffer_t, int>
vaapi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
util::Either<buffer_t, int>
cuda_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
util::Either<buffer_t, int> dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx); int
util::Either<buffer_t, int> vaapi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx); hwframe_ctx(ctx_t &ctx, platf::hwdevice_t *hwdevice, buffer_t &hwdevice_ctx, AVPixelFormat format);
util::Either<buffer_t, int> cuda_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx);
int hwframe_ctx(ctx_t &ctx, platf::hwdevice_t *hwdevice, buffer_t &hwdevice_ctx, AVPixelFormat format);
class swdevice_t: public platf::hwdevice_t { class swdevice_t: public platf::hwdevice_t {
public: public:
int convert(platf::img_t &img) override { int
convert(platf::img_t &img) override {
av_frame_make_writable(sw_frame.get()); av_frame_make_writable(sw_frame.get());
const int linesizes[2] { const int linesizes[2] {
@@ -131,7 +140,8 @@ public:
return 0; return 0;
} }
int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) { int
set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) {
this->frame = frame; this->frame = frame;
// If it's a hwframe, allocate buffers for hardware // If it's a hwframe, allocate buffers for hardware
@@ -147,7 +157,8 @@ public:
return 0; return 0;
} }
void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override { void
set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) override {
sws_setColorspaceDetails(sws.get(), sws_setColorspaceDetails(sws.get(),
sws_getCoefficients(SWS_CS_DEFAULT), 0, sws_getCoefficients(SWS_CS_DEFAULT), 0,
sws_getCoefficients(colorspace), color_range - 1, sws_getCoefficients(colorspace), color_range - 1,
@@ -157,7 +168,8 @@ public:
/** /**
* When preserving aspect ratio, ensure that padding is black * When preserving aspect ratio, ensure that padding is black
*/ */
int prefill() { int
prefill() {
auto frame = sw_frame ? sw_frame.get() : this->frame; auto frame = sw_frame ? sw_frame.get() : this->frame;
auto width = frame->width; auto width = frame->width;
auto height = frame->height; auto height = frame->height;
@@ -195,7 +207,8 @@ public:
return 0; return 0;
} }
int init(int in_width, int in_height, AVFrame *frame, AVPixelFormat format, bool hardware) { int
init(int in_width, int in_height, AVFrame *frame, AVPixelFormat format, bool hardware) {
// If the device used is hardware, yet the image resides on main memory // If the device used is hardware, yet the image resides on main memory
if (hardware) { if (hardware) {
sw_frame.reset(av_frame_alloc()); sw_frame.reset(av_frame_alloc());
@@ -273,7 +286,8 @@ struct encoder_t {
MAX_FLAGS MAX_FLAGS
}; };
static std::string_view from_flag(flag_e flag) { static std::string_view
from_flag(flag_e flag) {
#define _CONVERT(x) \ #define _CONVERT(x) \
case flag_e::x: \ case flag_e::x: \
return #x##sv return #x##sv
@@ -300,7 +314,8 @@ struct encoder_t {
std::string name; std::string name;
std::variant<int, int *, std::optional<int> *, std::string, std::string *> value; std::variant<int, int *, std::optional<int> *, std::string, std::string *> value;
option_t(std::string &&name, decltype(value) &&value) : name { std::move(name) }, value { std::move(value) } {} option_t(std::string &&name, decltype(value) &&value):
name { std::move(name) }, value { std::move(value) } {}
}; };
AVHWDeviceType base_dev_type, derived_dev_type; AVHWDeviceType base_dev_type, derived_dev_type;
@@ -317,11 +332,13 @@ struct encoder_t {
std::string name; std::string name;
std::bitset<MAX_FLAGS> capabilities; std::bitset<MAX_FLAGS> capabilities;
bool operator[](flag_e flag) const { bool
operator[](flag_e flag) const {
return capabilities[(std::size_t) flag]; return capabilities[(std::size_t) flag];
} }
std::bitset<MAX_FLAGS>::reference operator[](flag_e flag) { std::bitset<MAX_FLAGS>::reference
operator[](flag_e flag) {
return capabilities[(std::size_t) flag]; return capabilities[(std::size_t) flag];
} }
} hevc, h264; } hevc, h264;
@@ -334,7 +351,8 @@ struct encoder_t {
class session_t { class session_t {
public: public:
session_t() = default; session_t() = default;
session_t(ctx_t &&ctx, std::shared_ptr<platf::hwdevice_t> &&device, int inject) : ctx { std::move(ctx) }, device { std::move(device) }, inject { inject } {} session_t(ctx_t &&ctx, std::shared_ptr<platf::hwdevice_t> &&device, int inject):
ctx { std::move(ctx) }, device { std::move(device) }, inject { inject } {}
session_t(session_t &&other) noexcept = default; session_t(session_t &&other) noexcept = default;
~session_t() { ~session_t() {
@@ -344,7 +362,8 @@ public:
} }
// Ensure objects are destroyed in the correct order // Ensure objects are destroyed in the correct order
session_t &operator=(session_t &&other) { session_t &
operator=(session_t &&other) {
device = std::move(other.device); device = std::move(other.device);
ctx = std::move(other.ctx); ctx = std::move(other.ctx);
replacements = std::move(other.replacements); replacements = std::move(other.replacements);
@@ -409,10 +428,14 @@ struct capture_thread_sync_ctx_t {
encode_session_ctx_queue_t encode_session_ctx_queue { 30 }; encode_session_ctx_queue_t encode_session_ctx_queue { 30 };
}; };
int start_capture_sync(capture_thread_sync_ctx_t &ctx); int
void end_capture_sync(capture_thread_sync_ctx_t &ctx); start_capture_sync(capture_thread_sync_ctx_t &ctx);
int start_capture_async(capture_thread_async_ctx_t &ctx); void
void end_capture_async(capture_thread_async_ctx_t &ctx); end_capture_sync(capture_thread_sync_ctx_t &ctx);
int
start_capture_async(capture_thread_async_ctx_t &ctx);
void
end_capture_async(capture_thread_async_ctx_t &ctx);
// Keep a reference counter to ensure the capture thread only runs when other threads have a reference to the capture thread // Keep a reference counter to ensure the capture thread only runs when other threads have a reference to the capture thread
auto capture_thread_async = safe::make_shared<capture_thread_async_ctx_t>(start_capture_async, end_capture_async); auto capture_thread_async = safe::make_shared<capture_thread_async_ctx_t>(start_capture_async, end_capture_async);
@@ -704,7 +727,8 @@ static std::vector<encoder_t> encoders {
software software
}; };
void reset_display(std::shared_ptr<platf::display_t> &disp, AVHWDeviceType type, const std::string &display_name, const config_t &config) { void
reset_display(std::shared_ptr<platf::display_t> &disp, AVHWDeviceType type, const std::string &display_name, const config_t &config) {
// We try this twice, in case we still get an error on reinitialization // We try this twice, in case we still get an error on reinitialization
for (int x = 0; x < 2; ++x) { for (int x = 0; x < 2; ++x) {
disp.reset(); disp.reset();
@@ -718,7 +742,8 @@ void reset_display(std::shared_ptr<platf::display_t> &disp, AVHWDeviceType type,
} }
} }
void captureThread( void
captureThread(
std::shared_ptr<safe::queue_t<capture_ctx_t>> capture_ctx_queue, std::shared_ptr<safe::queue_t<capture_ctx_t>> capture_ctx_queue,
sync_util::sync_t<std::weak_ptr<platf::display_t>> &display_wp, sync_util::sync_t<std::weak_ptr<platf::display_t>> &display_wp,
safe::signal_t &reinit_event, safe::signal_t &reinit_event,
@@ -822,7 +847,6 @@ void captureThread(
}, },
*round_robin++, &display_cursor); *round_robin++, &display_cursor);
if (artificial_reinit && status != platf::capture_e::error) { if (artificial_reinit && status != platf::capture_e::error) {
status = platf::capture_e::reinit; status = platf::capture_e::reinit;
@@ -898,7 +922,8 @@ void captureThread(
} }
} }
int encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::mail_raw_t::queue_t<packet_t> &packets, void *channel_data) { int
encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::mail_raw_t::queue_t<packet_t> &packets, void *channel_data) {
frame->pts = frame_nr; frame->pts = frame_nr;
auto &ctx = session.ctx; auto &ctx = session.ctx;
@@ -946,7 +971,6 @@ int encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::m
session.inject = 0; session.inject = 0;
session.replacements.emplace_back( session.replacements.emplace_back(
std::string_view((char *) std::begin(sps.old), sps.old.size()), std::string_view((char *) std::begin(sps.old), sps.old.size()),
std::string_view((char *) std::begin(sps._new), sps._new.size())); std::string_view((char *) std::begin(sps._new), sps._new.size()));
@@ -960,7 +984,8 @@ int encode(int64_t frame_nr, session_t &session, frame_t::pointer frame, safe::m
return 0; return 0;
} }
std::optional<session_t> make_session(platf::display_t *disp, const encoder_t &encoder, const config_t &config, int width, int height, std::shared_ptr<platf::hwdevice_t> &&hwdevice) { std::optional<session_t>
make_session(platf::display_t *disp, const encoder_t &encoder, const config_t &config, int width, int height, std::shared_ptr<platf::hwdevice_t> &&hwdevice) {
bool hardware = encoder.base_dev_type != AV_HWDEVICE_TYPE_NONE; bool hardware = encoder.base_dev_type != AV_HWDEVICE_TYPE_NONE;
auto &video_format = config.videoFormat == 0 ? encoder.h264 : encoder.hevc; auto &video_format = config.videoFormat == 0 ? encoder.h264 : encoder.hevc;
@@ -1270,7 +1295,8 @@ std::optional<session_t> make_session(platf::display_t *disp, const encoder_t &e
return std::make_optional(std::move(session)); return std::make_optional(std::move(session));
} }
void encode_run( void
encode_run(
int &frame_nr, // Store progress of the frame number int &frame_nr, // Store progress of the frame number
safe::mail_t mail, safe::mail_t mail,
img_event_t images, img_event_t images,
@@ -1280,7 +1306,6 @@ void encode_run(
safe::signal_t &reinit_event, safe::signal_t &reinit_event,
const encoder_t &encoder, const encoder_t &encoder,
void *channel_data) { void *channel_data) {
auto session = make_session(disp.get(), encoder, config, disp->width, disp->height, std::move(hwdevice)); auto session = make_session(disp.get(), encoder, config, disp->width, disp->height, std::move(hwdevice));
if (!session) { if (!session) {
return; return;
@@ -1334,7 +1359,8 @@ void encode_run(
} }
} }
input::touch_port_t make_port(platf::display_t *display, const config_t &config) { input::touch_port_t
make_port(platf::display_t *display, const config_t &config) {
float wd = display->width; float wd = display->width;
float hd = display->height; float hd = display->height;
@@ -1362,7 +1388,8 @@ input::touch_port_t make_port(platf::display_t *display, const config_t &config)
}; };
} }
std::optional<sync_session_t> make_synced_session(platf::display_t *disp, const encoder_t &encoder, platf::img_t &img, sync_session_ctx_t &ctx) { std::optional<sync_session_t>
make_synced_session(platf::display_t *disp, const encoder_t &encoder, platf::img_t &img, sync_session_ctx_t &ctx) {
sync_session_t encode_session; sync_session_t encode_session;
encode_session.ctx = &ctx; encode_session.ctx = &ctx;
@@ -1394,10 +1421,10 @@ std::optional<sync_session_t> make_synced_session(platf::display_t *disp, const
return std::move(encode_session); return std::move(encode_session);
} }
encode_e encode_run_sync( encode_e
encode_run_sync(
std::vector<std::unique_ptr<sync_session_ctx_t>> &synced_session_ctxs, std::vector<std::unique_ptr<sync_session_ctx_t>> &synced_session_ctxs,
encode_session_ctx_queue_t &encode_session_ctx_queue) { encode_session_ctx_queue_t &encode_session_ctx_queue) {
const auto &encoder = encoders.front(); const auto &encoder = encoders.front();
auto display_names = platf::display_names(map_base_dev_type(encoder.base_dev_type)); auto display_names = platf::display_names(map_base_dev_type(encoder.base_dev_type));
int display_p = 0; int display_p = 0;
@@ -1543,7 +1570,8 @@ encode_e encode_run_sync(
return encode_e::ok; return encode_e::ok;
} }
void captureThreadSync() { void
captureThreadSync() {
auto ref = capture_thread_sync.ref(); auto ref = capture_thread_sync.ref();
std::vector<std::unique_ptr<sync_session_ctx_t>> synced_session_ctxs; std::vector<std::unique_ptr<sync_session_ctx_t>> synced_session_ctxs;
@@ -1569,11 +1597,11 @@ void captureThreadSync() {
while (encode_run_sync(synced_session_ctxs, ctx) == encode_e::reinit) {} while (encode_run_sync(synced_session_ctxs, ctx) == encode_e::reinit) {}
} }
void capture_async( void
capture_async(
safe::mail_t mail, safe::mail_t mail,
config_t &config, config_t &config,
void *channel_data) { void *channel_data) {
auto shutdown_event = mail->event<bool>(mail::shutdown); auto shutdown_event = mail->event<bool>(mail::shutdown);
auto images = std::make_shared<img_event_t::element_type>(); auto images = std::make_shared<img_event_t::element_type>();
@@ -1646,11 +1674,11 @@ void capture_async(
} }
} }
void capture( void
capture(
safe::mail_t mail, safe::mail_t mail,
config_t config, config_t config,
void *channel_data) { void *channel_data) {
auto idr_events = mail->event<bool>(mail::idr); auto idr_events = mail->event<bool>(mail::idr);
idr_events->raise(true); idr_events->raise(true);
@@ -1682,7 +1710,8 @@ enum validate_flag_e {
NALU_PREFIX_5b = 0x02, NALU_PREFIX_5b = 0x02,
}; };
int validate_config(std::shared_ptr<platf::display_t> &disp, const encoder_t &encoder, const config_t &config) { int
validate_config(std::shared_ptr<platf::display_t> &disp, const encoder_t &encoder, const config_t &config) {
reset_display(disp, encoder.base_dev_type, config::video.output_name, config); reset_display(disp, encoder.base_dev_type, config::video.output_name, config);
if (!disp) { if (!disp) {
return -1; return -1;
@@ -1740,7 +1769,8 @@ int validate_config(std::shared_ptr<platf::display_t> &disp, const encoder_t &en
return flag; return flag;
} }
bool validate_encoder(encoder_t &encoder) { bool
validate_encoder(encoder_t &encoder) {
std::shared_ptr<platf::display_t> disp; std::shared_ptr<platf::display_t> disp;
BOOST_LOG(info) << "Trying encoder ["sv << encoder.name << ']'; BOOST_LOG(info) << "Trying encoder ["sv << encoder.name << ']';
@@ -1868,7 +1898,8 @@ retry:
return true; return true;
} }
int init() { int
init() {
bool encoder_found = false; bool encoder_found = false;
if (!config::video.encoder.empty()) { if (!config::video.encoder.empty()) {
// If there is a specific encoder specified, use it if it passes validation // If there is a specific encoder specified, use it if it passes validation
@@ -1985,7 +2016,8 @@ int init() {
return 0; return 0;
} }
int hwframe_ctx(ctx_t &ctx, platf::hwdevice_t *hwdevice, buffer_t &hwdevice_ctx, AVPixelFormat format) { int
hwframe_ctx(ctx_t &ctx, platf::hwdevice_t *hwdevice, buffer_t &hwdevice_ctx, AVPixelFormat format) {
buffer_t frame_ref { av_hwframe_ctx_alloc(hwdevice_ctx.get()) }; buffer_t frame_ref { av_hwframe_ctx_alloc(hwdevice_ctx.get()) };
auto frame_ctx = (AVHWFramesContext *) frame_ref->data; auto frame_ctx = (AVHWFramesContext *) frame_ref->data;
@@ -2010,7 +2042,8 @@ int hwframe_ctx(ctx_t &ctx, platf::hwdevice_t *hwdevice, buffer_t &hwdevice_ctx,
// Linux only declaration // Linux only declaration
typedef int (*vaapi_make_hwdevice_ctx_fn)(platf::hwdevice_t *base, AVBufferRef **hw_device_buf); typedef int (*vaapi_make_hwdevice_ctx_fn)(platf::hwdevice_t *base, AVBufferRef **hw_device_buf);
util::Either<buffer_t, int> vaapi_make_hwdevice_ctx(platf::hwdevice_t *base) { util::Either<buffer_t, int>
vaapi_make_hwdevice_ctx(platf::hwdevice_t *base) {
buffer_t hw_device_buf; buffer_t hw_device_buf;
// If an egl hwdevice // If an egl hwdevice
@@ -2034,7 +2067,8 @@ util::Either<buffer_t, int> vaapi_make_hwdevice_ctx(platf::hwdevice_t *base) {
return hw_device_buf; return hw_device_buf;
} }
util::Either<buffer_t, int> cuda_make_hwdevice_ctx(platf::hwdevice_t *base) { util::Either<buffer_t, int>
cuda_make_hwdevice_ctx(platf::hwdevice_t *base) {
buffer_t hw_device_buf; buffer_t hw_device_buf;
auto status = av_hwdevice_ctx_create(&hw_device_buf, AV_HWDEVICE_TYPE_CUDA, nullptr, nullptr, 1 /* AV_CUDA_USE_PRIMARY_CONTEXT */); auto status = av_hwdevice_ctx_create(&hw_device_buf, AV_HWDEVICE_TYPE_CUDA, nullptr, nullptr, 1 /* AV_CUDA_USE_PRIMARY_CONTEXT */);
@@ -2050,10 +2084,12 @@ util::Either<buffer_t, int> cuda_make_hwdevice_ctx(platf::hwdevice_t *base) {
#ifdef _WIN32 #ifdef _WIN32
} }
void do_nothing(void *) {} void
do_nothing(void *) {}
namespace video { namespace video {
util::Either<buffer_t, int> dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx) { util::Either<buffer_t, int>
dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_ctx) {
buffer_t ctx_buf { av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA) }; buffer_t ctx_buf { av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA) };
auto ctx = (AVD3D11VADeviceContext *) ((AVHWDeviceContext *) ctx_buf->data)->hwctx; auto ctx = (AVD3D11VADeviceContext *) ((AVHWDeviceContext *) ctx_buf->data)->hwctx;
@@ -2080,7 +2116,8 @@ util::Either<buffer_t, int> dxgi_make_hwdevice_ctx(platf::hwdevice_t *hwdevice_c
} }
#endif #endif
int start_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) { int
start_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
capture_thread_ctx.encoder_p = &encoders.front(); capture_thread_ctx.encoder_p = &encoders.front();
capture_thread_ctx.reinit_event.reset(); capture_thread_ctx.reinit_event.reset();
@@ -2096,19 +2133,23 @@ int start_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
return 0; return 0;
} }
void end_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) { void
end_capture_async(capture_thread_async_ctx_t &capture_thread_ctx) {
capture_thread_ctx.capture_ctx_queue->stop(); capture_thread_ctx.capture_ctx_queue->stop();
capture_thread_ctx.capture_thread.join(); capture_thread_ctx.capture_thread.join();
} }
int start_capture_sync(capture_thread_sync_ctx_t &ctx) { int
start_capture_sync(capture_thread_sync_ctx_t &ctx) {
std::thread { &captureThreadSync }.detach(); std::thread { &captureThreadSync }.detach();
return 0; return 0;
} }
void end_capture_sync(capture_thread_sync_ctx_t &ctx) {} void
end_capture_sync(capture_thread_sync_ctx_t &ctx) {}
platf::mem_type_e map_base_dev_type(AVHWDeviceType type) { platf::mem_type_e
map_base_dev_type(AVHWDeviceType type) {
switch (type) { switch (type) {
case AV_HWDEVICE_TYPE_D3D11VA: case AV_HWDEVICE_TYPE_D3D11VA:
return platf::mem_type_e::dxgi; return platf::mem_type_e::dxgi;
@@ -2125,7 +2166,8 @@ platf::mem_type_e map_base_dev_type(AVHWDeviceType type) {
return platf::mem_type_e::unknown; return platf::mem_type_e::unknown;
} }
platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt) { platf::pix_fmt_e
map_pix_fmt(AVPixelFormat fmt) {
switch (fmt) { switch (fmt) {
case AV_PIX_FMT_YUV420P10: case AV_PIX_FMT_YUV420P10:
return platf::pix_fmt_e::yuv420p10; return platf::pix_fmt_e::yuv420p10;
@@ -2142,7 +2184,8 @@ platf::pix_fmt_e map_pix_fmt(AVPixelFormat fmt) {
return platf::pix_fmt_e::unknown; return platf::pix_fmt_e::unknown;
} }
color_t make_color_matrix(float Cr, float Cb, const float2 &range_Y, const float2 &range_UV) { color_t
make_color_matrix(float Cr, float Cb, const float2 &range_Y, const float2 &range_UV) {
float Cg = 1.0f - Cr - Cb; float Cg = 1.0f - Cr - Cb;
float Cr_i = 1.0f - Cr; float Cr_i = 1.0f - Cr;

View File

@@ -15,16 +15,19 @@ struct AVPacket;
namespace video { namespace video {
struct packet_raw_t { struct packet_raw_t {
void init_packet() { void
init_packet() {
this->av_packet = av_packet_alloc(); this->av_packet = av_packet_alloc();
} }
template <class P> template <class P>
explicit packet_raw_t(P *user_data) : channel_data { user_data } { explicit packet_raw_t(P *user_data):
channel_data { user_data } {
init_packet(); init_packet();
} }
explicit packet_raw_t(std::nullptr_t) : channel_data { nullptr } { explicit packet_raw_t(std::nullptr_t):
channel_data { nullptr } {
init_packet(); init_packet();
} }
@@ -38,7 +41,8 @@ struct packet_raw_t {
KITTY_DEFAULT_CONSTR_MOVE(replace_t) KITTY_DEFAULT_CONSTR_MOVE(replace_t)
replace_t(std::string_view old, std::string_view _new) noexcept : old { std::move(old) }, _new { std::move(_new) } {} replace_t(std::string_view old, std::string_view _new) noexcept:
old { std::move(old) }, _new { std::move(_new) } {}
}; };
AVPacket *av_packet; AVPacket *av_packet;
@@ -49,8 +53,10 @@ struct packet_raw_t {
using packet_t = std::unique_ptr<packet_raw_t>; using packet_t = std::unique_ptr<packet_raw_t>;
struct hdr_info_raw_t { struct hdr_info_raw_t {
explicit hdr_info_raw_t(bool enabled) : enabled { enabled }, metadata {} {}; explicit hdr_info_raw_t(bool enabled):
explicit hdr_info_raw_t(bool enabled, const SS_HDR_METADATA &metadata) : enabled { enabled }, metadata { metadata } {}; enabled { enabled }, metadata {} {};
explicit hdr_info_raw_t(bool enabled, const SS_HDR_METADATA &metadata):
enabled { enabled }, metadata { metadata } {};
bool enabled; bool enabled;
SS_HDR_METADATA metadata; SS_HDR_METADATA metadata;
@@ -84,12 +90,14 @@ struct alignas(16) color_t {
extern color_t colors[6]; extern color_t colors[6];
void capture( void
capture(
safe::mail_t mail, safe::mail_t mail,
config_t config, config_t config,
void *channel_data); void *channel_data);
int init(); int
init();
} // namespace video } // namespace video
#endif // SUNSHINE_VIDEO_H #endif // SUNSHINE_VIDEO_H

View File

@@ -148,7 +148,6 @@ typedef EGLNativeDisplayType NativeDisplayType;
typedef EGLNativePixmapType NativePixmapType; typedef EGLNativePixmapType NativePixmapType;
typedef EGLNativeWindowType NativeWindowType; typedef EGLNativeWindowType NativeWindowType;
/* Define EGLint. This must be a signed integral type large enough to contain /* Define EGLint. This must be a signed integral type large enough to contain
* all legal attribute names and values passed into and out of EGL, whether * all legal attribute names and values passed into and out of EGL, whether
* their type is boolean, bitmask, enumerant (symbolic constant), integer, * their type is boolean, bitmask, enumerant (symbolic constant), integer,
@@ -158,7 +157,6 @@ typedef EGLNativeWindowType NativeWindowType;
*/ */
typedef khronos_int32_t EGLint; typedef khronos_int32_t EGLint;
/* C++ / C typecast macros for special EGL handle values */ /* C++ / C typecast macros for special EGL handle values */
#if defined(__cplusplus) #if defined(__cplusplus)
#define EGL_CAST(type, value) (static_cast<type>(value)) #define EGL_CAST(type, value) (static_cast<type>(value))

View File

@@ -142,7 +142,6 @@
*-----------------------------------------------------------------------*/ *-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/* /*
* Using <stdint.h> * Using <stdint.h>
*/ */
@@ -221,7 +220,6 @@ typedef uint64_t khronos_uint64_t;
#endif #endif
/* /*
* Types that are (so far) the same on all platforms * Types that are (so far) the same on all platforms
*/ */

View File

@@ -28,7 +28,6 @@
#ifndef GLAD_EGL_H_ #ifndef GLAD_EGL_H_
#define GLAD_EGL_H_ #define GLAD_EGL_H_
#define GLAD_EGL #define GLAD_EGL
#define GLAD_OPTION_EGL_LOADER #define GLAD_OPTION_EGL_LOADER
@@ -316,12 +315,10 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define EGL_WIDTH 0x3057 #define EGL_WIDTH 0x3057
#define EGL_WINDOW_BIT 0x0004 #define EGL_WINDOW_BIT 0x0004
#include <KHR/khrplatform.h> #include <KHR/khrplatform.h>
#include <EGL/eglplatform.h> #include <EGL/eglplatform.h>
struct AHardwareBuffer; struct AHardwareBuffer;
struct wl_buffer; struct wl_buffer;
@@ -330,7 +327,6 @@ struct wl_display;
struct wl_resource; struct wl_resource;
typedef unsigned int EGLBoolean; typedef unsigned int EGLBoolean;
typedef unsigned int EGLenum; typedef unsigned int EGLenum;
@@ -410,7 +406,6 @@ typedef void(GLAD_API_PTR *EGLDEBUGPROCKHR)(EGLenum error, const char *command,
#define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC #define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC
#define EGL_VERSION_1_0 1 #define EGL_VERSION_1_0 1
GLAD_API_CALL int GLAD_EGL_VERSION_1_0; GLAD_API_CALL int GLAD_EGL_VERSION_1_0;
#define EGL_VERSION_1_1 1 #define EGL_VERSION_1_1 1
@@ -424,7 +419,6 @@ GLAD_API_CALL int GLAD_EGL_VERSION_1_4;
#define EGL_VERSION_1_5 1 #define EGL_VERSION_1_5 1
GLAD_API_CALL int GLAD_EGL_VERSION_1_5; GLAD_API_CALL int GLAD_EGL_VERSION_1_5;
typedef EGLBoolean(GLAD_API_PTR *PFNEGLBINDAPIPROC)(EGLenum api); typedef EGLBoolean(GLAD_API_PTR *PFNEGLBINDAPIPROC)(EGLenum api);
typedef EGLBoolean(GLAD_API_PTR *PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer); typedef EGLBoolean(GLAD_API_PTR *PFNEGLBINDTEXIMAGEPROC)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
typedef EGLBoolean(GLAD_API_PTR *PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); typedef EGLBoolean(GLAD_API_PTR *PFNEGLCHOOSECONFIGPROC)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
@@ -567,15 +561,18 @@ GLAD_API_CALL PFNEGLWAITNATIVEPROC glad_eglWaitNative;
GLAD_API_CALL PFNEGLWAITSYNCPROC glad_eglWaitSync; GLAD_API_CALL PFNEGLWAITSYNCPROC glad_eglWaitSync;
#define eglWaitSync glad_eglWaitSync #define eglWaitSync glad_eglWaitSync
GLAD_API_CALL int
GLAD_API_CALL int gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void *userptr); gladLoadEGLUserPtr(EGLDisplay display, GLADuserptrloadfunc load, void *userptr);
GLAD_API_CALL int gladLoadEGL(EGLDisplay display, GLADloadfunc load); GLAD_API_CALL int
gladLoadEGL(EGLDisplay display, GLADloadfunc load);
#ifdef GLAD_EGL #ifdef GLAD_EGL
GLAD_API_CALL int gladLoaderLoadEGL(EGLDisplay display); GLAD_API_CALL int
gladLoaderLoadEGL(EGLDisplay display);
GLAD_API_CALL void gladLoaderUnloadEGL(void); GLAD_API_CALL void
gladLoaderUnloadEGL(void);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1983,7 +1983,6 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro
#define GL_ZOOM_X 0x0D16 #define GL_ZOOM_X 0x0D16
#define GL_ZOOM_Y 0x0D17 #define GL_ZOOM_Y 0x0D17
#include <KHR/khrplatform.h> #include <KHR/khrplatform.h>
typedef unsigned int GLenum; typedef unsigned int GLenum;
@@ -2090,7 +2089,6 @@ typedef GLintptr GLvdpauSurfaceNV;
typedef void(GLAD_API_PTR *GLVULKANPROCNV)(void); typedef void(GLAD_API_PTR *GLVULKANPROCNV)(void);
#define GL_VERSION_1_0 1 #define GL_VERSION_1_0 1
#define GL_VERSION_1_1 1 #define GL_VERSION_1_1 1
#define GL_VERSION_1_2 1 #define GL_VERSION_1_2 1
@@ -4235,15 +4233,17 @@ typedef struct GladGLContext {
PFNGLWINDOWPOS3SVPROC WindowPos3sv; PFNGLWINDOWPOS3SVPROC WindowPos3sv;
} GladGLContext; } GladGLContext;
GLAD_API_CALL int
GLAD_API_CALL int gladLoadGLContextUserPtr(GladGLContext *context, GLADuserptrloadfunc load, void *userptr); gladLoadGLContextUserPtr(GladGLContext *context, GLADuserptrloadfunc load, void *userptr);
GLAD_API_CALL int gladLoadGLContext(GladGLContext *context, GLADloadfunc load); GLAD_API_CALL int
gladLoadGLContext(GladGLContext *context, GLADloadfunc load);
#ifdef GLAD_GL #ifdef GLAD_GL
GLAD_API_CALL int gladLoaderLoadGLContext(GladGLContext *context); GLAD_API_CALL int
GLAD_API_CALL void gladLoaderUnloadGL(void); gladLoaderLoadGLContext(GladGLContext *context);
GLAD_API_CALL void
gladLoaderUnloadGL(void);
#endif #endif

View File

@@ -1525,7 +1525,8 @@ typedef struct _NVFBC_TOGL_GRAB_FRAME_PARAMS {
* A NULL terminated error message, or an empty string. Its maximum length * A NULL terminated error message, or an empty string. Its maximum length
* is NVFBC_ERROR_STR_LEN. * is NVFBC_ERROR_STR_LEN.
*/ */
const char *NVFBCAPI NvFBCGetLastErrorStr(const NVFBC_SESSION_HANDLE sessionHandle); const char *NVFBCAPI
NvFBCGetLastErrorStr(const NVFBC_SESSION_HANDLE sessionHandle);
/*! /*!
* \brief Allocates a new handle for an NvFBC client. * \brief Allocates a new handle for an NvFBC client.
@@ -1551,7 +1552,8 @@ const char *NVFBCAPI NvFBCGetLastErrorStr(const NVFBC_SESSION_HANDLE sessionHand
* ::NVFBC_ERR_GL * ::NVFBC_ERR_GL
* *
*/ */
NVFBCSTATUS NVFBCAPI NvFBCCreateHandle(NVFBC_SESSION_HANDLE *pSessionHandle, NVFBC_CREATE_HANDLE_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCCreateHandle(NVFBC_SESSION_HANDLE *pSessionHandle, NVFBC_CREATE_HANDLE_PARAMS *pParams);
/*! /*!
* \brief Destroys the handle of an NvFBC client. * \brief Destroys the handle of an NvFBC client.
@@ -1577,7 +1579,8 @@ NVFBCSTATUS NVFBCAPI NvFBCCreateHandle(NVFBC_SESSION_HANDLE *pSessionHandle, NVF
* ::NVFBC_ERR_CONTEXT \n * ::NVFBC_ERR_CONTEXT \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCDestroyHandle(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_HANDLE_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCDestroyHandle(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_HANDLE_PARAMS *pParams);
/*! /*!
* \brief Gets the current status of the display driver. * \brief Gets the current status of the display driver.
@@ -1596,7 +1599,8 @@ NVFBCSTATUS NVFBCAPI NvFBCDestroyHandle(const NVFBC_SESSION_HANDLE sessionHandle
* ::NVFBC_ERR_INTERNAL \n * ::NVFBC_ERR_INTERNAL \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCGetStatus(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_GET_STATUS_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCGetStatus(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_GET_STATUS_PARAMS *pParams);
/*! /*!
* \brief Binds the FBC context to the calling thread. * \brief Binds the FBC context to the calling thread.
@@ -1630,7 +1634,8 @@ NVFBCSTATUS NVFBCAPI NvFBCGetStatus(const NVFBC_SESSION_HANDLE sessionHandle, NV
* ::NVFBC_ERR_INTERNAL \n * ::NVFBC_ERR_INTERNAL \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCBindContext(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_BIND_CONTEXT_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCBindContext(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_BIND_CONTEXT_PARAMS *pParams);
/*! /*!
* \brief Releases the FBC context from the calling thread. * \brief Releases the FBC context from the calling thread.
@@ -1651,7 +1656,8 @@ NVFBCSTATUS NVFBCAPI NvFBCBindContext(const NVFBC_SESSION_HANDLE sessionHandle,
* ::NVFBC_ERR_INTERNAL \n * ::NVFBC_ERR_INTERNAL \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCReleaseContext(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_RELEASE_CONTEXT_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCReleaseContext(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_RELEASE_CONTEXT_PARAMS *pParams);
/*! /*!
* \brief Creates a capture session for an FBC client. * \brief Creates a capture session for an FBC client.
@@ -1686,7 +1692,8 @@ NVFBCSTATUS NVFBCAPI NvFBCReleaseContext(const NVFBC_SESSION_HANDLE sessionHandl
* ::NVFBC_ERR_MUST_RECREATE \n * ::NVFBC_ERR_MUST_RECREATE \n
* ::NVFBC_ERR_INTERNAL * ::NVFBC_ERR_INTERNAL
*/ */
NVFBCSTATUS NVFBCAPI NvFBCCreateCaptureSession(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_CREATE_CAPTURE_SESSION_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCCreateCaptureSession(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_CREATE_CAPTURE_SESSION_PARAMS *pParams);
/*! /*!
* \brief Destroys a capture session for an FBC client. * \brief Destroys a capture session for an FBC client.
@@ -1710,7 +1717,8 @@ NVFBCSTATUS NVFBCAPI NvFBCCreateCaptureSession(const NVFBC_SESSION_HANDLE sessio
* ::NVFBC_ERR_INTERNAL \n * ::NVFBC_ERR_INTERNAL \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCDestroyCaptureSession(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_CAPTURE_SESSION_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCDestroyCaptureSession(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_DESTROY_CAPTURE_SESSION_PARAMS *pParams);
/*! /*!
* \brief Sets up a capture to system memory session. * \brief Sets up a capture to system memory session.
@@ -1742,7 +1750,8 @@ NVFBCSTATUS NVFBCAPI NvFBCDestroyCaptureSession(const NVFBC_SESSION_HANDLE sessi
* ::NVFBC_ERR_OUT_OF_MEMORY \n * ::NVFBC_ERR_OUT_OF_MEMORY \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCToSysSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_SETUP_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCToSysSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_SETUP_PARAMS *pParams);
/*! /*!
* \brief Captures a frame to a buffer in system memory. * \brief Captures a frame to a buffer in system memory.
@@ -1782,7 +1791,8 @@ NVFBCSTATUS NVFBCAPI NvFBCToSysSetUp(const NVFBC_SESSION_HANDLE sessionHandle, N
* \see NvFBCCreateCaptureSession \n * \see NvFBCCreateCaptureSession \n
* \see NvFBCToSysSetUp * \see NvFBCToSysSetUp
*/ */
NVFBCSTATUS NVFBCAPI NvFBCToSysGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_GRAB_FRAME_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCToSysGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOSYS_GRAB_FRAME_PARAMS *pParams);
/*! /*!
* \brief Sets up a capture to video memory session. * \brief Sets up a capture to video memory session.
@@ -1809,7 +1819,8 @@ NVFBCSTATUS NVFBCAPI NvFBCToSysGrabFrame(const NVFBC_SESSION_HANDLE sessionHandl
* ::NVFBC_ERR_GL \n * ::NVFBC_ERR_GL \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCToCudaSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_SETUP_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCToCudaSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_SETUP_PARAMS *pParams);
/*! /*!
* \brief Captures a frame to a CUDA device in video memory. * \brief Captures a frame to a CUDA device in video memory.
@@ -1838,7 +1849,8 @@ NVFBCSTATUS NVFBCAPI NvFBCToCudaSetUp(const NVFBC_SESSION_HANDLE sessionHandle,
* \see NvFBCCreateCaptureSession \n * \see NvFBCCreateCaptureSession \n
* \see NvFBCToCudaSetUp * \see NvFBCToCudaSetUp
*/ */
NVFBCSTATUS NVFBCAPI NvFBCToCudaGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_GRAB_FRAME_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCToCudaGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOCUDA_GRAB_FRAME_PARAMS *pParams);
/*! /*!
* \brief Sets up a capture to OpenGL buffer in video memory session. * \brief Sets up a capture to OpenGL buffer in video memory session.
@@ -1865,7 +1877,8 @@ NVFBCSTATUS NVFBCAPI NvFBCToCudaGrabFrame(const NVFBC_SESSION_HANDLE sessionHand
* ::NVFBC_ERR_GL \n * ::NVFBC_ERR_GL \n
* ::NVFBC_ERR_X * ::NVFBC_ERR_X
*/ */
NVFBCSTATUS NVFBCAPI NvFBCToGLSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_SETUP_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCToGLSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_SETUP_PARAMS *pParams);
/*! /*!
* \brief Captures a frame to an OpenGL buffer in video memory. * \brief Captures a frame to an OpenGL buffer in video memory.
@@ -1893,7 +1906,8 @@ NVFBCSTATUS NVFBCAPI NvFBCToGLSetUp(const NVFBC_SESSION_HANDLE sessionHandle, NV
* \see NvFBCCreateCaptureSession \n * \see NvFBCCreateCaptureSession \n
* \see NvFBCToCudaSetUp * \see NvFBCToCudaSetUp
*/ */
NVFBCSTATUS NVFBCAPI NvFBCToGLGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_GRAB_FRAME_PARAMS *pParams); NVFBCSTATUS NVFBCAPI
NvFBCToGLGrabFrame(const NVFBC_SESSION_HANDLE sessionHandle, NVFBC_TOGL_GRAB_FRAME_PARAMS *pParams);
/*! /*!
* \cond FBC_PFN * \cond FBC_PFN
@@ -1966,7 +1980,8 @@ typedef struct
* ::NVFBC_ERR_INVALID_PTR \n * ::NVFBC_ERR_INVALID_PTR \n
* ::NVFBC_ERR_API_VERSION * ::NVFBC_ERR_API_VERSION
*/ */
NVFBCSTATUS NVFBCAPI NvFBCCreateInstance(NVFBC_API_FUNCTION_LIST *pFunctionList); NVFBCSTATUS NVFBCAPI
NvFBCCreateInstance(NVFBC_API_FUNCTION_LIST *pFunctionList);
/*! /*!
* \ingroup FBC_FUNC * \ingroup FBC_FUNC
* *

File diff suppressed because it is too large Load Diff

View File

@@ -31,12 +31,14 @@ int device_state_filter = DEVICE_STATE_ACTIVE;
namespace audio { namespace audio {
template <class T> template <class T>
void Release(T *p) { void
Release(T *p) {
p->Release(); p->Release();
} }
template <class T> template <class T>
void co_task_free(T *p) { void
co_task_free(T *p) {
CoTaskMemFree((LPVOID) p); CoTaskMemFree((LPVOID) p);
} }
@@ -65,7 +67,8 @@ public:
PROPVARIANT prop; PROPVARIANT prop;
}; };
const wchar_t *no_null(const wchar_t *str) { const wchar_t *
no_null(const wchar_t *str) {
return str ? str : L"Unknown"; return str ? str : L"Unknown";
} }
@@ -100,7 +103,8 @@ struct format_t {
SPEAKER_SIDE_RIGHT } SPEAKER_SIDE_RIGHT }
}; };
void set_wave_format(audio::wave_format_t &wave_format, const format_t &format) { void
set_wave_format(audio::wave_format_t &wave_format, const format_t &format) {
wave_format->nChannels = format.channels; wave_format->nChannels = format.channels;
wave_format->nBlockAlign = wave_format->nChannels * wave_format->wBitsPerSample / 8; wave_format->nBlockAlign = wave_format->nChannels * wave_format->wBitsPerSample / 8;
wave_format->nAvgBytesPerSec = wave_format->nSamplesPerSec * wave_format->nBlockAlign; wave_format->nAvgBytesPerSec = wave_format->nSamplesPerSec * wave_format->nBlockAlign;
@@ -110,7 +114,8 @@ void set_wave_format(audio::wave_format_t &wave_format, const format_t &format)
} }
} }
audio_client_t make_audio_client(device_t &device, const format_t &format) { audio_client_t
make_audio_client(device_t &device, const format_t &format) {
audio_client_t audio_client; audio_client_t audio_client;
auto status = device->Activate( auto status = device->Activate(
IID_IAudioClient, IID_IAudioClient,
@@ -171,7 +176,8 @@ audio_client_t make_audio_client(device_t &device, const format_t &format) {
return audio_client; return audio_client;
} }
void print_device(device_t &device) { void
print_device(device_t &device) {
audio::wstring_t wstring; audio::wstring_t wstring;
DWORD device_state; DWORD device_state;
@@ -231,14 +237,16 @@ void print_device(device_t &device) {
} }
} // namespace audio } // namespace audio
void print_help() { void
print_help() {
std::cout std::cout
<< "==== Help ===="sv << std::endl << "==== Help ===="sv << std::endl
<< "Usage:"sv << std::endl << "Usage:"sv << std::endl
<< " audio-info [Active|Disabled|Unplugged|Not-Present]" << std::endl; << " audio-info [Active|Disabled|Unplugged|Not-Present]" << std::endl;
} }
int main(int argc, char *argv[]) { int
main(int argc, char *argv[]) {
CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY); CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY);
auto fg = util::fail_guard([]() { auto fg = util::fail_guard([]() {

View File

@@ -11,7 +11,8 @@
using namespace std::literals; using namespace std::literals;
namespace dxgi { namespace dxgi {
template <class T> template <class T>
void Release(T *dxgi) { void
Release(T *dxgi) {
dxgi->Release(); dxgi->Release();
} }
@@ -24,7 +25,8 @@ using dup_t = util::safe_ptr<IDXGIOutputDuplication, Release<IDXGIOutputDup
} // namespace dxgi } // namespace dxgi
LSTATUS set_gpu_preference(int preference) { LSTATUS
set_gpu_preference(int preference) {
// The GPU preferences key uses app path as the value name. // The GPU preferences key uses app path as the value name.
WCHAR executable_path[MAX_PATH]; WCHAR executable_path[MAX_PATH];
GetModuleFileNameW(NULL, executable_path, ARRAYSIZE(executable_path)); GetModuleFileNameW(NULL, executable_path, ARRAYSIZE(executable_path));
@@ -46,7 +48,8 @@ LSTATUS set_gpu_preference(int preference) {
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
HRESULT test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) { HRESULT
test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output) {
D3D_FEATURE_LEVEL featureLevels[] { D3D_FEATURE_LEVEL featureLevels[] {
D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_0,
@@ -85,7 +88,8 @@ HRESULT test_dxgi_duplication(dxgi::adapter_t &adapter, dxgi::output_t &output)
return output1->DuplicateOutput((IUnknown *) device.get(), &dup); return output1->DuplicateOutput((IUnknown *) device.get(), &dup);
} }
int main(int argc, char *argv[]) { int
main(int argc, char *argv[]) {
HRESULT status; HRESULT status;
// Display name may be omitted // Display name may be omitted

View File

@@ -12,7 +12,8 @@
using namespace std::literals; using namespace std::literals;
namespace dxgi { namespace dxgi {
template <class T> template <class T>
void Release(T *dxgi) { void
Release(T *dxgi) {
dxgi->Release(); dxgi->Release();
} }
@@ -22,7 +23,8 @@ using output_t = util::safe_ptr<IDXGIOutput, Release<IDXGIOutput>>;
} // namespace dxgi } // namespace dxgi
int main(int argc, char *argv[]) { int
main(int argc, char *argv[]) {
HRESULT status; HRESULT status;
dxgi::factory1_t::pointer factory_p {}; dxgi::factory1_t::pointer factory_p {};

View File

@@ -19,7 +19,8 @@
* To run a command, such as 'ipconfig /flushdns', with administrative privileges, execute: * To run a command, such as 'ipconfig /flushdns', with administrative privileges, execute:
* elevator.exe cmd /C "ipconfig /flushdns" * elevator.exe cmd /C "ipconfig /flushdns"
*/ */
int main(int argc, char *argv[]) { int
main(int argc, char *argv[]) {
// Check if the user provided at least one argument (the command to run) // Check if the user provided at least one argument (the command to run)
if (argc < 2) { if (argc < 2) {
std::cout << "Usage: " << argv[0] << " <command> [arguments]" << std::endl; std::cout << "Usage: " << argv[0] << " <command> [arguments]" << std::endl;

Some files were not shown because too many files have changed in this diff Show More