Command to output all audio devices

This commit is contained in:
Kovid Goyal 2023-01-29 12:05:05 +05:30
parent e006a23b70
commit 5eb1e106a8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -32,6 +32,8 @@
#include <winrt/windows.media.speechsynthesis.h> #include <winrt/windows.media.speechsynthesis.h>
#include <winrt/windows.media.core.h> #include <winrt/windows.media.core.h>
#include <winrt/windows.media.playback.h> #include <winrt/windows.media.playback.h>
#include <winrt/windows.media.devices.h>
#include <winrt/windows.devices.enumeration.h>
#ifdef max #ifdef max
#undef max #undef max
@ -41,6 +43,8 @@ using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Media::SpeechSynthesis; using namespace winrt::Windows::Media::SpeechSynthesis;
using namespace winrt::Windows::Media::Playback; using namespace winrt::Windows::Media::Playback;
using namespace winrt::Windows::Media::Core; using namespace winrt::Windows::Media::Core;
using namespace winrt::Windows::Media::Devices;
using namespace winrt::Windows::Devices::Enumeration;
using namespace winrt::Windows::Storage::Streams; using namespace winrt::Windows::Storage::Streams;
typedef uint64_t id_type; typedef uint64_t id_type;
@ -257,18 +261,58 @@ public:
case VoiceGender::Female: gender = "female"; break; case VoiceGender::Female: gender = "female"; break;
} }
object = { object = {
{"display_name", json_val(voice.DisplayName())}, {"display_name", voice.DisplayName()},
{"description", json_val(voice.Description())}, {"description", voice.Description()},
{"id", json_val(voice.Id())}, {"id", voice.Id()},
{"language", json_val(voice.Language())}, {"language", voice.Language()},
{"gender", json_val(gender)}, {"gender", gender},
}; };
} }
json_val(IVectorView<VoiceInformation> const& voices) : type(DT_LIST) { json_val(IVectorView<VoiceInformation> const& voices) : type(DT_LIST) {
list.reserve(voices.Size()); list.reserve(voices.Size());
for(auto const& voice : voices) { for(auto const& voice : voices) {
list.emplace_back(json_val(voice)); list.emplace_back(voice);
}
}
json_val(DeviceInformationKind const dev) : type(DT_STRING) {
switch(dev) {
case DeviceInformationKind::Unknown:
s = "unknown"; break;
case DeviceInformationKind::AssociationEndpoint:
s = "association_endpoint"; break;
case DeviceInformationKind::AssociationEndpointContainer:
s = "association_endpoint_container"; break;
case DeviceInformationKind::AssociationEndpointService:
s = "association_endpoint_service"; break;
case DeviceInformationKind::Device:
s = "device"; break;
case DeviceInformationKind::DevicePanel:
s = "device_panel"; break;
case DeviceInformationKind::DeviceInterface:
s = "device_interface"; break;
case DeviceInformationKind::DeviceInterfaceClass:
s = "device_interface_class"; break;
case DeviceInformationKind::DeviceContainer:
s = "device_container"; break;
}
}
json_val(DeviceInformation const& dev) : type(DT_OBJECT) {
object = {
{"id", dev.Id()},
{"name", dev.Name()},
{"kind", dev.Kind()},
{"is_default", dev.IsDefault()},
{"is_enabled", dev.IsEnabled()},
};
}
json_val(DeviceInformationCollection const& devices) : type(DT_LIST) {
list.reserve(devices.Size());
for(auto const& dev : devices) {
list.emplace_back(json_val(dev));
} }
} }
@ -309,26 +353,22 @@ public:
}; };
} }
template<typename T> json_val(T x) { template<typename T> json_val(T const x) {
static_assert(sizeof(bool) < sizeof(int16_t), "The bool type on this machine is more than one byte"); if constexpr (std::is_same_v<T, bool>) {
if constexpr (std::is_same_v<T, int64_t> || std::is_same_v<T, int32_t> || std::is_same_v<T, int16_t>) {
type = DT_INT;
i = x;
} else if constexpr (std::is_same_v<T, uint64_t> || std::is_same_v<T, uint32_t> || std::is_same_v<T, uint16_t>) {
type = DT_UINT;
u = x;
} else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>) {
type = DT_FLOAT;
f = x;
} else if constexpr (std::is_same_v<T, bool>) {
type = DT_BOOL; type = DT_BOOL;
b = x; b = x;
} else if constexpr (std::is_unsigned_v<T>) {
type = DT_UINT;
u = x;
} else if constexpr (std::is_integral_v<T>) {
type = DT_INT;
i = x;
} else if constexpr (std::is_floating_point_v<T>) {
type = DT_FLOAT;
f = x;
} else {
static_assert(!sizeof(T), "Unknown type T cannot be converted to JSON");
} }
#ifdef _MSVC
else {
static_assert(false, "Unknown type T cannot be converted to JSON");
}
#endif
} }
friend std::ostream& operator<<(std::ostream &os, const json_val &self) { friend std::ostream& operator<<(std::ostream &os, const json_val &self) {
@ -383,6 +423,7 @@ struct Mark {
uint32_t id, pos_in_text; uint32_t id, pos_in_text;
Mark(uint32_t id, uint32_t pos) : id(id), pos_in_text(pos) {} Mark(uint32_t id, uint32_t pos) : id(id), pos_in_text(pos) {}
}; };
typedef std::vector<Mark> Marks; typedef std::vector<Mark> Marks;
class Synthesizer { class Synthesizer {
@ -490,6 +531,22 @@ class Synthesizer {
return player.PlaybackSession().PlaybackState(); return player.PlaybackSession().PlaybackState();
} }
DeviceInformation audio_device() const {
return player.AudioDevice();
}
void audio_device(DeviceInformation const &di) const {
player.AudioDevice(di);
}
VoiceInformation voice() const {
return synth.Voice();
}
void voice(VoiceInformation const &v) const {
return synth.Voice(v);
}
}; };
static Synthesizer sx; static Synthesizer sx;
@ -835,6 +892,11 @@ handle_stdin_message(winrt::hstring const &&msg) {
else if (command == L"all_voices") { else if (command == L"all_voices") {
output(cmd_id, "all_voices", SpeechSynthesizer::AllVoices()); output(cmd_id, "all_voices", SpeechSynthesizer::AllVoices());
} }
else if (command == L"all_audio_devices") {
try {
output(cmd_id, "all_audio_devices", DeviceInformation::FindAllAsync(MediaDevice::GetAudioRenderSelector()).get());
} CATCH_ALL_EXCEPTIONS("Failed to list audio devices", cmd_id) { }
}
else if (command == L"speak") { else if (command == L"speak") {
handle_speak(cmd_id, parts); handle_speak(cmd_id, parts);
} }