Skip to main content

linux_media/
media_pad.rs

1use derive_more::{Display, From, Into};
2use linux_media_sys as media;
3use serde::{Deserialize, Serialize};
4
5use crate::error;
6use crate::media_entity::EntityId;
7use crate::version::Version;
8
9#[derive(
10    Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, From, Into, Display, Serialize, Deserialize,
11)]
12pub struct PadId(u32);
13
14#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
15pub enum MediaPadFlags {
16    /// Input pad, relative to the entity. Input pads sink data and are targets of links.
17    Sink,
18    /// Output pad, relative to the entity. Output pads source data and are origins of links.
19    Source,
20    /// The pad is an input pad and the pad is linked to any other pad, then at least one of those links must be enabled for the entity to be able to stream. There could be temporary reasons (e.g. device configuration dependent) for the pad to need enabled links even when this flag isn’t set; the absence of the flag doesn’t imply there is none.
21    SinkMustConnect,
22    /// The pad is an output pad and the pad is linked to any other pad, then at least one of those links must be enabled for the entity to be able to stream. There could be temporary reasons (e.g. device configuration dependent) for the pad to need enabled links even when this flag isn’t set; the absence of the flag doesn’t imply there is none.
23    SourceMustConnect,
24}
25
26impl TryFrom<u32> for MediaPadFlags {
27    type Error = error::Error;
28    fn try_from(v: u32) -> error::Result<Self> {
29        use MediaPadFlags::*;
30        if v & media::MEDIA_PAD_FL_SINK != 0 {
31            if v & media::MEDIA_PAD_FL_MUST_CONNECT != 0 {
32                Ok(SinkMustConnect)
33            } else {
34                Ok(Sink)
35            }
36        } else if v & media::MEDIA_PAD_FL_SOURCE != 0 {
37            if v & media::MEDIA_PAD_FL_MUST_CONNECT != 0 {
38                Ok(SourceMustConnect)
39            } else {
40                Ok(Source)
41            }
42        } else {
43            Err(error::Error::PadFlagsParseError { from: v })
44        }
45    }
46}
47
48impl From<MediaPadFlags> for u32 {
49    fn from(flags: MediaPadFlags) -> u32 {
50        use MediaPadFlags::*;
51        match flags {
52            Sink => media::MEDIA_PAD_FL_SINK,
53            Source => media::MEDIA_PAD_FL_SOURCE,
54            SinkMustConnect => media::MEDIA_PAD_FL_SINK | media::MEDIA_PAD_FL_MUST_CONNECT,
55            SourceMustConnect => media::MEDIA_PAD_FL_SOURCE | media::MEDIA_PAD_FL_MUST_CONNECT,
56        }
57    }
58}
59
60#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
61pub struct MediaPad {
62    /// Unique ID for the pad. Do not expect that the ID will always be the same for each instance of the device. In other words, do not hardcode pad IDs in an application.
63    pub id: PadId,
64    /// Unique ID for the entity where this pad belongs.
65    pub entity_id: EntityId,
66    pub flags: MediaPadFlags,
67    /// Pad index, starts at 0. Only valid if [has_index(media_version)][MediaPad::has_index] returns true.
68    pub index: Option<usize>,
69}
70
71impl MediaPad {
72    pub fn has_index(media_version: Version) -> bool {
73        media::MEDIA_V2_PAD_HAS_INDEX(Into::<u32>::into(media_version).into())
74    }
75
76    pub fn from(version: Version, pad: media::media_v2_pad) -> Self {
77        Self {
78            id: pad.id.into(),
79            entity_id: pad.entity_id.into(),
80            flags: pad.flags.try_into().unwrap(),
81            index: if Self::has_index(version) {
82                Some(pad.index as usize)
83            } else {
84                None
85            },
86        }
87    }
88}