use {DeviceInfo, ApplicationId, SessionId, Status, Event, Error,
VolumeLevel};
use back;
use std::collections::VecDeque;
use std;
use mio;
const EVENT_QUEUE_MAXIMUM_COUNT: usize = 500;
const SENDER_ID: &'static str = "sender-0";
const RECEIVER_ID: &'static str = "sender-0";
pub struct Device
{
info: DeviceInfo,
status: Option<Status>,
connection: back::Connection,
event_queue: VecDeque<Event>,
}
impl Device
{
pub fn new(info: DeviceInfo,
connection: back::Connection) -> Self {
Device {
info: info,
connection: connection,
status: None,
event_queue: VecDeque::new(),
}
}
pub fn connect(info: DeviceInfo, io: &mut back::net::Io)
-> Result<Self, Error> {
let connection = back::Connection::connect_to(&info, io)?;
let mut device = Device::new(info, connection);
device.send_message(back::protocol::namespace::connection(),
back::protocol::MessageKind::Connect)?;
Ok(device)
}
pub fn update_status(&mut self) -> Result<(), Error> {
self.send_message(back::protocol::namespace::receiver(),
back::protocol::MessageKind::GetStatus)
}
pub fn launch(&mut self, app_id: ApplicationId) -> Result<(), Error> {
self.send_message(back::protocol::namespace::receiver(),
back::protocol::MessageKind::Launch {
app_id: app_id,
request_id: 1,
})
}
pub fn stop(&mut self, session_id: SessionId) -> Result<(), Error> {
self.send_message(back::protocol::namespace::receiver(),
back::protocol::MessageKind::Stop {
session_id: session_id,
})
}
pub fn set_volume(&mut self, level: Option<VolumeLevel>, muted: Option<bool>)
-> Result<(), Error> {
self.send_message(back::protocol::namespace::receiver(),
back::protocol::MessageKind::SetVolume {
level: level,
muted: muted,
})
}
pub fn handle_io(&mut self, event: mio::Event) -> Result<(), Error> {
self.connection.handle_event(event)?;
self.process_incoming()
}
pub fn events(&mut self) -> VecDeque<Event> {
std::mem::replace(&mut self.event_queue, VecDeque::new())
}
pub fn info(&self) -> &DeviceInfo { &self.info }
pub fn status(&self) -> Option<&Status> { self.status.as_ref() }
fn send_message(&mut self,
namespace: back::protocol::Namespace,
kind: back::protocol::MessageKind) -> Result<(), Error> {
self.connection.send(&back::protocol::Message {
source: back::protocol::EndpointName(SENDER_ID.to_owned()),
destination: back::protocol::EndpointName(RECEIVER_ID.to_owned()),
namespace: namespace,
kind: kind,
})
}
fn process_incoming(&mut self) -> Result<(), Error> {
for message in self.connection.receive()? {
match message.kind {
back::protocol::MessageKind::Ping => {
self.connection.send(&back::protocol::Message {
source: message.destination.clone(),
destination: message.source.clone(),
namespace: message.namespace.clone(),
kind: back::protocol::MessageKind::Pong,
}).expect("failed to send PONG");
},
back::protocol::MessageKind::ReceiverStatus(status) => {
self.status = Some(status);
self.add_event(Event::StatusUpdated);
},
msg => {
println!("received unimplemented message: {:?}", msg);
},
}
}
Ok(())
}
fn add_event(&mut self, event: Event) {
self.event_queue.push_back(event);
if self.event_queue.len() > EVENT_QUEUE_MAXIMUM_COUNT {
self.event_queue.drain(EVENT_QUEUE_MAXIMUM_COUNT-1..);
}
}
}