pulseaudio/protocol/command/
upload_stream.rs

1use crate::protocol::{serde::*, ProtocolError};
2use crate::protocol::{ChannelMap, Props, SampleSpec};
3
4use std::ffi::CString;
5
6use super::CommandReply;
7
8/// Parameters for [`super::Command::CreateUploadStream`].
9#[derive(Default, Debug, Clone, Eq, PartialEq)]
10pub struct UploadStreamParams {
11    /// Name of the sample.
12    pub media_name: Option<CString>,
13
14    /// Sample format for the stream.
15    pub sample_spec: SampleSpec,
16
17    /// Channel map for the stream.
18    pub channel_map: ChannelMap,
19
20    /// Length of the sample in bytes.
21    pub length: u32,
22
23    /// Additional properties for the stream.
24    pub props: Props,
25}
26
27impl TagStructRead for UploadStreamParams {
28    fn read(ts: &mut TagStructReader<'_>, _protocol_version: u16) -> Result<Self, ProtocolError> {
29        Ok(Self {
30            media_name: ts.read_string()?,
31            sample_spec: ts.read()?,
32            channel_map: ts.read()?,
33            length: ts.read_u32()?,
34            props: ts.read()?,
35        })
36    }
37}
38
39impl TagStructWrite for UploadStreamParams {
40    fn write(
41        &self,
42        ts: &mut TagStructWriter<'_>,
43        _protocol_version: u16,
44    ) -> Result<(), ProtocolError> {
45        ts.write_string(self.media_name.as_ref())?;
46        ts.write(self.sample_spec)?;
47        ts.write(self.channel_map)?;
48        ts.write_u32(self.length)?;
49        ts.write(&self.props)?;
50        Ok(())
51    }
52}
53
54/// The server response to [`super::Command::CreateUploadStream`].
55#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
56pub struct CreateUploadStreamReply {
57    /// Channel ID, which is used in other commands to refer to this stream.
58    /// Unlike the stream index, it is scoped to the connection.
59    pub channel: u32,
60
61    /// The length of the sample in bytes.
62    pub length: u32,
63}
64
65impl CommandReply for CreateUploadStreamReply {}
66
67impl TagStructRead for CreateUploadStreamReply {
68    fn read(ts: &mut TagStructReader<'_>, _protocol_version: u16) -> Result<Self, ProtocolError> {
69        let reply = Self {
70            channel: ts.read_u32()?,
71            length: ts.read_u32()?,
72        };
73
74        Ok(reply)
75    }
76}
77
78impl TagStructWrite for CreateUploadStreamReply {
79    fn write(
80        &self,
81        w: &mut TagStructWriter<'_>,
82        _protocol_version: u16,
83    ) -> Result<(), ProtocolError> {
84        w.write_u32(self.channel)?;
85        w.write_u32(self.length)?;
86        Ok(())
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use crate::protocol::test_util::test_serde;
93
94    use super::*;
95
96    #[test]
97    fn params_serde() -> anyhow::Result<()> {
98        let params = UploadStreamParams {
99            media_name: Some(CString::new("media_name")?),
100            sample_spec: SampleSpec {
101                format: SampleFormat::S16Le,
102                sample_rate: 44100,
103                channels: 2,
104            },
105            channel_map: ChannelMap::stereo(),
106            length: 1024,
107            props: Props::new(),
108        };
109
110        test_serde(&params)
111    }
112
113    #[test]
114    fn reply_serde() -> anyhow::Result<()> {
115        let reply = CreateUploadStreamReply {
116            channel: 0,
117            length: 1024,
118        };
119
120        test_serde(&reply)
121    }
122}
123
124#[cfg(test)]
125#[cfg(feature = "_integration-tests")]
126mod integration_tests {
127    use super::*;
128    use crate::integration_test_util::*;
129    use crate::protocol::*;
130
131    #[test]
132    fn create_upload_stream() -> anyhow::Result<()> {
133        let (mut sock, protocol_version) = connect_and_init()?;
134
135        write_command_message(
136            sock.get_mut(),
137            0,
138            &Command::CreateUploadStream(UploadStreamParams {
139                media_name: Some(CString::new("media_name")?),
140                sample_spec: SampleSpec {
141                    format: SampleFormat::S16Le,
142                    sample_rate: 44100,
143                    channels: 2,
144                },
145                channel_map: ChannelMap::stereo(),
146                length: 1024,
147                ..Default::default()
148            }),
149            protocol_version,
150        )?;
151
152        let (_, reply) =
153            read_reply_message::<CreateUploadStreamReply>(&mut sock, protocol_version)?;
154        assert_eq!(reply.length, 1024);
155
156        Ok(())
157    }
158}