Skip to main content

gosuto_livekit/room/track/
local_audio_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 core::panic;
16use std::{fmt::Debug, sync::Arc};
17
18use gosuto_libwebrtc::{prelude::*, stats::RtcStats};
19use livekit_protocol as proto;
20
21use super::TrackInner;
22use crate::{prelude::*, rtc_engine::lk_runtime::LkRuntime};
23
24#[derive(Clone)]
25pub struct LocalAudioTrack {
26    inner: Arc<TrackInner>,
27    source: RtcAudioSource,
28}
29
30impl Debug for LocalAudioTrack {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        f.debug_struct("LocalAudioTrack")
33            .field("sid", &self.sid())
34            .field("name", &self.name())
35            .field("source", &self.source())
36            .finish()
37    }
38}
39
40impl LocalAudioTrack {
41    pub(crate) fn new(name: String, rtc_track: RtcAudioTrack, source: RtcAudioSource) -> Self {
42        Self {
43            inner: Arc::new(super::new_inner(
44                "TR_unknown".to_owned().try_into().unwrap(),
45                name,
46                TrackKind::Audio,
47                MediaStreamTrack::Audio(rtc_track),
48            )),
49            source,
50        }
51    }
52
53    pub fn create_audio_track(name: &str, source: RtcAudioSource) -> LocalAudioTrack {
54        let rtc_track = match source.clone() {
55            #[cfg(not(target_arch = "wasm32"))]
56            RtcAudioSource::Native(native_source) => {
57                use gosuto_libwebrtc::peer_connection_factory::native::PeerConnectionFactoryExt;
58                LkRuntime::instance()
59                    .pc_factory()
60                    .create_audio_track(&gosuto_libwebrtc::native::create_random_uuid(), native_source)
61            }
62            _ => panic!("unsupported audio source"),
63        };
64        Self::new(name.to_string(), rtc_track, source)
65    }
66
67    pub fn sid(&self) -> TrackSid {
68        self.inner.info.read().sid.clone()
69    }
70
71    pub fn name(&self) -> String {
72        self.inner.info.read().name.clone()
73    }
74
75    pub fn kind(&self) -> TrackKind {
76        self.inner.info.read().kind
77    }
78
79    pub fn source(&self) -> TrackSource {
80        self.inner.info.read().source
81    }
82
83    pub fn stream_state(&self) -> StreamState {
84        self.inner.info.read().stream_state
85    }
86
87    pub fn is_enabled(&self) -> bool {
88        self.inner.rtc_track.enabled()
89    }
90
91    pub fn enable(&self) {
92        self.inner.rtc_track.set_enabled(true);
93    }
94
95    pub fn disable(&self) {
96        self.inner.rtc_track.set_enabled(false);
97    }
98
99    pub fn is_muted(&self) -> bool {
100        self.inner.info.read().muted
101    }
102
103    pub fn mute(&self) {
104        super::set_muted(&self.inner, &Track::LocalAudio(self.clone()), true);
105    }
106
107    pub fn unmute(&self) {
108        super::set_muted(&self.inner, &Track::LocalAudio(self.clone()), false);
109    }
110
111    pub fn rtc_track(&self) -> RtcAudioTrack {
112        if let MediaStreamTrack::Audio(audio) = self.inner.rtc_track.clone() {
113            return audio;
114        }
115        unreachable!();
116    }
117
118    pub fn rtc_source(&self) -> RtcAudioSource {
119        self.source.clone()
120    }
121
122    pub fn is_remote(&self) -> bool {
123        false
124    }
125
126    pub async fn get_stats(&self) -> RoomResult<Vec<RtcStats>> {
127        super::local_track::get_stats(&self.inner).await
128    }
129
130    pub(crate) fn on_muted(&self, f: impl Fn(Track) + Send + 'static) {
131        self.inner.events.lock().muted.replace(Box::new(f));
132    }
133
134    pub(crate) fn on_unmuted(&self, f: impl Fn(Track) + Send + 'static) {
135        self.inner.events.lock().unmuted.replace(Box::new(f));
136    }
137
138    pub(crate) fn transceiver(&self) -> Option<RtpTransceiver> {
139        self.inner.info.read().transceiver.clone()
140    }
141
142    pub(crate) fn set_transceiver(&self, transceiver: Option<RtpTransceiver>) {
143        self.inner.info.write().transceiver = transceiver;
144    }
145
146    pub(crate) fn update_info(&self, info: proto::TrackInfo) {
147        super::update_info(&self.inner, &Track::LocalAudio(self.clone()), info);
148    }
149}