示例#1
0
    def read_text(self, text: str, **config) -> None:
        """Reads out text."""
        text = self.clean_text(text)
        text = TextParser.escape_tags(text)
        split_text = TextParser.split_text(text)

        rate = config.get('rate')
        volume = config.get('volume')
        voice = config.get('voice')
        assert voice, "Voice needs to be provided"  # TODO: Does it?

        ssml = SSML(text, rate=rate, volume=volume)

        if self._cached_ssml == ssml and self._cached_voice == voice:
            self._logger.debug("Playing cached file")
            filepaths = self._cached_filepaths
        else:
            self._logger.debug("Re_cached_textquest from Polly")
            filepaths = []
            # TODO: This should obviously be asynchronous!
            for idx, parted_text in enumerate(split_text):
                parted_ssml = SSML(parted_text, rate=rate, volume=volume)
                response = self.ask_polly(str(parted_ssml), voice)
                filename = create_filename(AbstractSpeaker.TMP_FILEPATH, idx)
                saved_filepath = save_mp3(response["AudioStream"].read(),
                                          filename)
                filepaths.append(saved_filepath)
            self.save_cache(ssml, filepaths, voice)
        self.play_files(filepaths)
        return
示例#2
0
    def test_split_text_above_3000_below_6000(self):
        document = 200 * self.sentece_24chars
        self.assertEqual(len(document), 4800,
                         "Document should have 4800 chars length")

        split_text = list(TextParser.split_text(document))
        self.assertEqual(len(split_text), 2, "Two parts")
示例#3
0
    def test_split_text_below_3000(self):
        document = 10 * self.sentece_24chars
        self.assertEqual(len(document), 240,
                         "Document should have 240 chars lenght")

        split_text = TextParser.split_text(document)
        list_split_text = list(split_text)
        self.assertEqual(len(list_split_text), 1, "Only one part")
        self.assertEqual(list_split_text[0], document,
                         "First part is the document")
示例#4
0
    def test_split_text_above_6000(self):
        document = "no dots in this text " * 300  # 21*300 = 6300
        self.assertEqual(len(document), 6300,
                         "Document should have 6300 chars length")

        split_text = list(TextParser.split_text(document))
        self.assertEqual(len(split_text), 3, "Two parts")
        self.assertEqual(len(split_text[0]), len(split_text[1]),
                         "Both parts should have the same length")
        self.assertEqual(len(split_text[2]), 300,
                         "Simple maths: 6300 - 6000 = 300")
示例#5
0
    def __init__(self, app: QApplication):
        super().__init__()
        self.app = app

        self.config = Configuration()
        _ = self.config.read_config()

        self.player = QMediaPlayer()
        self.speaker: AbstractSpeaker = self.get_speaker(
            self.config.speaker, self.player)
        self.textParser = TextParser(config_path=self.config.parser_config)

        self.gui = MainWindow(self.config, speakers=self.SPEAKER)
        self.gui.speaker = self.speaker
        self.gui.player = self.player

        self.key_manager = KeyBoardManager(self.app)

        # Event on closing GUI application
        self.gui.closeAppEvent.connect(self._close)

        self._last_pid = None
示例#6
0
class Cracker(object):
    """Logic for running the Cracker program"""

    SPEAKER = {Polly.__name__: Polly, Espeak.__name__: Espeak}
    _logger = logging.getLogger(__name__)

    def __init__(self, app: QApplication):
        super().__init__()
        self.app = app

        self.config = Configuration()
        _ = self.config.read_config()

        self.player = QMediaPlayer()
        self.speaker: AbstractSpeaker = self.get_speaker(
            self.config.speaker, self.player)
        self.textParser = TextParser(config_path=self.config.parser_config)

        self.gui = MainWindow(self.config, speakers=self.SPEAKER)
        self.gui.speaker = self.speaker
        self.gui.player = self.player

        self.key_manager = KeyBoardManager(self.app)

        # Event on closing GUI application
        self.gui.closeAppEvent.connect(self._close)

        self._last_pid = None

    def _close(self):
        "Handles closing whole application"
        self.key_manager.stop()

    def get_speaker(self, speaker_name, player) -> AbstractSpeaker:
        if speaker_name == Polly.__name__:
            if "profile_name" in self.config.default_values:
                profile_name = self.config.default_values["profile_name"]
                return Polly(player, profile_name)
            else:
                return Polly(player)
        elif speaker_name == Espeak.__name__:
            return Espeak(player)
        raise ValueError(
            f"No speaker was selected. Provided speaker name '{speaker_name}'")

    def run(self):
        self.gui.init()
        self.set_action()
        self.gui.show()

    def reduce_text(self):
        text = self.gui.textEdit.toPlainText()
        new_text = self.textParser.reduce_text(text)
        self.gui.textEdit.setText(new_text)

    def reduce_cite(self):
        text = self.gui.textEdit.toPlainText()
        new_text = self.textParser.reduce_cite(text)
        self.gui.textEdit.setText(new_text)

    def wiki_text(self):
        """Sets the text box with wikipedia specific cleaned text.
        Example of this is removing `citation needed` and other references.
        """
        text = self.gui.textEdit.toPlainText()
        text = self.textParser.wiki_text(text)
        self.gui.textEdit.setText(text)

    def read_text_area(self):
        """Reads out text in the text_box with selected speaker."""
        self.stop_text()
        text = self.gui.textEdit.toPlainText(
        )  # TODO: toHtml() gives more control

        self.textParser.parser_rules = self.config.regex_config
        text = self.textParser.reduce_text(text)
        self._read(text)

    def toggle_read_text_clipboard(self):
        """Reads out text from the clipboard with selected speaker."""
        if self.player.state() == QMediaPlayer.PlayingState:
            self.stop_text()
            self.player.stop()
        else:
            self.stop_text()
            text = self.app.clipboard().text()

            self.textParser.parser_rules = self.config.regex_config
            text = self.textParser.reduce_text(text)
            self._read(text)

    def _read(self, text):
        speaker_config = self._prepare_config()
        self._last_pid = self.speaker.read_text(text, **speaker_config)

    def toggle_read(self):
        if self.player.state() == QMediaPlayer.PausedState:
            self.player.play()
        else:
            self.player.pause()

    def stop_text(self):
        self.speaker.stop_text()

    def _prepare_config(self):
        config = dict(rate=self.gui.rate,
                      volume=self.gui.volume,
                      voice=self.gui.config.voice)
        return config

    def change_speaker(self, speaker_name):
        """Action on changing speaker.

        Important: Each speaker has its own configuration. These values should be updated on change."""
        self.speaker = self.SPEAKER[speaker_name](self.player)
        self.gui.change_speaker(speaker_name)

    def set_action(self):
        self.gui.stop_action.triggered.connect(self.stop_text)
        self.gui.read_action.triggered.connect(self.read_text_area)
        self.gui.clipboard_read_action.triggered.connect(
            self.toggle_read_text_clipboard)
        self.gui.toggle_action.triggered.connect(self.toggle_read)
        self.gui.reduce_action.triggered.connect(self.reduce_text)
        self.gui.wiki_action.triggered.connect(self.wiki_text)
        self.gui.speakerW.currentTextChanged.connect(self.change_speaker)

        self.key_manager.GlobalReadSignal.connect(
            self.toggle_read_text_clipboard)

        args = (["space", "control", "shift"], )
        p = Thread(target=self.key_manager.run, args=args)
        p.start()
示例#7
0
 def test_escape_tags_xml(self):
     s = '<he><said>She said</said></he>'
     out_s = TextParser.escape_tags(s)
     expected_s = '&lt;he&gt;&lt;said&gt;She said&lt;/said&gt;&lt;/he&gt;'
     self.assertEqual(out_s, expected_s,
                      "Tags should be converted to &...;")
示例#8
0
 def test_escape_char_quote(self):
     s = 'He said "she said"'
     out_s = TextParser.escape_tags(s)
     self.assertEqual(out_s, s, "Quotes shouldn't be changed")
示例#9
0
    def test_split_text_generator_type(self):
        document = self.sentece_24chars

        split_text = TextParser.split_text(document)
        self.assertIsInstance(split_text, types.GeneratorType,
                              "Return generator type")
示例#10
0
 def test_paper_two_square_brackets(self):
     paper_text = "It's hard to argue with this [Smartguy, 1003; Follower, 1004]"
     expected_text = "It's hard to argue with this "
     reduced_text = TextParser.reduce_cite(paper_text)
     self.assertEqual(reduced_text, expected_text)
示例#11
0
 def test_paper_single_square_brackets(self):
     paper_text = "Someone said something [Smartguy, 1002]"
     expected_text = "Someone said something "
     reduced_text = TextParser.reduce_cite(paper_text)
     self.assertEqual(expected_text, reduced_text)
示例#12
0
 def test_paper_single_round_brackets(self):
     paper_text = "Someone said something (Smartguy, 1002)"
     expected_text = "Someone said something "
     reduced_text = TextParser.reduce_cite(paper_text)
     self.assertEqual(reduced_text, expected_text)