Sunshine/sunshine/platform/common.h

316 lines
7.4 KiB
C
Raw Normal View History

//
// Created by loki on 6/21/19.
//
#ifndef SUNSHINE_COMMON_H
#define SUNSHINE_COMMON_H
2021-05-18 11:36:12 +00:00
#include <bitset>
#include <filesystem>
2021-07-18 09:05:34 +00:00
#include <functional>
2021-05-17 19:21:57 +00:00
#include <mutex>
#include <string>
2021-07-18 09:05:34 +00:00
#include "sunshine/thread_safe.h"
#include "sunshine/utility.h"
2020-02-08 15:26:38 +00:00
struct sockaddr;
struct AVFrame;
namespace platf {
2020-03-15 20:22:42 +00:00
constexpr auto MAX_GAMEPADS = 32;
2020-01-25 00:05:43 +00:00
constexpr std::uint16_t DPAD_UP = 0x0001;
constexpr std::uint16_t DPAD_DOWN = 0x0002;
constexpr std::uint16_t DPAD_LEFT = 0x0004;
constexpr std::uint16_t DPAD_RIGHT = 0x0008;
constexpr std::uint16_t START = 0x0010;
constexpr std::uint16_t BACK = 0x0020;
constexpr std::uint16_t LEFT_STICK = 0x0040;
constexpr std::uint16_t RIGHT_STICK = 0x0080;
constexpr std::uint16_t LEFT_BUTTON = 0x0100;
constexpr std::uint16_t RIGHT_BUTTON = 0x0200;
constexpr std::uint16_t HOME = 0x0400;
constexpr std::uint16_t A = 0x1000;
constexpr std::uint16_t B = 0x2000;
constexpr std::uint16_t X = 0x4000;
constexpr std::uint16_t Y = 0x8000;
2021-07-18 09:05:34 +00:00
struct rumble_t {
KITTY_DEFAULT_CONSTR(rumble_t)
rumble_t(std::uint16_t id, std::uint16_t lowfreq, std::uint16_t highfreq)
: id { id }, lowfreq { lowfreq }, highfreq { highfreq } {}
std::uint16_t id;
std::uint16_t lowfreq;
std::uint16_t highfreq;
};
using rumble_queue_t = safe::mail_raw_t::queue_t<rumble_t>;
2021-05-19 16:11:06 +00:00
namespace speaker {
enum speaker_e {
FRONT_LEFT,
FRONT_RIGHT,
FRONT_CENTER,
LOW_FREQUENCY,
BACK_LEFT,
BACK_RIGHT,
SIDE_LEFT,
SIDE_RIGHT,
MAX_SPEAKERS,
2021-05-19 16:11:06 +00:00
};
constexpr std::uint8_t map_stereo[] {
FRONT_LEFT, FRONT_RIGHT
};
constexpr std::uint8_t map_surround51[] {
2021-05-22 17:51:01 +00:00
FRONT_LEFT,
FRONT_RIGHT,
FRONT_CENTER,
LOW_FREQUENCY,
BACK_LEFT,
BACK_RIGHT,
2021-05-19 16:11:06 +00:00
};
constexpr std::uint8_t map_surround71[] {
FRONT_LEFT,
FRONT_RIGHT,
2021-05-22 17:51:01 +00:00
FRONT_CENTER,
LOW_FREQUENCY,
LOW_FREQUENCY,
BACK_LEFT,
2021-05-19 16:11:06 +00:00
BACK_RIGHT,
SIDE_LEFT,
SIDE_RIGHT,
};
} // namespace speaker
enum class mem_type_e {
system,
vaapi,
2020-04-11 23:33:17 +00:00
dxgi,
cuda,
2020-04-11 23:33:17 +00:00
unknown
};
2020-04-02 18:13:44 +00:00
enum class pix_fmt_e {
yuv420p,
2020-04-11 23:33:17 +00:00
yuv420p10,
nv12,
p010,
2020-04-11 23:33:17 +00:00
unknown
2020-04-02 18:13:44 +00:00
};
2021-04-30 18:01:15 +00:00
inline std::string_view from_pix_fmt(pix_fmt_e pix_fmt) {
2021-05-17 19:21:57 +00:00
using namespace std::literals;
#define _CONVERT(x) \
case pix_fmt_e::x: \
return #x##sv
2021-04-30 18:01:15 +00:00
switch(pix_fmt) {
_CONVERT(yuv420p);
_CONVERT(yuv420p10);
_CONVERT(nv12);
_CONVERT(p010);
_CONVERT(unknown);
}
#undef _CONVERT
return "unknown"sv;
}
// Dimensions for touchscreen input
struct touch_port_t {
int offset_x, offset_y;
int width, height;
};
struct gamepad_state_t {
std::uint16_t buttonFlags;
std::uint8_t lt;
std::uint8_t rt;
std::int16_t lsX;
std::int16_t lsY;
std::int16_t rsX;
std::int16_t rsY;
};
class deinit_t {
public:
virtual ~deinit_t() = default;
};
struct img_t {
public:
2021-09-22 09:36:59 +00:00
img_t() = default;
img_t(img_t &&) = delete;
img_t(const img_t &) = delete;
img_t &operator=(img_t &&) = delete;
img_t &operator=(const img_t &) = delete;
2021-05-17 19:21:57 +00:00
std::uint8_t *data {};
std::int32_t width {};
2020-01-11 00:17:57 +00:00
std::int32_t height {};
std::int32_t pixel_pitch {};
std::int32_t row_pitch {};
2020-01-11 00:17:57 +00:00
2020-01-09 11:12:18 +00:00
virtual ~img_t() = default;
};
2021-05-19 16:11:06 +00:00
struct sink_t {
// Play on host PC
std::string host;
// On Windows, it is not possible to create a virtual sink
// Therefore, it is optional
struct null_t {
std::string stereo;
std::string surround51;
std::string surround71;
};
std::optional<null_t> null;
2021-05-18 11:36:12 +00:00
};
2020-04-15 17:16:20 +00:00
struct hwdevice_t {
void *data {};
AVFrame *frame {};
2020-04-02 18:13:44 +00:00
2020-04-15 17:16:20 +00:00
virtual int convert(platf::img_t &img) {
return -1;
2020-04-02 18:13:44 +00:00
}
2020-04-15 17:16:20 +00:00
/**
* implementations must take ownership of 'frame'
*/
virtual int set_frame(AVFrame *frame) {
std::abort(); // ^ This function must never be called
return -1;
};
2020-04-10 12:39:50 +00:00
virtual void set_colorspace(std::uint32_t colorspace, std::uint32_t color_range) {};
2020-04-02 18:13:44 +00:00
2020-04-15 17:16:20 +00:00
virtual ~hwdevice_t() = default;
2020-04-02 18:13:44 +00:00
};
2020-01-09 11:12:18 +00:00
enum class capture_e : int {
ok,
reinit,
timeout,
error
};
class display_t {
public:
/**
* When display has a new image ready, this callback will be called with the new image.
*
2021-07-26 18:56:32 +00:00
* On Break Request -->
* Returns nullptr
*
* On Success -->
* Returns the image object that should be filled next.
* This may or may not be the image send with the callback
*/
using snapshot_cb_t = std::function<std::shared_ptr<img_t>(std::shared_ptr<img_t> &img)>;
display_t() noexcept : offset_x { 0 }, offset_y { 0 } {}
/**
* snapshot_cb --> the callback
* std::shared_ptr<img_t> img --> The first image to use
* bool *cursor --> A pointer to the flag that indicates wether the cursor should be captured as well
*
* Returns either:
* capture_e::ok when stopping
* capture_e::error on error
* 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 std::shared_ptr<img_t> alloc_img() = 0;
2020-01-09 11:12:18 +00:00
2020-04-10 12:39:50 +00:00
virtual int dummy_img(img_t *img) = 0;
2021-06-05 10:25:19 +00:00
virtual std::shared_ptr<hwdevice_t> make_hwdevice(pix_fmt_e pix_fmt) {
2020-04-15 17:16:20 +00:00
return std::make_shared<hwdevice_t>();
}
2019-12-30 10:49:45 +00:00
virtual ~display_t() = default;
2020-04-15 17:16:20 +00:00
// Offsets for when streaming a specific monitor. By default, they are 0.
int offset_x, offset_y;
int env_width, env_height;
2020-04-15 17:16:20 +00:00
int width, height;
2019-12-30 10:49:45 +00:00
};
class mic_t {
public:
virtual capture_e sample(std::vector<std::int16_t> &frame_buffer) = 0;
2019-12-30 10:49:45 +00:00
virtual ~mic_t() = default;
};
2021-05-18 11:36:12 +00:00
class audio_control_t {
public:
2021-05-19 16:11:06 +00:00
virtual int set_sink(const std::string &sink) = 0;
2021-05-18 11:36:12 +00:00
2021-05-19 16:11:06 +00:00
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;
2021-05-18 11:36:12 +00:00
2021-05-19 16:11:06 +00:00
virtual std::optional<sink_t> sink_info() = 0;
2021-05-18 11:36:12 +00:00
virtual ~audio_control_t() = default;
};
2020-01-19 23:22:13 +00:00
2021-05-17 19:21:57 +00:00
void freeInput(void *);
2020-01-09 11:12:18 +00:00
using input_t = util::safe_ptr<void, freeInput>;
2019-12-05 23:13:16 +00:00
std::filesystem::path appdata();
std::string get_mac_address(const std::string_view &address);
2019-12-06 15:33:13 +00:00
2020-02-08 15:26:38 +00:00
std::string from_sockaddr(const sockaddr *const);
std::pair<std::uint16_t, std::string> from_sockaddr_ex(const sockaddr *const);
2020-02-08 15:26:38 +00:00
2021-05-18 11:36:12 +00:00
std::unique_ptr<audio_control_t> audio_control();
/**
* display_name --> The name of the monitor that SHOULD be displayed
* If display_name is empty --> Use the first monitor that's compatible you can find
* If you require to use this parameter in a seperate thread --> make a copy of it.
*
* framerate --> The peak number of images per second
*
* Returns display_t based on hwdevice_type
*/
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, int framerate);
2021-07-29 15:27:22 +00:00
// 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);
2019-12-06 15:33:13 +00:00
input_t input();
void move_mouse(input_t &input, int deltaX, int deltaY);
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y);
2019-12-06 15:33:13 +00:00
void button_mouse(input_t &input, int button, bool release);
void scroll(input_t &input, int distance);
void keyboard(input_t &input, uint16_t modcode, bool release);
2020-01-25 19:46:14 +00:00
void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state);
int 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_TYPE "_nvstream._tcp"
namespace publish {
2021-06-26 13:48:07 +00:00
[[nodiscard]] std::unique_ptr<deinit_t> start();
}
[[nodiscard]] std::unique_ptr<deinit_t> init();
2021-07-18 13:32:26 +00:00
std::vector<std::string_view> &supported_gamepads();
2021-05-17 19:21:57 +00:00
} // namespace platf
#endif //SUNSHINE_COMMON_H