diff --git a/src/calibre/utils/windows/winspeech.cpp b/src/calibre/utils/windows/winspeech.cpp index b86020eb34..b12cc1bd67 100644 --- a/src/calibre/utils/windows/winspeech.cpp +++ b/src/calibre/utils/windows/winspeech.cpp @@ -838,6 +838,8 @@ handle_stdin_message(winrt::hstring const &&msg) { return exit_code; } +#define INITIALIZE_FAILURE_MESSAGE "Failed to initialize SpeechSynthesizer and MediaPlayer" + static PyObject* run_main_loop(PyObject*, PyObject*) { if (!run_catching_exceptions([]() { @@ -864,7 +866,7 @@ run_main_loop(PyObject*, PyObject*) { media_player = MediaPlayer(); media_player.AudioCategory(MediaPlayerAudioCategory::Speech); media_player.AutoPlay(true); - }, "Failed to initialize SpeechSynthesizer and MediaPlayer", __LINE__)) { + }, INITIALIZE_FAILURE_MESSAGE, __LINE__)) { return PyLong_FromLongLong(1); } @@ -916,6 +918,7 @@ static PyMethodDef methods[] = { static int exec_module(PyObject *m) { + PyModule_AddStringMacro(m, INITIALIZE_FAILURE_MESSAGE); return 0; } diff --git a/src/calibre/utils/windows/winspeech.py b/src/calibre/utils/windows/winspeech.py index 476f56a070..8c91716d28 100644 --- a/src/calibre/utils/windows/winspeech.py +++ b/src/calibre/utils/windows/winspeech.py @@ -107,11 +107,22 @@ class SpeechError(OSError): class NoAudioDevices(OSError): + display_to_user = True def __init__(self): super().__init__(_('No active audio output devices found.' ' Connect headphones or speakers. If you are using Remote Desktop then enable Remote Audio for it.')) +class NoMediaPack(OSError): + display_to_user = True + + def __init__(self): + super().__init__(_('This computer is missing the Windows MediaPack, which is needed for Read aloud. Instructions' + ' for installing it are available at {}').format( + + 'https://support.medal.tv/support/solutions/articles/48001157311-windows-is-missing-media-pack')) + + class Error(NamedTuple): msg: str error: str = '' @@ -121,8 +132,11 @@ class Error(NamedTuple): related_to: int = 0 def as_exception(self, msg='', check_for_no_audio_devices=False): + from calibre_extensions.winspeech import INITIALIZE_FAILURE_MESSAGE if check_for_no_audio_devices and self.hr == 0xc00d36fa: return NoAudioDevices() + if check_for_no_audio_devices and self.hr == 0x80070002 and self.msg == INITIALIZE_FAILURE_MESSAGE: + return NoMediaPack() return SpeechError(self, msg)