1pub mod stream;
4
5pub use self::stream::Stream;
6use crate::protocol::{self, command, Command as CommandTrait, ReadFromBytes, WriteToBytes};
7use byteorder;
8use std::error::Error;
9use std::{fmt, io, ops};
10
11#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
16pub struct Addressed {
17 pub mac_address: MacAddress,
21 pub dac: Dac,
23}
24
25#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
30pub struct Dac {
31 pub hw_revision: u16,
34 pub sw_revision: u16,
38 pub buffer_capacity: u16,
40 pub max_point_rate: u32,
42 pub status: Status,
46}
47
48#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
55pub struct MacAddress(pub [u8; 6]);
56
57#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
61pub struct Status {
62 pub protocol: u8,
66 pub light_engine: LightEngine,
68 pub playback: Playback,
70 pub data_source: DataSource,
72 pub light_engine_flags: LightEngineFlags,
74 pub playback_flags: PlaybackFlags,
76 pub buffer_fullness: u16,
78 pub point_rate: u32,
83 pub point_count: u32,
88}
89
90#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
93pub enum LightEngine {
94 Ready,
95 Warmup,
98 Cooldown,
100 EmergencyStop,
103}
104
105#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
111pub enum Playback {
112 Idle,
119 Prepared,
123 Playing,
125}
126
127#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
129pub enum DataSource {
130 NetworkStreaming,
132 IldaPlayback(IldaPlaybackFlags),
134 InternalAbstractGenerator(InternalAbstractGeneratorFlags),
136}
137
138bitflags! {
139 pub struct LightEngineFlags: u16 {
141 const EMERGENCY_STOP_PACKET_OR_INVALID_COMMAND = 0b00000001;
142 const EMERGENCY_STOP_PROJECTOR_INPUT = 0b00000010;
143 const EMERGENCY_STOP_PROJECTOR_INPUT_ACTIVE = 0b00000100;
144 const EMERGENCY_STOP_OVER_TEMPERATURE = 0b00001000;
145 const EMERGENCY_STOP_OVER_TEMPERATURE_ACTIVE = 0b00010000;
146 const EMERGENCY_STOP_LOST_ETHERNET_LINK = 0b00100000;
147 }
148}
149
150bitflags! {
151 pub struct PlaybackFlags: u16 {
153 const SHUTTER_OPEN = 0b00000001;
155 const UNDERFLOWED = 0b00000010;
157 const EMERGENCY_STOP = 0b00000100;
161 }
162}
163
164bitflags! {
165 pub struct IldaPlaybackFlags: u16 {
167 const PLAYING = 0b0;
168 const REPEAT = 0b1;
169 }
170}
171
172bitflags! {
173 pub struct InternalAbstractGeneratorFlags: u16 {
175 const PLAYING = 0;
176 }
177}
178
179bitflags! {
180 pub struct PointControl: u16 {
182 const CHANGE_RATE = 0b10000000_00000000;
187 }
188}
189
190#[derive(Clone, Debug, PartialEq, Eq, Hash)]
196pub enum Command<'a> {
197 PrepareStream(command::PrepareStream),
198 Begin(command::Begin),
199 PointRate(command::PointRate),
200 Data(command::Data<'a>),
201 Stop(command::Stop),
202 EmergencyStop(command::EmergencyStop),
203 ClearEmergencyStop(command::ClearEmergencyStop),
204 Ping(command::Ping),
205}
206
207#[derive(Debug)]
209pub enum ProtocolError {
210 UnknownLightEngineState,
211 UnknownPlaybackState,
212 UnknownDataSource,
213}
214
215impl Addressed {
216 pub fn from_broadcast(dac_broadcast: &protocol::DacBroadcast) -> Result<Self, ProtocolError> {
218 let protocol::DacBroadcast {
219 mac_address,
220 hw_revision,
221 sw_revision,
222 buffer_capacity,
223 max_point_rate,
224 dac_status,
225 } = *dac_broadcast;
226 let mac_address = MacAddress(mac_address);
227 let status = Status::from_protocol(&dac_status)?;
228 let dac = Dac {
229 hw_revision,
230 sw_revision,
231 buffer_capacity,
232 max_point_rate,
233 status,
234 };
235 let addressed = Addressed { mac_address, dac };
236 Ok(addressed)
237 }
238}
239
240impl Dac {
241 pub fn update_status(&mut self, status: &protocol::DacStatus) -> Result<(), ProtocolError> {
243 self.status.update(status)
244 }
245}
246
247impl Status {
248 pub fn from_protocol(status: &protocol::DacStatus) -> Result<Self, ProtocolError> {
250 let protocol = status.protocol;
251 let light_engine = LightEngine::from_protocol(status.light_engine_state)
252 .ok_or(ProtocolError::UnknownLightEngineState)?;
253 let playback = Playback::from_protocol(status.playback_state)
254 .ok_or(ProtocolError::UnknownPlaybackState)?;
255 let data_source = DataSource::from_protocol(status.source, status.source_flags)
256 .ok_or(ProtocolError::UnknownDataSource)?;
257 let light_engine_flags = LightEngineFlags::from_bits_truncate(status.light_engine_flags);
258 let playback_flags = PlaybackFlags::from_bits_truncate(status.playback_flags);
259 let buffer_fullness = status.buffer_fullness;
260 let point_rate = status.point_rate;
261 let point_count = status.point_count;
262 Ok(Status {
263 protocol,
264 light_engine,
265 playback,
266 data_source,
267 light_engine_flags,
268 playback_flags,
269 buffer_fullness,
270 point_rate,
271 point_count,
272 })
273 }
274
275 pub fn update(&mut self, status: &protocol::DacStatus) -> Result<(), ProtocolError> {
277 self.protocol = status.protocol;
278 self.light_engine = LightEngine::from_protocol(status.light_engine_state)
279 .ok_or(ProtocolError::UnknownLightEngineState)?;
280 self.playback = Playback::from_protocol(status.playback_state)
281 .ok_or(ProtocolError::UnknownPlaybackState)?;
282 self.data_source = DataSource::from_protocol(status.source, status.source_flags)
283 .ok_or(ProtocolError::UnknownDataSource)?;
284 self.light_engine_flags = LightEngineFlags::from_bits_truncate(status.light_engine_flags);
285 self.playback_flags = PlaybackFlags::from_bits_truncate(status.playback_flags);
286 self.buffer_fullness = status.buffer_fullness;
287 self.point_rate = status.point_rate;
288 self.point_count = status.point_count;
289 Ok(())
290 }
291
292 pub fn to_protocol(&self) -> protocol::DacStatus {
294 let protocol = self.protocol;
295 let light_engine_state = self.light_engine.to_protocol();
296 let playback_state = self.playback.to_protocol();
297 let (source, source_flags) = self.data_source.to_protocol();
298 let light_engine_flags = self.light_engine_flags.bits();
299 let playback_flags = self.playback_flags.bits();
300 let buffer_fullness = self.buffer_fullness;
301 let point_rate = self.point_rate;
302 let point_count = self.point_count;
303 protocol::DacStatus {
304 protocol,
305 light_engine_state,
306 playback_state,
307 source,
308 light_engine_flags,
309 playback_flags,
310 source_flags,
311 buffer_fullness,
312 point_rate,
313 point_count,
314 }
315 }
316}
317
318impl LightEngine {
319 pub fn from_protocol(state: u8) -> Option<Self> {
323 let light_engine = match state {
324 protocol::DacStatus::LIGHT_ENGINE_READY => LightEngine::Ready,
325 protocol::DacStatus::LIGHT_ENGINE_WARMUP => LightEngine::Warmup,
326 protocol::DacStatus::LIGHT_ENGINE_COOLDOWN => LightEngine::Cooldown,
327 protocol::DacStatus::LIGHT_ENGINE_EMERGENCY_STOP => LightEngine::EmergencyStop,
328 _ => return None,
329 };
330 Some(light_engine)
331 }
332
333 pub fn to_protocol(&self) -> u8 {
335 match *self {
336 LightEngine::Ready => protocol::DacStatus::LIGHT_ENGINE_READY,
337 LightEngine::Warmup => protocol::DacStatus::LIGHT_ENGINE_WARMUP,
338 LightEngine::Cooldown => protocol::DacStatus::LIGHT_ENGINE_COOLDOWN,
339 LightEngine::EmergencyStop => protocol::DacStatus::LIGHT_ENGINE_EMERGENCY_STOP,
340 }
341 }
342}
343
344impl Playback {
345 pub fn from_protocol(state: u8) -> Option<Self> {
349 let playback = match state {
350 protocol::DacStatus::PLAYBACK_IDLE => Playback::Idle,
351 protocol::DacStatus::PLAYBACK_PREPARED => Playback::Prepared,
352 protocol::DacStatus::PLAYBACK_PLAYING => Playback::Playing,
353 _ => return None,
354 };
355 Some(playback)
356 }
357
358 pub fn to_protocol(&self) -> u8 {
360 match *self {
361 Playback::Idle => protocol::DacStatus::PLAYBACK_IDLE,
362 Playback::Prepared => protocol::DacStatus::PLAYBACK_PREPARED,
363 Playback::Playing => protocol::DacStatus::PLAYBACK_PLAYING,
364 }
365 }
366}
367
368impl DataSource {
369 pub fn from_protocol(source: u8, flags: u16) -> Option<Self> {
373 match source {
374 protocol::DacStatus::SOURCE_NETWORK_STREAMING => Some(DataSource::NetworkStreaming),
375 protocol::DacStatus::SOURCE_ILDA_PLAYBACK_SD => {
376 Some(IldaPlaybackFlags::from_bits_truncate(flags)).map(DataSource::IldaPlayback)
377 }
378 protocol::DacStatus::SOURCE_INTERNAL_ABSTRACT_GENERATOR => {
379 Some(InternalAbstractGeneratorFlags::from_bits_truncate(flags))
380 .map(DataSource::InternalAbstractGenerator)
381 }
382 _ => None,
383 }
384 }
385
386 pub fn to_protocol(&self) -> (u8, u16) {
390 match *self {
391 DataSource::NetworkStreaming => (protocol::DacStatus::SOURCE_NETWORK_STREAMING, 0),
392 DataSource::IldaPlayback(ref flags) => {
393 (protocol::DacStatus::SOURCE_ILDA_PLAYBACK_SD, flags.bits())
394 }
395 DataSource::InternalAbstractGenerator(ref flags) => (
396 protocol::DacStatus::SOURCE_INTERNAL_ABSTRACT_GENERATOR,
397 flags.bits(),
398 ),
399 }
400 }
401}
402
403impl ops::Deref for Addressed {
404 type Target = Dac;
405 fn deref(&self) -> &Self::Target {
406 &self.dac
407 }
408}
409
410impl ops::DerefMut for Addressed {
411 fn deref_mut(&mut self) -> &mut Self::Target {
412 &mut self.dac
413 }
414}
415
416impl From<[u8; 6]> for MacAddress {
417 fn from(bytes: [u8; 6]) -> Self {
418 MacAddress(bytes)
419 }
420}
421
422impl Into<[u8; 6]> for MacAddress {
423 fn into(self) -> [u8; 6] {
424 self.0
425 }
426}
427
428impl ops::Deref for MacAddress {
429 type Target = [u8; 6];
430 fn deref(&self) -> &Self::Target {
431 &self.0
432 }
433}
434
435impl fmt::Display for MacAddress {
436 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
437 let a = &self.0;
438 write!(
439 f,
440 "{:X}:{:X}:{:X}:{:X}:{:X}:{:X}",
441 a[0], a[1], a[2], a[3], a[4], a[5]
442 )
443 }
444}
445
446impl ReadFromBytes for Command<'static> {
447 fn read_from_bytes<R: byteorder::ReadBytesExt>(mut reader: R) -> io::Result<Self> {
448 let command = reader.read_u8()?;
449 let kind = match command {
450 command::PrepareStream::START_BYTE => command::PrepareStream.into(),
451 command::Begin::START_BYTE => command::Begin::read_fields(reader)?.into(),
452 command::PointRate::START_BYTE => command::PointRate::read_fields(reader)?.into(),
453 command::Data::START_BYTE => command::Data::read_fields(reader)?.into(),
454 command::Stop::START_BYTE => command::Stop.into(),
455 command::EmergencyStop::START_BYTE => command::EmergencyStop.into(),
456 command::EmergencyStopAlt::START_BYTE => command::EmergencyStop.into(),
457 command::ClearEmergencyStop::START_BYTE => command::ClearEmergencyStop.into(),
458 command::Ping::START_BYTE => command::Ping.into(),
459 unknown => {
460 let err_msg = format!("invalid command byte \"{}\"", unknown);
461 return Err(io::Error::new(io::ErrorKind::InvalidData, err_msg));
462 }
463 };
464 Ok(kind)
465 }
466}
467
468impl<'a> WriteToBytes for Command<'a> {
469 fn write_to_bytes<W: byteorder::WriteBytesExt>(&self, writer: W) -> io::Result<()> {
470 match *self {
471 Command::PrepareStream(ref cmd) => cmd.write_to_bytes(writer),
472 Command::Begin(ref cmd) => cmd.write_to_bytes(writer),
473 Command::PointRate(ref cmd) => cmd.write_to_bytes(writer),
474 Command::Data(ref cmd) => cmd.write_to_bytes(writer),
475 Command::Stop(ref cmd) => cmd.write_to_bytes(writer),
476 Command::EmergencyStop(ref cmd) => cmd.write_to_bytes(writer),
477 Command::ClearEmergencyStop(ref cmd) => cmd.write_to_bytes(writer),
478 Command::Ping(ref cmd) => cmd.write_to_bytes(writer),
479 }
480 }
481}
482
483impl<'a> From<command::PrepareStream> for Command<'a> {
484 fn from(command: command::PrepareStream) -> Self {
485 Command::PrepareStream(command)
486 }
487}
488
489impl<'a> From<command::Begin> for Command<'a> {
490 fn from(command: command::Begin) -> Self {
491 Command::Begin(command)
492 }
493}
494
495impl<'a> From<command::PointRate> for Command<'a> {
496 fn from(command: command::PointRate) -> Self {
497 Command::PointRate(command)
498 }
499}
500
501impl<'a> From<command::Data<'a>> for Command<'a> {
502 fn from(command: command::Data<'a>) -> Self {
503 Command::Data(command)
504 }
505}
506
507impl<'a> From<command::Stop> for Command<'a> {
508 fn from(command: command::Stop) -> Self {
509 Command::Stop(command)
510 }
511}
512
513impl<'a> From<command::EmergencyStop> for Command<'a> {
514 fn from(command: command::EmergencyStop) -> Self {
515 Command::EmergencyStop(command)
516 }
517}
518
519impl<'a> From<command::EmergencyStopAlt> for Command<'a> {
520 fn from(_: command::EmergencyStopAlt) -> Self {
521 Command::EmergencyStop(command::EmergencyStop)
522 }
523}
524
525impl<'a> From<command::ClearEmergencyStop> for Command<'a> {
526 fn from(command: command::ClearEmergencyStop) -> Self {
527 Command::ClearEmergencyStop(command)
528 }
529}
530
531impl<'a> From<command::Ping> for Command<'a> {
532 fn from(command: command::Ping) -> Self {
533 Command::Ping(command)
534 }
535}
536
537impl fmt::Display for ProtocolError {
538 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
539 let s = match *self {
540 ProtocolError::UnknownLightEngineState => "unknown light engine state",
541 ProtocolError::UnknownPlaybackState => "unknown playback state",
542 ProtocolError::UnknownDataSource => "unknown data source",
543 };
544 write!(f, "{}", s)
545 }
546}
547
548impl Error for ProtocolError {}