From 8abbc265604ff14364b29af850af6e9974a7149a Mon Sep 17 00:00:00 2001 From: 0xMRTT <0xMRTT@proton.me> Date: Sat, 29 Apr 2023 17:29:45 +0200 Subject: [PATCH] main: begin add tts --- src/main.py | 75 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/src/main.py b/src/main.py index a5fe4da..917add3 100644 --- a/src/main.py +++ b/src/main.py @@ -26,15 +26,21 @@ import socket gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") gi.require_version("Gdk", "4.0") +gi.require_version('Gst', '1.0') -from gi.repository import Gtk, Gio, Adw, Gdk, GLib +from gi.repository import Gtk, Gio, Adw, Gdk, GLib, Gst from .window import BavarderWindow from .preferences import Preferences from .constants import app_id, version -from baichat_py import BAIChat +from hgchat import HGChat +from gtts import gTTS +from tempfile import NamedTemporaryFile +from baichat_py import BaiChat + +BACKEND = "hgchat" # "hgchat" or "bai" class BavarderApplication(Adw.Application): """The main application singleton class.""" @@ -50,11 +56,30 @@ class BavarderApplication(Adw.Application): self.create_action("copy_prompt", self.on_copy_prompt_action) self.create_action("copy_bot", self.on_copy_bot_action) self.create_action("ask", self.on_ask_action, ["Return"]) + self.create_action("speak", self.on_speak_action, ["S"]) + self.create_action("listen", self.on_listen_action, ["L"]) self.settings = Gio.Settings(schema_id="io.github.Bavarder.Bavarder") self.clear_after_send = self.settings.get_boolean("clear-after-send") + if BACKEND == "hgchat": + self.chat = HGChat() + elif BACKEND == "bai": + self.chat = BAIChat() + else: + raise ValueError("Invalid backend") + + # GStreamer playbin object and related setup + Gst.init(None) + self.player = Gst.ElementFactory.make('playbin', 'player') + self.pipeline = Gst.Pipeline() + # bus = self.player.get_bus() + # bus.add_signal_watch() + # bus.connect('message', self.on_gst_message) + self.player_event = threading.Event() # An event for letting us know when Gst is done playing + + def do_activate(self): """Called when the application is activated. @@ -138,9 +163,11 @@ class BavarderApplication(Adw.Application): self.win.toast_overlay.add_toast(toast) def ask(self, prompt): - chat = BAIChat(sync=True) try: - response = chat.sync_ask(self.prompt) + if BACKEND == "hgchat": + response = self.chat.ask(self.prompt) + elif BACKEND == "bai": + response = self.chat.sync_ask(self.prompt) except KeyError: self.win.banner.set_revealed(False) return "" @@ -150,7 +177,15 @@ class BavarderApplication(Adw.Application): return "" else: self.win.banner.set_revealed(False) - return response.text + r = "" + for i in response: + char = i["token"]["text"] + if char == "": + r += "\n" + else: + r += char + self.win.bot_text_view.get_buffer().set_text(r) + return r def on_ask_action(self, widget, _): """Callback for the app.ask action.""" @@ -161,7 +196,6 @@ class BavarderApplication(Adw.Application): self.prompt = self.win.prompt_text_view.get_buffer().props.text def thread_run(): - # call heavy here response = self.ask(self.prompt) GLib.idle_add(cleanup, response) @@ -171,13 +205,40 @@ class BavarderApplication(Adw.Application): self.win.wait_button.set_visible(False) t.join() self.win.bot_text_view.get_buffer().set_text(response) - if self.clear_after_send: self.win.prompt_text_view.get_buffer().set_text("") t = threading.Thread(target=thread_run) t.start() + def on_speak_action(self, widget, _): + """Callback for the app.speak action.""" + print("app.speak action activated") + + try: + + with NamedTemporaryFile() as file_to_play: + + tts = gTTS(self.win.bot_text_view.get_buffer().props.text) + tts.write_to_fp(file_to_play) + file_to_play.seek(0) + self._play_audio(file_to_play.name) + except Exception as exc: + print(exc) + + def _play_audio(self, path): + uri = 'file://' + path + self.player.set_property('uri', uri) + self.pipeline.add(self.player) + self.pipeline.set_state(Gst.State.PLAYING) + self.player.set_state(Gst.State.PLAYING) + + + + def on_listen_action(self, widget, _): + """Callback for the app.listen action.""" + print("app.listen action activated") + def create_action(self, name, callback, shortcuts=None): """Add an application action.