diff libervia/cli/cmd_call.py @ 4206:0f8ea0768a3b

cli (call): implement GUI output: ``call`` commands now handle various output. Beside the original one (now named ``simple``), a new ``gui`` one display a full featured GUI (make with Qt). PyQt 6 or more needs to be installed. rel 427
author Goffi <goffi@goffi.org>
date Sun, 11 Feb 2024 23:20:24 +0100
parents 849721e1563b
children 9218d4331bb2
line wrap: on
line diff
--- a/libervia/cli/cmd_call.py	Thu Jan 18 23:29:25 2024 +0100
+++ b/libervia/cli/cmd_call.py	Sun Feb 11 23:20:24 2024 +0100
@@ -20,9 +20,12 @@
 
 from argparse import ArgumentParser
 import asyncio
+from dataclasses import dataclass
 from functools import partial
 import logging
 import os
+from pathlib import Path
+from typing import Callable
 
 from prompt_toolkit.input import create_input
 from prompt_toolkit.keys import Keys
@@ -42,14 +45,27 @@
 __commands__ = ["Call"]
 
 
+@dataclass
+class CallData:
+    callee: jid.JID
+    sid: str|None = None
+    action_id: str|None = None
+
+
 class WebRTCCall:
-    def __init__(self, host, profile: str, callee: jid.JID):
+    def __init__(self, host, profile: str, callee: jid.JID, **kwargs):
+        """Create and setup a webRTC instance
+
+        @param profile: profile making or receiving the call
+        @param callee: peer jid
+        @param kwargs: extra kw args to use when instantiating WebRTC
+        """
         from libervia.frontends.tools import webrtc
 
         aio.install_glib_asyncio_iteration()
         self.host = host
         self.profile = profile
-        self.webrtc = webrtc.WebRTC(host.bridge, profile)
+        self.webrtc = webrtc.WebRTC(host.bridge, profile, **kwargs)
         self.webrtc.callee = callee
         host.bridge.register_signal(
             "ice_candidates_new", self.on_ice_candidates_new, "plugin"
@@ -197,6 +213,19 @@
 
 class Common(base.CommandBase):
 
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(
+            *args,
+            use_output=C.OUTPUT_CUSTOM,
+            extra_outputs={
+                "default": self.auto_output,
+                "simple": self.simple_output,
+                "gui": self.gui_output,
+            },
+            **kwargs
+        )
+
     def add_parser_options(self):
         self.parser.add_argument(
             "--no-ui", action="store_true", help=_("disable user interface")
@@ -214,11 +243,51 @@
         if self.verbosity >= 2:
             root_logger.setLevel(logging.DEBUG)
 
-    async def start_ui(self, webrtc_call):
+    async def make_webrtc_call(self, call_data: CallData, **kwargs) -> WebRTCCall:
+        """Create the webrtc_call instance
+
+        @param call_data: Call data of the command
+        @param kwargs: extra args used to instanciate WebRTCCall
+
+        """
+        webrtc_call = WebRTCCall(self.host, self.profile, call_data.callee, **kwargs)
+        if call_data.sid is None:
+            # we are making the call
+            await webrtc_call.start()
+        else:
+            # we are receiving the call
+            webrtc_call.sid = call_data.sid
+            if call_data.action_id is not None:
+                await self.host.bridge.action_launch(
+                    call_data.action_id,
+                    data_format.serialise({"cancelled": False}),
+                    self.profile
+                )
+        return webrtc_call
+
+    async def auto_output(self, call_data: CallData):
+        """Make a guess on the best output to use on current platform"""
+        # For now we just use simple output
+        await self.simple_output(call_data)
+
+    async def simple_output(self, call_data: CallData):
+        """Run simple output, with GStreamer ``autovideosink``"""
+        webrtc_call = await self.make_webrtc_call(call_data)
         if not self.args.no_ui:
             ui = UI(self.host, webrtc_call.webrtc)
             await ui.start()
 
+    async def gui_output(self, call_data: CallData):
+        """Run GUI output"""
+        media_dir = Path(await self.host.bridge.config_get("", "media_dir"))
+        icons_path = media_dir / "fonts/fontello/svg"
+        try:
+            from .call_gui import AVCallGUI
+            await AVCallGUI.run(self, call_data, icons_path)
+        except Exception as e:
+            self.disp(f"Error starting GUI: {e}", error=True)
+            self.host.quit(C.EXIT_ERROR)
+
 
 class Make(Common):
     def __init__(self, host):
@@ -239,10 +308,9 @@
 
     async def start(self):
         await super().start()
-        callee = jid.JID(self.args.entity)
-        webrtc_call = WebRTCCall(self.host, self.profile, callee)
-        await webrtc_call.start()
-        await super().start_ui(webrtc_call)
+        await super().output(CallData(
+            callee=jid.JID(self.args.entity),
+        ))
 
 
 class Receive(Common):
@@ -297,12 +365,11 @@
 
         self.disp(_("✅ Incoming call from {caller} accepted.").format(caller=caller))
 
-        webrtc_call = WebRTCCall(self.host, self.profile, peer_jid)
-        webrtc_call.sid = action_data["session_id"]
-        await self.host.bridge.action_launch(
-            action_id, data_format.serialise({"cancelled": False}), profile
-        )
-        await super().start_ui(webrtc_call)
+        await super().output(CallData(
+            callee=peer_jid,
+            sid=action_data["session_id"],
+            action_id=action_id
+        ))
 
     async def start(self):
         await super().start()