annotate libervia/cli/call_tui.py @ 4240:79c8a70e1813

backend, frontend: prepare remote control: This is a series of changes necessary to prepare the implementation of remote control feature: - XEP-0166: add a `priority` attribute to `ApplicationData`: this is needed when several applications are working in a same session, to know which one must be handled first. Will be used to make Remote Control have precedence over Call content. - XEP-0166: `_call_plugins` is now async and is not used with `DeferredList` anymore: the benefit to have methods called in parallels is very low, and it cause a lot of trouble as we can't predict order. Methods are now called sequentially so workflow can be predicted. - XEP-0167: fix `senders` XMPP attribute <=> SDP mapping - XEP-0234: preflight acceptance key is now `pre-accepted` instead of `file-accepted`, so the same key can be used with other jingle applications. - XEP-0167, XEP-0343: move some method to XEP-0167 - XEP-0353: use new `priority` feature to call preflight methods of applications according to it. - frontend (webrtc): refactor the sources/sink handling with a more flexible mechanism based on Pydantic models. It is now possible to have has many Data Channel as necessary, to have them in addition to A/V streams, to specify manually GStreamer sources and sinks, etc. - frontend (webrtc): rework of the pipeline to reduce latency. - frontend: new `portal_desktop` method. Screenshare portal handling has been moved there, and RemoteDesktop portal has been added. - frontend (webrtc): fix `extract_ufrag_pwd` method. rel 436
author Goffi <goffi@goffi.org>
date Sat, 11 May 2024 13:52:41 +0200
parents d01b8d002619
children 0d7bb4df2343
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4210
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # Libervia CLI
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 # Copyright (C) 2009-2024 Jérôme Poisson (goffi@goffi.org)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
18
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
19
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 import asyncio
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from functools import partial
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 import sys
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
23
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 from PIL import Image
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 import gi
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from rich.padding import Padding
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from term_image import image as t_image
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
28
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from libervia.cli.constants import Const as C
4233
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
30 from libervia.frontends.tools import aio, webrtc
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
31 from libervia.frontends.tools.webrtc import CallData, WebRTCCall
4210
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
32
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from .call_simple import BaseAVTUI
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
34
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 gi.require_versions({"Gst": "1.0", "GstWebRTC": "1.0"})
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
36
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 from gi.repository import Gst
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
38
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
39
4233
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
40 aio.install_glib_asyncio_iteration()
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
41
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
42
4210
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 class AVCallUI(BaseAVTUI):
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 def __init__(self, parent):
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 super().__init__(parent.host, align="center")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 self.parent = parent
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 self.image_rows = 0
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 self.buffer = None
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 self._processing = False
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 self.render_class: t_image.ImageMeta | None = None
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 self.target_size
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 self.fps = 25
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
53 for oo in parent.args.output_opts:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 if oo.startswith("renderer="):
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
55 renderer = oo[9:].lower().strip()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
56 match renderer:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 case "auto":
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 # we let None as it will auto-detect best option later
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 pass
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 case "block":
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 self.render_class = t_image.BlockImage
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 case "iterm2":
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 self.render_class = t_image.ITerm2Image
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 case "kitty":
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 self.render_class = t_image.KittyImage
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 case _:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 parent.parser.error(f"Invalid renderer: {renderer!r}")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 elif oo.startswith("fps="):
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 try:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 self.fps = int(oo[4:])
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
71 except ValueError:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 parent.parser.error(f"Invalid FPS: {oo[4:]!r}")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
73
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
74 async def init_call(self, call_data):
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 kwargs = self.parse_output_opts(self.parent)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 if "target_size" not in kwargs:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 # we use low res by default for performance reason
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
78 kwargs["target_size"] = (640, 380)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 webrtc_call = await WebRTCCall.make_webrtc_call(
4233
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
80 self.parent.host.bridge,
4210
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 self.parent.profile,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 call_data,
4240
79c8a70e1813 backend, frontend: prepare remote control:
Goffi <goffi@goffi.org>
parents: 4233
diff changeset
83 sinks_data=webrtc.SinksApp(
4210
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 local_video_cb=partial(self.on_new_sample, video_stream="local"),
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 remote_video_cb=None,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 ),
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 merge_pip=True,
4233
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
88 # we want to be sure that call is ended if user presses `Ctrl + c` or anything
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
89 # else stops the session.
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
90 on_call_setup_cb=lambda sid, profile: self.parent.host.add_on_quit_callback(
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
91 self.parent.host.bridge.call_end, sid, "", profile
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
92 ),
d01b8d002619 cli (call, file), frontends: implement webRTC data channel transfer:
Goffi <goffi@goffi.org>
parents: 4210
diff changeset
93 on_call_ended_cb=lambda sid, profile: self.parent.host.a_quit(),
4210
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 **kwargs,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 )
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 self.webrtc = webrtc_call.webrtc
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
97
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 async def start(self, call_data):
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 term_rows = self.host.console.size.height
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 if term_rows < 20:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 self.host.disp(
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 "Your terminal must have a height of a least 20 rows.", error=True
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 )
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 self.host.a_quit(C.EXIT_ERROR)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 self.image_rows = term_rows - 6
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 self.image_cols = self.host.console.size.width
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 await self.init_call(call_data)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 assert self.webrtc is not None
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
109
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 idx = 0
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 self.buffer = ""
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
112
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 # we detect render
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 if self.render_class is None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 self.render_class = t_image.auto_image_class()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
116
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 loop_sleep = 1/self.fps
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
118
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 with self.input.raw_mode():
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 # for whatever reason, using self.input.attach is breaking KittyImage and uses
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 # a BlockImage style rendering instead. So we don't use it and we call
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 # ``self.keys_ready()`` ourself in the loop, below.
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
123 # cursor is not restored despite the ``screen`` context if peer is hanging up,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
124 # so we reactivate cursor here
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 self.host.add_on_quit_callback(self.host.console.show_cursor, True)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
126 with self.host.console.screen():
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 while True:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 idx += 1
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 if self.buffer is not None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 sys.stdout.write(self.buffer)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 sys.stdout.write("\n")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 self.parent.console.print(
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 # the padding avoid artifact when toggling buttons
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
134 Padding(self.generate_control_bar(), (0, 2, 0, 0))
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 )
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 sys.stdout.flush()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
137 rendered = True
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 else:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 rendered = False
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
140 await asyncio.sleep(loop_sleep)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 self.keys_ready()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 if self.done.is_set():
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 break
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 if rendered:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 # we put cursor back at the top of image to print the next frame
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 # FIXME: we use +4 for the controls because we know the height of the
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 # renderable, but it would be better to measure it dynamically.
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 sys.stdout.write(f"\033[{self.image_rows+4}A")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
149
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 await self.webrtc.end_call()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 await self.host.a_quit()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
152
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 @classmethod
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 async def run(cls, parent, call_data: CallData) -> None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 ui = cls(parent)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 await ui.start(call_data)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
157
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 def on_new_sample(self, video_sink, video_stream: str) -> bool:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 if self._processing:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 # image encoding for terminal is slow, if one is already processing, we don't
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 # bother going further
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 return False
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 sample = video_sink.emit("pull-sample")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 if sample is None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 return False
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
166
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
167 video_pad = video_sink.get_static_pad("sink")
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 assert video_pad is not None
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 s = video_pad.get_current_caps().get_structure(0)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 stream_size = (s.get_value("width"), s.get_value("height"))
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 buf = sample.get_buffer()
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
172 result, mapinfo = buf.map(Gst.MapFlags.READ)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 if result and self.render_class is not None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 self._processing = True
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 image_data = mapinfo.data
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 image = Image.frombuffer("RGB", stream_size, image_data, "raw", "RGB", 0, 1)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 img_renderer = self.render_class(image, height=self.image_rows)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 img_fmt = f"<{self.image_cols}.^1"
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 if self.render_class == t_image.KittyImage:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 # we don't do compression to speed up things
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 img_fmt += "+Wc0"
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 self.host.loop.loop.call_soon_threadsafe(
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 self.update_sample,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 sample,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 stream_size,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 video_stream,
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 format(img_renderer, img_fmt),
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 )
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 self._processing = False
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
190
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 buf.unmap(mapinfo)
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
192
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 return False
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
194
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 def update_sample(self, sample, stream_size, video_stream: str, buffer) -> None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 if sample is None:
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 return
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
198
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 if video_stream == "remote":
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 return
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
201
9218d4331bb2 cli (call): `tui` output implementation:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 self.buffer = buffer