1use crate::{
2 AudioStream, ConnectionQuality, LocalAudioTrack, LocalTrackPublication, LocalVideoTrack,
3 Participant, ParticipantIdentity, RemoteTrack, RemoteTrackPublication, TrackSid,
4 test::{Room, WeakRoom},
5};
6use anyhow::Result;
7use collections::HashMap;
8use gpui::{
9 AsyncApp, DevicePixels, ScreenCaptureSource, ScreenCaptureStream, SourceMetadata, size,
10};
11use std::sync::{Arc, atomic::AtomicU64};
12
13#[derive(Clone, Debug)]
14pub struct LocalParticipant {
15 pub(crate) identity: ParticipantIdentity,
16 pub(crate) room: Room,
17}
18
19#[derive(Clone, Debug)]
20pub struct RemoteParticipant {
21 pub(crate) identity: ParticipantIdentity,
22 pub(crate) room: WeakRoom,
23}
24
25impl Participant {
26 pub fn identity(&self) -> ParticipantIdentity {
27 match self {
28 Participant::Local(participant) => participant.identity.clone(),
29 Participant::Remote(participant) => participant.identity.clone(),
30 }
31 }
32
33 pub fn connection_quality(&self) -> ConnectionQuality {
34 match self {
35 Participant::Local(p) => p.connection_quality(),
36 Participant::Remote(p) => p.connection_quality(),
37 }
38 }
39
40 pub fn audio_level(&self) -> f32 {
41 match self {
42 Participant::Local(p) => p.audio_level(),
43 Participant::Remote(p) => p.audio_level(),
44 }
45 }
46}
47
48impl LocalParticipant {
49 pub fn connection_quality(&self) -> ConnectionQuality {
50 ConnectionQuality::Excellent
51 }
52
53 pub fn audio_level(&self) -> f32 {
54 0.0
55 }
56
57 pub async fn unpublish_track(&self, track: TrackSid, _cx: &AsyncApp) -> Result<()> {
58 self.room
59 .test_server()
60 .unpublish_track(self.room.token(), &track)
61 .await
62 }
63
64 pub(crate) async fn publish_microphone_track(
65 &self,
66 _cx: &AsyncApp,
67 ) -> Result<(LocalTrackPublication, AudioStream, Arc<AtomicU64>)> {
68 let this = self.clone();
69 let server = this.room.test_server();
70 let sid = server
71 .publish_audio_track(this.room.token(), &LocalAudioTrack {})
72 .await?;
73
74 Ok((
75 LocalTrackPublication {
76 room: self.room.downgrade(),
77 sid,
78 },
79 AudioStream {},
80 Arc::new(AtomicU64::new(0)),
81 ))
82 }
83
84 pub async fn publish_screenshare_track(
85 &self,
86 _source: &dyn ScreenCaptureSource,
87 _cx: &mut AsyncApp,
88 ) -> Result<(LocalTrackPublication, Box<dyn ScreenCaptureStream>)> {
89 let this = self.clone();
90 let server = this.room.test_server();
91 let sid = server
92 .publish_video_track(this.room.token(), LocalVideoTrack {})
93 .await?;
94 Ok((
95 LocalTrackPublication {
96 room: self.room.downgrade(),
97 sid,
98 },
99 Box::new(TestScreenCaptureStream {}),
100 ))
101 }
102}
103
104impl RemoteParticipant {
105 pub fn connection_quality(&self) -> ConnectionQuality {
106 ConnectionQuality::Excellent
107 }
108
109 pub fn audio_level(&self) -> f32 {
110 0.0
111 }
112
113 pub fn track_publications(&self) -> HashMap<TrackSid, RemoteTrackPublication> {
114 if let Some(room) = self.room.upgrade() {
115 let server = room.test_server();
116 let audio = server
117 .audio_tracks(room.token())
118 .unwrap()
119 .into_iter()
120 .filter(|track| track.publisher_id() == self.identity)
121 .map(|track| {
122 (
123 track.sid(),
124 RemoteTrackPublication {
125 sid: track.sid(),
126 room: self.room.clone(),
127 track: RemoteTrack::Audio(track),
128 },
129 )
130 });
131 let video = server
132 .video_tracks(room.token())
133 .unwrap()
134 .into_iter()
135 .filter(|track| track.publisher_id() == self.identity)
136 .map(|track| {
137 (
138 track.sid(),
139 RemoteTrackPublication {
140 sid: track.sid(),
141 room: self.room.clone(),
142 track: RemoteTrack::Video(track),
143 },
144 )
145 });
146 audio.chain(video).collect()
147 } else {
148 HashMap::default()
149 }
150 }
151
152 pub fn identity(&self) -> ParticipantIdentity {
153 self.identity.clone()
154 }
155}
156
157struct TestScreenCaptureStream;
158
159impl ScreenCaptureStream for TestScreenCaptureStream {
160 fn metadata(&self) -> Result<SourceMetadata> {
161 Ok(SourceMetadata {
162 id: 0,
163 is_main: None,
164 label: None,
165 resolution: size(DevicePixels(1), DevicePixels(1)),
166 })
167 }
168}