Skip to content

Commit e3d6659

Browse files
committed
feat: Configure display device based on user config
# Conflicts: # src/audio.h
1 parent 1543f58 commit e3d6659

File tree

22 files changed

+1650
-97
lines changed

22 files changed

+1650
-97
lines changed

docs/configuration.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,210 @@ editing the `conf` file in a text editor. Use the examples as reference.
942942
</tr>
943943
</table>
944944

945+
### dd_configuration_option
946+
947+
<table>
948+
<tr>
949+
<td>Description</td>
950+
<td colspan="2">
951+
@warning{Windows only!}
952+
Perform additional configuration for the display device:
953+
<ul>
954+
<li>`disabled` - perform no additional configuration (disables all `dd_` configuration options).</li>
955+
<li>`verify_only` - verify that display is active only (required for changing display mode and other options).</li>
956+
<li>`ensure_active` - activate the display if it's currently inactive.</li>
957+
<li>`ensure_primary` - activate the display if it's currently inactive and make it primary.</li>
958+
<li>`ensure_only_display` - activate the display if it's currently inactive and disable all others.</li>
959+
</ul>
960+
</td>
961+
</tr>
962+
<tr>
963+
<td>Default</td>
964+
<td colspan="2">@code{}verify_only@endcode</td>
965+
</tr>
966+
<tr>
967+
<td>Example</td>
968+
<td colspan="2">@code{}
969+
dd_configuration_option = ensure_only_display
970+
@endcode</td>
971+
</tr>
972+
</table>
973+
974+
### dd_resolution_option
975+
976+
<table>
977+
<tr>
978+
<td>Description</td>
979+
<td colspan="2">
980+
@warning{Windows only!}
981+
@note{"Optimize game settings" must be enabled for this option to work.}
982+
Perform additional resolution configuration for the display device:
983+
<ul>
984+
<li>`disabled` - perform no additional configuration.</li>
985+
<li>`automatic` - change resolution to the requested resolution from the client.</li>
986+
<li>`manual` - change resolution to the user specified one (set via `dd_manual_resolution`).</li>
987+
</ul>
988+
</td>
989+
</tr>
990+
<tr>
991+
<td>Default</td>
992+
<td colspan="2">@code{}automatic@endcode</td>
993+
</tr>
994+
<tr>
995+
<td>Example</td>
996+
<td colspan="2">@code{}
997+
dd_resolution_option = manual
998+
@endcode</td>
999+
</tr>
1000+
</table>
1001+
1002+
### dd_manual_resolution
1003+
1004+
<table>
1005+
<tr>
1006+
<td>Description</td>
1007+
<td colspan="2">
1008+
@warning{Windows only!}
1009+
@note{`dd_resolution_option` must be set to `manual`}
1010+
Specify manual resolution to be used.
1011+
</td>
1012+
</tr>
1013+
<tr>
1014+
<td>Default</td>
1015+
<td colspan="2">No value</td>
1016+
</tr>
1017+
<tr>
1018+
<td>Example</td>
1019+
<td colspan="2">@code{}
1020+
dd_manual_resolution = 1920x1080
1021+
@endcode</td>
1022+
</tr>
1023+
</table>
1024+
1025+
### dd_refresh_rate_option
1026+
1027+
<table>
1028+
<tr>
1029+
<td>Description</td>
1030+
<td colspan="2">
1031+
@warning{Windows only!}
1032+
Perform additional refresh rate configuration for the display device:
1033+
<ul>
1034+
<li>`disabled` - perform no additional configuration.</li>
1035+
<li>`automatic` - change refresh rate to the requested FPS value from the client.</li>
1036+
<li>`manual` - change refresh rate to the user specified one (set via `dd_manual_refresh_rate`).</li>
1037+
</ul>
1038+
</td>
1039+
</tr>
1040+
<tr>
1041+
<td>Default</td>
1042+
<td colspan="2">@code{}automatic@endcode</td>
1043+
</tr>
1044+
<tr>
1045+
<td>Example</td>
1046+
<td colspan="2">@code{}
1047+
dd_refresh_rate_option = manual
1048+
@endcode</td>
1049+
</tr>
1050+
</table>
1051+
1052+
### dd_manual_refresh_rate
1053+
1054+
<table>
1055+
<tr>
1056+
<td>Description</td>
1057+
<td colspan="2">
1058+
@warning{Windows only!}
1059+
@note{`dd_refresh_rate_option` must be set to `manual`}
1060+
Specify manual refresh rate to be used.
1061+
</td>
1062+
</tr>
1063+
<tr>
1064+
<td>Default</td>
1065+
<td colspan="2">No value</td>
1066+
</tr>
1067+
<tr>
1068+
<td>Example</td>
1069+
<td colspan="2">@code{}
1070+
dd_manual_resolution = 120
1071+
dd_manual_resolution = 59.95
1072+
@endcode</td>
1073+
</tr>
1074+
</table>
1075+
1076+
### dd_hdr_option
1077+
1078+
<table>
1079+
<tr>
1080+
<td>Description</td>
1081+
<td colspan="2">
1082+
@warning{Windows only!}
1083+
Perform additional HDR configuration for the display device:
1084+
<ul>
1085+
<li>`disabled` - perform no additional configuration.</li>
1086+
<li>`automatic` - change HDR to the requested state from the client if the display supports it.</li>
1087+
</ul>
1088+
</td>
1089+
</tr>
1090+
<tr>
1091+
<td>Default</td>
1092+
<td colspan="2">@code{}automatic@endcode</td>
1093+
</tr>
1094+
<tr>
1095+
<td>Example</td>
1096+
<td colspan="2">@code{}
1097+
dd_hdr_option = disabled
1098+
@endcode</td>
1099+
</tr>
1100+
</table>
1101+
1102+
### dd_wa_hdr_toggle
1103+
1104+
<table>
1105+
<tr>
1106+
<td>Description</td>
1107+
<td colspan="2">
1108+
@warning{Windows only!}
1109+
@note{This option works independently of `dd_hdr_option`}
1110+
When using virtual display device as for streaming, it might display incorrect (high-contrast) color.
1111+
With this option enabled, Sunshine will try to mitigate this issue.
1112+
</td>
1113+
</tr>
1114+
<tr>
1115+
<td>Default</td>
1116+
<td colspan="2">@code{}false@endcode</td>
1117+
</tr>
1118+
<tr>
1119+
<td>Example</td>
1120+
<td colspan="2">@code{}
1121+
dd_wa_hdr_toggle = true
1122+
@endcode</td>
1123+
</tr>
1124+
</table>
1125+
1126+
### dd_config_revert_delay
1127+
1128+
<table>
1129+
<tr>
1130+
<td>Description</td>
1131+
<td colspan="2">
1132+
@warning{Windows only!}
1133+
Additional delay in milliseconds to wait before reverting configuration when the app has been closed or the last session terminated.
1134+
Main purpose is to provide a smoother transition when quickly switching between apps.
1135+
</td>
1136+
</tr>
1137+
<tr>
1138+
<td>Default</td>
1139+
<td colspan="2">@code{}3000@endcode</td>
1140+
</tr>
1141+
<tr>
1142+
<td>Example</td>
1143+
<td colspan="2">@code{}
1144+
dd_config_revert_delay = 1500
1145+
@endcode</td>
1146+
</tr>
1147+
</table>
1148+
9451149
### min_fps_factor
9461150

9471151
<table>

src/audio.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,6 @@ namespace audio {
2020
using opus_t = util::safe_ptr<OpusMSEncoder, opus_multistream_encoder_destroy>;
2121
using sample_queue_t = std::shared_ptr<safe::queue_t<std::vector<float>>>;
2222

23-
struct audio_ctx_t {
24-
// We want to change the sink for the first stream only
25-
std::unique_ptr<std::atomic_bool> sink_flag;
26-
27-
std::unique_ptr<platf::audio_control_t> control;
28-
29-
bool restore_sink;
30-
platf::sink_t sink;
31-
};
32-
3323
static int
3424
start_audio_control(audio_ctx_t &ctx);
3525
static void
@@ -95,8 +85,6 @@ namespace audio {
9585
},
9686
};
9787

98-
auto control_shared = safe::make_shared<audio_ctx_t>(start_audio_control, stop_audio_control);
99-
10088
void
10189
encodeThread(sample_queue_t samples, config_t config, void *channel_data) {
10290
auto packets = mail::man->queue<packet_t>(mail::audio_packets);
@@ -149,7 +137,7 @@ namespace audio {
149137
apply_surround_params(stream, config.customStreamParams);
150138
}
151139

152-
auto ref = control_shared.ref();
140+
auto ref = get_audio_ctx_ref();
153141
if (!ref) {
154142
return;
155143
}
@@ -255,6 +243,26 @@ namespace audio {
255243
}
256244
}
257245

246+
audio_ctx_ref_t
247+
get_audio_ctx_ref() {
248+
static auto control_shared { safe::make_shared<audio_ctx_t>(start_audio_control, stop_audio_control) };
249+
return control_shared.ref();
250+
}
251+
252+
bool
253+
is_audio_ctx_sink_available(const audio_ctx_t &ctx) {
254+
if (!ctx.control) {
255+
return false;
256+
}
257+
258+
const std::string &sink = ctx.sink.host.empty() ? config::audio.sink : ctx.sink.host;
259+
if (sink.empty()) {
260+
return false;
261+
}
262+
263+
return ctx.control->is_sink_available(sink);
264+
}
265+
258266
int
259267
map_stream(int channels, bool quality) {
260268
int shift = quality ? 1 : 0;

src/audio.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
#pragma once
66

7+
// local includes
8+
#include "platform/common.h"
79
#include "thread_safe.h"
810
#include "utility.h"
911

@@ -55,8 +57,50 @@ namespace audio {
5557
std::bitset<MAX_FLAGS> flags;
5658
};
5759

60+
struct audio_ctx_t {
61+
// We want to change the sink for the first stream only
62+
std::unique_ptr<std::atomic_bool> sink_flag;
63+
64+
std::unique_ptr<platf::audio_control_t> control;
65+
66+
bool restore_sink;
67+
platf::sink_t sink;
68+
};
69+
5870
using buffer_t = util::buffer_t<std::uint8_t>;
5971
using packet_t = std::pair<void *, buffer_t>;
72+
using audio_ctx_ref_t = safe::shared_t<audio_ctx_t>::ptr_t;
73+
6074
void
6175
capture(safe::mail_t mail, config_t config, void *channel_data);
76+
77+
/**
78+
* @brief Get the reference to the audio context.
79+
* @returns A shared pointer reference to audio context.
80+
* @note Aside from the configuration purposes, it can be used to extend the
81+
* audio sink lifetime to capture sink earlier and restore it later.
82+
*
83+
* @examples
84+
* audio_ctx_ref_t audio = get_audio_ctx_ref()
85+
* @examples_end
86+
*/
87+
audio_ctx_ref_t
88+
get_audio_ctx_ref();
89+
90+
/**
91+
* @brief Check if the audio sink held by audio context is available.
92+
* @returns True if available (and can probably be restored), false otherwise.
93+
* @note Useful for delaying the release of audio context shared pointer (which
94+
* tries to restore original sink).
95+
*
96+
* @examples
97+
* audio_ctx_ref_t audio = get_audio_ctx_ref()
98+
* if (audio.get()) {
99+
* return is_audio_ctx_sink_available(*audio.get());
100+
* }
101+
* return false;
102+
* @examples_end
103+
*/
104+
bool
105+
is_audio_ctx_sink_available(const audio_ctx_t &ctx);
62106
} // namespace audio

0 commit comments

Comments
 (0)