annotate libervia/desktop_kivy/plugins/plugin_wid_calls.py @ 514:d78728d7fd6a default tip

plugin wid calls, core: implements WebRTC DataChannel file transfer: - Add a new "file" icon in call UI to send a file via WebRTC. - Handle new preflight mechanism, and WebRTC file transfer. - Native file chooser handling has been moved to new `core.file_chooser` module, and now supports "save" and "dir" modes (based on `plyer`). rel 442
author Goffi <goffi@goffi.org>
date Sat, 06 Apr 2024 13:37:27 +0200
parents 644a8d165e5a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 from dataclasses import dataclass
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
2 from pathlib import Path
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 from typing import Optional, Callable
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
4 from functools import partial
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # from gi.repository import GLib
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 from gi.repository import GObject, Gst, GstWebRTC, GstSdp
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
8 from kivy.metrics import dp
514
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
9 from libervia.desktop_kivy.core.file_chooser import FileChooser
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 try:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 from gi.overrides import Gst as _
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 except ImportError:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 print(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
15 "no GStreamer python overrides available, please install relevant pacakges on "
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 "your system."
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
18 from kivy.clock import Clock
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
19 from kivy.core.audio import Sound, SoundLoader
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
20 from kivy.core.window import Window
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from kivy.graphics.texture import Texture
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
22 from kivy.properties import (
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
23 BooleanProperty,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
24 ColorProperty,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
25 NumericProperty,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
26 ObjectProperty,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
27 ReferenceListProperty,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
28 )
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from kivy.support import install_gobject_iteration
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 from kivy.uix.button import Button
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from kivy.uix.image import Image
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
32 from kivy.uix.popup import Popup
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
33 from kivy.uix.screenmanager import Screen
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
34 from kivy.uix.widget import Widget
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 from libervia.backend.core.constants import Const as C
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
36 from libervia.backend.core import log as logging
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 from libervia.backend.core.i18n import _
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 from libervia.backend.core import exceptions
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 from libervia.backend.tools.common import data_format
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 from libervia.frontends.quick_frontend import quick_widgets
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
41 from libervia.frontends.tools import aio, display_servers, jid, webrtc
514
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
42 from libervia.frontends.tools.webrtc_file import WebRTCFileSender
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
43
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
44 from libervia.desktop_kivy import G
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
45
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 from ..core import cagou_widget
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
47 from ..core import common
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
48 from ..core.behaviors import FilterBehavior
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
49
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 log = logging.getLogger(__name__)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
51
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 install_gobject_iteration()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 Gst.init(None)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
55
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
56
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 PLUGIN_INFO = {
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 "name": _("calls"),
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 "main": "Calls",
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 "description": _("Audio/Video calls"),
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 "icon_symbol": "phone",
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 }
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
63
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
64
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 @dataclass
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
66 class TextureData:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 texture: Optional[Texture] = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 size: Optional[tuple[int, int]] = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
69
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
70
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
71 class SearchScreen(Screen):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
72 pass
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
73
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
74
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
75 class InCallScreen(Screen):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
76 pass
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
77
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
78
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 class CallButton(Button):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 parent_widget = ObjectProperty(None)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
81
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
82
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
83 class CallControlButton(common.SymbolButton):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
84 active = BooleanProperty(True)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
85 background_color = ColorProperty()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
86 margin_x = NumericProperty(0)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
87 margin_y = NumericProperty(0)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
88 margin = ReferenceListProperty(margin_x, margin_y)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
89
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
90
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 class VideoStreamWidget(Image):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 pass
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
93
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
94
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 class WebRTC:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 """WebRTC implementation for audio and video communication.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
97
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 This class encapsulates the WebRTC functionalities required for initiating and
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 handling audio and video calls.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
100
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 @attribute test_mode: A flag to indicate whether the WebRTC instance is in test mode.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 If true, test video and audio sources will be used. Otherwise first webcam and
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 microphone available will be used.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 """
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
105
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 test_mode: bool = False
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
107
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
108 PROXIED_PROPERTIES = {
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
109 'audio_muted', 'callee', 'desktop_sharing', 'sid', 'video_muted', 'desktop_sharing_data'
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
110 }
512
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
111 PROXIED_METHODS = {'answer_call', 'bind', 'end_call', 'on_accepted_call', 'on_ice_candidates_new', 'setup_call', 'start_pipeline'}
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
112
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 def __init__(self, parent_calls: "Calls", profile: str) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 self.parent_calls = parent_calls
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 self.profile = profile
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
116 self.webrtc = webrtc.WebRTC(
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
117 G.host.a_bridge,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
118 profile,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
119 sinks=webrtc.SINKS_TEST if self.test_mode else webrtc.SINKS_APP,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
120 appsink_data=webrtc.AppSinkData(
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
121 local_video_cb=partial(
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
122 self.on_new_sample,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
123 update_sample_method=self.update_sample,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
124 video_widget=self.parent_calls.local_video
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
125 ),
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
126 remote_video_cb=partial(
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
127 self.on_new_sample,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
128 update_sample_method=self.update_sample,
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
129 video_widget=self.parent_calls.remote_video
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
130 )
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
131 ),
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
132 reset_cb=self.on_reset
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
133
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
134 )
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
135 self.pipeline = None
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
136
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
137 def __getattr__(self, name):
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
138 if name in self.PROXIED_PROPERTIES or name in self.PROXIED_METHODS:
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
139 return getattr(self.webrtc, name)
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
140 raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
141
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
142 def __setattr__(self, name, value):
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
143 if name in self.PROXIED_PROPERTIES:
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
144 setattr(self.webrtc, name, value)
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
145 else:
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
146 super().__setattr__(name, value)
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
147
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
148 def on_reset(self):
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
149 self.texture_map: dict[VideoStreamWidget, TextureData] = {}
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
150
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 def on_new_sample(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 self,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 video_sink: Gst.Element,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 update_sample_method: Callable,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 video_widget: VideoStreamWidget,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 ) -> bool:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 """Handles a new sample from the video sink.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
158
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 @param video_sink: The video sink to pull samples from.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 @param update_sample_method: The method to call for updating the sample.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
161 @param video_widget: The video widget (either local_video or remote_video).
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 @return: Always False
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
163 """
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
164 sample = video_sink.emit("pull-sample")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 if sample is None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 return False
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
167
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
168 try:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 texture_data = self.texture_map[video_widget]
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 except KeyError:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
171 texture_data = self.texture_map[video_widget] = TextureData()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
172
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
173 # Get the current video size
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 video_pad = video_sink.get_static_pad("sink")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
175 assert video_pad is not None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
176 s = video_pad.get_current_caps().get_structure(0)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 stream_size = (s.get_value("width"), s.get_value("height"))
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
178
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 # Compare with the texture size
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 texture_size = texture_data.size
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 if texture_size != stream_size:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 log.debug(f"sample size update: {texture_size} => {stream_size}")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
183 texture_data.size = stream_size
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 # texture needs to be recreated, so we reset the one in texture_data
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
185 texture_data.texture = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
186
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 Clock.schedule_once(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 partial(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
189 update_sample_method,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 sample=sample,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 video_widget=video_widget,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
192 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 return False
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
195
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 def update_sample(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 self,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 dt: float,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 sample: Optional[Gst.Sample],
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 video_widget: VideoStreamWidget,
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
201 ) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 """Updates the video sample.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
203
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 This method runs in the main thread.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
205
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 @param dt: Time delta since the last call. This is passed by Clock.schedule_once.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 @param sample: The video sample to update.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 @param texture_id: identifier of the texture data (e.g. "local" or "remote")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 @param texture: The texture object.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
210 @param texture_size: The texture size.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 @param video_widget: The video widget.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 """
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
213 if sample is None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 return
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 try:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 texture_data = self.texture_map[video_widget]
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 except KeyError:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 log.warning(f"no texture data found for {video_widget}")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 return
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
220
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 if texture_data.texture is None and texture_data.size is not None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 log.debug(f"===> creating texture for {video_widget}: {texture_data.size=}")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 texture = Texture.create(size=texture_data.size, colorfmt="rgb")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
224 assert texture is not None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 texture_data.texture = texture
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 texture.flip_vertical()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 video_widget.texture = texture
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
228
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 mapinfo = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 buf = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 try:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 buf = sample.get_buffer()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
233 _, mapinfo = buf.map(Gst.MapFlags.READ)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
234
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 buffer = mapinfo.data.tobytes()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
236
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 if texture_data.texture is None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 log.debug("can't copy the buffer, texture is None")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 return
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
240 texture_data.texture.blit_buffer(buffer, colorfmt="rgb")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 assert video_widget.canvas is not None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 video_widget.canvas.ask_update()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 buf.unmap(mapinfo)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 finally:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 if buf is not None and mapinfo is not None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 buf.unmap(mapinfo)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
247
512
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
248
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
249 class WindowSelectButton(Button):
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
250 pass
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
251
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
252
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
253 class DesktopScreenDialog(Popup):
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
254 windows_buttons = ObjectProperty()
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
255
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
256 def __init__(self, calls: "Calls", **kwargs):
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
257 super().__init__(**kwargs)
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
258 self.calls = calls
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
259 if display_servers.detect() == display_servers.X11:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
260 windows_data = display_servers.x11_list_windows()
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
261 for window_data in windows_data:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
262 log.debug(f"- X11 windows found: {window_data}")
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
263 button = WindowSelectButton(
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
264 text = window_data["title"],
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
265 on_press=partial(self.on_window_selected, xid=window_data["id"])
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
266 )
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
267 self.windows_buttons.add_widget(button)
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
268
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
269 def on_window_selected(self, instance, xid: str) -> None:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
270 if xid is not None:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
271 self.calls.webrtc.desktop_sharing_data = {"xid": xid}
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
272 else:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
273 self.calls.webrtc.desktop_sharing_data = None
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
274 self.calls.desktop_sharing = True
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
275 self.dismiss()
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
276
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
277
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
278 class Calls(
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
279 quick_widgets.QuickWidget,
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
280 cagou_widget.LiberviaDesktopKivyWidget,
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
281 FilterBehavior
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
282 ):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
283 audio_muted = BooleanProperty(False)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
284 call_layout = ObjectProperty()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
285 call_screen = ObjectProperty()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
286 fullscreen = BooleanProperty(False)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
287 in_call = BooleanProperty(False)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
288 incoming_call_dialog: dict[str, Widget] = {}
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
289 jid_selector = ObjectProperty()
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
290 local_video = ObjectProperty()
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
291 remote_video = ObjectProperty()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
292 ringtone: Sound | None = None
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
293 screen_manager = ObjectProperty()
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 signals_registered = False
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
295 use_header_input = True
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
296 video_muted = BooleanProperty(False)
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
297 desktop_sharing = BooleanProperty(False)
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
298
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
299 def __init__(self, host, target, profiles):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
300 quick_widgets.QuickWidget.__init__(self, G.host, target, profiles)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
301 cagou_widget.LiberviaDesktopKivyWidget.__init__(self)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
302 call_btn = CallButton(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 parent_widget=self, on_press=lambda *__: aio.run_async(self.toggle_call())
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
304 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
305 self.header_input_add_extra(call_btn)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
306 self.webrtc = WebRTC(self, self.profile)
512
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
307 self.webrtc.bind(
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
308 desktop_sharing=partial(setattr, self, "desktop_sharing")
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
309 )
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
310 self.previous_fullscreen = None
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
311 self.reset_instance()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
312
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
313 @property
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
314 def sid(self):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
315 return self.webrtc.sid
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
316
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
317 def hang_up(self):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
318 if self.sid is not None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
319 aio.run_async(self.toggle_call())
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
320
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 async def toggle_call(self):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
322 """Toggle between making a call and hanging up.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
323
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
324 This function will initiate or terminate a call based on the call state.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
325 """
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
326 if self.sid is None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
327 # Initiate the call
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
328 log.info("initiating call")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
329 callee = jid.JID(self.header_input.text.strip())
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
330 if not callee:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
331 return
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
332 if not callee.is_valid():
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
333 G.host.add_note(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
334 _("Calls"),
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
335 _("Can't make a call: invalid destinee {}").format(repr(callee)),
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
336 level=C.XMLUI_DATA_LVL_ERROR
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
337 )
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
338 return
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
339
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 self.webrtc.callee = callee
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
341 await self.webrtc.setup_call("initiator")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
342 self.webrtc.start_pipeline()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
343 self.in_call = True
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
344 else:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
345 # Terminate the call
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
346 sid = self.sid
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 await self.end_call({"reason": "terminated"}, self.profile)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 await G.host.a_bridge.call_end(sid, "", self.profile)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
349 self.in_call = False
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
350
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 async def on_incoming_call(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
352 self, action_data: dict, action_id: str, profile: str
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
353 ) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
354 """Handle incoming call notifications.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
355
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 @param action_data: A dictionary containing data related to the incoming call
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
357 @param action_id: The ID corresponding to the incoming call action.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
358 @param profile: The profile associated with the incoming call.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
359 """
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 if self.sid is not None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
361 # FIXME: show a double remote call notification
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 log.warning("Ignoring new remote call as we are already in a call.")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
363 return
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
364 sid = action_data["session_id"]
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
365 self.in_call = True
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
366 self.webrtc.sid = sid
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
367 # FIXME: we accept all remote calls for now, will be changed when proper UI/UX
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
368 # will be implemented
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
369 log.warning("auto-accepting remote call")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
370 await G.host.a_bridge.action_launch(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
371 action_id, data_format.serialise({"cancelled": False}), profile
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
372 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
373
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
374 async def on_call_setup(self, setup_data: dict, profile: str) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
375 """Call has been accepted, connection can be established
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
376
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 @param session_id: Session identifier
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
378 @param setup_data: Data with following keys:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 role: initiator or responser
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 sdp: Session Description Protocol data
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
381 @param profile: Profile associated
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
382 """
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
383 try:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
384 role = setup_data["role"]
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
385 sdp = setup_data["sdp"]
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
386 except KeyError:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 log.error(f"Invalid setup data received: {setup_data}")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
388 return
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 if role == "initiator":
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 self.webrtc.on_accepted_call(sdp, profile)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
391 elif role == "responder":
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
392 await self.webrtc.answer_call(sdp, profile)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
393 else:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
394 log.error(f"Invalid role received during setup: {setup_data}")
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
395
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 def reset_instance(self) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 self.in_call = False
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
398 self.local_video.texture = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
399 self.remote_video.texture = None
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
400
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
401 async def end_call(self, data: dict, profile: str) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
402 """End current call if any and reset the instance
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
403
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
404 @param data: end call data, often includes the reason of the call ending.
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
405 """
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
406 await self.webrtc.end_call()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
407 self.reset_instance()
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
408
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
409 def on_in_call(self, instance, in_call: bool) -> None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
410 if in_call:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
411 self.screen_manager.transition.direction = "up"
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
412 self.screen_manager.current = "call"
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
413 else:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
414 self.fullscreen = False
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
415 self.screen_manager.transition.direction = "down"
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
416 self.screen_manager.current = "search"
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
417
509
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
418 def on_audio_muted(self, instance, muted: bool) -> None:
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
419 self.webrtc.audio_muted = muted
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
420
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
421 def on_video_muted(self, instance, muted: bool) -> None:
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
422 self.webrtc.video_muted = muted
f0ce49b360c8 calls: move webrtc code to core:
Goffi <goffi@goffi.org>
parents: 506
diff changeset
423
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
424 def on_desktop_btn_press(self) -> None:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
425 if self.desktop_sharing:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
426 self.desktop_sharing = False
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
427 else:
512
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
428 if display_servers.detect() == display_servers.X11:
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
429 DesktopScreenDialog(self).open()
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
430 else:
644a8d165e5a plugin calls: use the new binding feature of webrtc module:
Goffi <goffi@goffi.org>
parents: 510
diff changeset
431 self.desktop_sharing = True
510
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
432
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
433 def on_desktop_sharing(self, instance, active: bool) -> None:
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
434 self.webrtc.desktop_sharing = active
97ab236e8f20 plugin calls: implement desktop sharing:
Goffi <goffi@goffi.org>
parents: 509
diff changeset
435
514
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
436 def on_file_btn_press(self) -> None:
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
437 aio.run_async(self.on_file_press())
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
438
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
439 async def on_file_press(self):
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
440 callee = self.webrtc.callee
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
441 if callee is None:
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
442 return
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
443 file_to_send = await FileChooser.a_open()
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
444 if file_to_send is None:
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
445 return
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
446 file_sender = WebRTCFileSender(
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
447 G.host.a_bridge,
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
448 self.profile
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
449 )
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
450 await file_sender.send_file_webrtc(file_to_send, self.webrtc.callee)
d78728d7fd6a plugin wid calls, core: implements WebRTC DataChannel file transfer:
Goffi <goffi@goffi.org>
parents: 512
diff changeset
451
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
452 def on_fullscreen(self, instance, fullscreen: bool) -> None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
453 if fullscreen:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
454 G.host.app.show_head_widget(False, animation=False)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
455 self.call_layout.parent.remove_widget(self.call_layout)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
456 G.host.show_extra_ui(self.call_layout)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
457 self.previous_fullscreen = Window.fullscreen
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
458 Window.fullscreen = "auto"
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
459 else:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
460 G.host.app.show_head_widget(True, animation=False)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
461 G.host.close_ui()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
462 self.call_screen.add_widget(self.call_layout)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
463 Window.fullscreen = self.previous_fullscreen or False
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
464
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
465 def on_header_wid_input(self):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
466 aio.run_async(self.toggle_call())
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
467
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
468 def on_header_wid_input_complete(self, wid, text, **kwargs):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
469 """we filter items when text is entered in input box"""
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
470 for layout in self.jid_selector.items_layouts:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
471 self.do_filter(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
472 layout,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
473 text,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
474 # we append nick to jid to filter on both
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
475 lambda c: c.jid + c.data.get('nick', ''),
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
476 width_cb=lambda c: c.base_width,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
477 height_cb=lambda c: c.minimum_height,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
478 continue_tests=[lambda c: not isinstance(c, common.ContactButton)])
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
479
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
480 def on_jid_select(self, contact_button):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
481 self.header_input.text = contact_button.jid
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
482 aio.run_async(self.toggle_call())
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
483
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
484 @classmethod
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
485 def ice_candidates_new_handler(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
486 cls, sid: str, candidates_s: str, profile: str
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
487 ) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
488 for wid in G.host.get_visible_list(cls):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
489 if profile not in wid.profiles or sid != wid.sid:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
490 continue
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
491 wid.webrtc.on_ice_candidates_new(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
492 data_format.deserialise(candidates_s),
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
493 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
494
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
495 @classmethod
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
496 def call_setup_handler(cls, sid: str, setup_data_s: str, profile: str) -> None:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
497 for wid in G.host.get_visible_list(cls):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
498 if profile not in wid.profiles or sid != wid.sid:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
499 continue
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
500 aio.run_async(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
501 wid.on_call_setup(data_format.deserialise(setup_data_s), profile)
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
502 )
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
503
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
504 @classmethod
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
505 def call_ended_handler(cls, sid: str, data_s: str, profile: str) -> None:
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
506 if sid in cls.incoming_call_dialog:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
507 dialog_wid = cls.incoming_call_dialog.pop(sid)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
508 G.host.del_notif_widget(dialog_wid)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
509 G.host.add_note(_("Call cancelled"), _("The call has been cancelled."))
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
510
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
511
499
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
512 for wid in G.host.get_visible_list(cls):
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
513 if profile not in wid.profiles or sid != wid.sid:
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
514 continue
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
515 aio.run_async(wid.end_call(data_format.deserialise(data_s), profile))
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
516
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
517 @classmethod
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
518 def action_new_handler(
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
519 cls, action_data: dict, action_id: str, security_limit: int, profile: str
f387992d8e37 plugins: new "call" plugin for A/V calls:
Goffi <goffi@goffi.org>
parents:
diff changeset
520 ) -> None:
506
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
521 if profile in G.host.profiles:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
522 if cls.ringtone is None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
523 cls.ringtone = SoundLoader.load(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
524 str(Path(G.host.media_dir) / "sounds/notifications/ring_1.mp3")
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
525 )
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
526 if cls.ringtone is not None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
527 cls.ringtone.play()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
528 peer_jid = jid.JID(action_data["from_jid"]).bare
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
529 sid = action_data["session_id"]
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
530 notif_body = f"{peer_jid} is calling you."
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
531 notif_title = "Incoming call"
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
532 G.host.desktop_notif(notif_body, title=notif_title, duration=10)
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
533
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
534 def on_call_answer(accepted, __):
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
535 del cls.incoming_call_dialog[sid]
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
536 if cls.ringtone is not None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
537 cls.ringtone.stop()
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
538 if accepted:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
539 wid = G.host.do_action("calls", str(peer_jid), [profile])
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
540 aio.run_async(wid.on_incoming_call(action_data, action_id, profile))
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
541 else:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
542 aio.run_async(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
543 G.host.a_bridge.action_launch(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
544 action_id, data_format.serialise({"cancelled": True}), profile
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
545 )
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
546 )
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
547
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
548 dialog_wid = G.host.show_dialog(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
549 notif_body, notif_title, type="yes/no", answer_cb=on_call_answer
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
550 )
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
551 cls.incoming_call_dialog[sid] = dialog_wid
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
552
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
553
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
554 if G.host is not None:
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
555 log.debug("registering signals")
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
556 G.host.register_signal(
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
557 "ice_candidates_new",
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
558 handler=Calls.ice_candidates_new_handler,
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
559 iface="plugin",
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
560 )
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
561 G.host.register_signal("call_setup", handler=Calls.call_setup_handler, iface="plugin")
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
562 G.host.register_signal("call_ended", handler=Calls.call_ended_handler, iface="plugin")
0480f883f0a6 plugin calls: update UI:
Goffi <goffi@goffi.org>
parents: 499
diff changeset
563 G.host.register_action_handler(C.META_TYPE_CALL, Calls.action_new_handler)