main.rs

  1mod live_kit_token;
  2
  3use futures::StreamExt;
  4use gpui::{
  5    actions,
  6    elements::{Canvas, *},
  7    keymap::Binding,
  8    platform::current::Surface,
  9    Menu, MenuItem, ViewContext,
 10};
 11use live_kit::{LocalVideoTrack, Room};
 12use log::LevelFilter;
 13use media::core_video::CVImageBuffer;
 14use simplelog::SimpleLogger;
 15use std::sync::Arc;
 16
 17actions!(capture, [Quit]);
 18
 19fn main() {
 20    SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
 21
 22    gpui::App::new(()).unwrap().run(|cx| {
 23        cx.platform().activate(true);
 24        cx.add_global_action(quit);
 25
 26        cx.add_bindings([Binding::new("cmd-q", Quit, None)]);
 27        cx.set_menus(vec![Menu {
 28            name: "Zed",
 29            items: vec![MenuItem::Action {
 30                name: "Quit",
 31                action: Box::new(Quit),
 32            }],
 33        }]);
 34
 35        let live_kit_url = std::env::var("LIVE_KIT_URL").unwrap();
 36        let live_kit_key = std::env::var("LIVE_KIT_KEY").unwrap();
 37        let live_kit_secret = std::env::var("LIVE_KIT_SECRET").unwrap();
 38
 39        cx.spawn(|mut cx| async move {
 40            let user1_token = live_kit_token::create_token(
 41                &live_kit_key,
 42                &live_kit_secret,
 43                "test-room",
 44                "test-participant-1",
 45            )
 46            .unwrap();
 47            let room1 = Room::new();
 48            room1.connect(&live_kit_url, &user1_token).await.unwrap();
 49
 50            let user2_token = live_kit_token::create_token(
 51                &live_kit_key,
 52                &live_kit_secret,
 53                "test-room",
 54                "test-participant-2",
 55            )
 56            .unwrap();
 57            let room2 = Room::new();
 58            room2.connect(&live_kit_url, &user2_token).await.unwrap();
 59            cx.add_window(Default::default(), |cx| ScreenCaptureView::new(room2, cx));
 60
 61            let windows = live_kit::list_windows();
 62            let window = windows
 63                .iter()
 64                .find(|w| w.owner_name.as_deref() == Some("Safari"))
 65                .unwrap();
 66            let track = LocalVideoTrack::screen_share_for_window(window.id);
 67            room1.publish_video_track(&track).await.unwrap();
 68
 69            std::mem::forget(track);
 70            std::mem::forget(room1);
 71        })
 72        .detach();
 73    });
 74}
 75
 76struct ScreenCaptureView {
 77    image_buffer: Option<CVImageBuffer>,
 78    _room: Arc<Room>,
 79}
 80
 81impl gpui::Entity for ScreenCaptureView {
 82    type Event = ();
 83}
 84
 85impl ScreenCaptureView {
 86    pub fn new(room: Arc<Room>, cx: &mut ViewContext<Self>) -> Self {
 87        let mut remote_video_tracks = room.remote_video_tracks();
 88        cx.spawn_weak(|this, mut cx| async move {
 89            if let Some(video_track) = remote_video_tracks.next().await {
 90                video_track.add_renderer(move |frame| {
 91                    if let Some(this) = this.upgrade(&cx) {
 92                        this.update(&mut cx, |this, cx| {
 93                            this.image_buffer = Some(frame);
 94                            cx.notify();
 95                        });
 96                    }
 97                });
 98            }
 99        })
100        .detach();
101        Self {
102            image_buffer: None,
103            _room: room,
104        }
105    }
106}
107
108impl gpui::View for ScreenCaptureView {
109    fn ui_name() -> &'static str {
110        "View"
111    }
112
113    fn render(&mut self, _: &mut gpui::RenderContext<Self>) -> gpui::ElementBox {
114        let image_buffer = self.image_buffer.clone();
115        Canvas::new(move |bounds, _, cx| {
116            if let Some(image_buffer) = image_buffer.clone() {
117                cx.scene.push_surface(Surface {
118                    bounds,
119                    image_buffer,
120                });
121            }
122        })
123        .boxed()
124    }
125}
126
127fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) {
128    cx.platform().quit();
129}