mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Implement audio device control
This commit is contained in:
parent
20de91c75e
commit
8939c81399
@ -665,6 +665,19 @@ handle_save(id_type cmd_id, std::vector<std::wstring_view> &parts) {
|
||||
|
||||
typedef std::function<void(id_type, std::vector<std::wstring_view>, int64_t*)> handler_function;
|
||||
|
||||
static DeviceInformationKind
|
||||
get_device_kind(const std::wstring x) {
|
||||
if (x == L"device") return DeviceInformationKind::Device;
|
||||
if (x == L"association_endpoint") return DeviceInformationKind::AssociationEndpoint;
|
||||
if (x == L"association_endpoint_container") return DeviceInformationKind::AssociationEndpointContainer;
|
||||
if (x == L"association_endpoint_service") return DeviceInformationKind::AssociationEndpointService;
|
||||
if (x == L"device_container") return DeviceInformationKind::DeviceContainer;
|
||||
if (x == L"device_interface") return DeviceInformationKind::DeviceInterface;
|
||||
if (x == L"device_interface_class") return DeviceInformationKind::DeviceInterfaceClass;
|
||||
if (x == L"device_panel") return DeviceInformationKind::DevicePanel;
|
||||
return DeviceInformationKind::Unknown;
|
||||
}
|
||||
|
||||
static const std::unordered_map<std::string, handler_function> handlers = {
|
||||
|
||||
{"exit", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t* exit_code) {
|
||||
@ -689,7 +702,9 @@ static const std::unordered_map<std::string, handler_function> handlers = {
|
||||
}},
|
||||
|
||||
{"state", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
output(cmd_id, "state", {{"playback_state", media_player.PlaybackSession().PlaybackState()}});
|
||||
auto ps = media_player.PlaybackSession();
|
||||
if (ps) output(cmd_id, "state", {{"playback_state", ps.PlaybackState()}});
|
||||
else output(cmd_id, "state", {{"playback_state", ""}});
|
||||
}},
|
||||
|
||||
{"default_voice", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
@ -709,17 +724,26 @@ static const std::unordered_map<std::string, handler_function> handlers = {
|
||||
}},
|
||||
|
||||
{"audio_device", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
bool found = false;
|
||||
if (parts.size()) {
|
||||
auto di = DeviceInformation::CreateFromIdAsync(parts[0]).get();
|
||||
media_player.AudioDevice(di);
|
||||
auto device_kind = std::wstring(parts.at(0));
|
||||
parts.erase(parts.begin(), parts.begin() + 1);
|
||||
auto device_id = join(parts);
|
||||
auto di = DeviceInformation::CreateFromIdAsync(device_id, {}, get_device_kind(device_kind)).get();
|
||||
if (di) {
|
||||
media_player.AudioDevice(di);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
output(cmd_id, "audio_device", {{"value", media_player.AudioDevice()}});
|
||||
auto x = media_player.AudioDevice();
|
||||
if (x) output(cmd_id, "audio_device", {{"value", x}, {"found", found}});
|
||||
else output(cmd_id, "audio_device", {{"value", ""}, {"found", found}});
|
||||
}},
|
||||
|
||||
{"voice", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
bool found = false;
|
||||
if (parts.size()) {
|
||||
auto voice_id = winrt::hstring(parts[0]);
|
||||
auto voice_id = winrt::hstring(parts.at(0));
|
||||
for (auto const &candidate : SpeechSynthesizer::AllVoices()) {
|
||||
if (candidate.Id() == voice_id) {
|
||||
speech_synthesizer.Voice(candidate);
|
||||
@ -728,12 +752,14 @@ static const std::unordered_map<std::string, handler_function> handlers = {
|
||||
}
|
||||
}
|
||||
}
|
||||
output(cmd_id, "voice", {{"value", speech_synthesizer.Voice()}, {"found", found}});
|
||||
auto x = speech_synthesizer.Voice();
|
||||
if (x) output(cmd_id, "voice", {{"value", speech_synthesizer.Voice()}, {"found", found}});
|
||||
else output(cmd_id, "voice", {{"value", ""}, {"found", found}});
|
||||
}},
|
||||
|
||||
{"volume", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
if (parts.size()) {
|
||||
auto vol = parse_double(parts[0].data());
|
||||
auto vol = parse_double(parts.at(0).data());
|
||||
if (vol < 0 || vol > 1) throw std::out_of_range("Invalid volume value must be between 0 and 1");
|
||||
speech_synthesizer.Options().AudioVolume(vol);
|
||||
}
|
||||
@ -742,7 +768,7 @@ static const std::unordered_map<std::string, handler_function> handlers = {
|
||||
|
||||
{"rate", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
if (parts.size()) {
|
||||
auto rate = parse_double(parts[0].data());
|
||||
auto rate = parse_double(parts.at(0).data());
|
||||
if (rate < 0.5 || rate > 6.0) throw std::out_of_range("Invalid rate value must be between 0.5 and 6");
|
||||
speech_synthesizer.Options().SpeakingRate(rate);
|
||||
}
|
||||
@ -751,7 +777,7 @@ static const std::unordered_map<std::string, handler_function> handlers = {
|
||||
|
||||
{"pitch", [](id_type cmd_id, std::vector<std::wstring_view> parts, int64_t*) {
|
||||
if (parts.size()) {
|
||||
auto pitch = parse_double(parts[0].data());
|
||||
auto pitch = parse_double(parts.at(0).data());
|
||||
if (pitch < 0 || pitch > 2) throw std::out_of_range("Invalid pitch value must be between 0 and 2");
|
||||
speech_synthesizer.Options().AudioPitch(pitch);
|
||||
}
|
||||
|
@ -133,3 +133,23 @@ def develop_save(text='Lucca Brazzi sleeps with the fishes.', filename="speech.w
|
||||
with SharedMemory(size=max_buffer_size(text)) as shm:
|
||||
sz = encode_to_file_object(text, shm)
|
||||
develop_loop(f'2 save {st} {sz} {shm.name} {filename}', 2)
|
||||
|
||||
|
||||
def develop_interactive():
|
||||
import subprocess
|
||||
from calibre.debug import run_calibre_debug
|
||||
print('\x1b[32mInteractive winspeech', '\x1b[39m]]'[:-2], flush=True)
|
||||
p = run_calibre_debug('-c', 'from calibre_extensions.winspeech import run_main_loop; raise SystemExit(run_main_loop())',
|
||||
stdin=subprocess.PIPE)
|
||||
try:
|
||||
while True:
|
||||
line = input()
|
||||
if p.poll() is not None:
|
||||
raise SystemExit(p.returncode)
|
||||
p.stdin.write((line + '\n').encode())
|
||||
p.stdin.flush()
|
||||
except KeyboardInterrupt:
|
||||
print('Exiting on interrupt', flush=True)
|
||||
finally:
|
||||
if p.poll() is None:
|
||||
p.kill()
|
||||
|
Loading…
x
Reference in New Issue
Block a user