Add basic sound handling infrastructure
This commit is contained in:
@@ -30,6 +30,7 @@ media = { path = "../media" }
|
||||
project = { path = "../project" }
|
||||
settings = { path = "../settings" }
|
||||
util = { path = "../util" }
|
||||
rodio = "0.17.1"
|
||||
|
||||
anyhow.workspace = true
|
||||
async-broadcast = "0.4"
|
||||
|
||||
+11
-3
@@ -1,24 +1,32 @@
|
||||
mod assets;
|
||||
pub mod participant;
|
||||
pub mod room;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use assets::SoundRegistry;
|
||||
use client::{proto, Client, TypedEnvelope, User, UserStore};
|
||||
use collections::HashSet;
|
||||
use futures::{future::Shared, FutureExt};
|
||||
use postage::watch;
|
||||
|
||||
use gpui::{
|
||||
AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription, Task,
|
||||
WeakModelHandle,
|
||||
AppContext, AssetSource, AsyncAppContext, Entity, ModelContext, ModelHandle, Subscription,
|
||||
Task, WeakModelHandle,
|
||||
};
|
||||
use project::Project;
|
||||
|
||||
pub use participant::ParticipantLocation;
|
||||
pub use room::Room;
|
||||
|
||||
pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut AppContext) {
|
||||
pub fn init(
|
||||
client: Arc<Client>,
|
||||
user_store: ModelHandle<UserStore>,
|
||||
source: impl AssetSource,
|
||||
cx: &mut AppContext,
|
||||
) {
|
||||
cx.set_global(SoundRegistry::new(source));
|
||||
let active_call = cx.add_model(|cx| ActiveCall::new(client, user_store, cx));
|
||||
cx.set_global(active_call);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::{
|
||||
assets::SoundRegistry,
|
||||
participant::{LocalParticipant, ParticipantLocation, RemoteParticipant, RemoteVideoTrack},
|
||||
IncomingCall,
|
||||
};
|
||||
@@ -18,11 +19,30 @@ use live_kit_client::{
|
||||
};
|
||||
use postage::stream::Stream;
|
||||
use project::Project;
|
||||
use rodio::{OutputStream, OutputStreamHandle, Source};
|
||||
use std::{future::Future, mem, pin::Pin, sync::Arc, time::Duration};
|
||||
use util::{post_inc, ResultExt, TryFutureExt};
|
||||
|
||||
pub const RECONNECT_TIMEOUT: Duration = Duration::from_secs(30);
|
||||
|
||||
enum Sound {
|
||||
Joined,
|
||||
Leaved,
|
||||
Mute,
|
||||
Unmute,
|
||||
}
|
||||
|
||||
impl Sound {
|
||||
fn file(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Joined => "joined",
|
||||
Self::Leaved => "leave",
|
||||
Self::Mute => "mute",
|
||||
Self::Unmute => "unmute",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Event {
|
||||
ParticipantLocationChanged {
|
||||
@@ -48,6 +68,8 @@ pub enum Event {
|
||||
pub struct Room {
|
||||
id: u64,
|
||||
live_kit: Option<LiveKitRoom>,
|
||||
_sound_output_stream: Option<OutputStream>,
|
||||
sound_output_handle: Option<OutputStreamHandle>,
|
||||
status: RoomStatus,
|
||||
shared_projects: HashSet<WeakModelHandle<Project>>,
|
||||
joined_projects: HashSet<WeakModelHandle<Project>>,
|
||||
@@ -176,9 +198,14 @@ impl Room {
|
||||
let maintain_connection =
|
||||
cx.spawn_weak(|this, cx| Self::maintain_connection(this, client.clone(), cx).log_err());
|
||||
|
||||
let (sound_output_stream, sound_output_handle) =
|
||||
OutputStream::try_default().log_err().unzip();
|
||||
|
||||
Self {
|
||||
id,
|
||||
live_kit: live_kit_room,
|
||||
_sound_output_stream: sound_output_stream,
|
||||
sound_output_handle,
|
||||
status: RoomStatus::Online,
|
||||
shared_projects: Default::default(),
|
||||
joined_projects: Default::default(),
|
||||
@@ -910,6 +937,18 @@ impl Room {
|
||||
})
|
||||
}
|
||||
|
||||
fn play_sound(&self, sound: Sound, cx: &AppContext) {
|
||||
let Some(output_handle) = self.sound_output_handle.as_ref() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(source) = SoundRegistry::global(cx).get(sound.file()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
output_handle.play_raw(source.convert_samples()).log_err();
|
||||
}
|
||||
|
||||
pub fn join_project(
|
||||
&mut self,
|
||||
id: u64,
|
||||
@@ -922,6 +961,9 @@ impl Room {
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let project =
|
||||
Project::remote(id, client, user_store, language_registry, fs, cx.clone()).await?;
|
||||
|
||||
cx.read(|cx| this.read(cx).play_sound(Sound::Joined, cx));
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.joined_projects.retain(|project| {
|
||||
if let Some(project) = project.upgrade(cx) {
|
||||
|
||||
@@ -203,7 +203,7 @@ impl TestServer {
|
||||
language::init(cx);
|
||||
editor::init_settings(cx);
|
||||
workspace::init(app_state.clone(), cx);
|
||||
call::init(client.clone(), user_store.clone(), cx);
|
||||
call::init(client.clone(), user_store.clone(), (), cx);
|
||||
});
|
||||
|
||||
client
|
||||
|
||||
@@ -7,6 +7,7 @@ use rust_embed::RustEmbed;
|
||||
#[include = "fonts/**/*"]
|
||||
#[include = "icons/**/*"]
|
||||
#[include = "themes/**/*"]
|
||||
#[include = "sounds/**/*"]
|
||||
#[include = "*.md"]
|
||||
#[exclude = "*.DS_Store"]
|
||||
pub struct Assets;
|
||||
|
||||
@@ -190,7 +190,7 @@ fn main() {
|
||||
theme_selector::init(cx);
|
||||
activity_indicator::init(cx);
|
||||
language_tools::init(cx);
|
||||
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||
call::init(app_state.client.clone(), app_state.user_store.clone(), Assets, cx);
|
||||
collab_ui::init(&app_state, cx);
|
||||
feedback::init(cx);
|
||||
welcome::init(cx);
|
||||
|
||||
@@ -2160,7 +2160,7 @@ mod tests {
|
||||
state.initialize_workspace = initialize_workspace;
|
||||
state.build_window_options = build_window_options;
|
||||
theme::init((), cx);
|
||||
call::init(app_state.client.clone(), app_state.user_store.clone(), cx);
|
||||
call::init(app_state.client.clone(), app_state.user_store.clone(), (), cx);
|
||||
workspace::init(app_state.clone(), cx);
|
||||
Project::init_settings(cx);
|
||||
language::init(cx);
|
||||
|
||||
Reference in New Issue
Block a user