diff --git a/src/calibre/utils/windows/winspeech.cpp b/src/calibre/utils/windows/winspeech.cpp index 365ab38bd0..fca6815e6e 100644 --- a/src/calibre/utils/windows/winspeech.cpp +++ b/src/calibre/utils/windows/winspeech.cpp @@ -32,6 +32,8 @@ #include #include #include +#include +#include #ifdef max #undef max @@ -41,6 +43,8 @@ using namespace winrt::Windows::Foundation::Collections; using namespace winrt::Windows::Media::SpeechSynthesis; using namespace winrt::Windows::Media::Playback; using namespace winrt::Windows::Media::Core; +using namespace winrt::Windows::Media::Devices; +using namespace winrt::Windows::Devices::Enumeration; using namespace winrt::Windows::Storage::Streams; typedef uint64_t id_type; @@ -257,18 +261,58 @@ public: case VoiceGender::Female: gender = "female"; break; } object = { - {"display_name", json_val(voice.DisplayName())}, - {"description", json_val(voice.Description())}, - {"id", json_val(voice.Id())}, - {"language", json_val(voice.Language())}, - {"gender", json_val(gender)}, + {"display_name", voice.DisplayName()}, + {"description", voice.Description()}, + {"id", voice.Id()}, + {"language", voice.Language()}, + {"gender", gender}, }; } json_val(IVectorView const& voices) : type(DT_LIST) { list.reserve(voices.Size()); 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 json_val(T 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 || std::is_same_v || std::is_same_v) { - type = DT_INT; - i = x; - } else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v) { - type = DT_UINT; - u = x; - } else if constexpr (std::is_same_v || std::is_same_v) { - type = DT_FLOAT; - f = x; - } else if constexpr (std::is_same_v) { + template json_val(T const x) { + if constexpr (std::is_same_v) { type = DT_BOOL; b = x; + } else if constexpr (std::is_unsigned_v) { + type = DT_UINT; + u = x; + } else if constexpr (std::is_integral_v) { + type = DT_INT; + i = x; + } else if constexpr (std::is_floating_point_v) { + 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) { @@ -383,6 +423,7 @@ struct Mark { uint32_t id, pos_in_text; Mark(uint32_t id, uint32_t pos) : id(id), pos_in_text(pos) {} }; + typedef std::vector Marks; class Synthesizer { @@ -490,6 +531,22 @@ class Synthesizer { 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; @@ -835,6 +892,11 @@ handle_stdin_message(winrt::hstring const &&msg) { else if (command == L"all_voices") { 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") { handle_speak(cmd_id, parts); }