participant.rs

 1use anyhow::{Context as _, Result};
 2use client::{ParticipantIndex, User, proto};
 3use collections::HashMap;
 4use gpui::WeakEntity;
 5use livekit_client::AudioStream;
 6use project::Project;
 7use std::sync::Arc;
 8
 9pub use livekit_client::TrackSid;
10pub use livekit_client::{RemoteAudioTrack, RemoteVideoTrack};
11
12#[derive(Copy, Clone, Debug, Eq, PartialEq)]
13pub enum ParticipantLocation {
14    SharedProject { project_id: u64 },
15    UnsharedProject,
16    External,
17}
18
19impl ParticipantLocation {
20    pub fn from_proto(location: Option<proto::ParticipantLocation>) -> Result<Self> {
21        match location
22            .and_then(|l| l.variant)
23            .context("participant location was not provided")?
24        {
25            proto::participant_location::Variant::SharedProject(project) => {
26                Ok(Self::SharedProject {
27                    project_id: project.id,
28                })
29            }
30            proto::participant_location::Variant::UnsharedProject(_) => Ok(Self::UnsharedProject),
31            proto::participant_location::Variant::External(_) => Ok(Self::External),
32        }
33    }
34}
35
36#[derive(Clone, Default)]
37pub struct LocalParticipant {
38    pub projects: Vec<proto::ParticipantProject>,
39    pub active_project: Option<WeakEntity<Project>>,
40    pub role: proto::ChannelRole,
41}
42
43impl LocalParticipant {
44    pub const fn can_write(&self) -> bool {
45        matches!(
46            self.role,
47            proto::ChannelRole::Admin | proto::ChannelRole::Member
48        )
49    }
50}
51
52pub struct RemoteParticipant {
53    pub user: Arc<User>,
54    pub peer_id: proto::PeerId,
55    pub role: proto::ChannelRole,
56    pub projects: Vec<proto::ParticipantProject>,
57    pub location: ParticipantLocation,
58    pub participant_index: ParticipantIndex,
59    pub muted: bool,
60    pub speaking: bool,
61    pub video_tracks: HashMap<TrackSid, RemoteVideoTrack>,
62    pub audio_tracks: HashMap<TrackSid, (RemoteAudioTrack, AudioStream)>,
63}
64
65impl RemoteParticipant {
66    pub fn has_video_tracks(&self) -> bool {
67        !self.video_tracks.is_empty()
68    }
69
70    pub const fn can_write(&self) -> bool {
71        matches!(
72            self.role,
73            proto::ChannelRole::Admin | proto::ChannelRole::Member
74        )
75    }
76}