fcast_protocol/lib.rs
1//! # FCast Protocol
2//!
3//! Implementation of the data models documented [here](https://gitlab.futo.org/videostreaming/fcast/-/wikis/Protocol-version-3).
4
5use serde::{Deserialize, Serialize};
6
7pub mod v2;
8pub mod v3;
9
10#[derive(Debug, thiserror::Error)]
11pub enum TryFromByteError {
12 #[error("Unknown opcode: {0}")]
13 UnknownOpcode(u8),
14}
15
16#[derive(Debug, PartialEq, Copy, Clone)]
17pub enum Opcode {
18 /// Not used
19 None = 0,
20 /// Sender message to play media content, body is [`v3::PlayMessage`]
21 Play = 1,
22 /// Sender message to pause media content, no body
23 Pause = 2,
24 /// Sender message to resume media content, no body
25 Resume = 3,
26 /// Sender message to stop media content, no body
27 Stop = 4,
28 /// Sender message to seek, body is [`SeekMessage`]
29 Seek = 5,
30 /// Receiver message to notify an updated playback state, body is [`v3::PlaybackUpdateMessage`]
31 PlaybackUpdate = 6,
32 /// Receiver message to notify when the volume has changed, body is [`VolumeUpdateMessage`]
33 VolumeUpdate = 7,
34 /// Sender message to change volume, body is [`SetVolumeMessage`]
35 SetVolume = 8,
36 /// Server message to notify the sender a playback error happened, body is [`PlaybackErrorMessage`]
37 PlaybackError = 9,
38 /// Sender message to change playback speed, body is [`SetSpeedMessage`]
39 SetSpeed = 10,
40 /// Message to notify the other of the current version, body is [`VersionMessage`]
41 Version = 11,
42 /// Message to get the other party to pong, no body
43 Ping = 12,
44 /// Message to respond to a ping from the other party, no body
45 Pong = 13,
46 /// Message to notify the other party of device information and state, body is InitialSenderMessage
47 /// if receiver or [`v3::InitialReceiverMessage`] if sender
48 Initial = 14,
49 /// Receiver message to notify all senders when any device has sent a [`v3::PlayMessage`], body is
50 /// [`v3::PlayUpdateMessage`]
51 PlayUpdate = 15,
52 /// Sender message to set the item index in a playlist to play content from, body is
53 /// [`v3::SetPlaylistItemMessage`]
54 SetPlaylistItem = 16,
55 /// Sender message to subscribe to a receiver event, body is [`v3::SubscribeEventMessage`]
56 SubscribeEvent = 17,
57 /// Sender message to unsubscribe to a receiver event, body is [`v3::UnsubscribeEventMessage`]
58 UnsubscribeEvent = 18,
59 /// Receiver message to notify when a sender subscribed event has occurred, body is [`v3::EventMessage`]
60 Event = 19,
61}
62
63impl TryFrom<u8> for Opcode {
64 type Error = TryFromByteError;
65
66 fn try_from(value: u8) -> Result<Self, Self::Error> {
67 Ok(match value {
68 0 => Opcode::None,
69 1 => Opcode::Play,
70 2 => Opcode::Pause,
71 3 => Opcode::Resume,
72 4 => Opcode::Stop,
73 5 => Opcode::Seek,
74 6 => Opcode::PlaybackUpdate,
75 7 => Opcode::VolumeUpdate,
76 8 => Opcode::SetVolume,
77 9 => Opcode::PlaybackError,
78 10 => Opcode::SetSpeed,
79 11 => Opcode::Version,
80 12 => Opcode::Ping,
81 13 => Opcode::Pong,
82 14 => Opcode::Initial,
83 15 => Opcode::PlayUpdate,
84 16 => Opcode::SetPlaylistItem,
85 17 => Opcode::SubscribeEvent,
86 18 => Opcode::UnsubscribeEvent,
87 19 => Opcode::Event,
88 _ => return Err(TryFromByteError::UnknownOpcode(value)),
89 })
90 }
91}
92
93#[allow(dead_code)]
94#[derive(Deserialize, Debug)]
95pub struct PlaybackErrorMessage {
96 pub message: String,
97}
98
99#[derive(Deserialize, Serialize, Debug)]
100pub struct VersionMessage {
101 pub version: u64,
102}
103
104#[derive(Serialize, Debug)]
105pub struct SetSpeedMessage {
106 pub speed: f64,
107}
108
109#[allow(dead_code)]
110#[derive(Deserialize, Debug)]
111pub struct VolumeUpdateMessage {
112 #[serde(rename = "generationTime")]
113 pub generation_time: u64,
114 pub volume: f64, //(0-1)
115}
116
117#[derive(Serialize, Debug)]
118pub struct SetVolumeMessage {
119 pub volume: f64,
120}
121
122#[derive(Serialize, Debug)]
123pub struct SeekMessage {
124 pub time: f64,
125}