linux_media/
media_link.rs1use std::marker::PhantomData;
2
3use derive_more::{From, Into};
4use linux_media_sys as media;
5use serde::{Deserialize, Serialize};
6
7use crate::error;
8use crate::media_entity::EntityId;
9use crate::media_interface::InterfaceId;
10use crate::media_pad::PadId;
11
12#[derive(
13 Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, From, Into, Serialize, Deserialize,
14)]
15pub struct LinkId(u32);
16
17bitflags::bitflags! {
18 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
19 pub struct MediaLinkFlags: u32 {
20 const Enabled = media::MEDIA_LNK_FL_ENABLED;
22 const Immutable = media::MEDIA_LNK_FL_IMMUTABLE;
24 const Dynamic = media::MEDIA_LNK_FL_DYNAMIC;
26 }
27}
28
29impl TryFrom<u32> for MediaLinkFlags {
30 type Error = error::Error;
31 fn try_from(v: u32) -> error::Result<Self> {
32 MediaLinkFlags::from_bits(v & !media::MEDIA_LNK_FL_LINK_TYPE)
33 .ok_or_else(|| error::Error::LinkFlagsParseError { from: v })
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
38pub struct PadIdOr<T>(u32, PhantomData<T>);
39
40#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
41pub enum LinkType {
42 DataLink { source_id: PadId, sink_id: PadId },
45 InterfaceLink {
48 source_id: InterfaceId,
49 sink_id: EntityId,
50 },
51 AncillaryLink {
53 source_id: PadIdOr<InterfaceId>,
54 sink_id: PadIdOr<EntityId>,
55 },
56}
57
58#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Serialize, Deserialize)]
59pub struct MediaLink {
60 id: LinkId,
61 r#type: LinkType,
62 flags: MediaLinkFlags,
63}
64
65impl MediaLink {
66 pub fn new(id: LinkId, r#type: LinkType, flags: MediaLinkFlags) -> Self {
67 Self { id, r#type, flags }
68 }
69
70 pub fn id(&self) -> LinkId {
72 self.id
73 }
74
75 pub fn r#type(&self) -> &LinkType {
76 &self.r#type
77 }
78
79 pub fn flags(&self) -> MediaLinkFlags {
80 self.flags
81 }
82}
83
84impl From<media::media_v2_link> for MediaLink {
85 fn from(link: media::media_v2_link) -> Self {
86 let r#type = match link.flags & media::MEDIA_LNK_FL_LINK_TYPE {
87 media::MEDIA_LNK_FL_DATA_LINK => LinkType::DataLink {
88 source_id: link.source_id.into(),
89 sink_id: link.sink_id.into(),
90 },
91 media::MEDIA_LNK_FL_INTERFACE_LINK => LinkType::InterfaceLink {
92 source_id: link.source_id.into(),
93 sink_id: link.sink_id.into(),
94 },
95 #[cfg(has_linux_media_sys__MEDIA_LNK_FL_ANCILLARY_LINK)]
96 media::MEDIA_LNK_FL_ANCILLARY_LINK => LinkType::AncillaryLink {
97 source_id: PadIdOr(link.source_id, PhantomData),
98 sink_id: PadIdOr(link.sink_id, PhantomData),
99 },
100 other => unreachable!("link type should not be there: {}", other),
101 };
102 Self {
103 id: link.id.into(),
104 r#type,
105 flags: link.flags.try_into().unwrap(),
106 }
107 }
108}