Package: release.debian.org Severity: normal User: release.debian....@packages.debian.org Usertags: unblock X-Debbugs-Cc: l...@packages.debian.org Control: affects -1 + src:lios
Hello, I have uploaded lios/2.7.2-5 to unstable, to hopefully make it to bookworm. [ Reason ] As reported on #990805 and #1033024, in the current version of lios when opening the general preferences dialog box, lios stays stuck for a couple minutes. This happens only when the espeak-ng package is installed, in which case there are thousands of voices available for the speech configuration part of this dialog box, thus making it very long to load. Upstream fixed the issue without telling me, we eventually found it was fixed in a more recent upstream snapshot, and I picked up the upstream commit for this, included in lios/2.7.2-5. The idea of the fix is to separate the voices by language, so that the user first chooses among a few hundred languages, and then chooses a voice person. This is enough to make the dialog box load in a snap. [ Impact ] Without this new version, users will have to either remove the espeak-ng package (but lios users are most often blind users so they do need it), or they have to wait for several minutes when they want to change some general preference. [ Tests ] This was tested manually as fixing the issue. [ Risks ] The code is relatively simple: in lios/speech.py, instead of having list_voices return a plain list, it creates a dictionary sorted by language. lios/preferences.py then contains an additional combobox, and the logic is reworked around these to implement the two-step selection. The upstream commit also includes selecting a default voice according to the current locale. I prefered to avoid splitting it from the upstream commit since the two parts seem related. [ Checklist ] [X] all changes are documented in the d/changelog [X] I reviewed all changes and I approve them [X] attach debdiff against the package in testing unblock lios/2.7.2-5
diff -Nru lios-2.7.2/debian/changelog lios-2.7.2/debian/changelog --- lios-2.7.2/debian/changelog 2023-03-13 20:00:26.000000000 +0100 +++ lios-2.7.2/debian/changelog 2023-04-03 23:22:12.000000000 +0200 @@ -1,3 +1,10 @@ +lios (2.7.2-5) unstable; urgency=medium + + * patches/preference-voice-list: Fix general preferences loading delay. + (Closes: #990805, #1033024). + + -- Samuel Thibault <sthiba...@debian.org> Mon, 03 Apr 2023 23:22:12 +0200 + lios (2.7.2-4) unstable; urgency=medium * Upload fix to unstable, thanks Gunnar! diff -Nru lios-2.7.2/debian/patches/preference-voice-list lios-2.7.2/debian/patches/preference-voice-list --- lios-2.7.2/debian/patches/preference-voice-list 1970-01-01 01:00:00.000000000 +0100 +++ lios-2.7.2/debian/patches/preference-voice-list 2023-04-03 23:21:39.000000000 +0200 @@ -0,0 +1,232 @@ +commit 565afb783dc50d4ec7c9d1d6caf486c26f47d1fe +Author: nalin.x.linux <nalin.x.li...@gmail.com> +Date: Sun Aug 28 15:27:27 2022 +0530 + + Preferences dialog startup fixed, speech person selection enabled, set default speech module and language using user's language + +--- + lios/main.py | 10 ++++- + lios/preferences.py | 104 +++++++++++++++++++++++++++++++++++++++++++++++----- + lios/speech.py | 13 +++++- + 3 files changed, 112 insertions(+), 15 deletions(-) + +--- a/lios/main.py ++++ b/lios/main.py +@@ -181,6 +181,7 @@ class linux_intelligent_ocr_solution(): + #Load Preferences + self.preferences = preferences.lios_preferences() + self.preferences.set_from_file(macros.preferences_file_path) ++ self.preferences.set_default_speech_module_and_language() + self.preferences.set_avalable_scanner_drivers([ item.name for item in self.available_scanner_driver_list]) + self.preferences.set_avalable_ocr_engines([ (item.name,item.get_available_languages()) + for item in self.available_ocr_engine_list ]) +@@ -1379,6 +1380,7 @@ pacman -S aspell-fr""")) + + def restore_preferences(self,*data): + self.preferences.__init__() ++ self.preferences.set_default_speech_module_and_language() + self.make_preferences_effective() + self.notify_information(_("Preferences Restored"),0) + +@@ -1441,8 +1443,12 @@ pacman -S aspell-fr""")) + self.is_reading = True + speaker = speech.Speech() + speaker.set_output_module(speaker.list_output_modules()[self.preferences.speech_module]) +- if(self.preferences.speech_module != -1 and len(speaker.list_voices()) > 1): +- speaker.set_synthesis_voice(speaker.list_voices()[self.preferences.speech_language]) ++ language_person_dict = speaker.get_language_person_dict() ++ ++ if(self.preferences.speech_module != -1 and len(language_person_dict.keys()) > 1): ++ voice = language_person_dict[list(language_person_dict)[self.preferences.speech_language]][self.preferences.speech_person] ++ speaker.set_synthesis_voice(voice) ++ + speaker.set_volume(self.preferences.speech_volume) + speaker.set_pitch(self.preferences.speech_pitch) + while(not self.textview.is_cursor_at_end()): +--- a/lios/preferences.py ++++ b/lios/preferences.py +@@ -39,7 +39,7 @@ class lios_preferences: + self.background_color="#000";self.font_color="#fff"; + self.highlight_color="#1572ffff0000"; + self.background_highlight_color="#00000bacffff"; +- self.speech_module=0;self.speech_language=10; ++ self.speech_module=-1;self.speech_language=-1;self.speech_person=-1; + self.speech_rate=0;self.speech_pitch=0;self.speech_volume=100; + self.time_between_repeated_scanning=0;self.scan_resolution=300; + self.scan_driver=1;self.scanner_cache_calibration=0; +@@ -72,6 +72,7 @@ class lios_preferences: + self.language=int(config.get('cfg',"language")) + self.speech_module=int(config.get('cfg',"speech_module")) + self.speech_language=int(config.get('cfg',"speech_language")) ++ self.speech_person=int(config.get('cfg',"speech_person")) + self.speech_rate=int(config.get('cfg',"speech_rate")) + self.speech_volume=int(config.get('cfg',"speech_volume")) + self.speech_pitch=int(config.get('cfg',"speech_pitch")) +@@ -96,6 +97,34 @@ class lios_preferences: + else: + self.__init__() + ++ # Set speech module, language and person if speech_module is not set ++ def set_default_speech_module_and_language(self): ++ if(self.speech_module == -1): ++ test = speech.Speech() ++ output_modules_list = test.list_output_modules() ++ if("espeak-ng" in output_modules_list): ++ self.speech_module = output_modules_list.index('espeak-ng') ++ test.set_output_module('espeak-ng') ++ elif("espeak" in output_modules_list): ++ self.speech_module = output_modules_list.index('espeak') ++ test.set_output_module('espeak') ++ ++ # if espeak or espeak-ng set language ++ if(self.speech_module != -1): ++ import locale ++ language_code, encoding = locale.getdefaultlocale() ++ localeValues = language_code.split('_') ++ language = localeValues[0] ++ language_person_dict = test.get_language_person_dict() ++ if(language in language_person_dict.keys()): ++ self.speech_language = list(language_person_dict.keys()).index(language) ++ self.speech_person=0; ++ else: ++ self.speech_module=0;self.speech_language=0;self.speech_person=0; ++ ++ #Closing ++ test.close() ++ + def save_to_file(self,filename): + #Removing old configuration file + try: +@@ -114,6 +143,7 @@ class lios_preferences: + config.set('cfg',"language",str(self.language)) + config.set('cfg',"speech_module",str(self.speech_module)) + config.set('cfg',"speech_language",str(self.speech_language)) ++ config.set('cfg',"speech_person",str(self.speech_person)) + config.set('cfg',"speech_pitch",str(self.speech_pitch)) + config.set('cfg',"speech_volume",str(self.speech_volume)) + config.set('cfg',"speech_rate",str(self.speech_rate)) +@@ -161,14 +191,62 @@ class lios_preferences: + combobox_language.set_active(self.language) + + def change_speech_module(*data): +- index_engine = combobox_speech_module.get_active() +- combobox_speech_language.clear() ++ module_index = combobox_speech_module.get_active() ++ + test = speech.Speech() +- list = test.list_output_modules() +- test.set_output_module(list[index_engine]) +- for item in test.list_voices(): +- combobox_speech_language.add_item(item) +- combobox_speech_language.set_active(self.speech_language) ++ output_modules_list = test.list_output_modules() ++ test.set_output_module(output_modules_list[module_index]) ++ ++ self.speech_language_person_dict = test.get_language_person_dict() ++ test.close() ++ ++ # Disconnecting for preventng function calls while clearing ++ # combobox_speech_language or adding each language to the same ++ try: ++ combobox_speech_language.disconnect_by_func(change_speech_language) ++ except(TypeError): ++ pass ++ ++ combobox_speech_language.clear() ++ ++ if(len(self.speech_language_person_dict.keys()) == 0): ++ combobox_speech_language.add_item(_("Default")) ++ self.speech_language = 0 ++ else: ++ for item in self.speech_language_person_dict.keys(): ++ combobox_speech_language.add_item(item) ++ ++ combobox_speech_language.connect_change_callback_function(change_speech_language) ++ ++ ++ if(self.speech_language < len(self.speech_language_person_dict.keys())): ++ combobox_speech_language.set_active(self.speech_language) ++ else: ++ combobox_speech_language.set_active(0) ++ self.speech_language = 0 ++ ++ def change_speech_language(*data): ++ combobox_speech_person.clear() ++ ++ # For users having preferences from old version ++ if(self.speech_person == -1): ++ self.speech_person = 0 ++ ++ if(len(list(self.speech_language_person_dict.keys())) == 0): ++ combobox_speech_person.add_item(_("Default")) ++ combobox_speech_person.set_active(0) ++ self.speech_person = 0 ++ return ++ ++ index_language = combobox_speech_language.get_active() ++ language = list(self.speech_language_person_dict.keys())[index_language] ++ ++ for item in self.speech_language_person_dict[language]: ++ combobox_speech_person.add_item(item) ++ ++ if(self.speech_person >= len(self.speech_language_person_dict[language])): ++ self.speech_person = 0 ++ combobox_speech_person.set_active(self.speech_person) + + def change_mode_of_rotation(*data): + if(combobox_mode_of_rotation.get_active() == 2): +@@ -227,10 +305,14 @@ class lios_preferences: + + label_speech_language = widget.Label(_("Speech-Language")) + combobox_speech_language = widget.ComboBox() +- combobox_speech_module.set_active(self.speech_module) +- combobox_speech_language.set_active(self.speech_language) + label_speech_language.set_mnemonic_widget(combobox_speech_language) + ++ label_speech_person = widget.Label(_("Speech Person")) ++ combobox_speech_person = widget.ComboBox() ++ label_speech_person.set_mnemonic_widget(combobox_speech_person) ++ ++ combobox_speech_module.set_active(self.speech_module) ++ + label_speech_rate = widget.Label(_("Speech-Rate")) + spin_speech_rate = widget.SpinButton(self.speech_rate,-100,100,1,10,0) + label_speech_rate.set_mnemonic_widget(spin_speech_rate) +@@ -252,6 +334,7 @@ class lios_preferences: + (label_highlight_background,1,1),(colorbutton_highlight_background,1,1),containers.Grid.NEW_ROW, + (label_speech_module,1,1),(combobox_speech_module,1,1),containers.Grid.NEW_ROW, + (label_speech_language,1,1),(combobox_speech_language,1,1),containers.Grid.NEW_ROW, ++ (label_speech_person,1,1),(combobox_speech_person,1,1),containers.Grid.NEW_ROW, + (label_speech_rate,1,1),(spin_speech_rate,1,1),containers.Grid.NEW_ROW, + (label_speech_pitch,1,1),(spin_speech_pitch,1,1),containers.Grid.NEW_ROW, + (label_speech_volume,1,1),(spin_speech_volume,1,1)]) +@@ -436,6 +519,7 @@ class lios_preferences: + self.language=combobox_language.get_active() + self.speech_module=combobox_speech_module.get_active() + self.speech_language=combobox_speech_language.get_active() ++ self.speech_person=combobox_speech_person.get_active() + self.speech_rate=spin_speech_rate.get_value() + self.speech_pitch=spin_speech_pitch.get_value() + self.speech_volume=spin_speech_volume.get_value() +--- a/lios/speech.py ++++ b/lios/speech.py +@@ -23,9 +23,16 @@ class Speech(speechd.SSIPClient): + def __init__(self,client_name="lios"): + super(Speech,self).__init__(client_name) + self.status = False +- +- def list_voices(self): +- return [ x[0] for x in self.list_synthesis_voices()] ++ ++ def get_language_person_dict(self): ++ dictionary = {} ++ voices = self.list_synthesis_voices() ++ for item in voices: ++ if(item[1] not in dictionary): ++ dictionary[item[1]] = [item[0]] ++ else: ++ dictionary[item[1]].append(item[0]) ++ return dictionary + + def say(self,text): + self.status = True diff -Nru lios-2.7.2/debian/patches/series lios-2.7.2/debian/patches/series --- lios-2.7.2/debian/patches/series 2023-03-13 19:57:48.000000000 +0100 +++ lios-2.7.2/debian/patches/series 2023-04-03 23:19:48.000000000 +0200 @@ -1,3 +1,4 @@ tesseract_langpath typo Use-exact-versions-when-importing-Gtk-and-friends.patch +preference-voice-list