pulseaudio/protocol/
command.rs

1//! Commands are the top-level IPC structure used in the protocol.
2
3use std::{
4    ffi::CString,
5    io::{BufRead, Write},
6};
7
8mod auth;
9mod card_info;
10mod client_event;
11mod client_info;
12mod extension;
13mod load_module;
14mod lookup;
15mod module_info;
16mod move_stream;
17mod playback_stream;
18mod record_stream;
19mod sample;
20mod sample_info;
21mod server_info;
22mod set_card_profile;
23mod set_client_name;
24mod set_port;
25mod set_port_latency_offset;
26mod sink_info;
27mod sink_input_info;
28mod source_info;
29mod source_output_info;
30mod stat;
31mod stream_events;
32mod subscribe;
33mod suspend;
34mod timing_info;
35mod update_client;
36mod update_stream;
37mod upload_stream;
38mod volume;
39
40pub use auth::*;
41pub use card_info::*;
42pub use client_event::*;
43pub use client_info::*;
44pub use extension::*;
45pub use load_module::*;
46pub use lookup::*;
47pub use module_info::*;
48pub use move_stream::*;
49pub use playback_stream::*;
50pub use record_stream::*;
51pub use sample::*;
52pub use sample_info::*;
53pub use server_info::*;
54pub use set_card_profile::*;
55pub use set_client_name::*;
56pub use set_port::*;
57pub use set_port_latency_offset::*;
58pub use sink_info::*;
59pub use sink_input_info::*;
60pub use source_info::*;
61pub use source_output_info::*;
62pub use stat::*;
63pub use stream_events::*;
64pub use subscribe::*;
65pub use suspend::*;
66pub use timing_info::*;
67pub use update_client::*;
68pub use update_stream::*;
69pub use upload_stream::*;
70pub use volume::*;
71
72use super::{serde::*, ProtocolError, PulseError};
73
74use enum_primitive_derive::Primitive;
75
76/// A tag describing a command payload.
77#[allow(missing_docs)]
78#[repr(u8)]
79#[derive(Debug, Copy, Clone, Eq, PartialEq, Primitive)]
80pub enum CommandTag {
81    /* Generic commands */
82    Error = 0,
83    Timeout = 1,              /* pseudo command */
84    Reply = 2,                /* actually used for command replies */
85    CreatePlaybackStream = 3, /* Payload changed in v9, v12 (0.9.0, 0.9.8) */
86    DeletePlaybackStream = 4,
87    CreateRecordStream = 5, /* Payload changed in v9, v12 (0.9.0, 0.9.8) */
88    DeleteRecordStream = 6,
89    Exit = 7,
90    Auth = 8,
91    SetClientName = 9,
92    LookupSink = 10,
93    LookupSource = 11,
94    DrainPlaybackStream = 12,
95    Stat = 13,
96    GetPlaybackLatency = 14,
97    CreateUploadStream = 15,
98    DeleteUploadStream = 16,
99    FinishUploadStream = 17,
100    PlaySample = 18,
101    RemoveSample = 19,
102    GetServerInfo = 20,
103    GetSinkInfo = 21,
104    GetSinkInfoList = 22,
105    GetSourceInfo = 23,
106    GetSourceInfoList = 24,
107    GetModuleInfo = 25,
108    GetModuleInfoList = 26,
109    GetClientInfo = 27,
110    GetClientInfoList = 28,
111    GetSinkInputInfo = 29,     /* Payload changed in v11 (0.9.7) */
112    GetSinkInputInfoList = 30, /* Payload changed in v11 (0.9.7) */
113    GetSourceOutputInfo = 31,
114    GetSourceOutputInfoList = 32,
115    GetSampleInfo = 33,
116    GetSampleInfoList = 34,
117    Subscribe = 35,
118    SetSinkVolume = 36,
119    SetSinkInputVolume = 37,
120    SetSourceVolume = 38,
121    SetSinkMute = 39,
122    SetSourceMute = 40,
123    CorkPlaybackStream = 41,
124    FlushPlaybackStream = 42,
125    TriggerPlaybackStream = 43,
126    SetDefaultSink = 44,
127    SetDefaultSource = 45,
128    SetPlaybackStreamName = 46,
129    SetRecordStreamName = 47,
130    KillClient = 48,
131    KillSinkInput = 49,
132    KillSourceOutput = 50,
133    LoadModule = 51,
134    UnloadModule = 52,
135    // AddAutoloadObsolete = 53,
136    // RemoveAutoloadObsolete = 54,
137    // GetAutoloadInfoObsolete = 55,
138    // GetAutoloadInfoListObsolete = 56,
139    GetRecordLatency = 57,
140    CorkRecordStream = 58,
141    FlushRecordStream = 59,
142    PrebufPlaybackStream = 60,
143    Request = 61,
144    Overflow = 62,
145    Underflow = 63,
146    PlaybackStreamKilled = 64,
147    RecordStreamKilled = 65,
148    SubscribeEvent = 66,
149    MoveSinkInput = 67,
150    MoveSourceOutput = 68,
151    SetSinkInputMute = 69,
152    SuspendSink = 70,
153    SuspendSource = 71,
154    SetPlaybackStreamBufferAttr = 72,
155    SetRecordStreamBufferAttr = 73,
156    UpdatePlaybackStreamSampleRate = 74,
157    UpdateRecordStreamSampleRate = 75,
158    PlaybackStreamSuspended = 76,
159    RecordStreamSuspended = 77,
160    PlaybackStreamMoved = 78,
161    RecordStreamMoved = 79,
162    UpdateRecordStreamProplist = 80,
163    UpdatePlaybackStreamProplist = 81,
164    UpdateClientProplist = 82,
165    RemoveRecordStreamProplist = 83,
166    RemovePlaybackStreamProplist = 84,
167    RemoveClientProplist = 85,
168    Started = 86,
169    Extension = 87,
170    GetCardInfo = 88,
171    GetCardInfoList = 89,
172    SetCardProfile = 90,
173    ClientEvent = 91,
174    PlaybackStreamEvent = 92,
175    RecordStreamEvent = 93,
176    PlaybackBufferAttrChanged = 94,
177    RecordBufferAttrChanged = 95,
178    SetSinkPort = 96,
179    SetSourcePort = 97,
180    SetSourceOutputVolume = 98,
181    SetSourceOutputMute = 99,
182    SetPortLatencyOffset = 100,
183    EnableSrbchannel = 101,
184    DisableSrbchannel = 102,
185    RegisterMemfdShmid = 103,
186    SendObjectMessage = 104,
187}
188
189/// A marker trait for reply data.
190pub trait CommandReply: TagStructRead + TagStructWrite {}
191
192#[derive(Debug, Clone, PartialEq)]
193#[allow(missing_docs)]
194pub enum Command {
195    /// An error reply to some other command.
196    Error(PulseError),
197    Timeout,
198    Exit,
199
200    /// A reply to some other command. If this is returned by [`Command::read_tag_prefixed`], the payload has yet to be read.
201    Reply,
202
203    // Authentication request (and protocol handshake).
204    Auth(AuthParams),
205
206    // Updates client properties (not just the name).
207    SetClientName(Props),
208
209    // Create and manage streams.
210    CreatePlaybackStream(PlaybackStreamParams),
211    DeletePlaybackStream(u32),
212    CreateRecordStream(RecordStreamParams),
213    DeleteRecordStream(u32),
214    DrainPlaybackStream(u32),
215    GetPlaybackLatency(LatencyParams),
216    GetRecordLatency(LatencyParams),
217    CreateUploadStream(UploadStreamParams),
218    DeleteUploadStream(u32),
219    FinishUploadStream(u32),
220    CorkPlaybackStream(CorkStreamParams),
221    CorkRecordStream(CorkStreamParams),
222    FlushPlaybackStream(u32),
223    FlushRecordStream(u32),
224    PrebufPlaybackStream(u32),
225    TriggerPlaybackStream(u32),
226    SetPlaybackStreamName(SetStreamNameParams),
227    SetRecordStreamName(SetStreamNameParams),
228    SetPlaybackStreamBufferAttr(SetPlaybackStreamBufferAttrParams),
229    SetRecordStreamBufferAttr(SetRecordStreamBufferAttrParams),
230    UpdatePlaybackStreamProplist(UpdatePropsParams),
231    UpdateRecordStreamProplist(UpdatePropsParams),
232    RemovePlaybackStreamProplist(u32),
233    RemoveRecordStreamProplist(u32),
234    UpdatePlaybackStreamSampleRate(UpdateSampleRateParams),
235    UpdateRecordStreamSampleRate(UpdateSampleRateParams),
236
237    // So-called introspection commands, to read back the state of the server.
238    Stat,
239    GetServerInfo,
240    GetCardInfo(GetCardInfo),
241    GetCardInfoList,
242    GetSinkInfo(GetSinkInfo),
243    GetSinkInfoList,
244    GetSourceInfo(GetSourceInfo),
245    GetSourceInfoList,
246    GetModuleInfo(u32),
247    GetModuleInfoList,
248    GetClientInfo(u32),
249    GetClientInfoList,
250    GetSinkInputInfo(u32),
251    GetSinkInputInfoList,
252    GetSourceOutputInfo(u32),
253    GetSourceOutputInfoList,
254    GetSampleInfo(u32),
255    GetSampleInfoList,
256    LookupSink(CString),
257    LookupSource(CString),
258    Subscribe(SubscriptionMask),
259
260    // Server management commands.
261    SetDefaultSink(CString),
262    SetDefaultSource(CString),
263    SetSinkPort(SetPortParams),
264    SetSourcePort(SetPortParams),
265    SetCardProfile(SetCardProfileParams),
266    KillClient(u32),
267    KillSinkInput(u32),
268    KillSourceOutput(u32),
269    MoveSinkInput(MoveStreamParams),
270    MoveSourceOutput(MoveStreamParams),
271    SuspendSink(SuspendParams),
272    SuspendSource(SuspendParams),
273    UpdateClientProplist(UpdateClientProplistParams),
274    RemoveClientProplist,
275    SetPortLatencyOffset(SetPortLatencyOffsetParams),
276
277    // Manage samples.
278    PlaySample(PlaySampleParams),
279    RemoveSample(CString),
280
281    // Manage modules.
282    LoadModule(LoadModuleParams),
283    UnloadModule(u32),
284    Extension(ExtensionParams),
285
286    // Set volume and mute.
287    SetSinkVolume(SetDeviceVolumeParams),
288    SetSinkInputVolume(SetStreamVolumeParams),
289    SetSourceVolume(SetDeviceVolumeParams),
290    SetSourceOutputVolume(SetStreamVolumeParams),
291    SetSinkMute(SetDeviceMuteParams),
292    SetSinkInputMute(SetStreamMuteParams),
293    SetSourceMute(SetDeviceMuteParams),
294    SetSourceOutputMute(SetStreamMuteParams),
295
296    // Events from the server to the client.
297    Started(u32),
298    Request(Request),
299    Overflow(u32),
300    Underflow(Underflow),
301    PlaybackStreamKilled(u32),
302    RecordStreamKilled(u32),
303    PlaybackStreamSuspended(StreamSuspendedParams),
304    RecordStreamSuspended(StreamSuspendedParams),
305    PlaybackStreamMoved(PlaybackStreamMovedParams),
306    RecordStreamMoved(RecordStreamMovedParams),
307    PlaybackBufferAttrChanged(PlaybackBufferAttrChanged),
308    RecordBufferAttrChanged(RecordBufferAttrChanged),
309    ClientEvent(ClientEvent),
310    PlaybackStreamEvent(GenericStreamEvent),
311    RecordStreamEvent(GenericStreamEvent),
312    SubscribeEvent(SubscriptionEvent),
313}
314
315impl Command {
316    /// Read a command message from a tagstruct. A result of [`Command::Reply`]
317    /// indicates that the payload has yet to be read.
318    pub fn read_tag_prefixed<R: BufRead>(
319        r: &mut R,
320        protocol_version: u16,
321    ) -> Result<(u32, Self), ProtocolError> {
322        let mut ts = TagStructReader::new(r, protocol_version);
323        let (command, seq) = (ts.read_enum()?, ts.read_u32()?);
324
325        let cmd = match command {
326            CommandTag::Timeout => Err(ProtocolError::Timeout),
327            CommandTag::Error => Ok(Command::Error(ts.read_enum()?)),
328            CommandTag::Reply => Ok(Command::Reply),
329
330            CommandTag::Exit => Ok(Command::Exit),
331            CommandTag::Auth => Ok(Command::Auth(ts.read()?)),
332            CommandTag::SetClientName => Ok(Command::SetClientName(ts.read()?)),
333
334            CommandTag::CreatePlaybackStream => Ok(Command::CreatePlaybackStream(ts.read()?)),
335            CommandTag::DeletePlaybackStream => Ok(Command::DeletePlaybackStream(ts.read_u32()?)),
336            CommandTag::CreateRecordStream => Ok(Command::CreateRecordStream(ts.read()?)),
337            CommandTag::DeleteRecordStream => Ok(Command::DeleteRecordStream(ts.read_u32()?)),
338            CommandTag::LookupSink => Ok(Command::LookupSink(ts.read_string_non_null()?)),
339            CommandTag::LookupSource => Ok(Command::LookupSource(ts.read_string_non_null()?)),
340            CommandTag::DrainPlaybackStream => Ok(Command::DrainPlaybackStream(ts.read_u32()?)),
341            CommandTag::Stat => Ok(Command::Stat),
342            CommandTag::GetPlaybackLatency => Ok(Command::GetPlaybackLatency(ts.read()?)),
343            CommandTag::CreateUploadStream => Ok(Command::CreateUploadStream(ts.read()?)),
344            CommandTag::DeleteUploadStream => Ok(Command::DeleteUploadStream(ts.read_u32()?)),
345            CommandTag::FinishUploadStream => Ok(Command::FinishUploadStream(ts.read_u32()?)),
346            CommandTag::PlaySample => Ok(Command::PlaySample(ts.read()?)),
347            CommandTag::RemoveSample => Ok(Command::RemoveSample(ts.read_string_non_null()?)),
348
349            CommandTag::GetServerInfo => Ok(Command::GetServerInfo),
350            CommandTag::GetSinkInfo => Ok(Command::GetSinkInfo(ts.read()?)),
351            CommandTag::GetSinkInfoList => Ok(Command::GetSinkInfoList),
352            CommandTag::GetSourceInfo => Ok(Command::GetSourceInfo(ts.read()?)),
353            CommandTag::GetSourceInfoList => Ok(Command::GetSourceInfoList),
354            CommandTag::GetModuleInfo => Ok(Command::GetModuleInfo(ts.read_u32()?)),
355            CommandTag::GetModuleInfoList => Ok(Command::GetModuleInfoList),
356            CommandTag::GetClientInfo => Ok(Command::GetClientInfo(ts.read_u32()?)),
357            CommandTag::GetClientInfoList => Ok(Command::GetClientInfoList),
358            CommandTag::GetSinkInputInfo => Ok(Command::GetSinkInputInfo(ts.read_u32()?)),
359            CommandTag::GetSinkInputInfoList => Ok(Command::GetSinkInputInfoList),
360            CommandTag::GetSourceOutputInfo => Ok(Command::GetSourceOutputInfo(ts.read_u32()?)),
361            CommandTag::GetSourceOutputInfoList => Ok(Command::GetSourceOutputInfoList),
362            CommandTag::GetSampleInfo => Ok(Command::GetSampleInfo(ts.read_u32()?)),
363            CommandTag::GetSampleInfoList => Ok(Command::GetSampleInfoList),
364            CommandTag::Subscribe => Ok(Command::Subscribe(ts.read()?)),
365            CommandTag::SubscribeEvent => Ok(Command::SubscribeEvent(ts.read()?)),
366
367            CommandTag::Request => Ok(Command::Request(ts.read()?)),
368            CommandTag::Overflow => Ok(Command::Overflow(ts.read_u32()?)),
369            CommandTag::Underflow => Ok(Command::Underflow(ts.read()?)),
370            CommandTag::PlaybackStreamKilled => Ok(Command::PlaybackStreamKilled(ts.read_u32()?)),
371            CommandTag::RecordStreamKilled => Ok(Command::RecordStreamKilled(ts.read_u32()?)),
372            CommandTag::Started => Ok(Command::Started(ts.read_u32()?)),
373            CommandTag::PlaybackBufferAttrChanged => {
374                Ok(Command::PlaybackBufferAttrChanged(ts.read()?))
375            }
376
377            CommandTag::SetSinkVolume => Ok(Command::SetSinkVolume(ts.read()?)),
378            CommandTag::SetSinkInputVolume => Ok(Command::SetSinkInputVolume(ts.read()?)),
379            CommandTag::SetSourceVolume => Ok(Command::SetSourceVolume(ts.read()?)),
380            CommandTag::SetSinkMute => Ok(Command::SetSinkMute(ts.read()?)),
381            CommandTag::SetSourceMute => Ok(Command::SetSourceMute(ts.read()?)),
382            CommandTag::CorkPlaybackStream => Ok(Command::CorkPlaybackStream(ts.read()?)),
383            CommandTag::FlushPlaybackStream => Ok(Command::FlushPlaybackStream(ts.read_u32()?)),
384            CommandTag::TriggerPlaybackStream => Ok(Command::TriggerPlaybackStream(ts.read_u32()?)),
385            CommandTag::SetDefaultSink => Ok(Command::SetDefaultSink(ts.read_string_non_null()?)),
386            CommandTag::SetDefaultSource => {
387                Ok(Command::SetDefaultSource(ts.read_string_non_null()?))
388            }
389            CommandTag::SetPlaybackStreamName => Ok(Command::SetPlaybackStreamName(ts.read()?)),
390            CommandTag::SetRecordStreamName => Ok(Command::SetRecordStreamName(ts.read()?)),
391            CommandTag::KillClient => Ok(Command::KillClient(ts.read_u32()?)),
392            CommandTag::KillSinkInput => Ok(Command::KillSinkInput(ts.read_u32()?)),
393            CommandTag::KillSourceOutput => Ok(Command::KillSourceOutput(ts.read_u32()?)),
394            CommandTag::LoadModule => Ok(Command::LoadModule(ts.read()?)),
395            CommandTag::UnloadModule => Ok(Command::UnloadModule(ts.read_u32()?)),
396            CommandTag::GetRecordLatency => Ok(Command::GetRecordLatency(ts.read()?)),
397            CommandTag::CorkRecordStream => Ok(Command::CorkRecordStream(ts.read()?)),
398            CommandTag::FlushRecordStream => Ok(Command::FlushRecordStream(ts.read_u32()?)),
399            CommandTag::PrebufPlaybackStream => Ok(Command::PrebufPlaybackStream(ts.read_u32()?)),
400            CommandTag::MoveSinkInput => Ok(Command::MoveSinkInput(ts.read()?)),
401            CommandTag::MoveSourceOutput => Ok(Command::MoveSourceOutput(ts.read()?)),
402            CommandTag::SetSinkInputMute => Ok(Command::SetSinkInputMute(ts.read()?)),
403            CommandTag::SuspendSink => Ok(Command::SuspendSink(ts.read()?)),
404            CommandTag::SuspendSource => Ok(Command::SuspendSource(ts.read()?)),
405            CommandTag::SetPlaybackStreamBufferAttr => {
406                Ok(Command::SetPlaybackStreamBufferAttr(ts.read()?))
407            }
408            CommandTag::SetRecordStreamBufferAttr => {
409                Ok(Command::SetRecordStreamBufferAttr(ts.read()?))
410            }
411            CommandTag::UpdatePlaybackStreamSampleRate => {
412                Ok(Command::UpdatePlaybackStreamSampleRate(ts.read()?))
413            }
414            CommandTag::UpdateRecordStreamSampleRate => {
415                Ok(Command::UpdateRecordStreamSampleRate(ts.read()?))
416            }
417            CommandTag::PlaybackStreamSuspended => Ok(Command::PlaybackStreamSuspended(ts.read()?)),
418            CommandTag::RecordStreamSuspended => Ok(Command::RecordStreamSuspended(ts.read()?)),
419            CommandTag::PlaybackStreamMoved => Ok(Command::PlaybackStreamMoved(ts.read()?)),
420            CommandTag::RecordStreamMoved => Ok(Command::RecordStreamMoved(ts.read()?)),
421            CommandTag::UpdateRecordStreamProplist => {
422                Ok(Command::UpdateRecordStreamProplist(ts.read()?))
423            }
424            CommandTag::UpdatePlaybackStreamProplist => {
425                Ok(Command::UpdatePlaybackStreamProplist(ts.read()?))
426            }
427            CommandTag::UpdateClientProplist => Ok(Command::UpdateClientProplist(ts.read()?)),
428            CommandTag::RemoveRecordStreamProplist => {
429                Ok(Command::RemoveRecordStreamProplist(ts.read_u32()?))
430            }
431            CommandTag::RemovePlaybackStreamProplist => {
432                Ok(Command::RemovePlaybackStreamProplist(ts.read_u32()?))
433            }
434            CommandTag::RemoveClientProplist => Ok(Command::RemoveClientProplist),
435            CommandTag::Extension => Ok(Command::Extension(ts.read()?)),
436            CommandTag::GetCardInfo => Ok(Command::GetCardInfo(ts.read()?)),
437            CommandTag::GetCardInfoList => Ok(Command::GetCardInfoList),
438            CommandTag::SetCardProfile => Ok(Command::SetCardProfile(ts.read()?)),
439            CommandTag::ClientEvent => Ok(Command::ClientEvent(ts.read()?)),
440            CommandTag::PlaybackStreamEvent => Ok(Command::PlaybackStreamEvent(ts.read()?)),
441            CommandTag::RecordStreamEvent => Ok(Command::RecordStreamEvent(ts.read()?)),
442
443            CommandTag::RecordBufferAttrChanged => Ok(Command::RecordBufferAttrChanged(ts.read()?)),
444
445            CommandTag::SetSinkPort => Ok(Command::SetSinkPort(ts.read()?)),
446            CommandTag::SetSourcePort => Ok(Command::SetSourcePort(ts.read()?)),
447            CommandTag::SetSourceOutputVolume => Ok(Command::SetSourceOutputVolume(ts.read()?)),
448            CommandTag::SetSourceOutputMute => Ok(Command::SetSourceOutputMute(ts.read()?)),
449            CommandTag::SetPortLatencyOffset => Ok(Command::SetPortLatencyOffset(ts.read()?)),
450            CommandTag::EnableSrbchannel => Err(ProtocolError::Unimplemented(seq, command)),
451            CommandTag::DisableSrbchannel => Err(ProtocolError::Unimplemented(seq, command)),
452            CommandTag::RegisterMemfdShmid => Err(ProtocolError::Unimplemented(seq, command)),
453            CommandTag::SendObjectMessage => Err(ProtocolError::Unimplemented(seq, command)),
454        }?;
455
456        Ok((seq, cmd))
457    }
458
459    /// Write a command message as a tagstruct. In the case of a [`Command::Reply`], the payload must be written separately.
460    pub fn write_tag_prefixed<W: Write>(
461        &self,
462        seq: u32,
463        w: &mut W,
464        protocol_version: u16,
465    ) -> Result<(), ProtocolError> {
466        let mut ts = TagStructWriter::new(w, protocol_version);
467
468        ts.write_u32(self.tag() as u32)?;
469        ts.write_u32(seq)?;
470        ts.write(self)?;
471
472        Ok(())
473    }
474
475    /// The matching tag for this command.
476    pub fn tag(&self) -> CommandTag {
477        match self {
478            /* Generic commands */
479            Command::Error(_) => CommandTag::Error,
480            Command::Timeout => CommandTag::Timeout, /* pseudo command */
481            Command::Reply => CommandTag::Reply,     /* actually used for command replies */
482            Command::CreatePlaybackStream(_) => CommandTag::CreatePlaybackStream, /* Payload changed in v9, v12 (0.9.0, 0.9.8) */
483            Command::DeletePlaybackStream(_) => CommandTag::DeletePlaybackStream,
484            Command::CreateRecordStream(_) => CommandTag::CreateRecordStream, /* Payload changed in v9, v12 (0.9.0, 0.9.8) */
485            Command::DeleteRecordStream(_) => CommandTag::DeleteRecordStream,
486            Command::Exit => CommandTag::Exit,
487            Command::Auth(_) => CommandTag::Auth,
488            Command::SetClientName(_) => CommandTag::SetClientName,
489            Command::LookupSink(_) => CommandTag::LookupSink,
490            Command::LookupSource(_) => CommandTag::LookupSource,
491            Command::DrainPlaybackStream(_) => CommandTag::DrainPlaybackStream,
492            Command::Stat => CommandTag::Stat,
493            Command::GetPlaybackLatency(_) => CommandTag::GetPlaybackLatency,
494            Command::CreateUploadStream(_) => CommandTag::CreateUploadStream,
495            Command::DeleteUploadStream(_) => CommandTag::DeleteUploadStream,
496            Command::FinishUploadStream(_) => CommandTag::FinishUploadStream,
497            Command::PlaySample(_) => CommandTag::PlaySample,
498            Command::RemoveSample(_) => CommandTag::RemoveSample,
499            Command::GetServerInfo => CommandTag::GetServerInfo,
500            Command::GetSinkInfo(_) => CommandTag::GetSinkInfo,
501            Command::GetSinkInfoList => CommandTag::GetSinkInfoList,
502            Command::GetSourceInfo(_) => CommandTag::GetSourceInfo,
503            Command::GetSourceInfoList => CommandTag::GetSourceInfoList,
504            Command::GetModuleInfo(_) => CommandTag::GetModuleInfo,
505            Command::GetModuleInfoList => CommandTag::GetModuleInfoList,
506            Command::GetClientInfo(_) => CommandTag::GetClientInfo,
507            Command::GetClientInfoList => CommandTag::GetClientInfoList,
508            Command::GetSinkInputInfo(_) => CommandTag::GetSinkInputInfo, /* Payload changed in v11 (0.9.7) */
509            Command::GetSinkInputInfoList => CommandTag::GetSinkInputInfoList, /* Payload changed in v11 (0.9.7) */
510            Command::GetSourceOutputInfo(_) => CommandTag::GetSourceOutputInfo,
511            Command::GetSourceOutputInfoList => CommandTag::GetSourceOutputInfoList,
512            Command::GetSampleInfo(_) => CommandTag::GetSampleInfo,
513            Command::GetSampleInfoList => CommandTag::GetSampleInfoList,
514            Command::Subscribe(_) => CommandTag::Subscribe,
515            Command::SetSinkVolume(_) => CommandTag::SetSinkVolume,
516            Command::SetSinkInputVolume(_) => CommandTag::SetSinkInputVolume,
517            Command::SetSourceVolume(_) => CommandTag::SetSourceVolume,
518            Command::SetSinkMute(_) => CommandTag::SetSinkMute,
519            Command::SetSourceMute(_) => CommandTag::SetSourceMute,
520            Command::CorkPlaybackStream(_) => CommandTag::CorkPlaybackStream,
521            Command::FlushPlaybackStream(_) => CommandTag::FlushPlaybackStream,
522            Command::TriggerPlaybackStream(_) => CommandTag::TriggerPlaybackStream,
523            Command::SetDefaultSink(_) => CommandTag::SetDefaultSink,
524            Command::SetDefaultSource(_) => CommandTag::SetDefaultSource,
525            Command::SetPlaybackStreamName(_) => CommandTag::SetPlaybackStreamName,
526            Command::SetRecordStreamName(_) => CommandTag::SetRecordStreamName,
527            Command::KillClient(_) => CommandTag::KillClient,
528            Command::KillSinkInput(_) => CommandTag::KillSinkInput,
529            Command::KillSourceOutput(_) => CommandTag::KillSourceOutput,
530            Command::LoadModule(_) => CommandTag::LoadModule,
531            Command::UnloadModule(_) => CommandTag::UnloadModule,
532            // Command::AddAutoloadObsolete(_) => CommandTag::AddAutoloadObsolete,
533            // Command::RemoveAutoloadObsolete(_) => CommandTag::RemoveAutoloadObsolete,
534            // Command::GetAutoloadInfoObsolete(_) => CommandTag::GetAutoloadInfoObsolete,
535            // Command::GetAutoloadInfoListObsolete(_) => CommandTag::GetAutoloadInfoListObsolete,
536            Command::GetRecordLatency(_) => CommandTag::GetRecordLatency,
537            Command::CorkRecordStream(_) => CommandTag::CorkRecordStream,
538            Command::FlushRecordStream(_) => CommandTag::FlushRecordStream,
539            Command::PrebufPlaybackStream(_) => CommandTag::PrebufPlaybackStream,
540            Command::Request(_) => CommandTag::Request,
541            Command::Overflow(_) => CommandTag::Overflow,
542            Command::Underflow(_) => CommandTag::Underflow,
543            Command::PlaybackStreamKilled(_) => CommandTag::PlaybackStreamKilled,
544            Command::RecordStreamKilled(_) => CommandTag::RecordStreamKilled,
545            Command::SubscribeEvent(_) => CommandTag::SubscribeEvent,
546            Command::MoveSinkInput(_) => CommandTag::MoveSinkInput,
547            Command::MoveSourceOutput(_) => CommandTag::MoveSourceOutput,
548            Command::SetSinkInputMute(_) => CommandTag::SetSinkInputMute,
549            Command::SuspendSink(_) => CommandTag::SuspendSink,
550            Command::SuspendSource(_) => CommandTag::SuspendSource,
551            Command::SetPlaybackStreamBufferAttr(_) => CommandTag::SetPlaybackStreamBufferAttr,
552            Command::SetRecordStreamBufferAttr(_) => CommandTag::SetRecordStreamBufferAttr,
553            Command::UpdatePlaybackStreamSampleRate(_) => {
554                CommandTag::UpdatePlaybackStreamSampleRate
555            }
556            Command::UpdateRecordStreamSampleRate(_) => CommandTag::UpdateRecordStreamSampleRate,
557            Command::PlaybackStreamSuspended(_) => CommandTag::PlaybackStreamSuspended,
558            Command::RecordStreamSuspended(_) => CommandTag::RecordStreamSuspended,
559            Command::PlaybackStreamMoved(_) => CommandTag::PlaybackStreamMoved,
560            Command::RecordStreamMoved(_) => CommandTag::RecordStreamMoved,
561            Command::UpdateRecordStreamProplist(_) => CommandTag::UpdateRecordStreamProplist,
562            Command::UpdatePlaybackStreamProplist(_) => CommandTag::UpdatePlaybackStreamProplist,
563            Command::UpdateClientProplist(_) => CommandTag::UpdateClientProplist,
564            Command::RemoveRecordStreamProplist(_) => CommandTag::RemoveRecordStreamProplist,
565            Command::RemovePlaybackStreamProplist(_) => CommandTag::RemovePlaybackStreamProplist,
566            Command::RemoveClientProplist => CommandTag::RemoveClientProplist,
567            Command::Started(_) => CommandTag::Started,
568            Command::Extension(_) => CommandTag::Extension,
569            Command::GetCardInfo(_) => CommandTag::GetCardInfo,
570            Command::GetCardInfoList => CommandTag::GetCardInfoList,
571            Command::SetCardProfile(_) => CommandTag::SetCardProfile,
572            Command::ClientEvent(_) => CommandTag::ClientEvent,
573            Command::PlaybackStreamEvent(_) => CommandTag::PlaybackStreamEvent,
574            Command::RecordStreamEvent(_) => CommandTag::RecordStreamEvent,
575            Command::PlaybackBufferAttrChanged(_) => CommandTag::PlaybackBufferAttrChanged,
576            Command::RecordBufferAttrChanged(_) => CommandTag::RecordBufferAttrChanged,
577            Command::SetSinkPort(_) => CommandTag::SetSinkPort,
578            Command::SetSourcePort(_) => CommandTag::SetSourcePort,
579            Command::SetSourceOutputVolume(_) => CommandTag::SetSourceOutputVolume,
580            Command::SetSourceOutputMute(_) => CommandTag::SetSourceOutputMute,
581            Command::SetPortLatencyOffset(_) => CommandTag::SetPortLatencyOffset,
582            // Command::EnableSrbchannel(_) => CommandTag::EnableSrbchannel,
583            // Command::DisableSrbchannel(_) => CommandTag::DisableSrbchannel,
584            // Command::RegisterMemfdShmid(_) => CommandTag::RegisterMemfdShmid,
585            // Command::SendObjectMessage(_) => CommandTag::SendObjectMessage,
586        }
587    }
588}
589
590impl TagStructWrite for Command {
591    fn write(
592        &self,
593        w: &mut TagStructWriter<'_>,
594        _protocol_version: u16,
595    ) -> Result<(), ProtocolError> {
596        match self {
597            Command::Error(e) => w.write_u32(*e as u32),
598            Command::Timeout => Ok(()),
599            Command::Reply => Ok(()),
600            Command::Exit => Ok(()),
601            Command::Auth(p) => w.write(p),
602            Command::SetClientName(p) => w.write(p),
603            Command::CreatePlaybackStream(p) => w.write(p),
604            Command::DeletePlaybackStream(id) => w.write_u32(*id),
605            Command::CreateRecordStream(p) => w.write(p),
606            Command::DeleteRecordStream(id) => w.write_u32(*id),
607            Command::DrainPlaybackStream(id) => w.write_u32(*id),
608            Command::GetPlaybackLatency(p) => w.write(p),
609            Command::GetRecordLatency(p) => w.write(p),
610            Command::CreateUploadStream(p) => w.write(p),
611            Command::DeleteUploadStream(id) => w.write_u32(*id),
612            Command::FinishUploadStream(id) => w.write_u32(*id),
613            Command::CorkPlaybackStream(p) => w.write(p),
614            Command::CorkRecordStream(p) => w.write(p),
615            Command::FlushPlaybackStream(id) => w.write_u32(*id),
616            Command::FlushRecordStream(id) => w.write_u32(*id),
617            Command::PrebufPlaybackStream(id) => w.write_u32(*id),
618            Command::TriggerPlaybackStream(id) => w.write_u32(*id),
619            Command::SetPlaybackStreamName(p) => w.write(p),
620            Command::SetRecordStreamName(p) => w.write(p),
621            Command::SetPlaybackStreamBufferAttr(p) => w.write(p),
622            Command::SetRecordStreamBufferAttr(p) => w.write(p),
623            Command::UpdatePlaybackStreamProplist(p) => w.write(p),
624            Command::UpdateRecordStreamProplist(p) => w.write(p),
625            Command::RemovePlaybackStreamProplist(id) => w.write_u32(*id),
626            Command::RemoveRecordStreamProplist(id) => w.write_u32(*id),
627            Command::UpdatePlaybackStreamSampleRate(p) => w.write(p),
628            Command::UpdateRecordStreamSampleRate(p) => w.write(p),
629            Command::Stat => Ok(()),
630            Command::GetServerInfo => Ok(()),
631            Command::GetCardInfo(p) => w.write(p),
632            Command::GetCardInfoList => Ok(()),
633            Command::GetSinkInfo(p) => w.write(p),
634            Command::GetSinkInfoList => Ok(()),
635            Command::GetSourceInfo(id) => w.write(id),
636            Command::GetSourceInfoList => Ok(()),
637            Command::GetModuleInfo(id) => w.write_u32(*id),
638            Command::GetModuleInfoList => Ok(()),
639            Command::GetClientInfo(id) => w.write_u32(*id),
640            Command::GetClientInfoList => Ok(()),
641            Command::GetSinkInputInfo(id) => w.write_u32(*id),
642            Command::GetSinkInputInfoList => Ok(()),
643            Command::GetSourceOutputInfo(id) => w.write_u32(*id),
644            Command::GetSourceOutputInfoList => Ok(()),
645            Command::GetSampleInfo(p) => w.write_u32(*p),
646            Command::GetSampleInfoList => Ok(()),
647            Command::LookupSink(p) => w.write_string(Some(p)),
648            Command::LookupSource(p) => w.write_string(Some(p)),
649            Command::Subscribe(p) => w.write(p),
650            Command::SetDefaultSink(p) => w.write_string(Some(p)),
651            Command::SetDefaultSource(p) => w.write_string(Some(p)),
652            Command::SetSinkPort(p) => w.write(p),
653            Command::SetSourcePort(p) => w.write(p),
654            Command::SetCardProfile(p) => w.write(p),
655            Command::KillClient(id) => w.write_u32(*id),
656            Command::KillSinkInput(id) => w.write_u32(*id),
657            Command::KillSourceOutput(id) => w.write_u32(*id),
658            Command::MoveSinkInput(p) => w.write(p),
659            Command::MoveSourceOutput(p) => w.write(p),
660            Command::SuspendSink(p) => w.write(p),
661            Command::SuspendSource(p) => w.write(p),
662            Command::UpdateClientProplist(p) => w.write(p),
663            Command::RemoveClientProplist => Ok(()),
664            Command::SetPortLatencyOffset(p) => w.write(p),
665            Command::PlaySample(p) => w.write(p),
666            Command::RemoveSample(p) => w.write_string(Some(p)),
667            Command::LoadModule(p) => w.write(p),
668            Command::UnloadModule(id) => w.write_u32(*id),
669            Command::Extension(p) => w.write(p),
670            Command::SetSinkVolume(p) => w.write(p),
671            Command::SetSinkInputVolume(p) => w.write(p),
672            Command::SetSourceVolume(p) => w.write(p),
673            Command::SetSourceOutputVolume(p) => w.write(p),
674            Command::SetSinkMute(p) => w.write(p),
675            Command::SetSinkInputMute(p) => w.write(p),
676            Command::SetSourceMute(p) => w.write(p),
677            Command::SetSourceOutputMute(p) => w.write(p),
678            Command::Started(id) => w.write_u32(*id),
679            Command::Request(p) => w.write(p),
680            Command::Overflow(id) => w.write_u32(*id),
681            Command::Underflow(p) => w.write(p),
682            Command::PlaybackStreamKilled(id) => w.write_u32(*id),
683            Command::RecordStreamKilled(id) => w.write_u32(*id),
684            Command::PlaybackStreamSuspended(p) => w.write(p),
685            Command::RecordStreamSuspended(p) => w.write(p),
686            Command::PlaybackStreamMoved(p) => w.write(p),
687            Command::RecordStreamMoved(p) => w.write(p),
688            Command::PlaybackBufferAttrChanged(p) => w.write(p),
689            Command::RecordBufferAttrChanged(p) => w.write(p),
690            Command::ClientEvent(p) => w.write(p),
691            Command::PlaybackStreamEvent(p) => w.write(p),
692            Command::RecordStreamEvent(p) => w.write(p),
693            Command::SubscribeEvent(p) => w.write(p),
694        }
695    }
696}