test_app.rs

  1use std::{sync::Arc, time::Duration};
  2
  3use futures::StreamExt;
  4use gpui::KeyBinding;
  5use live_kit_client2::{
  6    LocalAudioTrack, LocalVideoTrack, RemoteAudioTrackUpdate, RemoteVideoTrackUpdate, Room,
  7};
  8use live_kit_server::token::{self, VideoGrant};
  9use log::LevelFilter;
 10use serde_derive::Deserialize;
 11use simplelog::SimpleLogger;
 12
 13#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq, Default)]
 14struct Quit;
 15
 16fn main() {
 17    SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
 18
 19    gpui::App::production(Arc::new(())).run(|cx| {
 20        #[cfg(any(test, feature = "test-support"))]
 21        println!("USING TEST LIVEKIT");
 22
 23        #[cfg(not(any(test, feature = "test-support")))]
 24        println!("USING REAL LIVEKIT");
 25
 26        cx.activate(true);
 27
 28        cx.on_action(quit);
 29        cx.bind_keys([KeyBinding::new("cmd-q", Quit, None)]);
 30
 31        // todo!()
 32        // cx.set_menus(vec![Menu {
 33        //     name: "Zed",
 34        //     items: vec![MenuItem::Action {
 35        //         name: "Quit",
 36        //         action: Box::new(Quit),
 37        //         os_action: None,
 38        //     }],
 39        // }]);
 40
 41        let live_kit_url = std::env::var("LIVE_KIT_URL").unwrap_or("http://localhost:7880".into());
 42        let live_kit_key = std::env::var("LIVE_KIT_KEY").unwrap_or("devkey".into());
 43        let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap_or("secret".into());
 44
 45        cx.spawn(|cx| async move {
 46            let user_a_token = token::create(
 47                &live_kit_key,
 48                &live_kit_secret,
 49                Some("test-participant-1"),
 50                VideoGrant::to_join("test-room"),
 51            )
 52            .unwrap();
 53            let room_a = Room::new();
 54            room_a.connect(&live_kit_url, &user_a_token).await.unwrap();
 55
 56            let user2_token = token::create(
 57                &live_kit_key,
 58                &live_kit_secret,
 59                Some("test-participant-2"),
 60                VideoGrant::to_join("test-room"),
 61            )
 62            .unwrap();
 63            let room_b = Room::new();
 64            room_b.connect(&live_kit_url, &user2_token).await.unwrap();
 65
 66            let mut audio_track_updates = room_b.remote_audio_track_updates();
 67            let audio_track = LocalAudioTrack::create();
 68            let audio_track_publication = room_a.publish_audio_track(audio_track).await.unwrap();
 69
 70            if let RemoteAudioTrackUpdate::Subscribed(track, _) =
 71                audio_track_updates.next().await.unwrap()
 72            {
 73                let remote_tracks = room_b.remote_audio_tracks("test-participant-1");
 74                assert_eq!(remote_tracks.len(), 1);
 75                assert_eq!(remote_tracks[0].publisher_id(), "test-participant-1");
 76                assert_eq!(track.publisher_id(), "test-participant-1");
 77            } else {
 78                panic!("unexpected message");
 79            }
 80
 81            audio_track_publication.set_mute(true).await.unwrap();
 82
 83            println!("waiting for mute changed!");
 84            if let RemoteAudioTrackUpdate::MuteChanged { track_id, muted } =
 85                audio_track_updates.next().await.unwrap()
 86            {
 87                let remote_tracks = room_b.remote_audio_tracks("test-participant-1");
 88                assert_eq!(remote_tracks[0].sid(), track_id);
 89                assert_eq!(muted, true);
 90            } else {
 91                panic!("unexpected message");
 92            }
 93
 94            audio_track_publication.set_mute(false).await.unwrap();
 95
 96            if let RemoteAudioTrackUpdate::MuteChanged { track_id, muted } =
 97                audio_track_updates.next().await.unwrap()
 98            {
 99                let remote_tracks = room_b.remote_audio_tracks("test-participant-1");
100                assert_eq!(remote_tracks[0].sid(), track_id);
101                assert_eq!(muted, false);
102            } else {
103                panic!("unexpected message");
104            }
105
106            println!("Pausing for 5 seconds to test audio, make some noise!");
107            let timer = cx.background_executor().timer(Duration::from_secs(5));
108            timer.await;
109            let remote_audio_track = room_b
110                .remote_audio_tracks("test-participant-1")
111                .pop()
112                .unwrap();
113            room_a.unpublish_track(audio_track_publication);
114
115            // Clear out any active speakers changed messages
116            let mut next = audio_track_updates.next().await.unwrap();
117            while let RemoteAudioTrackUpdate::ActiveSpeakersChanged { speakers } = next {
118                println!("Speakers changed: {:?}", speakers);
119                next = audio_track_updates.next().await.unwrap();
120            }
121
122            if let RemoteAudioTrackUpdate::Unsubscribed {
123                publisher_id,
124                track_id,
125            } = next
126            {
127                assert_eq!(publisher_id, "test-participant-1");
128                assert_eq!(remote_audio_track.sid(), track_id);
129                assert_eq!(room_b.remote_audio_tracks("test-participant-1").len(), 0);
130            } else {
131                panic!("unexpected message");
132            }
133
134            let mut video_track_updates = room_b.remote_video_track_updates();
135            let displays = room_a.display_sources().await.unwrap();
136            let display = displays.into_iter().next().unwrap();
137
138            let local_video_track = LocalVideoTrack::screen_share_for_display(&display);
139            let local_video_track_publication =
140                room_a.publish_video_track(local_video_track).await.unwrap();
141
142            if let RemoteVideoTrackUpdate::Subscribed(track) =
143                video_track_updates.next().await.unwrap()
144            {
145                let remote_video_tracks = room_b.remote_video_tracks("test-participant-1");
146                assert_eq!(remote_video_tracks.len(), 1);
147                assert_eq!(remote_video_tracks[0].publisher_id(), "test-participant-1");
148                assert_eq!(track.publisher_id(), "test-participant-1");
149            } else {
150                panic!("unexpected message");
151            }
152
153            let remote_video_track = room_b
154                .remote_video_tracks("test-participant-1")
155                .pop()
156                .unwrap();
157            room_a.unpublish_track(local_video_track_publication);
158            if let RemoteVideoTrackUpdate::Unsubscribed {
159                publisher_id,
160                track_id,
161            } = video_track_updates.next().await.unwrap()
162            {
163                assert_eq!(publisher_id, "test-participant-1");
164                assert_eq!(remote_video_track.sid(), track_id);
165                assert_eq!(room_b.remote_video_tracks("test-participant-1").len(), 0);
166            } else {
167                panic!("unexpected message");
168            }
169
170            cx.update(|cx| cx.quit()).ok();
171        })
172        .detach();
173    });
174}
175
176fn quit(_: &Quit, cx: &mut gpui::AppContext) {
177    cx.quit();
178}