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}