use super::{
AndroidAutoCommonMessage, AndroidAutoConfiguration, AndroidAutoFrame, AvChannelMessage,
ChannelHandlerTrait, ChannelId,
};
use crate::{AndroidAutoMainTrait, StreamMux, Wifi};
use protobuf::Message;
struct InnerChannelHandler {
session: Option<i32>,
}
impl InnerChannelHandler {
pub fn new() -> Self {
Self { session: None }
}
}
pub struct VideoChannelHandler {
inner: std::sync::Mutex<InnerChannelHandler>,
}
impl VideoChannelHandler {
pub fn new() -> Self {
Self {
inner: std::sync::Mutex::new(InnerChannelHandler::new()),
}
}
}
impl ChannelHandlerTrait for VideoChannelHandler {
fn build_channel<T: AndroidAutoMainTrait + ?Sized>(
&self,
_config: &AndroidAutoConfiguration,
chanid: ChannelId,
main: &T,
) -> Option<Wifi::ChannelDescriptor> {
let mut chan = Wifi::ChannelDescriptor::new();
let mut avchan = Wifi::AVChannel::new();
chan.set_channel_id(chanid as u32);
avchan.set_stream_type(Wifi::avstream_type::Enum::VIDEO);
avchan.set_available_while_in_call(true);
avchan.set_audio_type(Wifi::audio_type::Enum::SYSTEM);
let mut vconfs = Vec::new();
vconfs.push({
let mut vc = Wifi::VideoConfig::new();
let vcs = main.retrieve_video_configuration();
vc.set_video_resolution(vcs.resolution);
vc.set_video_fps(vcs.fps);
vc.set_dpi(vcs.dpi as u32);
vc.set_margin_height(0);
vc.set_margin_width(0);
if !vc.is_initialized() {
panic!();
}
vc
});
for v in vconfs {
avchan.video_configs.push(v);
}
chan.av_channel.0.replace(Box::new(avchan));
if !chan.is_initialized() {
panic!("Channel not initialized?");
}
Some(chan)
}
async fn receive_data<T: super::AndroidAutoMainTrait + ?Sized>(
&self,
msg: AndroidAutoFrame,
stream: &crate::WriteHalf,
_config: &AndroidAutoConfiguration,
main: &T,
) -> Result<(), super::FrameIoError> {
let channel = msg.header.channel_id;
let msg2: Result<AndroidAutoCommonMessage, String> = (&msg).try_into();
if let Ok(msg2) = msg2 {
match msg2 {
AndroidAutoCommonMessage::ChannelOpenResponse(_, _) => unimplemented!(),
AndroidAutoCommonMessage::ChannelOpenRequest(m) => {
log::info!("Got channel open request for video: {:?}", m);
let mut m2 = Wifi::ChannelOpenResponse::new();
m2.set_status(if main.setup_video().await.is_ok() {
Wifi::status::Enum::OK
} else {
Wifi::status::Enum::FAIL
});
stream
.write_frame(
AndroidAutoCommonMessage::ChannelOpenResponse(channel, m2).into(),
)
.await?;
}
}
return Ok(());
}
let msg2: Result<AvChannelMessage, String> = (&msg).try_into();
if let Ok(msg2) = msg2 {
match msg2 {
AvChannelMessage::AvChannelOpen(_chan, _m) => todo!(),
AvChannelMessage::MediaIndicationAck(_, _) => unimplemented!(),
AvChannelMessage::MediaIndication(_chan, time, data) => {
main.receive_video(data, time).await;
let mut m2 = Wifi::AVMediaAckIndication::new();
{
let inner = self.inner.lock().unwrap();
m2.set_session(
inner
.session
.ok_or(super::FrameSequenceError::VideoChannelNotOpen)?,
);
}
m2.set_value(1);
stream
.write_frame(AvChannelMessage::MediaIndicationAck(channel, m2).into())
.await?;
}
AvChannelMessage::SetupRequest(_chan, _m) => {
let mut m2 = Wifi::AVChannelSetupResponse::new();
m2.set_max_unacked(1);
m2.set_media_status(Wifi::avchannel_setup_status::Enum::OK);
m2.configs.push(0);
stream
.write_frame(AvChannelMessage::SetupResponse(channel, m2).into())
.await?;
main.wait_for_focus().await;
let mut m2 = Wifi::VideoFocusIndication::new();
m2.set_focus_mode(Wifi::video_focus_mode::Enum::FOCUSED);
m2.set_unrequested(false);
stream
.write_frame(AvChannelMessage::VideoIndicationResponse(channel, m2).into())
.await?;
}
AvChannelMessage::SetupResponse(_chan, _m) => unimplemented!(),
AvChannelMessage::VideoFocusRequest(_chan, m) => {
let mut m2 = Wifi::VideoFocusIndication::new();
main.set_focus(m.focus_mode() == Wifi::video_focus_mode::Enum::FOCUSED)
.await;
m2.set_focus_mode(m.focus_mode());
m2.set_unrequested(false);
stream
.write_frame(AvChannelMessage::VideoIndicationResponse(channel, m2).into())
.await?;
}
AvChannelMessage::VideoIndicationResponse(_, _) => unimplemented!(),
AvChannelMessage::StartIndication(_chan, m) => {
let mut inner = self.inner.lock().unwrap();
inner.session = Some(m.session());
}
AvChannelMessage::StopIndication(_chan, _m) => {
let mut inner = self.inner.lock().unwrap();
inner.session.take();
}
}
return Ok(());
}
todo!("{:x?}", msg);
}
}