Skip to main content

gosuto_livekit/room/publication/
local.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::{fmt::Debug, sync::Arc};
16
17use livekit_protocol::{self as proto, AudioTrackFeature};
18use parking_lot::Mutex;
19
20use super::TrackPublicationInner;
21use crate::{e2ee::EncryptionType, options::TrackPublishOptions, prelude::*};
22
23#[derive(Default)]
24struct LocalInfo {
25    publish_options: Mutex<TrackPublishOptions>,
26}
27
28#[derive(Clone)]
29pub struct LocalTrackPublication {
30    inner: Arc<TrackPublicationInner>,
31    local: Arc<LocalInfo>,
32}
33
34impl Debug for LocalTrackPublication {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        f.debug_struct("LocalTrackPublication")
37            .field("sid", &self.sid())
38            .field("name", &self.name())
39            .field("kind", &self.kind())
40            .finish()
41    }
42}
43
44impl LocalTrackPublication {
45    pub(crate) fn new(info: proto::TrackInfo, track: LocalTrack) -> Self {
46        Self {
47            inner: super::new_inner(info, Some(track.into())),
48            local: Arc::new(LocalInfo::default()),
49        }
50    }
51
52    pub(crate) fn on_muted(&self, f: impl Fn(TrackPublication) + Send + 'static) {
53        *self.inner.events.muted.lock() = Some(Box::new(f));
54    }
55
56    pub(crate) fn on_unmuted(&self, f: impl Fn(TrackPublication) + Send + 'static) {
57        *self.inner.events.unmuted.lock() = Some(Box::new(f));
58    }
59
60    pub(crate) fn set_track(&self, track: Option<Track>) {
61        super::set_track(&self.inner, &TrackPublication::Local(self.clone()), track);
62    }
63
64    pub(crate) fn proto_info(&self) -> proto::TrackInfo {
65        self.inner.info.read().proto_info.clone()
66    }
67
68    #[allow(dead_code)]
69    pub(crate) fn update_info(&self, info: proto::TrackInfo) {
70        super::update_info(&self.inner, &TrackPublication::Local(self.clone()), info);
71    }
72
73    pub(crate) fn update_publish_options(&self, opts: TrackPublishOptions) {
74        *self.local.publish_options.lock() = opts;
75    }
76
77    pub fn publish_options(&self) -> TrackPublishOptions {
78        self.local.publish_options.lock().clone()
79    }
80
81    pub fn mute(&self) {
82        if let Some(track) = self.track() {
83            track.mute();
84        }
85
86        if let Some(mute_update_needed) = self.inner.events.muted.lock().as_ref() {
87            mute_update_needed(TrackPublication::Local(self.clone()))
88        }
89    }
90
91    pub fn unmute(&self) {
92        if let Some(track) = self.track() {
93            track.unmute();
94        }
95
96        if let Some(unmute_update_needed) = self.inner.events.unmuted.lock().as_ref() {
97            unmute_update_needed(TrackPublication::Local(self.clone()))
98        }
99    }
100
101    pub fn sid(&self) -> TrackSid {
102        self.inner.info.read().sid.clone()
103    }
104
105    pub fn name(&self) -> String {
106        self.inner.info.read().name.clone()
107    }
108
109    pub fn kind(&self) -> TrackKind {
110        self.inner.info.read().kind
111    }
112
113    pub fn source(&self) -> TrackSource {
114        self.inner.info.read().source
115    }
116
117    pub fn simulcasted(&self) -> bool {
118        self.inner.info.read().simulcasted
119    }
120
121    pub fn dimension(&self) -> TrackDimension {
122        self.inner.info.read().dimension
123    }
124
125    pub fn track(&self) -> Option<LocalTrack> {
126        self.inner.info.read().track.clone().map(|track| track.try_into().unwrap())
127    }
128
129    pub fn mime_type(&self) -> String {
130        self.inner.info.read().mime_type.clone()
131    }
132
133    pub fn is_muted(&self) -> bool {
134        if let Some(track) = self.track() {
135            return track.is_muted();
136        }
137
138        self.inner.info.read().muted
139    }
140
141    pub fn is_remote(&self) -> bool {
142        false
143    }
144
145    pub fn encryption_type(&self) -> EncryptionType {
146        self.inner.info.read().encryption_type
147    }
148
149    pub fn audio_features(&self) -> Vec<AudioTrackFeature> {
150        self.inner.info.read().audio_features.clone()
151    }
152}