use std::thread;
use ipc_channel::ipc::{IpcSender, channel};
use log::{trace, warn};
use paint_api::{WebRenderExternalImageIdManager, WebRenderImageHandlerType};
use rustc_hash::FxHashMap;
use webrender_api::ExternalImageId;
use crate::{GLPlayerMsg, GLPlayerMsgForward};
pub struct GLPlayerThread {
players: FxHashMap<u64, IpcSender<GLPlayerMsgForward>>,
external_image_id_manager: WebRenderExternalImageIdManager,
}
impl GLPlayerThread {
pub fn new(external_image_id_manager: WebRenderExternalImageIdManager) -> Self {
GLPlayerThread {
players: Default::default(),
external_image_id_manager,
}
}
pub fn start(
external_image_id_manager: WebRenderExternalImageIdManager,
) -> IpcSender<GLPlayerMsg> {
let (sender, receiver) = channel().unwrap();
thread::Builder::new()
.name("GLPlayer".to_owned())
.spawn(move || {
let mut renderer = GLPlayerThread::new(external_image_id_manager);
loop {
let msg = receiver.recv().unwrap();
let exit = renderer.handle_msg(msg);
if exit {
return;
}
}
})
.expect("Thread spawning failed");
sender
}
#[inline]
fn handle_msg(&mut self, msg: GLPlayerMsg) -> bool {
trace!("processing {:?}", msg);
match msg {
GLPlayerMsg::RegisterPlayer(sender) => {
let id = self
.external_image_id_manager
.next_id(WebRenderImageHandlerType::Media);
self.players.insert(id.0, sender.clone());
sender.send(GLPlayerMsgForward::PlayerId(id.0)).unwrap();
},
GLPlayerMsg::UnregisterPlayer(id) => {
self.external_image_id_manager.remove(&ExternalImageId(id));
if self.players.remove(&id).is_none() {
warn!("Tried to remove an unknown player");
}
},
GLPlayerMsg::Lock(id, handler_sender) => {
if let Some(sender) = self.players.get(&id) {
sender.send(GLPlayerMsgForward::Lock(handler_sender)).ok();
}
},
GLPlayerMsg::Unlock(id) => {
if let Some(sender) = self.players.get(&id) {
sender.send(GLPlayerMsgForward::Unlock()).ok();
}
},
GLPlayerMsg::Exit => return true,
}
false
}
}