From 1c1f614ffa1c000063fbddfa2e9522f21487047b Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Fri, 3 Jan 2025 20:43:22 +0100 Subject: [PATCH 1/7] use system-deps to resolve native dep instead of just linking to libdisplay-info use system-deps, which will use pkg-config internally, to resolve the native lib. this also limits the version to the currently supported one --- libdisplay-info-sys/Cargo.toml | 9 +++++++-- libdisplay-info-sys/build.rs | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libdisplay-info-sys/Cargo.toml b/libdisplay-info-sys/Cargo.toml index 109d91b..d09c384 100644 --- a/libdisplay-info-sys/Cargo.toml +++ b/libdisplay-info-sys/Cargo.toml @@ -4,7 +4,7 @@ categories = ["api-bindings"] description = "Low-level bindings for libdisplay-info." documentation = "https://docs.rs/libdisplay-info-sys/" edition = "2021" -version = "0.1.0" +version = "0.1.1" keywords = ["libdisplay", "DisplayID", "EDID"] license = "MIT" name = "libdisplay-info-sys" @@ -13,4 +13,9 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html -[dependencies] +[build-dependencies] +system-deps = "7.0.3" + +[package.metadata.system-deps.libdisplay-info] +name = "libdisplay-info" +version = ">= 0.1.0, < 0.2.0" diff --git a/libdisplay-info-sys/build.rs b/libdisplay-info-sys/build.rs index dce09d2..eec6d52 100644 --- a/libdisplay-info-sys/build.rs +++ b/libdisplay-info-sys/build.rs @@ -1,3 +1,3 @@ fn main() { - println!("cargo:rustc-link-lib=display-info"); + system_deps::Config::new().probe().unwrap(); } From 129ce7b7abf61b5dcb7baa0a48cdc92900daf4ba Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Fri, 3 Jan 2025 22:15:36 +0100 Subject: [PATCH 2/7] support for v0.2 --- libdisplay-info-sys/Cargo.toml | 11 +- libdisplay-info-sys/build.rs | 10 +- libdisplay-info-sys/src/cta.rs | 640 +++++++++++++++++++++++++-- libdisplay-info-sys/src/displayid.rs | 226 +++++++--- libdisplay-info-sys/src/edid.rs | 104 ++++- libdisplay-info-sys/src/info.rs | 329 ++++++++++++++ libdisplay-info/Cargo.toml | 7 +- libdisplay-info/examples/decode.rs | 26 +- libdisplay-info/src/cta.rs | 209 ++++++++- libdisplay-info/src/displayid.rs | 101 +++-- libdisplay-info/src/edid.rs | 4 +- libdisplay-info/src/info.rs | 128 ++++++ 12 files changed, 1658 insertions(+), 137 deletions(-) diff --git a/libdisplay-info-sys/Cargo.toml b/libdisplay-info-sys/Cargo.toml index d09c384..2584497 100644 --- a/libdisplay-info-sys/Cargo.toml +++ b/libdisplay-info-sys/Cargo.toml @@ -4,7 +4,7 @@ categories = ["api-bindings"] description = "Low-level bindings for libdisplay-info." documentation = "https://docs.rs/libdisplay-info-sys/" edition = "2021" -version = "0.1.1" +version = "0.2.0" keywords = ["libdisplay", "DisplayID", "EDID"] license = "MIT" name = "libdisplay-info-sys" @@ -13,9 +13,16 @@ readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +v0_2 = [] + [build-dependencies] system-deps = "7.0.3" +semver = "1.0.24" + +[dependencies] [package.metadata.system-deps.libdisplay-info] name = "libdisplay-info" -version = ">= 0.1.0, < 0.2.0" +version = "0.1.0" +v0_2 = { version = "0.2.0" } diff --git a/libdisplay-info-sys/build.rs b/libdisplay-info-sys/build.rs index eec6d52..501b63d 100644 --- a/libdisplay-info-sys/build.rs +++ b/libdisplay-info-sys/build.rs @@ -1,3 +1,11 @@ fn main() { - system_deps::Config::new().probe().unwrap(); + let deps = system_deps::Config::new().probe().unwrap(); + let native_lib = deps.get_by_name("libdisplay-info").unwrap(); + let native_version = semver::Version::parse(&native_lib.version).unwrap(); + let has_v2 = semver::VersionReq::parse(">=0.2") + .unwrap() + .matches(&native_version); + if has_v2 { + println!("cargo:rustc-cfg=feature=\"v0_2\""); + } } diff --git a/libdisplay-info-sys/src/cta.rs b/libdisplay-info-sys/src/cta.rs index 5451861..51a9864 100644 --- a/libdisplay-info-sys/src/cta.rs +++ b/libdisplay-info-sys/src/cta.rs @@ -948,10 +948,10 @@ extern "C" { data_block: *const di_cta_data_block, ) -> *const *const di_cta_sad; } -#[doc = " Speaker allocation data block (SADB), defined in section 7.5.3.\n\n This block indicates which speakers are present. See figure 6 for the meaning\n of the fields."] +#[doc = " Indicates which speakers are present. See figure 6 for the meaning of the\n fields."] #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct di_cta_speaker_alloc_block { +pub struct di_cta_speaker_allocation { pub flw_frw: bool, pub flc_frc: bool, pub bc: bool, @@ -972,26 +972,26 @@ pub struct di_cta_speaker_alloc_block { pub tpbl_tpbr: bool, } #[test] -fn bindgen_test_layout_di_cta_speaker_alloc_block() { - const UNINIT: ::std::mem::MaybeUninit = +fn bindgen_test_layout_di_cta_speaker_allocation() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::(), + ::std::mem::size_of::(), 18usize, - concat!("Size of: ", stringify!(di_cta_speaker_alloc_block)) + concat!("Size of: ", stringify!(di_cta_speaker_allocation)) ); assert_eq!( - ::std::mem::align_of::(), + ::std::mem::align_of::(), 1usize, - concat!("Alignment of ", stringify!(di_cta_speaker_alloc_block)) + concat!("Alignment of ", stringify!(di_cta_speaker_allocation)) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).flw_frw) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(flw_frw) ) @@ -1001,7 +1001,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 1usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(flc_frc) ) @@ -1011,7 +1011,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 2usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(bc) ) @@ -1021,7 +1021,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 3usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(bl_br) ) @@ -1031,7 +1031,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 4usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(fc) ) @@ -1041,7 +1041,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 5usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(lfe1) ) @@ -1051,7 +1051,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 6usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(fl_fr) ) @@ -1061,7 +1061,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 7usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(tpsil_tpsir) ) @@ -1071,7 +1071,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 8usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(sil_sir) ) @@ -1081,7 +1081,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 9usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(tpbc) ) @@ -1091,7 +1091,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 10usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(lfe2) ) @@ -1101,7 +1101,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 11usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(ls_rs) ) @@ -1111,7 +1111,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 12usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(tpfc) ) @@ -1121,7 +1121,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 13usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(tpc) ) @@ -1131,7 +1131,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 14usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(tpfl_tpfr) ) @@ -1141,7 +1141,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 15usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(btfl_btfr) ) @@ -1151,7 +1151,7 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 16usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(btfc) ) @@ -1161,12 +1161,44 @@ fn bindgen_test_layout_di_cta_speaker_alloc_block() { 17usize, concat!( "Offset of field: ", - stringify!(di_cta_speaker_alloc_block), + stringify!(di_cta_speaker_allocation), "::", stringify!(tpbl_tpbr) ) ); } +#[doc = " Speaker allocation data block (SADB), defined in section 7.5.3."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct di_cta_speaker_alloc_block { + pub speakers: di_cta_speaker_allocation, +} +#[test] +fn bindgen_test_layout_di_cta_speaker_alloc_block() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 18usize, + concat!("Size of: ", stringify!(di_cta_speaker_alloc_block)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(di_cta_speaker_alloc_block)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).speakers) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_alloc_block), + "::", + stringify!(speakers) + ) + ); +} extern "C" { #[doc = " Get the speaker allocation from a CTA data block.\n\n Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_SPEAKER_ALLOC."] pub fn di_cta_data_block_get_speaker_alloc( @@ -2633,6 +2665,172 @@ extern "C" { block: *const di_cta_data_block, ) -> *const di_cta_ycbcr420_cap_map; } +#[cfg(feature = "v0_2")] +pub const di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_UNKNOWN: + di_cta_hdmi_audio_3d_channels = 0; +#[cfg(feature = "v0_2")] +pub const di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_10_2: + di_cta_hdmi_audio_3d_channels = 1; +#[cfg(feature = "v0_2")] +pub const di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_22_2: + di_cta_hdmi_audio_3d_channels = 2; +#[cfg(feature = "v0_2")] +pub const di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_30_2: + di_cta_hdmi_audio_3d_channels = 3; +#[cfg(feature = "v0_2")] +pub type di_cta_hdmi_audio_3d_channels = ::std::os::raw::c_uint; +#[doc = " HDMI 3D Audio"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_cta_hdmi_audio_3d { + pub sads: *const *const di_cta_sad, + pub channels: di_cta_hdmi_audio_3d_channels, + pub speakers: di_cta_speaker_allocation, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_cta_hdmi_audio_3d() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 32usize, + concat!("Size of: ", stringify!(di_cta_hdmi_audio_3d)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(di_cta_hdmi_audio_3d)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).sads) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_3d), + "::", + stringify!(sads) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).channels) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_3d), + "::", + stringify!(channels) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).speakers) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_3d), + "::", + stringify!(speakers) + ) + ); +} +#[doc = " HDMI Multi-Stream Audio"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_cta_hdmi_audio_multi_stream { + pub max_streams: ::std::os::raw::c_int, + pub supports_non_mixed: bool, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_cta_hdmi_audio_multi_stream() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(di_cta_hdmi_audio_multi_stream)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(di_cta_hdmi_audio_multi_stream)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_streams) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_multi_stream), + "::", + stringify!(max_streams) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).supports_non_mixed) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_multi_stream), + "::", + stringify!(supports_non_mixed) + ) + ); +} +#[doc = " HDMI Audio"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_cta_hdmi_audio_block { + pub multi_stream: *const di_cta_hdmi_audio_multi_stream, + pub audio_3d: *const di_cta_hdmi_audio_3d, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_cta_hdmi_audio_block() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(di_cta_hdmi_audio_block)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(di_cta_hdmi_audio_block)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).multi_stream) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_block), + "::", + stringify!(multi_stream) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).audio_3d) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(di_cta_hdmi_audio_block), + "::", + stringify!(audio_3d) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get the HDMI Audio information from a CTA data block.\n\n Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_HDMI_AUDIO."] + pub fn di_cta_data_block_get_hdmi_audio( + block: *const di_cta_data_block, + ) -> *const di_cta_hdmi_audio_block; +} pub const di_cta_infoframe_type_DI_CTA_INFOFRAME_TYPE_AUXILIARY_VIDEO_INFORMATION: di_cta_infoframe_type = 0; pub const di_cta_infoframe_type_DI_CTA_INFOFRAME_TYPE_SOURCE_PRODUCT_DESCRIPTION: @@ -2725,6 +2923,315 @@ extern "C" { block: *const di_cta_data_block, ) -> *const di_cta_infoframe_block; } +#[doc = " Room Configuration Data Block, defined in section 7.5.15."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_cta_room_configuration { + pub speakers: di_cta_speaker_allocation, + pub speaker_count: ::std::os::raw::c_int, + pub has_speaker_location_descriptors: bool, + pub max_x: ::std::os::raw::c_int, + pub max_y: ::std::os::raw::c_int, + pub max_z: ::std::os::raw::c_int, + pub display_x: f64, + pub display_y: f64, + pub display_z: f64, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_cta_room_configuration() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 64usize, + concat!("Size of: ", stringify!(di_cta_room_configuration)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(di_cta_room_configuration)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).speakers) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(speakers) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).speaker_count) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(speaker_count) + ) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).has_speaker_location_descriptors) as usize - ptr as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(has_speaker_location_descriptors) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_x) as usize - ptr as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(max_x) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_y) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(max_y) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_z) as usize - ptr as usize }, + 36usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(max_z) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).display_x) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(display_x) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).display_y) as usize - ptr as usize }, + 48usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(display_y) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).display_z) as usize - ptr as usize }, + 56usize, + concat!( + "Offset of field: ", + stringify!(di_cta_room_configuration), + "::", + stringify!(display_z) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get the Room Configuration from a CTA data block.\n\n Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_ROOM_CONFIG."] + pub fn di_cta_data_block_get_room_configuration( + block: *const di_cta_data_block, + ) -> *const di_cta_room_configuration; +} +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FL: di_cta_speaker_placement = 0; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FR: di_cta_speaker_placement = 1; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FC: di_cta_speaker_placement = 2; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_LFE1: di_cta_speaker_placement = 3; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BL: di_cta_speaker_placement = 4; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BR: di_cta_speaker_placement = 5; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FLC: di_cta_speaker_placement = 6; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FRC: di_cta_speaker_placement = 7; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BC: di_cta_speaker_placement = 8; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_LFE2: di_cta_speaker_placement = 9; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_SIL: di_cta_speaker_placement = 10; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_SIR: di_cta_speaker_placement = 11; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPFL: di_cta_speaker_placement = 12; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPFR: di_cta_speaker_placement = 13; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPFC: di_cta_speaker_placement = 14; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPC: di_cta_speaker_placement = 15; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPBL: di_cta_speaker_placement = 16; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPBR: di_cta_speaker_placement = 17; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPSIL: di_cta_speaker_placement = 18; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPSIR: di_cta_speaker_placement = 19; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPBC: di_cta_speaker_placement = 20; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BTFC: di_cta_speaker_placement = 21; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BTFL: di_cta_speaker_placement = 22; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BRFR: di_cta_speaker_placement = 23; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FLW: di_cta_speaker_placement = 24; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FRW: di_cta_speaker_placement = 25; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_LS: di_cta_speaker_placement = 26; +#[cfg(feature = "v0_2")] +pub const di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_RS: di_cta_speaker_placement = 27; +#[cfg(feature = "v0_2")] +pub type di_cta_speaker_placement = ::std::os::raw::c_uint; +#[doc = " Speaker Location Data Block, defined in section 7.5.16."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_cta_speaker_locations { + pub channel_index: ::std::os::raw::c_int, + pub is_active: bool, + pub has_coords: bool, + pub x: f64, + pub y: f64, + pub z: f64, + pub speaker_id: di_cta_speaker_placement, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_cta_speaker_locations() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 40usize, + concat!("Size of: ", stringify!(di_cta_speaker_locations)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(di_cta_speaker_locations)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).channel_index) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(channel_index) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).is_active) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(is_active) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).has_coords) as usize - ptr as usize }, + 5usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(has_coords) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(x) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(y) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).z) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(z) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).speaker_id) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(di_cta_speaker_locations), + "::", + stringify!(speaker_id) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get an array of Speaker Locations.\n\n Returns NULL if the data block tag is not DI_CTA_DATA_BLOCK_SPEAKER_LOCATION.\n\n The returned array is NULL-terminated."] + pub fn di_cta_data_block_get_speaker_locations( + block: *const di_cta_data_block, + ) -> *const *const di_cta_speaker_locations; +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_displayid_type_i_ii_vii_timing { + _unused: [u8; 0], +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get the DisplayID Type VII Video Timing from a CTA data block.\n\n Returns NULL if the data block tag is not\n DI_CTA_DATA_BLOCK_DISPLAYID_VIDEO_TIMING_VII."] + pub fn di_cta_data_block_get_did_type_vii_timing( + block: *const di_cta_data_block, + ) -> *const di_displayid_type_i_ii_vii_timing; +} #[repr(C)] #[derive(Debug, Copy, Clone)] pub struct di_edid_detailed_timing_def { @@ -2736,3 +3243,84 @@ extern "C" { cta: *const di_edid_cta, ) -> *const *const di_edid_detailed_timing_def; } +#[cfg(feature = "v0_2")] +pub const di_cta_svr_type_DI_CTA_SVR_TYPE_VIC: di_cta_svr_type = 0; +#[cfg(feature = "v0_2")] +pub const di_cta_svr_type_DI_CTA_SVR_TYPE_DTD_INDEX: di_cta_svr_type = 1; +#[cfg(feature = "v0_2")] +pub const di_cta_svr_type_DI_CTA_SVR_TYPE_T7T10VTDB: di_cta_svr_type = 2; +#[cfg(feature = "v0_2")] +pub const di_cta_svr_type_DI_CTA_SVR_TYPE_FIRST_T8VTDB: di_cta_svr_type = 3; +#[cfg(feature = "v0_2")] +pub type di_cta_svr_type = ::std::os::raw::c_uint; +#[doc = " Short Video Reference, defined in section 7.5.12."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_cta_svr { + pub type_: di_cta_svr_type, + pub vic: u8, + pub dtd_index: u8, + pub t7_t10_vtdb_index: u8, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_cta_svr() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(di_cta_svr)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(di_cta_svr)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_cta_svr), + "::", + stringify!(type_) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).vic) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_cta_svr), + "::", + stringify!(vic) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).dtd_index) as usize - ptr as usize }, + 5usize, + concat!( + "Offset of field: ", + stringify!(di_cta_svr), + "::", + stringify!(dtd_index) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).t7_t10_vtdb_index) as usize - ptr as usize }, + 6usize, + concat!( + "Offset of field: ", + stringify!(di_cta_svr), + "::", + stringify!(t7_t10_vtdb_index) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get an array of Short Video References (SVRs) from a CTA data block. The\n first SVR refers to the most-preferred Video Format, while the next SVRs\n are listed in order of decreasing preference.\n\n Returns NULL if the data block tag is not\n DI_CTA_DATA_BLOCK_VIDEO_FORMAT_PREF.\n\n The returned array is NULL-terminated."] + pub fn di_cta_data_block_get_svrs(block: *const di_cta_data_block) -> *const *const di_cta_svr; +} diff --git a/libdisplay-info-sys/src/displayid.rs b/libdisplay-info-sys/src/displayid.rs index e1d65ab..4ad694f 100644 --- a/libdisplay-info-sys/src/displayid.rs +++ b/libdisplay-info-sys/src/displayid.rs @@ -330,44 +330,41 @@ extern "C" { data_block: *const di_displayid_data_block, ) -> *const di_displayid_display_params; } -pub const di_displayid_type_i_timing_stereo_3d_DI_DISPLAYID_TYPE_I_TIMING_STEREO_3D_NEVER: - di_displayid_type_i_timing_stereo_3d = 0; -pub const di_displayid_type_i_timing_stereo_3d_DI_DISPLAYID_TYPE_I_TIMING_STEREO_3D_ALWAYS: - di_displayid_type_i_timing_stereo_3d = 1; -pub const di_displayid_type_i_timing_stereo_3d_DI_DISPLAYID_TYPE_I_TIMING_STEREO_3D_USER: - di_displayid_type_i_timing_stereo_3d = 2; -pub type di_displayid_type_i_timing_stereo_3d = ::std::os::raw::c_uint; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_1_1: - di_displayid_type_i_timing_aspect_ratio = 0; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_5_4: - di_displayid_type_i_timing_aspect_ratio = 1; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_4_3: - di_displayid_type_i_timing_aspect_ratio = 2; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_15_9: - di_displayid_type_i_timing_aspect_ratio = 3; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_16_9: - di_displayid_type_i_timing_aspect_ratio = 4; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_16_10: - di_displayid_type_i_timing_aspect_ratio = 5; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_64_27: - di_displayid_type_i_timing_aspect_ratio = 6; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_256_135 : di_displayid_type_i_timing_aspect_ratio = 7 ; -pub const di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_UNDEFINED : di_displayid_type_i_timing_aspect_ratio = 8 ; -pub type di_displayid_type_i_timing_aspect_ratio = ::std::os::raw::c_uint; -pub const di_displayid_type_i_timing_sync_polarity_DI_DISPLAYID_TYPE_I_TIMING_SYNC_NEGATIVE: - di_displayid_type_i_timing_sync_polarity = 0; -pub const di_displayid_type_i_timing_sync_polarity_DI_DISPLAYID_TYPE_I_TIMING_SYNC_POSITIVE: - di_displayid_type_i_timing_sync_polarity = 1; -pub type di_displayid_type_i_timing_sync_polarity = ::std::os::raw::c_uint; -#[doc = " Type I timing, defined in section 4.4.1."] +pub const di_displayid_type_i_ii_vii_timing_stereo_3d_DI_DISPLAYID_TYPE_I_II_VII_TIMING_STEREO_3D_NEVER : di_displayid_type_i_ii_vii_timing_stereo_3d = 0 ; +pub const di_displayid_type_i_ii_vii_timing_stereo_3d_DI_DISPLAYID_TYPE_I_II_VII_TIMING_STEREO_3D_ALWAYS : di_displayid_type_i_ii_vii_timing_stereo_3d = 1 ; +pub const di_displayid_type_i_ii_vii_timing_stereo_3d_DI_DISPLAYID_TYPE_I_II_VII_TIMING_STEREO_3D_USER : di_displayid_type_i_ii_vii_timing_stereo_3d = 2 ; +pub type di_displayid_type_i_ii_vii_timing_stereo_3d = ::std::os::raw::c_uint; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_1_1: + di_displayid_timing_aspect_ratio = 0; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_5_4: + di_displayid_timing_aspect_ratio = 1; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_4_3: + di_displayid_timing_aspect_ratio = 2; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_15_9: + di_displayid_timing_aspect_ratio = 3; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_16_9: + di_displayid_timing_aspect_ratio = 4; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_16_10: + di_displayid_timing_aspect_ratio = 5; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_64_27: + di_displayid_timing_aspect_ratio = 6; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_256_135: + di_displayid_timing_aspect_ratio = 7; +pub const di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_UNDEFINED: + di_displayid_timing_aspect_ratio = 8; +pub type di_displayid_timing_aspect_ratio = ::std::os::raw::c_uint; +pub const di_displayid_type_i_ii_vii_timing_sync_polarity_DI_DISPLAYID_TYPE_I_II_VII_TIMING_SYNC_NEGATIVE : di_displayid_type_i_ii_vii_timing_sync_polarity = 0 ; +pub const di_displayid_type_i_ii_vii_timing_sync_polarity_DI_DISPLAYID_TYPE_I_II_VII_TIMING_SYNC_POSITIVE : di_displayid_type_i_ii_vii_timing_sync_polarity = 1 ; +pub type di_displayid_type_i_ii_vii_timing_sync_polarity = ::std::os::raw::c_uint; +#[doc = " Type I timing, defined in DisplayID 1.3 section 4.4.1 and\n Type II timing, defined in DisplayID 1.3 section 4.4.2 and\n Type VII timing, defined in DisplayID 2.0 section 4.3.1."] #[repr(C)] #[derive(Debug, Copy, Clone)] -pub struct di_displayid_type_i_timing { +pub struct di_displayid_type_i_ii_vii_timing { pub pixel_clock_mhz: f64, pub preferred: bool, - pub stereo_3d: di_displayid_type_i_timing_stereo_3d, + pub stereo_3d: di_displayid_type_i_ii_vii_timing_stereo_3d, pub interlaced: bool, - pub aspect_ratio: di_displayid_type_i_timing_aspect_ratio, + pub aspect_ratio: di_displayid_timing_aspect_ratio, pub horiz_active: i32, pub vert_active: i32, pub horiz_blank: i32, @@ -376,30 +373,33 @@ pub struct di_displayid_type_i_timing { pub vert_offset: i32, pub horiz_sync_width: i32, pub vert_sync_width: i32, - pub horiz_sync_polarity: di_displayid_type_i_timing_sync_polarity, - pub vert_sync_polarity: di_displayid_type_i_timing_sync_polarity, + pub horiz_sync_polarity: di_displayid_type_i_ii_vii_timing_sync_polarity, + pub vert_sync_polarity: di_displayid_type_i_ii_vii_timing_sync_polarity, } #[test] -fn bindgen_test_layout_di_displayid_type_i_timing() { - const UNINIT: ::std::mem::MaybeUninit = +fn bindgen_test_layout_di_displayid_type_i_ii_vii_timing() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); let ptr = UNINIT.as_ptr(); assert_eq!( - ::std::mem::size_of::(), + ::std::mem::size_of::(), 64usize, - concat!("Size of: ", stringify!(di_displayid_type_i_timing)) + concat!("Size of: ", stringify!(di_displayid_type_i_ii_vii_timing)) ); assert_eq!( - ::std::mem::align_of::(), + ::std::mem::align_of::(), 8usize, - concat!("Alignment of ", stringify!(di_displayid_type_i_timing)) + concat!( + "Alignment of ", + stringify!(di_displayid_type_i_ii_vii_timing) + ) ); assert_eq!( unsafe { ::std::ptr::addr_of!((*ptr).pixel_clock_mhz) as usize - ptr as usize }, 0usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(pixel_clock_mhz) ) @@ -409,7 +409,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 8usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(preferred) ) @@ -419,7 +419,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 12usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(stereo_3d) ) @@ -429,7 +429,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 16usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(interlaced) ) @@ -439,7 +439,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 20usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(aspect_ratio) ) @@ -449,7 +449,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 24usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(horiz_active) ) @@ -459,7 +459,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 28usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(vert_active) ) @@ -469,7 +469,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 32usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(horiz_blank) ) @@ -479,7 +479,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 36usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(vert_blank) ) @@ -489,7 +489,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 40usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(horiz_offset) ) @@ -499,7 +499,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 44usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(vert_offset) ) @@ -509,7 +509,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 48usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(horiz_sync_width) ) @@ -519,7 +519,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 52usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(vert_sync_width) ) @@ -529,7 +529,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 56usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(horiz_sync_polarity) ) @@ -539,7 +539,7 @@ fn bindgen_test_layout_di_displayid_type_i_timing() { 60usize, concat!( "Offset of field: ", - stringify!(di_displayid_type_i_timing), + stringify!(di_displayid_type_i_ii_vii_timing), "::", stringify!(vert_sync_polarity) ) @@ -549,7 +549,14 @@ extern "C" { #[doc = " Get type I timings from a DisplayID data block.\n\n The returned array is NULL-terminated.\n\n Returns NULL if the data block tag isn't\n DI_DISPLAYID_DATA_BLOCK_TYPE_I_TIMING."] pub fn di_displayid_data_block_get_type_i_timings( data_block: *const di_displayid_data_block, - ) -> *const *const di_displayid_type_i_timing; + ) -> *const *const di_displayid_type_i_ii_vii_timing; +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get type II timings from a DisplayID data block.\n\n The returned array is NULL-terminated.\n\n Returns NULL if the data block tag isn't\n DI_DISPLAYID_DATA_BLOCK_TYPE_II_TIMING."] + pub fn di_displayid_data_block_get_type_ii_timings( + data_block: *const di_displayid_data_block, + ) -> *const *const di_displayid_type_i_ii_vii_timing; } pub const di_displayid_tiled_topo_missing_recv_behavior_DI_DISPLAYID_TILED_TOPO_MISSING_RECV_UNDEF : di_displayid_tiled_topo_missing_recv_behavior = 0 ; pub const di_displayid_tiled_topo_missing_recv_behavior_DI_DISPLAYID_TILED_TOPO_MISSING_RECV_TILE_ONLY : di_displayid_tiled_topo_missing_recv_behavior = 1 ; @@ -829,6 +836,111 @@ extern "C" { data_block: *const di_displayid_data_block, ) -> *const di_displayid_tiled_topo; } +#[cfg(feature = "v0_2")] +pub const di_displayid_type_iii_timing_algo_DI_DISPLAYID_TYPE_III_TIMING_CVT_STANDARD_BLANKING: + di_displayid_type_iii_timing_algo = 0; +#[cfg(feature = "v0_2")] +pub const di_displayid_type_iii_timing_algo_DI_DISPLAYID_TYPE_III_TIMING_CVT_REDUCED_BLANKING: + di_displayid_type_iii_timing_algo = 1; +#[doc = " Formula/algorithm for type III timings."] +#[cfg(feature = "v0_2")] +pub type di_displayid_type_iii_timing_algo = ::std::os::raw::c_uint; +#[doc = " Type III timing, defined in section 4.4.3."] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_displayid_type_iii_timing { + pub preferred: bool, + pub algo: di_displayid_type_iii_timing_algo, + pub aspect_ratio: di_displayid_timing_aspect_ratio, + pub horiz_active: i32, + pub interlaced: bool, + pub refresh_rate_hz: i32, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_displayid_type_iii_timing() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(di_displayid_type_iii_timing)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(di_displayid_type_iii_timing)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).preferred) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_displayid_type_iii_timing), + "::", + stringify!(preferred) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).algo) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_displayid_type_iii_timing), + "::", + stringify!(algo) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).aspect_ratio) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(di_displayid_type_iii_timing), + "::", + stringify!(aspect_ratio) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).horiz_active) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(di_displayid_type_iii_timing), + "::", + stringify!(horiz_active) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).interlaced) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(di_displayid_type_iii_timing), + "::", + stringify!(interlaced) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).refresh_rate_hz) as usize - ptr as usize }, + 20usize, + concat!( + "Offset of field: ", + stringify!(di_displayid_type_iii_timing), + "::", + stringify!(refresh_rate_hz) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get type III timings from a DisplayID data block.\n\n The returned array is NULL-terminated.\n\n Returns NULL if the data block tag isn't\n DI_DISPLAYID_DATA_BLOCK_TYPE_III_TIMING."] + pub fn di_displayid_data_block_get_type_iii_timings( + data_block: *const di_displayid_data_block, + ) -> *const *const di_displayid_type_iii_timing; +} extern "C" { #[doc = " Get DisplayID data blocks.\n\n The returned array is NULL-terminated."] pub fn di_displayid_get_data_blocks( diff --git a/libdisplay-info-sys/src/edid.rs b/libdisplay-info-sys/src/edid.rs index fd84bf3..a3d15c5 100644 --- a/libdisplay-info-sys/src/edid.rs +++ b/libdisplay-info-sys/src/edid.rs @@ -1727,6 +1727,10 @@ fn bindgen_test_layout_di_edid_display_range_limits_cvt() { ) ); } +#[cfg(not(feature = "v0_2"))] +pub type di_edid_display_range_limits_max_pixel_clock_hz = i32; +#[cfg(feature = "v0_2")] +pub type di_edid_display_range_limits_max_pixel_clock_hz = i64; #[doc = " EDID display range limits, defined in section 3.10.3.3.1."] #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -1735,12 +1739,13 @@ pub struct di_edid_display_range_limits { pub max_vert_rate_hz: i32, pub min_horiz_rate_hz: i32, pub max_horiz_rate_hz: i32, - pub max_pixel_clock_hz: i32, + pub max_pixel_clock_hz: di_edid_display_range_limits_max_pixel_clock_hz, pub type_: di_edid_display_range_limits_type, pub secondary_gtf: *const di_edid_display_range_limits_secondary_gtf, pub cvt: *const di_edid_display_range_limits_cvt, } #[test] +#[cfg(not(feature = "v0_2"))] fn bindgen_test_layout_di_edid_display_range_limits() { const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); @@ -1836,6 +1841,103 @@ fn bindgen_test_layout_di_edid_display_range_limits() { ) ); } +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_edid_display_range_limits() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 48usize, + concat!("Size of: ", stringify!(di_edid_display_range_limits)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(di_edid_display_range_limits)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).min_vert_rate_hz) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(min_vert_rate_hz) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_vert_rate_hz) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(max_vert_rate_hz) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).min_horiz_rate_hz) as usize - ptr as usize }, + 8usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(min_horiz_rate_hz) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_horiz_rate_hz) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(max_horiz_rate_hz) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).max_pixel_clock_hz) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(max_pixel_clock_hz) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize }, + 24usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(type_) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).secondary_gtf) as usize - ptr as usize }, + 32usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(secondary_gtf) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).cvt) as usize - ptr as usize }, + 40usize, + concat!( + "Offset of field: ", + stringify!(di_edid_display_range_limits), + "::", + stringify!(cvt) + ) + ); +} extern "C" { #[doc = " Get the contents of a display range limits descriptor.\n\n Returns NULL if the display descriptor tag isn't\n DI_EDID_DISPLAY_DESCRIPTOR_RANGE_LIMITS."] pub fn di_edid_display_descriptor_get_range_limits( diff --git a/libdisplay-info-sys/src/info.rs b/libdisplay-info-sys/src/info.rs index d1de4d3..ab162f7 100644 --- a/libdisplay-info-sys/src/info.rs +++ b/libdisplay-info-sys/src/info.rs @@ -39,3 +39,332 @@ extern "C" { #[doc = " Get the serial of the display device.\n\n This is the product serial string or the serial number.\n This string is informational and not meant to be used in programmatic\n decisions, configuration keys, etc.\n\n The string is in UTF-8 and may contain any characters except ASCII control\n codes.\n\n The caller is responsible for free'ing the returned string.\n NULL is returned if the information is not available."] pub fn di_info_get_serial(info: *const di_info) -> *mut ::std::os::raw::c_char; } +#[doc = " Display HDR static metadata"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_hdr_static_metadata { + pub desired_content_max_luminance: f32, + pub desired_content_max_frame_avg_luminance: f32, + pub desired_content_min_luminance: f32, + pub type1: bool, + pub traditional_sdr: bool, + pub traditional_hdr: bool, + pub pq: bool, + pub hlg: bool, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_hdr_static_metadata() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 20usize, + concat!("Size of: ", stringify!(di_hdr_static_metadata)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(di_hdr_static_metadata)) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).desired_content_max_luminance) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(desired_content_max_luminance) + ) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).desired_content_max_frame_avg_luminance) as usize + - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(desired_content_max_frame_avg_luminance) + ) + ); + assert_eq!( + unsafe { + ::std::ptr::addr_of!((*ptr).desired_content_min_luminance) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(desired_content_min_luminance) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).type1) as usize - ptr as usize }, + 12usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(type1) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).traditional_sdr) as usize - ptr as usize }, + 13usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(traditional_sdr) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).traditional_hdr) as usize - ptr as usize }, + 14usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(traditional_hdr) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).pq) as usize - ptr as usize }, + 15usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(pq) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).hlg) as usize - ptr as usize }, + 16usize, + concat!( + "Offset of field: ", + stringify!(di_hdr_static_metadata), + "::", + stringify!(hlg) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get HDR static metadata support information as defined in ANSI/CTA-861-H\n as HDR Static Metadata Data Block.\n\n The returned pointer is owned by the struct di_info passed in. It remains\n valid only as long as the di_info exists, and must not be freed by the\n caller.\n\n This function does not return NULL. When HDR static metadata does not exist,\n all luminance fields are zero and only traditional_sdr is flagged as\n supported."] + pub fn di_info_get_hdr_static_metadata(info: *const di_info) -> *const di_hdr_static_metadata; +} +#[doc = " CIE 1931 2-degree observer chromaticity coordinates"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_chromaticity_cie1931 { + pub x: f32, + pub y: f32, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_chromaticity_cie1931() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(di_chromaticity_cie1931)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(di_chromaticity_cie1931)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_chromaticity_cie1931), + "::", + stringify!(x) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).y) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_chromaticity_cie1931), + "::", + stringify!(y) + ) + ); +} +#[doc = " Display color primaries and default white point"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_color_primaries { + pub has_primaries: bool, + pub has_default_white_point: bool, + pub primary: [di_chromaticity_cie1931; 3usize], + pub default_white: di_chromaticity_cie1931, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_color_primaries() { + const UNINIT: ::std::mem::MaybeUninit = ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 36usize, + concat!("Size of: ", stringify!(di_color_primaries)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(di_color_primaries)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).has_primaries) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_color_primaries), + "::", + stringify!(has_primaries) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).has_default_white_point) as usize - ptr as usize }, + 1usize, + concat!( + "Offset of field: ", + stringify!(di_color_primaries), + "::", + stringify!(has_default_white_point) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).primary) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_color_primaries), + "::", + stringify!(primary) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).default_white) as usize - ptr as usize }, + 28usize, + concat!( + "Offset of field: ", + stringify!(di_color_primaries), + "::", + stringify!(default_white) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get display color primaries and default white point\n\n Get the parameters of the default RGB colorimetry mode which is always\n supported. Primaries for monochrome displays might be all zeroes.\n\n These primaries might not be display's physical primaries, but only the\n primaries of the default RGB colorimetry signal when using IT Video Format\n (ANSI/CTA-861-H, Section 5).\n\n The returned pointer is owned by the struct di_info passed in. It remains\n valid only as long as the di_info exists, and must not be freed by the\n caller.\n\n This function does not return NULL."] + pub fn di_info_get_default_color_primaries(info: *const di_info) -> *const di_color_primaries; +} +#[doc = " Additional signal colorimetry encodings supported by the display"] +#[repr(C)] +#[derive(Debug, Copy, Clone)] +#[cfg(feature = "v0_2")] +pub struct di_supported_signal_colorimetry { + pub bt2020_cycc: bool, + pub bt2020_ycc: bool, + pub bt2020_rgb: bool, + pub st2113_rgb: bool, + pub ictcp: bool, +} +#[test] +#[cfg(feature = "v0_2")] +fn bindgen_test_layout_di_supported_signal_colorimetry() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 5usize, + concat!("Size of: ", stringify!(di_supported_signal_colorimetry)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(di_supported_signal_colorimetry)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).bt2020_cycc) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(di_supported_signal_colorimetry), + "::", + stringify!(bt2020_cycc) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).bt2020_ycc) as usize - ptr as usize }, + 1usize, + concat!( + "Offset of field: ", + stringify!(di_supported_signal_colorimetry), + "::", + stringify!(bt2020_ycc) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).bt2020_rgb) as usize - ptr as usize }, + 2usize, + concat!( + "Offset of field: ", + stringify!(di_supported_signal_colorimetry), + "::", + stringify!(bt2020_rgb) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).st2113_rgb) as usize - ptr as usize }, + 3usize, + concat!( + "Offset of field: ", + stringify!(di_supported_signal_colorimetry), + "::", + stringify!(st2113_rgb) + ) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).ictcp) as usize - ptr as usize }, + 4usize, + concat!( + "Offset of field: ", + stringify!(di_supported_signal_colorimetry), + "::", + stringify!(ictcp) + ) + ); +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get signal colorimetry encodings supported by the display\n\n These signal colorimetry encodings are supported in addition to the\n display's default RGB colorimetry. When you wish to use one of the additional\n encodings, they need to be explicitly enabled in the video signal. How to\n do that is specific to the signalling used, e.g. HDMI.\n\n Signal colorimetry encoding provides the color space that the signal is\n encoded for. This includes primary and white point chromaticities, and the\n YCbCr-RGB conversion if necessary. Also the transfer function is implied\n unless explicitly set otherwise, e.g. with HDR static metadata.\n See ANSI/CTA-861-H for details.\n\n The signal color volume can be considerably larger than the physically\n displayable color volume.\n\n The returned pointer is owned by the struct di_info passed in. It remains\n valid only as long as the di_info exists, and must not be freed by the\n caller.\n\n This function does not return NULL."] + pub fn di_info_get_supported_signal_colorimetry( + info: *const di_info, + ) -> *const di_supported_signal_colorimetry; +} +#[cfg(feature = "v0_2")] +extern "C" { + #[doc = " Get display default transfer characteristic exponent (gamma)\n\n This should be the display gamma value when the display has been reset to\n its factory defaults, and it is driven with the default RGB colorimetry.\n The value is zero when unknown."] + pub fn di_info_get_default_gamma(info: *const di_info) -> f32; +} diff --git a/libdisplay-info/Cargo.toml b/libdisplay-info/Cargo.toml index e7f72c1..cb4fa22 100644 --- a/libdisplay-info/Cargo.toml +++ b/libdisplay-info/Cargo.toml @@ -4,7 +4,7 @@ categories = ["api-bindings"] description = "EDID and DisplayID library." documentation = "https://docs.rs/libdisplay-info/" edition = "2021" -version = "0.1.0" +version = "0.2.0" keywords = ["libdisplay", "DisplayID", "EDID"] license = "MIT" name = "libdisplay-info" @@ -13,8 +13,11 @@ readme = "../README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +v0_2 = ["libdisplay-info-sys/v0_2"] + [dependencies] -libdisplay-info-sys = { version = "0.1.0", path = "../libdisplay-info-sys" } +libdisplay-info-sys = { version = "0.2.0", path = "../libdisplay-info-sys" } libc = "0.2.155" thiserror = "1.0.63" libdisplay-info-derive = { version = "0.1.0", path = "../libdisplay-info-derive" } diff --git a/libdisplay-info/examples/decode.rs b/libdisplay-info/examples/decode.rs index 12cb71d..04cc428 100644 --- a/libdisplay-info/examples/decode.rs +++ b/libdisplay-info/examples/decode.rs @@ -804,7 +804,7 @@ fn print_cta(cta: CTA<'_>) { } } cta::DataBlockTag::SpeakerAlloc => { - let speaker_alloc = data_block.speaker_alloc().unwrap(); + let speaker_alloc = data_block.speaker_alloc().unwrap().speakers; if speaker_alloc.flw_frw { println!(" FLw/FRw - Front Left/Right Wide"); @@ -1514,7 +1514,7 @@ fn print_displayid_type_i_timing_block(data_block: &displayid::DataBlockRef) { } } -fn print_displayid_type_i_timing(t: displayid::TypeITiming) { +fn print_displayid_type_i_timing(t: displayid::TypeIIIVIITiming) { let (horiz_ratio, vert_ratio) = displayid_type_i_timing_aspect_ratio(t.aspect_ratio); let horiz_total = t.horiz_active + t.horiz_blank; @@ -1536,7 +1536,7 @@ fn print_displayid_type_i_timing(t: displayid::TypeITiming) { t.pixel_clock_mhz ); print!(" (aspect "); - if t.aspect_ratio == displayid::TypeITimingAspectRatio::Undefined { + if t.aspect_ratio == displayid::TimingAspectRatio::Undefined { print!("undefined"); } else { print!("{}:{}", horiz_ratio, vert_ratio); @@ -1562,17 +1562,17 @@ fn print_displayid_type_i_timing(t: displayid::TypeITiming) { println!(); } -fn displayid_type_i_timing_aspect_ratio(ratio: displayid::TypeITimingAspectRatio) -> (i32, i32) { +fn displayid_type_i_timing_aspect_ratio(ratio: displayid::TimingAspectRatio) -> (i32, i32) { match ratio { - displayid::TypeITimingAspectRatio::_1_1 => (1, 1), - displayid::TypeITimingAspectRatio::_5_4 => (5, 4), - displayid::TypeITimingAspectRatio::_4_3 => (4, 3), - displayid::TypeITimingAspectRatio::_15_9 => (15, 9), - displayid::TypeITimingAspectRatio::_16_9 => (16, 9), - displayid::TypeITimingAspectRatio::_16_10 => (16, 10), - displayid::TypeITimingAspectRatio::_64_27 => (64, 27), - displayid::TypeITimingAspectRatio::_256_135 => (256, 135), - displayid::TypeITimingAspectRatio::Undefined => (0, 0), + displayid::TimingAspectRatio::_1_1 => (1, 1), + displayid::TimingAspectRatio::_5_4 => (5, 4), + displayid::TimingAspectRatio::_4_3 => (4, 3), + displayid::TimingAspectRatio::_15_9 => (15, 9), + displayid::TimingAspectRatio::_16_9 => (16, 9), + displayid::TimingAspectRatio::_16_10 => (16, 10), + displayid::TimingAspectRatio::_64_27 => (64, 27), + displayid::TimingAspectRatio::_256_135 => (256, 135), + displayid::TimingAspectRatio::Undefined => (0, 0), } } diff --git a/libdisplay-info/src/cta.rs b/libdisplay-info/src/cta.rs index 920fe3b..0c4b7ea 100644 --- a/libdisplay-info/src/cta.rs +++ b/libdisplay-info/src/cta.rs @@ -245,6 +245,55 @@ impl DataBlockRef { pub fn infoframe(&self) -> Option { InfoframeBlockRef::from_ptr(unsafe { ffi::cta::di_cta_data_block_get_infoframe(self.0) }) } + + /// Get the HDMI Audio information from a CTA data block. + /// + /// Returns `None` if the data block tag is not DI_CTA_DATA_BLOCK_HDMI_AUDIO. + #[cfg(feature = "v0_2")] + pub fn hdmi_audio(&self) -> Option { + HdmiAudioBlockRef::from_ptr(unsafe { ffi::cta::di_cta_data_block_get_hdmi_audio(self.0) }) + } + + /// Get the Room Configuration from a CTA data block. + /// + /// Returns `None` if the data block tag is not DI_CTA_DATA_BLOCK_ROOM_CONFIG. + #[cfg(feature = "v0_2")] + pub fn room_configuration(&self) -> Option { + RoomConfiguration::from_ptr(unsafe { + ffi::cta::di_cta_data_block_get_room_configuration(self.0) + }) + } + + /// Get an array of Speaker Locations. + /// + /// Returns `None` if the data block tag is not DI_CTA_DATA_BLOCK_SPEAKER_LOCATION. + #[cfg(feature = "v0_2")] + pub fn speaker_locations(&self) -> impl Iterator { + FFIIter::new(unsafe { ffi::cta::di_cta_data_block_get_speaker_locations(self.0) }) + } + + /// Get the DisplayID Type VII Video Timing from a CTA data block. + /// + /// Returns `None` if the data block tag is not + /// DI_CTA_DATA_BLOCK_DISPLAYID_VIDEO_TIMING_VII. + #[cfg(feature = "v0_2")] + pub fn did_type_vii_timing(&self) -> Option { + crate::displayid::TypeIIIVIITiming::from_ptr(unsafe { + ffi::cta::di_cta_data_block_get_did_type_vii_timing(self.0) + as *const ffi::displayid::di_displayid_type_i_ii_vii_timing + }) + } + + /// Get an array of Short Video References (SVRs) from a CTA data block. The + /// first SVR refers to the most-preferred Video Format, while the next SVRs + /// are listed in order of decreasing preference. + /// + /// Returns `None` if the data block tag is not + /// DI_CTA_DATA_BLOCK_VIDEO_FORMAT_PREF. + #[cfg(feature = "v0_2")] + pub fn svrs(&self) -> impl Iterator { + FFIIter::new(unsafe { ffi::cta::di_cta_data_block_get_svrs(self.0) }) + } } /// CTA data block tag. @@ -437,13 +486,12 @@ pub struct Sad { pub wma_pro: Option, } -/// Speaker allocation data block (SADB), defined in section 7.5.3. +/// Indicates which speakers are present. /// -/// This block indicates which speakers are present. See figure 6 for the meaning -/// of the fields. +/// See figure 6 for the meaning of the fields. #[derive(Debug, Copy, Clone, FFIFrom)] -#[ffi(ffi::cta::di_cta_speaker_alloc_block)] -pub struct SpeakerAllocBlock { +#[ffi(ffi::cta::di_cta_speaker_allocation)] +pub struct SpeakerAllocation { pub flw_frw: bool, pub flc_frc: bool, pub bc: bool, @@ -464,6 +512,13 @@ pub struct SpeakerAllocBlock { pub tpbl_tpbr: bool, } +/// Speaker allocation data block (SADB), defined in section 7.5.3. +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::cta::di_cta_speaker_alloc_block)] +pub struct SpeakerAllocBlock { + pub speakers: SpeakerAllocation, +} + /// Over- and underscan capability. #[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] #[ffi(ffi::cta::di_cta_video_cap_over_underscan)] @@ -865,3 +920,147 @@ impl InfoframeBlockRef { FFIIter::new(unsafe { (*self.0).infoframes }) } } + +/// InfoFrame types, defined in table 7. +/// +/// Note, the enum values don't match the specification. +#[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] +#[ffi(ffi::cta::di_cta_hdmi_audio_3d_channels)] +#[repr(u32)] +#[cfg(feature = "v0_2")] +pub enum HdmiAudio3DChannels { + Unknown = ffi::cta::di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_UNKNOWN, + _10_2 = ffi::cta::di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_10_2, + _22_2 = ffi::cta::di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_22_2, + _30_2 = ffi::cta::di_cta_hdmi_audio_3d_channels_DI_CTA_HDMI_AUDIO_3D_CHANNELS_30_2, +} + +/// HDMI 3D Audio +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::cta::di_cta_hdmi_audio_3d)] +#[wrap] +#[cfg(feature = "v0_2")] +pub struct HdmiAudio3d { + pub channels: HdmiAudio3DChannels, + pub speakers: SpeakerAllocation, +} + +#[cfg(feature = "v0_2")] +impl HdmiAudio3dRef { + pub fn sads(&self) -> impl Iterator { + FFIIter::new(unsafe { (*self.0).sads }) + } +} + +/// HDMI Multi-Stream Audio +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::cta::di_cta_hdmi_audio_multi_stream)] +#[cfg(feature = "v0_2")] +pub struct HdmiAudioMultiStream { + pub max_streams: ::std::os::raw::c_int, + pub supports_non_mixed: bool, +} + +/// HDMI Audio +#[derive(Debug, FFIFrom)] +#[ffi(ffi::cta::di_cta_hdmi_audio_block)] +#[wrap] +#[cfg(feature = "v0_2")] +pub struct HdmiAudioBlock { + #[ptr_deref] + pub multi_stream: Option, +} + +#[cfg(feature = "v0_2")] +impl HdmiAudioBlockRef { + pub fn audio_3d(&self) -> Option { + HdmiAudio3dRef::from_ptr(unsafe { (*self.0).audio_3d }) + } +} + +/// Room Configuration Data Block, defined in section 7.5.15. +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::cta::di_cta_room_configuration)] +#[cfg(feature = "v0_2")] +pub struct RoomConfiguration { + pub speakers: SpeakerAllocation, + pub speaker_count: ::std::os::raw::c_int, + pub has_speaker_location_descriptors: bool, + pub max_x: ::std::os::raw::c_int, + pub max_y: ::std::os::raw::c_int, + pub max_z: ::std::os::raw::c_int, + pub display_x: f64, + pub display_y: f64, + pub display_z: f64, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] +#[ffi(ffi::cta::di_cta_speaker_placement)] +#[repr(u32)] +#[cfg(feature = "v0_2")] +pub enum SpeakerPlacement { + FL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FL, + FR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FR, + FC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FC, + LFE1 = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_LFE1, + BL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BL, + BR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BR, + FLC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FLC, + FRC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FRC, + BC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BC, + LFE2 = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_LFE2, + SIL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_SIL, + SIR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_SIR, + TPFL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPFL, + TPFR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPFR, + TPFC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPFC, + TPC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPC, + TPBL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPBL, + TPBR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPBR, + TPSIL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPSIL, + TPSIR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPSIR, + TPBC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_TPBC, + BTFC = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BTFC, + BTFL = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BTFL, + BRFR = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_BRFR, + FLW = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FLW, + FRW = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_FRW, + LS = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_LS, + RS = ffi::cta::di_cta_speaker_placement_DI_CTA_SPEAKER_PLACEMENT_RS, +} + +/// Speaker Location Data Block, defined in section 7.5.16. +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::cta::di_cta_speaker_locations)] +#[cfg(feature = "v0_2")] +pub struct SpeakerLocations { + pub channel_index: ::std::os::raw::c_int, + pub is_active: bool, + pub has_coords: bool, + pub x: f64, + pub y: f64, + pub z: f64, + pub speaker_id: SpeakerPlacement, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] +#[ffi(ffi::cta::di_cta_svr_type)] +#[repr(u32)] +#[cfg(feature = "v0_2")] +pub enum SvrType { + VIC = ffi::cta::di_cta_svr_type_DI_CTA_SVR_TYPE_VIC, + DtdIndex = ffi::cta::di_cta_svr_type_DI_CTA_SVR_TYPE_DTD_INDEX, + T7T10VTDB = ffi::cta::di_cta_svr_type_DI_CTA_SVR_TYPE_T7T10VTDB, + FirstT8vtdb = ffi::cta::di_cta_svr_type_DI_CTA_SVR_TYPE_FIRST_T8VTDB, +} + +/// Short Video Reference, defined in section 7.5.12. +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::cta::di_cta_svr)] +#[cfg(feature = "v0_2")] +pub struct Svr { + pub type_: SvrType, + pub vic: u8, + pub dtd_index: u8, + pub t7_t10_vtdb_index: u8, +} diff --git a/libdisplay-info/src/displayid.rs b/libdisplay-info/src/displayid.rs index 80b7717..354bc28 100644 --- a/libdisplay-info/src/displayid.rs +++ b/libdisplay-info/src/displayid.rs @@ -137,10 +137,28 @@ impl DataBlockRef { /// Get type I timings from a DisplayID data block. /// Returns `None` if the data block tag isn't /// DI_DISPLAYID_DATA_BLOCK_TYPE_I_TIMING. - pub fn type_i_timings(&self) -> impl Iterator { + pub fn type_i_timings(&self) -> impl Iterator { FFIIter::new(unsafe { ffi::displayid::di_displayid_data_block_get_type_i_timings(self.0) }) } + /// Get type II timings from a DisplayID data block. + /// Returns `None` if the data block tag isn't + /// DI_DISPLAYID_DATA_BLOCK_TYPE_II_TIMING. + #[cfg(feature = "v0_2")] + pub fn type_ii_timings(&self) -> impl Iterator { + FFIIter::new(unsafe { ffi::displayid::di_displayid_data_block_get_type_ii_timings(self.0) }) + } + + /// Get type III timings from a DisplayID data block. + /// Returns `None` if the data block tag isn't + /// DI_DISPLAYID_DATA_BLOCK_TYPE_III_TIMING. + #[cfg(feature = "v0_2")] + pub fn type_iii_timings(&self) -> impl Iterator { + FFIIter::new(unsafe { + ffi::displayid::di_displayid_data_block_get_type_iii_timings(self.0) + }) + } + /// Get tiled display topology from a DisplayID data block. /// /// Returns `None` if the data block tag isn't @@ -184,46 +202,50 @@ pub struct DisplayParams { } #[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] -#[ffi(ffi::displayid::di_displayid_type_i_timing_stereo_3d)] +#[ffi(ffi::displayid::di_displayid_type_i_ii_vii_timing_stereo_3d)] #[repr(u32)] -pub enum TypeITimingStereo3d { - Never = ffi::displayid::di_displayid_type_i_timing_stereo_3d_DI_DISPLAYID_TYPE_I_TIMING_STEREO_3D_NEVER, - Always = ffi::displayid::di_displayid_type_i_timing_stereo_3d_DI_DISPLAYID_TYPE_I_TIMING_STEREO_3D_ALWAYS, - User = ffi::displayid::di_displayid_type_i_timing_stereo_3d_DI_DISPLAYID_TYPE_I_TIMING_STEREO_3D_USER, +pub enum TypeIIIVIITimingStereo3d { + Never = ffi::displayid::di_displayid_type_i_ii_vii_timing_stereo_3d_DI_DISPLAYID_TYPE_I_II_VII_TIMING_STEREO_3D_NEVER, + Always = ffi::displayid::di_displayid_type_i_ii_vii_timing_stereo_3d_DI_DISPLAYID_TYPE_I_II_VII_TIMING_STEREO_3D_ALWAYS, + User = ffi::displayid::di_displayid_type_i_ii_vii_timing_stereo_3d_DI_DISPLAYID_TYPE_I_II_VII_TIMING_STEREO_3D_USER, } #[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] -#[ffi(ffi::displayid::di_displayid_type_i_timing_aspect_ratio)] +#[ffi(ffi::displayid::di_displayid_timing_aspect_ratio)] #[repr(u32)] -pub enum TypeITimingAspectRatio { - _1_1 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_1_1, - _5_4 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_5_4, - _4_3 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_4_3, - _15_9 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_15_9, - _16_9 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_16_9, - _16_10 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_16_10, - _64_27 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_64_27, - _256_135 = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_256_135, - Undefined = ffi::displayid::di_displayid_type_i_timing_aspect_ratio_DI_DISPLAYID_TYPE_I_TIMING_ASPECT_RATIO_UNDEFINED, +pub enum TimingAspectRatio { + _1_1 = ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_1_1, + _5_4 = ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_5_4, + _4_3 = ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_4_3, + _15_9 = ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_15_9, + _16_9 = ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_16_9, + _16_10 = + ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_16_10, + _64_27 = + ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_64_27, + _256_135 = + ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_256_135, + Undefined = + ffi::displayid::di_displayid_timing_aspect_ratio_DI_DISPLAYID_TIMING_ASPECT_RATIO_UNDEFINED, } #[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] -#[ffi(ffi::displayid::di_displayid_type_i_timing_sync_polarity)] +#[ffi(ffi::displayid::di_displayid_type_i_ii_vii_timing_sync_polarity)] #[repr(u32)] -pub enum TypeITimingSyncPolarity { - Negative = ffi::displayid::di_displayid_type_i_timing_sync_polarity_DI_DISPLAYID_TYPE_I_TIMING_SYNC_NEGATIVE, - Positive = ffi::displayid::di_displayid_type_i_timing_sync_polarity_DI_DISPLAYID_TYPE_I_TIMING_SYNC_POSITIVE, +pub enum TypeIIIVIITimingSyncPolarity { + Negative = ffi::displayid::di_displayid_type_i_ii_vii_timing_sync_polarity_DI_DISPLAYID_TYPE_I_II_VII_TIMING_SYNC_NEGATIVE, + Positive = ffi::displayid::di_displayid_type_i_ii_vii_timing_sync_polarity_DI_DISPLAYID_TYPE_I_II_VII_TIMING_SYNC_POSITIVE, } -// Type I timing, defined in section 4.4.1. +/// Type I timing, defined in section 4.4.1. #[derive(Debug, Copy, Clone, FFIFrom)] -#[ffi(ffi::displayid::di_displayid_type_i_timing)] -pub struct TypeITiming { +#[ffi(ffi::displayid::di_displayid_type_i_ii_vii_timing)] +pub struct TypeIIIVIITiming { pub pixel_clock_mhz: f64, pub preferred: bool, - pub stereo_3d: TypeITimingStereo3d, + pub stereo_3d: TypeIIIVIITimingStereo3d, pub interlaced: bool, - pub aspect_ratio: TypeITimingAspectRatio, + pub aspect_ratio: TimingAspectRatio, pub horiz_active: i32, pub vert_active: i32, pub horiz_blank: i32, @@ -232,8 +254,31 @@ pub struct TypeITiming { pub vert_offset: i32, pub horiz_sync_width: i32, pub vert_sync_width: i32, - pub horiz_sync_polarity: TypeITimingSyncPolarity, - pub vert_sync_polarity: TypeITimingSyncPolarity, + pub horiz_sync_polarity: TypeIIIVIITimingSyncPolarity, + pub vert_sync_polarity: TypeIIIVIITimingSyncPolarity, +} + +/// Formula/algorithm for type III timings. +#[derive(Debug, Clone, Copy, PartialEq, Eq, FFIFrom)] +#[ffi(ffi::displayid::di_displayid_type_iii_timing_algo)] +#[repr(u32)] +#[cfg(feature = "v0_2")] +pub enum TyoeIIITimingAlgo { + CvtStandardBlanking = ffi::displayid::di_displayid_type_iii_timing_algo_DI_DISPLAYID_TYPE_III_TIMING_CVT_STANDARD_BLANKING, + CvtReducedBlacking = ffi::displayid::di_displayid_type_iii_timing_algo_DI_DISPLAYID_TYPE_III_TIMING_CVT_REDUCED_BLANKING, +} + +/// Type I timing, defined in section 4.4.1. +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::displayid::di_displayid_type_iii_timing)] +#[cfg(feature = "v0_2")] +pub struct TypeIIITiming { + pub preferred: bool, + pub algo: TyoeIIITimingAlgo, + pub aspect_ratio: TimingAspectRatio, + pub horiz_active: i32, + pub interlaced: bool, + pub refresh_rate_hz: i32, } /// Behavior when more than 1 tile and less than total number of tiles are driven diff --git a/libdisplay-info/src/edid.rs b/libdisplay-info/src/edid.rs index 9595381..96f4a46 100644 --- a/libdisplay-info/src/edid.rs +++ b/libdisplay-info/src/edid.rs @@ -716,8 +716,8 @@ pub struct DisplayRangeLimits { pub max_vert_rate_hz: i32, pub min_horiz_rate_hz: i32, pub max_horiz_rate_hz: i32, - #[optional(0i32)] - pub max_pixel_clock_hz: Option, + #[optional(0)] + pub max_pixel_clock_hz: Option, pub type_: DisplayRangeLimitsType, #[ptr_deref] pub secondary_gtf: Option, diff --git a/libdisplay-info/src/info.rs b/libdisplay-info/src/info.rs index 356a2bb..a80f930 100644 --- a/libdisplay-info/src/info.rs +++ b/libdisplay-info/src/info.rs @@ -1,6 +1,56 @@ //! High-level API. use crate::{edid::Edid, ffi, string_from_owned_ffi_ptr}; +#[cfg(feature = "v0_2")] +use libdisplay_info_derive::FFIFrom; + +/// Display HDR static metadata +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::info::di_hdr_static_metadata)] +#[cfg(feature = "v0_2")] +pub struct HdrStaticMetadata { + pub desired_content_max_luminance: f32, + pub desired_content_max_frame_avg_luminance: f32, + pub desired_content_min_luminance: f32, + pub type1: bool, + pub traditional_sdr: bool, + pub traditional_hdr: bool, + pub pq: bool, + pub hlg: bool, +} + +/// CIE 1931 2-degree observer chromaticity coordinates +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::info::di_chromaticity_cie1931)] +#[cfg(feature = "v0_2")] +pub struct ChromaticityCie1931 { + pub x: f32, + pub y: f32, +} + +/// Display color primaries and default white point +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::info::di_color_primaries)] +#[cfg(feature = "v0_2")] +pub struct ColorPrimaries { + pub has_primaries: bool, + pub has_default_white_point: bool, + pub primary: [ChromaticityCie1931; 3usize], + pub default_white: ChromaticityCie1931, +} + +/// Additional signal colorimetry encodings supported by the display +#[derive(Debug, Copy, Clone, FFIFrom)] +#[ffi(ffi::info::di_supported_signal_colorimetry)] +#[cfg(feature = "v0_2")] +pub struct SupportedSignalColorimetry { + pub bt2020_cycc: bool, + pub bt2020_ycc: bool, + pub bt2020_rgb: bool, + pub st2113_rgb: bool, + pub ictcp: bool, +} + /// Information about a display device. /// /// This includes at least one EDID or DisplayID blob. @@ -94,6 +144,84 @@ impl Info { pub fn serial(&self) -> Option { string_from_owned_ffi_ptr(unsafe { ffi::info::di_info_get_serial(self.0) }) } + + /// Get HDR static metadata support information as defined in ANSI/CTA-861-H + /// as HDR Static Metadata Data Block. + /// + /// When HDR static metadata does not exist, + /// all luminance fields are zero and only traditional_sdr is flagged as + /// supported. + #[cfg(feature = "v0_2")] + pub fn hdr_static_metadata(&self) -> HdrStaticMetadata { + // SAFETY: The returned pointer is owned by the struct di_info passed in. It remains + // valid only as long as the di_info exists, and must not be freed by the + // caller. + // + // This function does not return NULL. + HdrStaticMetadata::from(unsafe { *ffi::info::di_info_get_hdr_static_metadata(self.0) }) + } + + /// Get display color primaries and default white point + /// + /// Get the parameters of the default RGB colorimetry mode which is always + /// supported. Primaries for monochrome displays might be all zeroes. + /// + /// These primaries might not be display's physical primaries, but only the + /// primaries of the default RGB colorimetry signal when using IT Video Format + /// (ANSI/CTA-861-H, Section 5). + #[cfg(feature = "v0_2")] + pub fn default_color_primaries(&self) -> ColorPrimaries { + // SAFETY: The returned pointer is owned by the struct di_info passed in. It remains + // valid only as long as the di_info exists, and must not be freed by the + // caller. + // + // This function does not return NULL. + ColorPrimaries::from(unsafe { *ffi::info::di_info_get_default_color_primaries(self.0) }) + } + + /// Get signal colorimetry encodings supported by the display + /// + /// These signal colorimetry encodings are supported in addition to the + /// display's default RGB colorimetry. When you wish to use one of the additional + /// encodings, they need to be explicitly enabled in the video signal. How to + /// do that is specific to the signalling used, e.g. HDMI. + /// + /// Signal colorimetry encoding provides the color space that the signal is + /// encoded for. This includes primary and white point chromaticities, and the + /// YCbCr-RGB conversion if necessary. Also the transfer function is implied + /// unless explicitly set otherwise, e.g. with HDR static metadata. + /// See ANSI/CTA-861-H for details. + /// + /// The signal color volume can be considerably larger than the physically + /// displayable color volume. + #[cfg(feature = "v0_2")] + pub fn supported_signal_colorimetry(&self) -> SupportedSignalColorimetry { + // SAFETY: The returned pointer is owned by the struct di_info passed in. It remains + // valid only as long as the di_info exists, and must not be freed by the + // caller. + // + // This function does not return NULL. + SupportedSignalColorimetry::from(unsafe { + *ffi::info::di_info_get_supported_signal_colorimetry(self.0) + }) + } + + /// Get display default transfer characteristic exponent (gamma) + /// + /// This should be the display gamma value when the display has been reset to + /// its factory defaults, and it is driven with the default RGB colorimetry. + /// + /// Returns `None` when unknown. + #[cfg(feature = "v0_2")] + pub fn default_gamma(&self) -> Option { + // SAFETY: The value is zero when unknown. + let default_gamma = unsafe { ffi::info::di_info_get_default_gamma(self.0) }; + if default_gamma == 0f32 { + None + } else { + Some(default_gamma) + } + } } impl Drop for Info { From 9b4460470d4de21a0ff69f503c302d5825d36e47 Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Fri, 3 Jan 2025 23:17:20 +0100 Subject: [PATCH 3/7] CI: do not run all features ubuntu 24.04 does not... ...contain libdisplay-info 0.2.0 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82d8b1f..42a5e42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,7 +50,7 @@ jobs: - name: System dependencies run: sudo apt-get update; sudo apt-get install libdisplay-info-dev - name: Clippy - run: cargo clippy --all --all-features --all-targets -- -D warnings + run: cargo clippy --all --all-targets -- -D warnings check-minimal: env: From edbe768810ccf6ff1dd9b442ef6d3e61dd305246 Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Fri, 3 Jan 2025 23:21:43 +0100 Subject: [PATCH 4/7] fix clippy warnings --- libdisplay-info/src/edid.rs | 2 +- libdisplay-info/src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libdisplay-info/src/edid.rs b/libdisplay-info/src/edid.rs index 96f4a46..facf50e 100644 --- a/libdisplay-info/src/edid.rs +++ b/libdisplay-info/src/edid.rs @@ -15,7 +15,7 @@ pub struct Edid<'info> { phantom: PhantomData<&'info ()>, } -impl<'info> Edid<'info> { +impl Edid<'_> { /// Get the EDID version. pub fn version(&self) -> i32 { unsafe { ffi::edid::di_edid_get_version(self.edid) } diff --git a/libdisplay-info/src/lib.rs b/libdisplay-info/src/lib.rs index 1a8b5f7..cb79f9f 100644 --- a/libdisplay-info/src/lib.rs +++ b/libdisplay-info/src/lib.rs @@ -45,7 +45,7 @@ struct FFIIter<'a, T, F> { phantom: PhantomData<&'a ()>, } -impl<'a, T, F> FFIIter<'a, T, F> { +impl FFIIter<'_, T, F> { fn new(ptr: *const *const F) -> Self { Self { ptr, @@ -55,7 +55,7 @@ impl<'a, T, F> FFIIter<'a, T, F> { } } -impl<'a, T, F> Iterator for FFIIter<'a, T, F> +impl Iterator for FFIIter<'_, T, F> where T: From, F: Copy, From 844605991483ce481a3b8dc3f38e8839a4028f4f Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Fri, 3 Jan 2025 23:48:08 +0100 Subject: [PATCH 5/7] bump MSRV to 1.70 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 42a5e42..b45f23d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,14 +89,14 @@ jobs: with: submodules: recursive - name: Rust toolchain - uses: dtolnay/rust-toolchain@1.65 + uses: dtolnay/rust-toolchain@1.70 - name: Cargo cache uses: actions/cache@v2 with: path: | ~/.cargo/registry ~/.cargo/git - key: ${{ runner.os }}-cargo-rust_1.65-${{ hashFiles('**/Cargo.toml') }} + key: ${{ runner.os }}-cargo-rust_1.70-${{ hashFiles('**/Cargo.toml') }} - name: System dependencies run: sudo apt-get update; sudo apt-get install libdisplay-info-dev - name: Check From 2b8a5c5908a1448a9e01e2e4e693a005ec9f4143 Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Fri, 3 Jan 2025 23:48:48 +0100 Subject: [PATCH 6/7] bump deps --- libdisplay-info/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdisplay-info/Cargo.toml b/libdisplay-info/Cargo.toml index cb4fa22..62ab6f6 100644 --- a/libdisplay-info/Cargo.toml +++ b/libdisplay-info/Cargo.toml @@ -19,7 +19,7 @@ v0_2 = ["libdisplay-info-sys/v0_2"] [dependencies] libdisplay-info-sys = { version = "0.2.0", path = "../libdisplay-info-sys" } libc = "0.2.155" -thiserror = "1.0.63" +thiserror = "2.0.9" libdisplay-info-derive = { version = "0.1.0", path = "../libdisplay-info-derive" } bitflags = "2.6" From a6d3ebb45cad92ca2dcdd2ace132d90b38d9c385 Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Sat, 4 Jan 2025 00:14:58 +0100 Subject: [PATCH 7/7] limit native version to 0.2 --- libdisplay-info-sys/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdisplay-info-sys/Cargo.toml b/libdisplay-info-sys/Cargo.toml index 2584497..f7bdfbe 100644 --- a/libdisplay-info-sys/Cargo.toml +++ b/libdisplay-info-sys/Cargo.toml @@ -24,5 +24,5 @@ semver = "1.0.24" [package.metadata.system-deps.libdisplay-info] name = "libdisplay-info" -version = "0.1.0" +version = ">= 0.1.0, < 0.3.0" v0_2 = { version = "0.2.0" }