Skip to main content

gosuto_livekit/room/track/
local_track.rs

1// Copyright 2025 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::Arc;
16
17use gosuto_libwebrtc::{prelude::*, stats::RtcStats};
18use livekit_protocol as proto;
19use livekit_protocol::enum_dispatch;
20
21use super::{track_dispatch, TrackInner};
22use crate::prelude::*;
23
24#[derive(Clone, Debug)]
25pub enum LocalTrack {
26    Audio(LocalAudioTrack),
27    Video(LocalVideoTrack),
28}
29
30impl LocalTrack {
31    track_dispatch!([Audio, Video]);
32
33    enum_dispatch!(
34       [Audio, Video];
35        pub fn mute(self: &Self) -> ();
36        pub fn unmute(self: &Self) -> ();
37    );
38
39    pub fn rtc_track(&self) -> MediaStreamTrack {
40        match self {
41            Self::Audio(track) => track.rtc_track().into(),
42            Self::Video(track) => track.rtc_track().into(),
43        }
44    }
45
46    pub async fn get_stats(&self) -> RoomResult<Vec<RtcStats>> {
47        match self {
48            Self::Audio(track) => track.get_stats().await,
49            Self::Video(track) => track.get_stats().await,
50        }
51    }
52}
53
54impl From<LocalTrack> for Track {
55    fn from(track: LocalTrack) -> Self {
56        match track {
57            LocalTrack::Audio(track) => Self::LocalAudio(track),
58            LocalTrack::Video(track) => Self::LocalVideo(track),
59        }
60    }
61}
62
63impl TryFrom<Track> for LocalTrack {
64    type Error = &'static str;
65
66    fn try_from(track: Track) -> Result<Self, Self::Error> {
67        match track {
68            Track::LocalAudio(track) => Ok(Self::Audio(track)),
69            Track::LocalVideo(track) => Ok(Self::Video(track)),
70            _ => Err("not a local track"),
71        }
72    }
73}
74
75pub(super) async fn get_stats(inner: &Arc<TrackInner>) -> RoomResult<Vec<RtcStats>> {
76    let transceiver = inner.info.read().transceiver.clone();
77    let Some(transceiver) = transceiver.as_ref() else {
78        return Err(RoomError::Internal("no transceiver found for track".into()));
79    };
80
81    Ok(transceiver.sender().get_stats().await?)
82}