Skip to main content

gosuto_livekit/room/track/
remote_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 RemoteTrack {
26    Audio(RemoteAudioTrack),
27    Video(RemoteVideoTrack),
28}
29
30impl RemoteTrack {
31    track_dispatch!([Audio, Video]);
32
33    #[inline]
34    pub fn rtc_track(&self) -> MediaStreamTrack {
35        match self {
36            Self::Audio(track) => track.rtc_track().into(),
37            Self::Video(track) => track.rtc_track().into(),
38        }
39    }
40
41    pub async fn get_stats(&self) -> RoomResult<Vec<RtcStats>> {
42        match self {
43            Self::Audio(track) => track.get_stats().await,
44            Self::Video(track) => track.get_stats().await,
45        }
46    }
47}
48
49pub(super) async fn get_stats(inner: &Arc<TrackInner>) -> RoomResult<Vec<RtcStats>> {
50    let transceiver = inner.info.read().transceiver.clone();
51    let Some(transceiver) = transceiver.as_ref() else {
52        return Err(RoomError::Internal("no transceiver found for track".into()));
53    };
54
55    Ok(transceiver.receiver().get_stats().await?)
56}
57
58pub(super) fn update_info(inner: &Arc<TrackInner>, track: &Track, new_info: proto::TrackInfo) {
59    super::update_info(inner, track, new_info.clone());
60    super::set_muted(inner, track, new_info.muted);
61}
62
63impl From<RemoteTrack> for Track {
64    fn from(track: RemoteTrack) -> Self {
65        match track {
66            RemoteTrack::Audio(track) => Self::RemoteAudio(track),
67            RemoteTrack::Video(track) => Self::RemoteVideo(track),
68        }
69    }
70}
71
72impl TryFrom<Track> for RemoteTrack {
73    type Error = &'static str;
74
75    fn try_from(track: Track) -> Result<Self, Self::Error> {
76        match track {
77            Track::RemoteAudio(track) => Ok(Self::Audio(track)),
78            Track::RemoteVideo(track) => Ok(Self::Video(track)),
79            _ => Err("not a local track"),
80        }
81    }
82}