Mercurial > libervia-web
annotate libervia/web/pages/calls/_browser/webrtc.py @ 1555:0796bb8bad2f
doc (calls): minor markup fix
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 14 Aug 2023 17:10:27 +0200 |
parents | 83c2a6faa2ae |
children | 410064b31dca |
rev | line source |
---|---|
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
1 import json |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
2 import re |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
3 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
4 from bridge import AsyncBridge as Bridge |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
5 from browser import aio, console as log, document, timer, window |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
6 import dialog |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
7 import errors |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
8 from javascript import JSObject |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
9 import jid |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
10 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
11 log.warning = log.warn |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
12 profile = window.profile or "" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
13 bridge = Bridge() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
14 GATHER_TIMEOUT = 10000 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
15 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
16 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
17 class WebRTC: |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
18 def __init__(self): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
19 self.reset_instance() |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
20 bridge.register_signal("ice_candidates_new", self._on_ice_candidates_new) |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
21 self.is_audio_muted = None |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
22 self.is_video_muted = None |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
23 self._is_sharing_screen = False |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
24 self.screen_sharing_cb = None |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
25 self.local_video_elt = document["local_video"] |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
26 self.remote_video_elt = document["remote_video"] |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
27 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
28 @property |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
29 def is_sharing_screen(self) -> bool: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
30 return self._is_sharing_screen |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
31 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
32 @is_sharing_screen.setter |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
33 def is_sharing_screen(self, sharing: bool) -> None: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
34 if sharing != self._is_sharing_screen: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
35 self._is_sharing_screen = sharing |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
36 if self.screen_sharing_cb is not None: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
37 self.screen_sharing_cb(sharing) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
38 |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
39 def reset_instance(self): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
40 """Inits or resets the instance variables to their default state.""" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
41 self._peer_connection = None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
42 self._media_types = None |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
43 self._media_types_inv = None |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
44 self._callee = None |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
45 self.sid = None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
46 self.local_candidates = None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
47 self.remote_stream = None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
48 self.candidates_buffer = { |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
49 "audio": {"candidates": []}, |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
50 "video": {"candidates": []}, |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
51 } |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
52 self.media_candidates = {} |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
53 self.candidates_gathered = aio.Future() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
54 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
55 @property |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
56 def media_types(self): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
57 if self._media_types is None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
58 raise Exception("self._media_types should not be None!") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
59 return self._media_types |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
60 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
61 @media_types.setter |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
62 def media_types(self, new_media_types: dict) -> None: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
63 self._media_types = new_media_types |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
64 self._media_types_inv = {v: k for k, v in new_media_types.items()} |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
65 |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
66 @property |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
67 def media_types_inv(self) -> dict: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
68 if self._media_types_inv is None: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
69 raise Exception("self._media_types_inv should not be None!") |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
70 return self._media_types_inv |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
71 |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
72 def get_sdp_mline_index(self, media_type): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
73 """Gets the sdpMLineIndex for a given media type. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
74 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
75 @param media_type: The type of the media. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
76 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
77 for index, m_type in self.media_types.items(): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
78 if m_type == media_type: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
79 return index |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
80 raise ValueError(f"Media type '{media_type}' not found") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
81 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
82 def extract_pwd_ufrag(self, sdp): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
83 """Retrieves ICE password and user fragment for SDP offer. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
84 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
85 @param sdp: The Session Description Protocol offer string. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
86 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
87 ufrag_line = re.search(r"ice-ufrag:(\S+)", sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
88 pwd_line = re.search(r"ice-pwd:(\S+)", sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
89 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
90 if ufrag_line and pwd_line: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
91 return ufrag_line.group(1), pwd_line.group(1) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
92 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
93 log.error(f"SDP with missing ice-ufrag or ice-pwd:\n{sdp}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
94 raise ValueError("Can't extract ice-ufrag and ice-pwd from SDP") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
95 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
96 def extract_fingerprint_data(self, sdp): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
97 """Retrieves fingerprint data from an SDP offer. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
98 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
99 @param sdp: The Session Description Protocol offer string. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
100 @return: A dictionary containing the fingerprint data. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
101 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
102 fingerprint_line = re.search(r"a=fingerprint:(\S+)\s+(\S+)", sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
103 if fingerprint_line: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
104 algorithm, fingerprint = fingerprint_line.groups() |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
105 fingerprint_data = {"hash": algorithm, "fingerprint": fingerprint} |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
106 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
107 setup_line = re.search(r"a=setup:(\S+)", sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
108 if setup_line: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
109 setup = setup_line.group(1) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
110 fingerprint_data["setup"] = setup |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
111 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
112 return fingerprint_data |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
113 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
114 raise ValueError("fingerprint should not be missing") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
115 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
116 def parse_ice_candidate(self, candidate_string): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
117 """Parses the ice candidate string. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
118 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
119 @param candidate_string: The ice candidate string to be parsed. |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
120 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
121 pattern = re.compile( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
122 r"candidate:(?P<foundation>\S+) (?P<component_id>\d+) (?P<transport>\S+) " |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
123 r"(?P<priority>\d+) (?P<address>\S+) (?P<port>\d+) typ " |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
124 r"(?P<type>\S+)(?: raddr (?P<rel_addr>\S+) rport " |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
125 r"(?P<rel_port>\d+))?(?: generation (?P<generation>\d+))?" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
126 ) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
127 match = pattern.match(candidate_string) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
128 if match: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
129 candidate_dict = match.groupdict() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
130 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
131 # Apply the correct types to the dictionary values |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
132 candidate_dict["component_id"] = int(candidate_dict["component_id"]) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
133 candidate_dict["priority"] = int(candidate_dict["priority"]) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
134 candidate_dict["port"] = int(candidate_dict["port"]) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
135 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
136 if candidate_dict["rel_port"]: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
137 candidate_dict["rel_port"] = int(candidate_dict["rel_port"]) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
138 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
139 if candidate_dict["generation"]: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
140 candidate_dict["generation"] = candidate_dict["generation"] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
141 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
142 # Remove None values |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
143 return {k: v for k, v in candidate_dict.items() if v is not None} |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
144 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
145 log.warning(f"can't parse candidate: {candidate_string!r}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
146 return None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
147 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
148 def build_ice_candidate(self, parsed_candidate): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
149 """Builds ICE candidate |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
150 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
151 @param parsed_candidate: Dictionary containing parsed ICE candidate |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
152 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
153 base_format = ( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
154 "candidate:{foundation} {component_id} {transport} {priority} " |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
155 "{address} {port} typ {type}" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
156 ) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
157 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
158 if parsed_candidate.get("rel_addr") and parsed_candidate.get("rel_port"): |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
159 base_format += " raddr {rel_addr} rport {rel_port}" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
160 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
161 if parsed_candidate.get("generation"): |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
162 base_format += " generation {generation}" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
163 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
164 return base_format.format(**parsed_candidate) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
165 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
166 def on_ice_candidate(self, event): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
167 """Handles ICE candidate event |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
168 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
169 @param event: Event containing the ICE candidate |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
170 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
171 log.debug(f"on ice candidate {event.candidate=}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
172 if event.candidate and event.candidate.candidate: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
173 window.last_event = event |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
174 parsed_candidate = self.parse_ice_candidate(event.candidate.candidate) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
175 if parsed_candidate is None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
176 return |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
177 try: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
178 media_type = self.media_types[event.candidate.sdpMLineIndex] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
179 except (TypeError, IndexError): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
180 log.error( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
181 f"Can't find media type.\n{event.candidate=}\n{self._media_types=}" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
182 ) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
183 return |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
184 self.media_candidates.setdefault(media_type, []).append(parsed_candidate) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
185 log.debug(f"ICE candidate [{media_type}]: {event.candidate.candidate}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
186 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
187 log.debug("All ICE candidates gathered") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
188 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
189 def _set_media_types(self, offer): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
190 """Sets media types from offer SDP |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
191 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
192 @param offer: RTC session description containing the offer |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
193 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
194 sdp_lines = offer.sdp.splitlines() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
195 media_types = {} |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
196 mline_index = 0 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
197 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
198 for line in sdp_lines: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
199 if line.startswith("m="): |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
200 media_types[mline_index] = line[2 : line.find(" ")] |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
201 mline_index += 1 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
202 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
203 self.media_types = media_types |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
204 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
205 def on_ice_gathering_state_change(self, event): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
206 """Handles ICE gathering state change |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
207 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
208 @param event: Event containing the ICE gathering state change |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
209 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
210 connection = event.target |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
211 log.debug(f"on_ice_gathering_state_change {connection.iceGatheringState=}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
212 if connection.iceGatheringState == "complete": |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
213 log.info("ICE candidates gathering done") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
214 self.candidates_gathered.set_result(None) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
215 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
216 async def _create_peer_connection( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
217 self, |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
218 ): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
219 """Creates peer connection""" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
220 if self._peer_connection is not None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
221 raise Exception("create_peer_connection can't be called twice!") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
222 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
223 external_disco = json.loads(await bridge.external_disco_get("")) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
224 ice_servers = [] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
225 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
226 for server in external_disco: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
227 ice_server = {} |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
228 if server["type"] == "stun": |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
229 ice_server["urls"] = f"stun:{server['host']}:{server['port']}" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
230 elif server["type"] == "turn": |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
231 ice_server[ |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
232 "urls" |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
233 ] = f"turn:{server['host']}:{server['port']}?transport={server['transport']}" |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
234 ice_server["username"] = server["username"] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
235 ice_server["credential"] = server["password"] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
236 ice_servers.append(ice_server) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
237 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
238 rtc_configuration = {"iceServers": ice_servers} |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
239 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
240 peer_connection = window.RTCPeerConnection.new(rtc_configuration) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
241 peer_connection.addEventListener("track", self.on_track) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
242 peer_connection.addEventListener("negotiationneeded", self.on_negotiation_needed) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
243 peer_connection.addEventListener("icecandidate", self.on_ice_candidate) |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
244 peer_connection.addEventListener( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
245 "icegatheringstatechange", self.on_ice_gathering_state_change |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
246 ) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
247 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
248 self._peer_connection = peer_connection |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
249 window.pc = self._peer_connection |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
250 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
251 async def _get_user_media(self, audio: bool = True, video: bool = True) -> None: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
252 """ |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
253 Gets user media (camera and microphone). |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
254 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
255 @param audio: True if an audio flux is required. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
256 @param video: True if a video flux is required. |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
257 """ |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
258 media_constraints = {"audio": audio, "video": video} |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
259 local_stream = await window.navigator.mediaDevices.getUserMedia(media_constraints) |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
260 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
261 if not local_stream: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
262 log.error("Failed to get the media stream.") |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
263 return |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
264 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
265 self.local_video_elt.srcObject = local_stream |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
266 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
267 for track in local_stream.getTracks(): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
268 self._peer_connection.addTrack(track) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
269 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
270 async def _replace_user_video( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
271 self, |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
272 screen: bool = False, |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
273 ) -> JSObject | None: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
274 """Replaces the user video track with either a camera or desktop sharing track. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
275 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
276 @param screen: True if desktop sharing is required. False will use the camera. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
277 @return: The local media stream or None if failed. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
278 """ |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
279 if screen: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
280 media_constraints = {"video": {"cursor": "always"}} |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
281 new_stream = await window.navigator.mediaDevices.getDisplayMedia( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
282 media_constraints |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
283 ) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
284 else: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
285 if self.local_video_elt.srcObject: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
286 for track in self.local_video_elt.srcObject.getTracks(): |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
287 if track.kind == "video": |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
288 track.stop() |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
289 media_constraints = {"video": True} |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
290 new_stream = await window.navigator.mediaDevices.getUserMedia( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
291 media_constraints |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
292 ) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
293 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
294 if not new_stream: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
295 log.error("Failed to get the media stream.") |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
296 return None |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
297 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
298 new_video_tracks = [ |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
299 track for track in new_stream.getTracks() if track.kind == "video" |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
300 ] |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
301 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
302 if not new_video_tracks: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
303 log.error("Failed to retrieve the video track from the new stream.") |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
304 return None |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
305 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
306 # Retrieve the current local stream's video track. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
307 local_stream = self.local_video_elt.srcObject |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
308 if local_stream: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
309 local_video_tracks = [ |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
310 track for track in local_stream.getTracks() if track.kind == "video" |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
311 ] |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
312 if local_video_tracks: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
313 # Remove the old video track and add the new one to the local stream. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
314 local_stream.removeTrack(local_video_tracks[0]) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
315 local_stream.addTrack(new_video_tracks[0]) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
316 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
317 video_sender = next( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
318 ( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
319 sender |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
320 for sender in self._peer_connection.getSenders() |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
321 if sender.track and sender.track.kind == "video" |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
322 ), |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
323 None, |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
324 ) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
325 if video_sender: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
326 await video_sender.replaceTrack(new_video_tracks[0]) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
327 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
328 if screen: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
329 # For screen sharing, we track the end event to properly stop the sharing when |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
330 # the user clicks on the browser's stop sharing dialog. |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
331 def on_track_ended(event): |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
332 aio.run(self.toggle_screen_sharing()) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
333 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
334 new_video_tracks[0].bind("ended", on_track_ended) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
335 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
336 self.is_sharing_screen = screen |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
337 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
338 return local_stream |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
339 |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
340 async def _gather_ice_candidates(self, is_initiator: bool, remote_candidates=None): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
341 """Get ICE candidates and wait to have them all before returning them |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
342 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
343 @param is_initiator: Boolean indicating if the user is the initiator of the connection |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
344 @param remote_candidates: Remote ICE candidates, if any |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
345 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
346 if self._peer_connection is None: |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
347 raise Exception( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
348 "The peer connection must be created before gathering ICE candidates!" |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
349 ) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
350 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
351 self.media_candidates.clear() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
352 gather_timeout = timer.set_timeout( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
353 lambda: self.candidates_gathered.set_exception( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
354 errors.TimeoutError("ICE gathering time out") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
355 ), |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
356 GATHER_TIMEOUT, |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
357 ) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
358 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
359 if is_initiator: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
360 offer = await self._peer_connection.createOffer() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
361 self._set_media_types(offer) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
362 await self._peer_connection.setLocalDescription(offer) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
363 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
364 answer = await self._peer_connection.createAnswer() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
365 self._set_media_types(answer) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
366 await self._peer_connection.setLocalDescription(answer) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
367 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
368 if not is_initiator: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
369 log.debug(self._peer_connection.localDescription.sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
370 await self.candidates_gathered |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
371 log.debug(self._peer_connection.localDescription.sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
372 timer.clear_timeout(gather_timeout) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
373 ufrag, pwd = self.extract_pwd_ufrag(self._peer_connection.localDescription.sdp) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
374 return { |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
375 "ufrag": ufrag, |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
376 "pwd": pwd, |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
377 "candidates": self.media_candidates, |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
378 } |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
379 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
380 async def accept_call(self, session_id: str, sdp: str, profile: str) -> None: |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
381 """Call has been accepted, connection can be established |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
382 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
383 @param session_id: Session identifier |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
384 @param sdp: Session Description Protocol data |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
385 @param profile: Profile associated |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
386 """ |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
387 await self._peer_connection.setRemoteDescription({"type": "answer", "sdp": sdp}) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
388 await self.on_ice_candidates_new(self.candidates_buffer) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
389 self.candidates_buffer.clear() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
390 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
391 def _on_ice_candidates_new(self, sid: str, candidates_s: str, profile: str) -> None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
392 """Called when new ICE candidates are received |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
393 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
394 @param sid: Session identifier |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
395 @param candidates_s: ICE candidates serialized |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
396 @param profile: Profile associated with the action |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
397 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
398 if sid != self.sid: |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
399 log.debug(f"ignoring peer ice candidates for {sid=} ({self.sid=}).") |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
400 return |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
401 candidates = json.loads(candidates_s) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
402 aio.run(self.on_ice_candidates_new(candidates)) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
403 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
404 async def on_ice_candidates_new(self, candidates: dict) -> None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
405 """Called when new ICE canidates are received from peer |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
406 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
407 @param candidates: Dictionary containing new ICE candidates |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
408 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
409 log.debug(f"new peer candidates received: {candidates}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
410 if ( |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
411 self._peer_connection is None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
412 or self._peer_connection.remoteDescription is None |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
413 ): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
414 for media_type in ("audio", "video"): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
415 media_candidates = candidates.get(media_type) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
416 if media_candidates: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
417 buffer = self.candidates_buffer[media_type] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
418 buffer["candidates"].extend(media_candidates["candidates"]) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
419 return |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
420 for media_type, ice_data in candidates.items(): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
421 for candidate in ice_data["candidates"]: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
422 candidate_sdp = self.build_ice_candidate(candidate) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
423 try: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
424 sdp_mline_index = self.get_sdp_mline_index(media_type) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
425 except Exception as e: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
426 log.warning(e) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
427 continue |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
428 ice_candidate = window.RTCIceCandidate.new( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
429 {"candidate": candidate_sdp, "sdpMLineIndex": sdp_mline_index} |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
430 ) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
431 await self._peer_connection.addIceCandidate(ice_candidate) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
432 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
433 def on_track(self, event): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
434 """New track has been received from peer |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
435 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
436 @param event: Event associated with the new track |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
437 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
438 if event.streams and event.streams[0]: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
439 remote_stream = event.streams[0] |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
440 self.remote_video_elt.srcObject = remote_stream |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
441 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
442 if self.remote_stream is None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
443 self.remote_stream = window.MediaStream.new() |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
444 self.remote_video_elt.srcObject = self.remote_stream |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
445 self.remote_stream.addTrack(event.track) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
446 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
447 def on_negotiation_needed(self, event) -> None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
448 log.debug(f"on_negotiation_needed {event=}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
449 # TODO |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
450 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
451 async def answer_call(self, sid: str, offer_sdp: str, profile: str): |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
452 """We respond to the call""" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
453 log.debug("answering call") |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
454 if sid != self.sid: |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
455 raise Exception(f"Internal Error: unexpected sid: {sid=} {self.sid=}") |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
456 await self._create_peer_connection() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
457 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
458 await self._peer_connection.setRemoteDescription( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
459 {"type": "offer", "sdp": offer_sdp} |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
460 ) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
461 await self.on_ice_candidates_new(self.candidates_buffer) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
462 self.candidates_buffer.clear() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
463 await self._get_user_media() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
464 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
465 # Gather local ICE candidates |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
466 local_ice_data = await self._gather_ice_candidates(False) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
467 self.local_candidates = local_ice_data["candidates"] |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
468 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
469 await bridge.call_answer_sdp(sid, self._peer_connection.localDescription.sdp) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
470 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
471 async def make_call( |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
472 self, callee_jid: jid.JID, audio: bool = True, video: bool = True |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
473 ) -> None: |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
474 """Start a WebRTC call |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
475 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
476 @param audio: True if an audio flux is required |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
477 @param video: True if a video flux is required |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
478 """ |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
479 await self._create_peer_connection() |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
480 await self._get_user_media(audio, video) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
481 await self._gather_ice_candidates(True) |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
482 |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
483 call_data = {"sdp": self._peer_connection.localDescription.sdp} |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
484 log.info(f"calling {callee_jid!r}") |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
485 self.sid = await bridge.call_start(str(callee_jid), json.dumps(call_data)) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
486 log.debug(f"Call SID: {self.sid}") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
487 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
488 async def end_call(self) -> None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
489 """Stop streaming and clean instance""" |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
490 if self._peer_connection is None: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
491 log.debug("There is currently no call to end.") |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
492 else: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
493 self._peer_connection.removeEventListener("track", self.on_track) |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
494 self._peer_connection.removeEventListener( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
495 "negotiationneeded", self.on_negotiation_needed |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
496 ) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
497 self._peer_connection.removeEventListener( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
498 "icecandidate", self.on_ice_candidate |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
499 ) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
500 self._peer_connection.removeEventListener( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
501 "icegatheringstatechange", self.on_ice_gathering_state_change |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
502 ) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
503 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
504 # Base64 encoded 1x1 black pixel image |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
505 # this is a trick to reset the image displayed, so we don't see last image of |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
506 # last stream |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
507 black_image_data = ( |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
508 "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0" |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
509 "lEQVR42mP8/wcAAwAB/uzNq7sAAAAASUVORK5CYII=" |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
510 ) |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
511 |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
512 local_video = self.local_video_elt |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
513 remote_video = self.remote_video_elt |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
514 if local_video.srcObject: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
515 for track in local_video.srcObject.getTracks(): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
516 track.stop() |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
517 local_video.src = black_image_data |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
518 |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
519 if remote_video.srcObject: |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
520 for track in remote_video.srcObject.getTracks(): |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
521 track.stop() |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
522 remote_video.src = black_image_data |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
523 |
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
524 self._peer_connection.close() |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
525 self.reset_instance() |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
526 |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
527 def toggle_media_mute(self, media_type: str) -> bool: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
528 """Toggle mute/unmute for media tracks. |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
529 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
530 @param media_type: 'audio' or 'video'. Determines which media tracks |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
531 to process. |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
532 """ |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
533 assert media_type in ("audio", "video"), "Invalid media type" |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
534 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
535 local_video = self.local_video_elt |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
536 is_muted_attr = f"is_{media_type}_muted" |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
537 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
538 if local_video.srcObject: |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
539 log.debug(f"{local_video.srcObject=}") |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
540 track_getter = getattr( |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
541 local_video.srcObject, f"get{media_type.capitalize()}Tracks" |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
542 ) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
543 log.debug("track go") |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
544 for track in track_getter(): |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
545 log.debug(f"{track=}") |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
546 track.enabled = not track.enabled |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
547 setattr(self, is_muted_attr, not track.enabled) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
548 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
549 media_name = self.media_types_inv.get(media_type) |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
550 if media_name is not None: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
551 extra = {"name": str(media_name)} |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
552 aio.run( |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
553 bridge.call_info( |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
554 self.sid, |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
555 "mute" if getattr(self, is_muted_attr) else "unmute", |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
556 json.dumps(extra), |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
557 ) |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
558 ) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
559 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
560 return getattr(self, is_muted_attr) |
1517
b8ed9726525b
browser: "calls" implementation, first draft:
Goffi <goffi@goffi.org>
parents:
diff
changeset
|
561 |
1549
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
562 def toggle_audio_mute(self) -> bool: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
563 """Toggle mute/unmute for audio tracks.""" |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
564 return self.toggle_media_mute("audio") |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
565 |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
566 def toggle_video_mute(self) -> bool: |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
567 """Toggle mute/unmute for video tracks.""" |
e47c24204449
browser (calls): update call to handle search, control buttons, and better UI/UX:
Goffi <goffi@goffi.org>
parents:
1518
diff
changeset
|
568 return self.toggle_media_mute("video") |
1553
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
569 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
570 async def toggle_screen_sharing(self): |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
571 log.debug(f"toggle_screen_sharing {self._is_sharing_screen=}") |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
572 |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
573 if self._is_sharing_screen: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
574 await self._replace_user_video(screen=False) |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
575 else: |
83c2a6faa2ae
browser (calls): screen sharing implementation:
Goffi <goffi@goffi.org>
parents:
1549
diff
changeset
|
576 await self._replace_user_video(screen=True) |