Skip to content

Commit

Permalink
new display options prototype, config http json
Browse files Browse the repository at this point in the history
  • Loading branch information
Hazer committed May 2, 2024
1 parent 2516960 commit ec5f163
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 51 deletions.
7 changes: 2 additions & 5 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <vector>

#include "nvenc/nvenc_config.h"
#include "display_device/dd.h"

namespace config {
struct video_t {
Expand Down Expand Up @@ -82,11 +83,7 @@ namespace config {
bool install_steam_drivers;
};

struct display_options_t {
int id;
std::string name;
bool is_primary_display;
};


constexpr int ENCRYPTION_MODE_NEVER = 0; // Never use video encryption, even if the client supports it
constexpr int ENCRYPTION_MODE_OPPORTUNISTIC = 1; // Use video encryption if available, but stream without it if not supported
Expand Down
32 changes: 11 additions & 21 deletions src/confighttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,34 +533,24 @@ namespace confighttp {

print_req(request);

pt::ptree outputTree;
nlohmann::json outputJson;
auto g = util::fail_guard([&]() {
std::ostringstream data;

pt::write_json(data, outputTree);
response->write(data.str());
response->write(outputJson.dump());
});

outputTree.put("status", "true");
outputTree.put("platform", SUNSHINE_PLATFORM);
outputTree.put("version", PROJECT_VER);

pt::ptree displays;
for (const auto &[id, name, is_primary_display] : platf::display_options()) {
pt::ptree display_value;
display_value.put("id", id);
display_value.put("name", name);
display_value.put("is_primary", is_primary_display);
displays.push_front(std::make_pair(std::to_string(id), display_value));
}
outputTree.push_back(std::make_pair("displays", displays));
outputJson.emplace("status", "true");
outputJson.emplace("platform", SUNSHINE_PLATFORM);
outputJson.emplace("version", PROJECT_VER);

nlohmann::json displays = platf::display_options();
outputJson.emplace("displays", displays);

auto vars = config::parse_config(file_handler::read_file(config::sunshine.config_file.c_str()));
pt::ptree config_file;
nlohmann::json config_file;
for (auto &[name, value] : vars) {
config_file.put(std::move(name), std::move(value));
config_file.emplace(std::move(name), std::move(value));
}
outputTree.push_back(std::make_pair("config_file", config_file));
outputJson.emplace(std::make_pair("config_file", config_file));
}

void
Expand Down
86 changes: 86 additions & 0 deletions src/display_device/dd.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,92 @@
#include <nlohmann/json.hpp>

namespace dd {

enum class device_state_e {
inactive,
active,
primary /**< Primary state is also implicitly active. */
};

/**
* @brief The device's HDR state in the operating system.
*/
enum class hdr_state_e {
unknown, /**< HDR state could not be retrieved from the OS (even if the display supports it). */
disabled,
enabled
};

/**
* @brief Display's origin position.
* @note Display origin may vary given the compositor running.
*/
struct origin_t {
int x;
int y;

[[nodiscard]] bool is_primary() const {
return this->x == 0 && this->y == 0;
}
// For JSON serialization
NLOHMANN_DEFINE_TYPE_INTRUSIVE(origin_t, x, y)
};

struct resolution_t {
unsigned int width;
unsigned int height;
double scale_factor;

// For JSON serialization
NLOHMANN_DEFINE_TYPE_INTRUSIVE(resolution_t, width, height, scale_factor)
};

/**
* @brief Display's refresh rate.
* @note Floating point is stored in a "numerator/denominator" form.
*/
struct refresh_rate_t {
unsigned int numerator;
unsigned int denominator;

// For JSON serialization
NLOHMANN_DEFINE_TYPE_INTRUSIVE(refresh_rate_t, numerator, denominator)
};

/**
* @brief Display's mode (resolution + refresh rate).
* @see resolution_t
* @see refresh_rate_t
*/
struct mode_t {
resolution_t resolution;
refresh_rate_t refresh_rate;

// For JSON serialization
NLOHMANN_DEFINE_TYPE_INTRUSIVE(mode_t, resolution, refresh_rate)
};


namespace options {
struct current_settings_t {
origin_t origin;
mode_t mode;

[[nodiscard]] bool is_primary() const {
return origin.is_primary();
}

// For JSON serialization
NLOHMANN_DEFINE_TYPE_INTRUSIVE(current_settings_t, origin, mode)
};

struct info_t {
std::string id;
std::string friendly_name;
current_settings_t current_settings;

// For JSON serialization
NLOHMANN_DEFINE_TYPE_INTRUSIVE(info_t, id, friendly_name, current_settings)
};
}
}
2 changes: 1 addition & 1 deletion src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ namespace platf {
std::vector<std::string>
display_names(mem_type_e hwdevice_type);

std::vector<config::display_options_t>
std::vector<dd::options::info_t>
display_options();

/**
Expand Down
24 changes: 0 additions & 24 deletions src/platform/macos/display.mm
Original file line number Diff line number Diff line change
Expand Up @@ -188,30 +188,6 @@
return display_names;
}

std::vector<config::display_options_t>
display_options() {
__block std::vector<config::display_options_t> display_options;

auto display_array = [AVVideo displayNames];

auto main_display_id = CGMainDisplayID();
display_options.reserve([display_array count]);

[display_array enumerateObjectsUsingBlock:^(NSDictionary *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) {
NSNumber *display_id = obj[@"id"];
NSString *name = obj[@"displayName"];

auto option = config::display_options_t {
[display_id intValue],
name.UTF8String,
main_display_id == [display_id unsignedIntValue]
};
display_options.emplace_back(option);
}];

return display_options;
}

/**
* @brief Returns if GPUs/drivers have changed since the last call to this function.
* @return `true` if a change has occurred or if it is unknown whether a change occurred.
Expand Down
83 changes: 83 additions & 0 deletions src/platform/macos/display_options.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* @file src/platform/macos/display_options.mm
* @brief todo
*/
#include "src/platform/common.h"
#include "src/platform/macos/av_video.h"

#include "src/config.h"
#include "src/logging.h"

#include <CoreGraphics/CoreGraphics.h>
#include <CoreGraphics/CGDirectDisplay.h>

namespace fs = std::filesystem;

namespace platf {
using namespace std::literals;

dd::options::info_t
display_mode(NSArray<NSScreen *>* screens, CGDirectDisplayID displayID) {
auto id = [NSNumber numberWithUnsignedInt:displayID];
for (NSScreen *screen in screens) {
if (screen.deviceDescription[@"NSScreenNumber"] == id) {
NSRect frame = screen.frame;
auto origin = dd::origin_t {
int(frame.origin.x),
int(frame.origin.y)
};
auto resolution = dd::resolution_t {
uint32_t(frame.size.width),
uint32_t(frame.size.height),
screen.backingScaleFactor
};

//auto minimumFramesPerSecond = uint32_t(screen.minimumFramesPerSecond);
//double displayUpdateGranularity = screen.displayUpdateGranularity;
auto refresh_rate = dd::refresh_rate_t {
uint32_t(screen.maximumFramesPerSecond),
0
};
auto current_mode = dd::mode_t {
resolution,
refresh_rate
};
auto settings = dd::options::current_settings_t {
origin,
current_mode
};
auto info = dd::options::info_t {
[id stringValue].UTF8String,
screen.localizedName.UTF8String,
settings
};
return info;
}
}

return {};
}

std::vector<dd::options::info_t>
display_options() {
CGDirectDisplayID active_displays[kMaxDisplays];
uint32_t count;
if (CGGetActiveDisplayList(kMaxDisplays, active_displays, &count) != kCGErrorSuccess) {
return {};
}

std::vector<dd::options::info_t> display_options;

display_options.reserve(count);

auto screens = [NSScreen screens];

for (uint32_t i = 0; i < count; i++) {
display_options.emplace_back(
platf::display_mode(screens, active_displays[i])
);
}

return display_options;
}
} // namespace platf

0 comments on commit ec5f163

Please sign in to comment.