Merge remote-tracking branch 'sunshine/master'

This commit is contained in:
Yukino Song
2025-04-01 20:05:27 +08:00
21 changed files with 270 additions and 72 deletions

View File

@@ -665,9 +665,13 @@ namespace config {
// Lists might contain newlines
if (*begin_val == '[') {
endl = skip_list(begin_val + 1, end);
if (endl == end) {
std::cout << "Warning: Config option ["sv << to_string(begin, end_name) << "] Missing ']'"sv;
// Check if we reached the end of the file without finding a closing bracket
// We know we have a valid closing bracket if:
// 1. We didn't reach the end, or
// 2. We reached the end but the last character was the matching closing bracket
if (endl == end && end == begin_val + 1) {
BOOST_LOG(warning) << "config: Missing ']' in config option: " << to_string(begin, end_name);
return std::make_pair(endl, std::nullopt);
}
}
@@ -1027,7 +1031,7 @@ namespace config {
// The list needs to be a multiple of 2
if (list.size() % 2) {
std::cout << "Warning: expected "sv << name << " to have a multiple of two elements --> not "sv << list.size() << std::endl;
BOOST_LOG(warning) << "config: expected "sv << name << " to have a multiple of two elements --> not "sv << list.size();
return;
}
@@ -1057,7 +1061,7 @@ namespace config {
config::sunshine.flags[config::flag::UPNP].flip();
break;
default:
std::cout << "Warning: Unrecognized flag: ["sv << *line << ']' << std::endl;
BOOST_LOG(warning) << "config: Unrecognized flag: ["sv << *line << ']' << std::endl;
ret = -1;
}
@@ -1083,11 +1087,7 @@ namespace config {
}
for (auto &[name, val] : vars) {
#ifdef _WIN32
std::cout << "["sv << name << "] -- ["sv << utf8ToAcp(val) << ']' << std::endl;
#else
std::cout << "["sv << name << "] -- ["sv << val << ']' << std::endl;
#endif
BOOST_LOG(info) << "config: '"sv << name << "' = "sv << val;
}
bool_f(vars, "headless_mode", video.headless_mode);
@@ -1485,7 +1485,7 @@ namespace config {
shell_exec_info.nShow = SW_NORMAL;
if (!ShellExecuteExW(&shell_exec_info)) {
auto winerr = GetLastError();
std::cout << "Error: ShellExecuteEx() failed:"sv << winerr << std::endl;
BOOST_LOG(error) << "Failed executing shell command: " << winerr << std::endl;
return 1;
}

View File

@@ -108,10 +108,6 @@ int main(int argc, char *argv[]) {
mail::man = std::make_shared<safe::mail_raw_t>();
if (config::parse(argc, argv)) {
return 0;
}
auto log_deinit_guard = logging::init(config::sunshine.min_log_level, config::sunshine.log_file);
if (!log_deinit_guard) {
BOOST_LOG(error) << "Logging failed to initialize"sv;
@@ -125,6 +121,11 @@ int main(int argc, char *argv[]) {
// Log publisher metadata
log_publisher_data();
// parse config file
if (config::parse(argc, argv)) {
return 0;
}
if (!config::sunshine.cmd.name.empty()) {
auto fn = cmd_to_func.find(config::sunshine.cmd.name);
if (fn == std::end(cmd_to_func)) {

View File

@@ -106,6 +106,7 @@ namespace platf {
rumble_triggers, ///< Rumble triggers
set_motion_event_state, ///< Set motion event state
set_rgb_led, ///< Set RGB LED
set_adaptive_triggers, ///< Set adaptive triggers
};
struct gamepad_feedback_msg_t {
@@ -142,6 +143,14 @@ namespace platf {
return msg;
}
static gamepad_feedback_msg_t make_adaptive_triggers(std::uint16_t id, uint8_t event_flags, uint8_t type_left, uint8_t type_right, const std::array<uint8_t, 10> &left, const std::array<uint8_t, 10> &right) {
gamepad_feedback_msg_t msg;
msg.type = gamepad_feedback_e::set_adaptive_triggers;
msg.id = id;
msg.data.adaptive_triggers = {.event_flags = event_flags, .type_left = type_left, .type_right = type_right, .left = left, .right = right};
return msg;
}
gamepad_feedback_e type;
std::uint16_t id;
@@ -166,6 +175,15 @@ namespace platf {
std::uint8_t g;
std::uint8_t b;
} rgb_led;
struct {
uint16_t controllerNumber;
uint8_t event_flags;
uint8_t type_left;
uint8_t type_right;
std::array<uint8_t, 10> left;
std::array<uint8_t, 10> right;
} adaptive_triggers;
} data;
};

View File

@@ -43,7 +43,7 @@ namespace platf::gamepad {
}
auto create_ds5() {
return inputtino::PS5Joypad::create({.name = "Sunshine DualSense (virtual) pad", .vendor_id = 0x054C, .product_id = 0x0CE6, .version = 0x8111});
return inputtino::PS5Joypad::create({.name = "Sunshine PS5 (virtual) pad", .vendor_id = 0x054C, .product_id = 0x0CE6, .version = 0x8111});
}
int alloc(input_raw_t *raw, const gamepad_id_t &id, const gamepad_arrival_t &metadata, feedback_queue_t feedback_queue) {
@@ -152,6 +152,10 @@ namespace platf::gamepad {
gamepad->last_rgb_led = msg;
});
(*ds5).set_on_trigger_effect([feedback_queue, idx = id.clientRelativeIndex](const inputtino::PS5Joypad::TriggerEffect &trigger_effect) {
feedback_queue->raise(gamepad_feedback_msg_t::make_adaptive_triggers(idx, trigger_effect.event_flags, trigger_effect.type_left, trigger_effect.type_right, trigger_effect.left, trigger_effect.right));
});
// Activate the motion sensors
feedback_queue->raise(gamepad_feedback_msg_t::make_motion_event_state(id.clientRelativeIndex, LI_MOTION_TYPE_ACCEL, 100));
feedback_queue->raise(gamepad_feedback_msg_t::make_motion_event_state(id.clientRelativeIndex, LI_MOTION_TYPE_GYRO, 100));

View File

@@ -52,6 +52,7 @@ extern "C" {
#define IDX_EXEC_SERVER_CMD 15
#define IDX_SET_CLIPBOARD 16
#define IDX_FILE_TRANSFER_NONCE_REQUEST 17
#define IDX_SET_ADAPTIVE_TRIGGERS 18
static const short packetTypes[] = {
0x0305, // Start A
@@ -72,6 +73,7 @@ static const short packetTypes[] = {
0x3000, // Execute Server Command (Apollo protocol extension)
0x3001, // Set Clipboard (Apollo protocol extension)
0x3002, // File transfer nonce request (Apollo protocol extension)
0x5503, // Set Adaptive triggers (Sunshine protocol extension)
};
namespace asio = boost::asio;
@@ -193,6 +195,21 @@ namespace stream {
std::uint8_t b;
};
struct control_adaptive_triggers_t {
control_header_v2 header;
std::uint16_t id;
/**
* 0x04 - Right trigger
* 0x08 - Left trigger
*/
std::uint8_t event_flags;
std::uint8_t type_left;
std::uint8_t type_right;
std::uint8_t left[DS_EFFECT_PAYLOAD_SIZE];
std::uint8_t right[DS_EFFECT_PAYLOAD_SIZE];
};
struct control_hdr_mode_t {
control_header_v2 header;
@@ -846,6 +863,22 @@ namespace stream {
plaintext.b = data.b;
BOOST_LOG(verbose) << "RGB: "sv << msg.id << " :: "sv << util::hex(data.r).to_string_view() << util::hex(data.g).to_string_view() << util::hex(data.b).to_string_view();
std::array<std::uint8_t, sizeof(control_encrypted_t) + crypto::cipher::round_to_pkcs7_padded(sizeof(plaintext)) + crypto::cipher::tag_size>
encrypted_payload;
payload = encode_control(session, util::view(plaintext), encrypted_payload);
} else if (msg.type == platf::gamepad_feedback_e::set_adaptive_triggers) {
control_adaptive_triggers_t plaintext;
plaintext.header.type = packetTypes[IDX_SET_ADAPTIVE_TRIGGERS];
plaintext.header.payloadLength = sizeof(plaintext) - sizeof(control_header_v2);
plaintext.id = util::endian::little(msg.id);
plaintext.event_flags = msg.data.adaptive_triggers.event_flags;
plaintext.type_left = msg.data.adaptive_triggers.type_left;
std::ranges::copy(msg.data.adaptive_triggers.left, plaintext.left);
plaintext.type_right = msg.data.adaptive_triggers.type_right;
std::ranges::copy(msg.data.adaptive_triggers.right, plaintext.right);
std::array<std::uint8_t, sizeof(control_encrypted_t) + crypto::cipher::round_to_pkcs7_padded(sizeof(plaintext)) + crypto::cipher::tag_size>
encrypted_payload;