From b0fce0cf712dae621ee62fa7cbd3d7865585f195 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 26 Mar 2020 00:04:34 +0100 Subject: [PATCH 01/25] init lv2-log crate --- Cargo.toml | 3 ++- log/Cargo.toml | 12 ++++++++++++ log/src/lib.rs | 13 +++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 log/Cargo.toml create mode 100644 log/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 5a4a5b0c..5202a6f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,7 @@ members = [ "atom", "core", "core/derive", + "log", "midi", "state", "sys", @@ -104,4 +105,4 @@ lv2-units = { path = "units" } urid = { path = "urid" } urid-derive = { path = "urid/derive" } lv2-urid = { path = "urid/lv2-urid" } -lv2-worker = { path = "worker" } \ No newline at end of file +lv2-worker = { path = "worker" } diff --git a/log/Cargo.toml b/log/Cargo.toml new file mode 100644 index 00000000..055234bd --- /dev/null +++ b/log/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "lv2-log" +version = "0.1.0" +authors = ["Yruama_Lairba "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lv2-sys = "1.0.0" +lv2-core = "1.0.0" +urid = "0.1.0" diff --git a/log/src/lib.rs b/log/src/lib.rs new file mode 100644 index 00000000..50c74dbc --- /dev/null +++ b/log/src/lib.rs @@ -0,0 +1,13 @@ +use lv2_core::feature::*; + +pub struct LogHandler<'a,P> { + internal:&'a lv2_sys::LV2_Log_Log, +} + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} From 79e0864c1ec81309f4409f02e7f4e51a263c3a21 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 26 Mar 2020 01:06:18 +0100 Subject: [PATCH 02/25] implement feature part of log --- log/src/lib.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 50c74dbc..0dc24eb5 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,7 +1,25 @@ use lv2_core::feature::*; +use std::os::raw::*; //get all common c_type +use urid::*; -pub struct LogHandler<'a,P> { - internal:&'a lv2_sys::LV2_Log_Log, +/// The Log feature +#[repr(transparent)] +pub struct Log<'a> { + internal: &'a lv2_sys::LV2_Log_Log, +} + +unsafe impl<'a> UriBound for Log<'a> { + const URI: &'static [u8] = lv2_sys::LV2_WORKER__schedule; +} + +unsafe impl<'a> Feature for Log<'a> { + // Note: this feature can be used in any threading class and doesn't seems to have thready + // unsafty + unsafe fn from_feature_ptr(feature: *const c_void, _class: ThreadingClass) -> Option { + (feature as *const lv2_sys::LV2_Log_Log) + .as_ref() + .map(|internal| Self { internal }) + } } #[cfg(test)] From 101d936b645d36660da22b330b08b2e5abba2fef Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 26 Mar 2020 01:58:06 +0100 Subject: [PATCH 03/25] impl Uribound and LogURIDcollection for type of log --- log/src/lib.rs | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 0dc24eb5..d211e163 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -2,6 +2,31 @@ use lv2_core::feature::*; use std::os::raw::*; //get all common c_type use urid::*; +pub struct EntryClass; +unsafe impl UriBound for EntryClass { + const URI: &'static [u8] = lv2_sys::LV2_LOG__Entry; +} + +pub struct ErrorClass; +unsafe impl UriBound for ErrorClass { + const URI: &'static [u8] = lv2_sys::LV2_LOG__Error; +} + +pub struct NoteClass; +unsafe impl UriBound for NoteClass { + const URI: &'static [u8] = lv2_sys::LV2_LOG__Note; +} + +pub struct TraceClass; +unsafe impl UriBound for TraceClass { + const URI: &'static [u8] = lv2_sys::LV2_LOG__Trace; +} + +pub struct WarningClass; +unsafe impl UriBound for WarningClass { + const URI: &'static [u8] = lv2_sys::LV2_LOG__Warning; +} + /// The Log feature #[repr(transparent)] pub struct Log<'a> { @@ -9,7 +34,7 @@ pub struct Log<'a> { } unsafe impl<'a> UriBound for Log<'a> { - const URI: &'static [u8] = lv2_sys::LV2_WORKER__schedule; + const URI: &'static [u8] = lv2_sys::LV2_LOG__log; } unsafe impl<'a> Feature for Log<'a> { @@ -22,6 +47,17 @@ unsafe impl<'a> Feature for Log<'a> { } } +/// A URID cache containing all time properties. +#[derive(URIDCollection)] +pub struct LogURIDCollection { + pub entry_class: URID, + pub error_class: URID, + pub note_class: URID, + pub trace_class: URID, + pub warning_class: URID, + //pub log: URID>, +} + #[cfg(test)] mod tests { #[test] From 875153ca306e4ee421cd54e9a3f3a1617e15c3fd Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 26 Mar 2020 23:09:09 +0100 Subject: [PATCH 04/25] usable but unsafe draft --- log/src/lib.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index d211e163..c6869a39 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,4 +1,5 @@ use lv2_core::feature::*; +//use std::ffi::CString; use std::os::raw::*; //get all common c_type use urid::*; @@ -27,6 +28,17 @@ unsafe impl UriBound for WarningClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Warning; } +/// Marker for URID representing the nature of a log message +// Note : it's may be better to have a URID trait to define a common interface +pub unsafe trait EntryType { + fn get(self) -> u32; +} + +unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} +unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} +unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} +unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} + /// The Log feature #[repr(transparent)] pub struct Log<'a> { @@ -47,8 +59,24 @@ unsafe impl<'a> Feature for Log<'a> { } } +impl<'a> Log<'a> { + pub fn print(&self, entry_type: impl EntryType, message: &[u8]) -> Result<(),()> { + let printf = if let Some(printf) = self.internal.printf { + printf + } else { + return Err(()); + }; + let res = unsafe { (printf)(self.internal.handle, entry_type.get(), message as *const _ as *const c_char )}; + if res > 0 { + Ok(()) + } else { + Err(()) + } + } +} + /// A URID cache containing all time properties. -#[derive(URIDCollection)] +#[derive(URIDCollection,Debug)] pub struct LogURIDCollection { pub entry_class: URID, pub error_class: URID, From 3d3a31e6d3f43050f4467dbb663dfbdbce86cd35 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Sun, 29 Mar 2020 01:46:31 +0100 Subject: [PATCH 05/25] avoid '%' be interpreted, Format code --- log/src/lib.rs | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index c6869a39..cd8ce050 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,5 +1,6 @@ use lv2_core::feature::*; //use std::ffi::CString; +use std::fmt; use std::os::raw::*; //get all common c_type use urid::*; @@ -34,10 +35,26 @@ pub unsafe trait EntryType { fn get(self) -> u32; } -unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} -unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} -unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} -unsafe impl EntryType for URID{ fn get(self) -> u32 {URID::::get(self)}} +unsafe impl EntryType for URID { + fn get(self) -> u32 { + URID::::get(self) + } +} +unsafe impl EntryType for URID { + fn get(self) -> u32 { + URID::::get(self) + } +} +unsafe impl EntryType for URID { + fn get(self) -> u32 { + URID::::get(self) + } +} +unsafe impl EntryType for URID { + fn get(self) -> u32 { + URID::::get(self) + } +} /// The Log feature #[repr(transparent)] @@ -60,13 +77,20 @@ unsafe impl<'a> Feature for Log<'a> { } impl<'a> Log<'a> { - pub fn print(&self, entry_type: impl EntryType, message: &[u8]) -> Result<(),()> { + pub fn print(&self, entry_type: impl EntryType, message: &[u8]) -> Result<(), ()> { let printf = if let Some(printf) = self.internal.printf { printf } else { return Err(()); }; - let res = unsafe { (printf)(self.internal.handle, entry_type.get(), message as *const _ as *const c_char )}; + let res = unsafe { + (printf)( + self.internal.handle, + entry_type.get(), + b"%s\0" as *const _ as *const c_char, + message as *const _ as *const c_char, + ) + }; if res > 0 { Ok(()) } else { @@ -76,7 +100,7 @@ impl<'a> Log<'a> { } /// A URID cache containing all time properties. -#[derive(URIDCollection,Debug)] +#[derive(URIDCollection, Debug)] pub struct LogURIDCollection { pub entry_class: URID, pub error_class: URID, From 862fa63771e3d7acc7a744e1375c4f49e7d51a0b Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Sun, 29 Mar 2020 17:34:40 +0200 Subject: [PATCH 06/25] check for null string terminator for safety --- log/src/lib.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index cd8ce050..a7e3e59b 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -68,7 +68,7 @@ unsafe impl<'a> UriBound for Log<'a> { unsafe impl<'a> Feature for Log<'a> { // Note: this feature can be used in any threading class and doesn't seems to have thready - // unsafty + // unsafty, but you are supposed to only use the trace log in rt context unsafe fn from_feature_ptr(feature: *const c_void, _class: ThreadingClass) -> Option { (feature as *const lv2_sys::LV2_Log_Log) .as_ref() @@ -77,17 +77,29 @@ unsafe impl<'a> Feature for Log<'a> { } impl<'a> Log<'a> { - pub fn print(&self, entry_type: impl EntryType, message: &[u8]) -> Result<(), ()> { + pub fn print(&self, entry_type: impl EntryType, message: &str) -> Result<(), ()> { let printf = if let Some(printf) = self.internal.printf { printf } else { return Err(()); }; + //checking for null terminator + let mut have_null = false; + for b in message.bytes() { + if b == b'\0' { + have_null = true; + break; + } + } + if !have_null { + return Err(()); + } + let res = unsafe { (printf)( self.internal.handle, entry_type.get(), - b"%s\0" as *const _ as *const c_char, + "%s\0" as *const _ as *const c_char, message as *const _ as *const c_char, ) }; From 92691a4a1e995eea31447477e65c41f1273fcf50 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Sun, 29 Mar 2020 19:34:59 +0200 Subject: [PATCH 07/25] create and use LogError enum --- log/src/lib.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index a7e3e59b..79366615 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -56,6 +56,19 @@ unsafe impl EntryType for URID { } } +/// Errors potentially generated by [`Log`](struct.Log.html) methods +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum LogError { + /// An error occured when sending message to the host + PrintError, + /// The provided string don't have a `'\0'` to indicate it's end + NoNullTerminator, + /// No callback was provided by the host + /// + /// This can only happen with a faulty host + NoCallback, +} + /// The Log feature #[repr(transparent)] pub struct Log<'a> { @@ -77,11 +90,11 @@ unsafe impl<'a> Feature for Log<'a> { } impl<'a> Log<'a> { - pub fn print(&self, entry_type: impl EntryType, message: &str) -> Result<(), ()> { + pub fn print(&self, entry_type: impl EntryType, message: &str) -> Result<(), LogError> { let printf = if let Some(printf) = self.internal.printf { printf } else { - return Err(()); + return Err(LogError::NoCallback); }; //checking for null terminator let mut have_null = false; @@ -92,7 +105,7 @@ impl<'a> Log<'a> { } } if !have_null { - return Err(()); + return Err(LogError::NoNullTerminator); } let res = unsafe { @@ -106,7 +119,7 @@ impl<'a> Log<'a> { if res > 0 { Ok(()) } else { - Err(()) + Err(LogError::PrintError) } } } From eca5acd95210304074453e4817be28caa3ed11cd Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Wed, 1 Apr 2020 02:31:16 +0200 Subject: [PATCH 08/25] Copy as supertrait for entry urid --- log/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 79366615..b8046700 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -31,7 +31,10 @@ unsafe impl UriBound for WarningClass { /// Marker for URID representing the nature of a log message // Note : it's may be better to have a URID trait to define a common interface -pub unsafe trait EntryType { +pub unsafe trait EntryType +where + Self: Copy, +{ fn get(self) -> u32; } From 40ea7b725cb68685d32660b38264d355544dcd4f Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Wed, 1 Apr 2020 03:49:41 +0200 Subject: [PATCH 09/25] add some doc --- log/src/lib.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index b8046700..a8c488ae 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -9,27 +9,31 @@ unsafe impl UriBound for EntryClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Entry; } +/// UriBound for an error message. pub struct ErrorClass; unsafe impl UriBound for ErrorClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Error; } +/// UriBound for an informative message. pub struct NoteClass; unsafe impl UriBound for NoteClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Note; } +/// UriBound for a debuging message. pub struct TraceClass; unsafe impl UriBound for TraceClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Trace; } +/// Uribound for an error message. pub struct WarningClass; unsafe impl UriBound for WarningClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Warning; } -/// Marker for URID representing the nature of a log message +/// Marker for URID representing the nature of a log message. // Note : it's may be better to have a URID trait to define a common interface pub unsafe trait EntryType where @@ -59,7 +63,7 @@ unsafe impl EntryType for URID { } } -/// Errors potentially generated by [`Log`](struct.Log.html) methods +/// Errors potentially generated by [`Log`](struct.Log.html) methods. #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum LogError { /// An error occured when sending message to the host @@ -72,7 +76,7 @@ pub enum LogError { NoCallback, } -/// The Log feature +/// The Log feature. #[repr(transparent)] pub struct Log<'a> { internal: &'a lv2_sys::LV2_Log_Log, @@ -93,6 +97,17 @@ unsafe impl<'a> Feature for Log<'a> { } impl<'a> Log<'a> { + /// Send a log message to the host. + /// + /// the `entry_type` parameter is an URID representing the kind of log message. There are four + /// kind of message: + /// * **note:** an informative message. + /// * **warning:** a warning message. + /// * **error:** an error message. + /// * **trace:** a debugging trace. These entries should not be displayed during normal + /// operation, but the host may implement an option to display them for debugging purposes. + /// This entry type is special in that it may be written to in a real-time thread. It is + /// assumed that if debug tracing is enabled, real-time considerations are not a concern. pub fn print(&self, entry_type: impl EntryType, message: &str) -> Result<(), LogError> { let printf = if let Some(printf) = self.internal.printf { printf @@ -127,7 +142,7 @@ impl<'a> Log<'a> { } } -/// A URID cache containing all time properties. +/// A URID cache containing all log properties. #[derive(URIDCollection, Debug)] pub struct LogURIDCollection { pub entry_class: URID, From 36bf4fe91221e213a613e6eee027e699bb1c1848 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 2 Apr 2020 21:44:50 +0200 Subject: [PATCH 10/25] restrict log feature to the instantiation threading class while this feature is not restricted to any threading class, i have some doubt about RT concern and threading issue --- log/src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index a8c488ae..8ab6c352 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -87,12 +87,20 @@ unsafe impl<'a> UriBound for Log<'a> { } unsafe impl<'a> Feature for Log<'a> { - // Note: this feature can be used in any threading class and doesn't seems to have thready - // unsafty, but you are supposed to only use the trace log in rt context - unsafe fn from_feature_ptr(feature: *const c_void, _class: ThreadingClass) -> Option { + // Note: this feature can be used in any threading class but: + // * i have a doubt about it's thread safety, can we assume the host provide this thread safety + // since this feature can be used anywhere ?. + // * i shouldn't be used in context where rt is a concern, that mean is audiothreadclass in + // practice, but it's acceptable to use it for debugging purpose + // So, at this time, i just giving access to it instanciation class + unsafe fn from_feature_ptr(feature: *const c_void, class: ThreadingClass) -> Option { + if class == ThreadingClass::Instantiation { (feature as *const lv2_sys::LV2_Log_Log) .as_ref() .map(|internal| Self { internal }) + } else { + panic!("The log feature is only allowed in the indtantiation threading class"); + } } } From fe6d8d790410a8690ef9340c69465fb94cddf3ed Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Mon, 6 Apr 2020 20:27:49 +0200 Subject: [PATCH 11/25] WIP --- log/src/lib.rs | 46 +++++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 8ab6c352..66d4e89c 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -95,9 +95,9 @@ unsafe impl<'a> Feature for Log<'a> { // So, at this time, i just giving access to it instanciation class unsafe fn from_feature_ptr(feature: *const c_void, class: ThreadingClass) -> Option { if class == ThreadingClass::Instantiation { - (feature as *const lv2_sys::LV2_Log_Log) - .as_ref() - .map(|internal| Self { internal }) + (feature as *const lv2_sys::LV2_Log_Log) + .as_ref() + .map(|internal| Self { internal }) } else { panic!("The log feature is only allowed in the indtantiation threading class"); } @@ -107,7 +107,7 @@ unsafe impl<'a> Feature for Log<'a> { impl<'a> Log<'a> { /// Send a log message to the host. /// - /// the `entry_type` parameter is an URID representing the kind of log message. There are four + /// The `entry_type` parameter is an URID representing the kind of log message. There are four /// kind of message: /// * **note:** an informative message. /// * **warning:** a warning message. @@ -122,24 +122,40 @@ impl<'a> Log<'a> { } else { return Err(LogError::NoCallback); }; - //checking for null terminator - let mut have_null = false; - for b in message.bytes() { - if b == b'\0' { - have_null = true; - break; - } - } - if !have_null { - return Err(LogError::NoNullTerminator); + let message = String::from(message) + "\0"; + + let res = unsafe { + (printf)( + self.internal.handle, + entry_type.get(), + "%s\0" as *const _ as *const c_char, + message.as_str() as *const _ as *const c_char, + ) + }; + if res > 0 { + Ok(()) + } else { + Err(LogError::PrintError) } + } + /// Send a message to the host with a new line at the end. + /// + /// It same as [print](struct.Log.html#method.print) but add a newline a the end of message. + /// See [print](struct.Log.html#method.print) documentation for details. + pub fn println(&self, entry_type: impl EntryType, message: &str) -> Result<(), LogError> { + let printf = if let Some(printf) = self.internal.printf { + printf + } else { + return Err(LogError::NoCallback); + }; + let message = String::from(message) + "\n\0"; let res = unsafe { (printf)( self.internal.handle, entry_type.get(), "%s\0" as *const _ as *const c_char, - message as *const _ as *const c_char, + message.as_str() as *const _ as *const c_char, ) }; if res > 0 { From 0eff4b058c3e02c27704057eea47ab01fcfec27a Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Tue, 10 Aug 2021 21:54:33 +0200 Subject: [PATCH 12/25] fix the code after merge --- log/Cargo.toml | 4 ++-- log/src/lib.rs | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/log/Cargo.toml b/log/Cargo.toml index 055234bd..f77c6a3a 100644 --- a/log/Cargo.toml +++ b/log/Cargo.toml @@ -7,6 +7,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lv2-sys = "1.0.0" -lv2-core = "1.0.0" +lv2-sys = "2.0.0" +lv2-core = "3.0.0" urid = "0.1.0" diff --git a/log/src/lib.rs b/log/src/lib.rs index 66d4e89c..845bd654 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,6 +1,5 @@ -use lv2_core::feature::*; +use lv2_core::feature::{Feature, ThreadingClass}; //use std::ffi::CString; -use std::fmt; use std::os::raw::*; //get all common c_type use urid::*; @@ -180,7 +179,5 @@ pub struct LogURIDCollection { #[cfg(test)] mod tests { #[test] - fn it_works() { - assert_eq!(2 + 2, 4); - } + fn it_works() {} } From 5eb55ab08028b7bd9a98c8f4e8f231f4f4bc28c7 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Tue, 10 Aug 2021 22:05:19 +0200 Subject: [PATCH 13/25] apply prokopyl suggestion to refactor code --- log/src/lib.rs | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 845bd654..7453d53b 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -38,29 +38,12 @@ pub unsafe trait EntryType where Self: Copy, { - fn get(self) -> u32; } -unsafe impl EntryType for URID { - fn get(self) -> u32 { - URID::::get(self) - } -} -unsafe impl EntryType for URID { - fn get(self) -> u32 { - URID::::get(self) - } -} -unsafe impl EntryType for URID { - fn get(self) -> u32 { - URID::::get(self) - } -} -unsafe impl EntryType for URID { - fn get(self) -> u32 { - URID::::get(self) - } -} +unsafe impl EntryType for URID {} +unsafe impl EntryType for URID {} +unsafe impl EntryType for URID {} +unsafe impl EntryType for URID {} /// Errors potentially generated by [`Log`](struct.Log.html) methods. #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -115,7 +98,7 @@ impl<'a> Log<'a> { /// operation, but the host may implement an option to display them for debugging purposes. /// This entry type is special in that it may be written to in a real-time thread. It is /// assumed that if debug tracing is enabled, real-time considerations are not a concern. - pub fn print(&self, entry_type: impl EntryType, message: &str) -> Result<(), LogError> { + pub fn print(&self, entry_type: URID, message: &str) -> Result<(), LogError> { let printf = if let Some(printf) = self.internal.printf { printf } else { @@ -141,7 +124,7 @@ impl<'a> Log<'a> { /// /// It same as [print](struct.Log.html#method.print) but add a newline a the end of message. /// See [print](struct.Log.html#method.print) documentation for details. - pub fn println(&self, entry_type: impl EntryType, message: &str) -> Result<(), LogError> { + pub fn println(&self, entry_type: URID, message: &str) -> Result<(), LogError> { let printf = if let Some(printf) = self.internal.printf { printf } else { From d27805300f6dc3f7b670a707dd78be99e9c9bd22 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Tue, 10 Aug 2021 22:29:30 +0200 Subject: [PATCH 14/25] forbid log feature only in the audio threading class --- log/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 7453d53b..dd4e3a09 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -76,12 +76,13 @@ unsafe impl<'a> Feature for Log<'a> { // practice, but it's acceptable to use it for debugging purpose // So, at this time, i just giving access to it instanciation class unsafe fn from_feature_ptr(feature: *const c_void, class: ThreadingClass) -> Option { - if class == ThreadingClass::Instantiation { - (feature as *const lv2_sys::LV2_Log_Log) + match class { + ThreadingClass::Audio => { + panic!("The log feature is not allowed in the audio threading class") + } + _ => (feature as *const lv2_sys::LV2_Log_Log) .as_ref() - .map(|internal| Self { internal }) - } else { - panic!("The log feature is only allowed in the indtantiation threading class"); + .map(|internal| Self { internal }), } } } From a5c2d6f39f30dae660dd057d7809164958a79109 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Tue, 17 Aug 2021 17:00:06 +0200 Subject: [PATCH 15/25] change print to print_cstr --- log/src/lib.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index dd4e3a09..7812466c 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,5 +1,5 @@ use lv2_core::feature::{Feature, ThreadingClass}; -//use std::ffi::CString; +use std::ffi::CStr; use std::os::raw::*; //get all common c_type use urid::*; @@ -99,20 +99,23 @@ impl<'a> Log<'a> { /// operation, but the host may implement an option to display them for debugging purposes. /// This entry type is special in that it may be written to in a real-time thread. It is /// assumed that if debug tracing is enabled, real-time considerations are not a concern. - pub fn print(&self, entry_type: URID, message: &str) -> Result<(), LogError> { + pub fn print_cstr( + &self, + entry_type: URID, + message: &CStr, + ) -> Result<(), LogError> { let printf = if let Some(printf) = self.internal.printf { printf } else { return Err(LogError::NoCallback); }; - let message = String::from(message) + "\0"; let res = unsafe { (printf)( self.internal.handle, entry_type.get(), "%s\0" as *const _ as *const c_char, - message.as_str() as *const _ as *const c_char, + message.as_ptr(), ) }; if res > 0 { From 5226867304cc8f5c1828eef5e903c7b666b51c0b Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Tue, 17 Aug 2021 17:07:58 +0200 Subject: [PATCH 16/25] remove println, it's not needed and almost useless --- log/src/lib.rs | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 7812466c..941c51b7 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -124,32 +124,6 @@ impl<'a> Log<'a> { Err(LogError::PrintError) } } - /// Send a message to the host with a new line at the end. - /// - /// It same as [print](struct.Log.html#method.print) but add a newline a the end of message. - /// See [print](struct.Log.html#method.print) documentation for details. - pub fn println(&self, entry_type: URID, message: &str) -> Result<(), LogError> { - let printf = if let Some(printf) = self.internal.printf { - printf - } else { - return Err(LogError::NoCallback); - }; - let message = String::from(message) + "\n\0"; - - let res = unsafe { - (printf)( - self.internal.handle, - entry_type.get(), - "%s\0" as *const _ as *const c_char, - message.as_str() as *const _ as *const c_char, - ) - }; - if res > 0 { - Ok(()) - } else { - Err(LogError::PrintError) - } - } } /// A URID cache containing all log properties. From 97c4175634beb5256683f99257c73666d7e61059 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Tue, 17 Aug 2021 17:39:20 +0200 Subject: [PATCH 17/25] fix EntryType marker trait --- log/src/lib.rs | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 941c51b7..44061eee 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -32,18 +32,13 @@ unsafe impl UriBound for WarningClass { const URI: &'static [u8] = lv2_sys::LV2_LOG__Warning; } -/// Marker for URID representing the nature of a log message. -// Note : it's may be better to have a URID trait to define a common interface -pub unsafe trait EntryType -where - Self: Copy, -{ -} +/// Marker trait for Uribound type representing nature of a log message. +pub unsafe trait EntryType {} -unsafe impl EntryType for URID {} -unsafe impl EntryType for URID {} -unsafe impl EntryType for URID {} -unsafe impl EntryType for URID {} +unsafe impl EntryType for ErrorClass {} +unsafe impl EntryType for NoteClass {} +unsafe impl EntryType for TraceClass {} +unsafe impl EntryType for WarningClass {} /// Errors potentially generated by [`Log`](struct.Log.html) methods. #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -139,6 +134,19 @@ pub struct LogURIDCollection { #[cfg(test)] mod tests { + use super::*; + fn _should_compile() { + let fake_logger = unsafe { + Log { + internal: &*(0xDEFEC8 as *const lv2_sys::LV2_Log_Log), + } + }; + let urid = unsafe { URID::::new_unchecked(42) }; + let message = CStr::from_bytes_with_nul(b"message\0").unwrap(); + + let _ = fake_logger.print_cstr(urid, message); + } + #[test] fn it_works() {} } From f6fd9ee9283f13c8fdf57e081e7a50570c8bb15c Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 19 Aug 2021 22:19:16 +0200 Subject: [PATCH 18/25] use a custom type to not have function pointer inside Option --- log/src/lib.rs | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 44061eee..508968c8 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -53,10 +53,28 @@ pub enum LogError { NoCallback, } +//replace the lv2_sys::Log_Log to avoid checking if function pointers are null +#[repr(C)] +struct LogInternal { + handle: lv2_sys::LV2_Log_Handle, + printf: unsafe extern "C" fn( + handle: lv2_sys::LV2_Log_Handle, + type_: lv2_sys::LV2_URID, + fmt: *const c_char, + ... + ) -> c_int, + vprintf: unsafe extern "C" fn( + handle: lv2_sys::LV2_Log_Handle, + type_: lv2_sys::LV2_URID, + fmt: *const c_char, + ap: *mut lv2_sys::__va_list_tag, + ) -> c_int, +} + /// The Log feature. #[repr(transparent)] pub struct Log<'a> { - internal: &'a lv2_sys::LV2_Log_Log, + internal: &'a LogInternal, } unsafe impl<'a> UriBound for Log<'a> { @@ -75,7 +93,7 @@ unsafe impl<'a> Feature for Log<'a> { ThreadingClass::Audio => { panic!("The log feature is not allowed in the audio threading class") } - _ => (feature as *const lv2_sys::LV2_Log_Log) + _ => (feature as *const LogInternal) .as_ref() .map(|internal| Self { internal }), } @@ -99,14 +117,8 @@ impl<'a> Log<'a> { entry_type: URID, message: &CStr, ) -> Result<(), LogError> { - let printf = if let Some(printf) = self.internal.printf { - printf - } else { - return Err(LogError::NoCallback); - }; - let res = unsafe { - (printf)( + (self.internal.printf)( self.internal.handle, entry_type.get(), "%s\0" as *const _ as *const c_char, @@ -138,7 +150,7 @@ mod tests { fn _should_compile() { let fake_logger = unsafe { Log { - internal: &*(0xDEFEC8 as *const lv2_sys::LV2_Log_Log), + internal: &*(0xDEFEC8 as *const LogInternal), } }; let urid = unsafe { URID::::new_unchecked(42) }; From 30656afdff3e594bee2150531879d5c58c109874 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Thu, 19 Aug 2021 23:19:01 +0200 Subject: [PATCH 19/25] replace LogError by PrintError --- log/src/lib.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 508968c8..00ab190f 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,5 +1,7 @@ use lv2_core::feature::{Feature, ThreadingClass}; +use std::error::Error; use std::ffi::CStr; +use std::fmt; use std::os::raw::*; //get all common c_type use urid::*; @@ -40,18 +42,16 @@ unsafe impl EntryType for NoteClass {} unsafe impl EntryType for TraceClass {} unsafe impl EntryType for WarningClass {} -/// Errors potentially generated by [`Log`](struct.Log.html) methods. +/// Returned if an error occured when sending a log to the host. #[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub enum LogError { - /// An error occured when sending message to the host - PrintError, - /// The provided string don't have a `'\0'` to indicate it's end - NoNullTerminator, - /// No callback was provided by the host - /// - /// This can only happen with a faulty host - NoCallback, +pub struct PrintError; + +impl fmt::Display for PrintError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "An error occured when sending a message to the host") + } } +impl Error for PrintError {} //replace the lv2_sys::Log_Log to avoid checking if function pointers are null #[repr(C)] @@ -116,7 +116,7 @@ impl<'a> Log<'a> { &self, entry_type: URID, message: &CStr, - ) -> Result<(), LogError> { + ) -> Result<(), PrintError> { let res = unsafe { (self.internal.printf)( self.internal.handle, @@ -128,7 +128,7 @@ impl<'a> Log<'a> { if res > 0 { Ok(()) } else { - Err(LogError::PrintError) + Err(PrintError) } } } From 6e0ee4a395dc4e2dd4656ecabb5364810b3bfec6 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Fri, 20 Aug 2021 00:52:22 +0200 Subject: [PATCH 20/25] shorten the name and redocument URID marker --- log/src/lib.rs | 74 +++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 00ab190f..9ba5bbbd 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,46 +1,46 @@ use lv2_core::feature::{Feature, ThreadingClass}; -use std::error::Error; +use std::error; use std::ffi::CStr; use std::fmt; use std::os::raw::*; //get all common c_type use urid::*; -pub struct EntryClass; -unsafe impl UriBound for EntryClass { - const URI: &'static [u8] = lv2_sys::LV2_LOG__Entry; -} - -/// UriBound for an error message. -pub struct ErrorClass; -unsafe impl UriBound for ErrorClass { +/// URID marker. The corresponding URID is used to log an error on the host. +pub struct Error; +unsafe impl UriBound for Error { const URI: &'static [u8] = lv2_sys::LV2_LOG__Error; } -/// UriBound for an informative message. -pub struct NoteClass; -unsafe impl UriBound for NoteClass { +/// URID marker. The corresponding URID is used to log an informative on the host. +pub struct Note; +unsafe impl UriBound for Note { const URI: &'static [u8] = lv2_sys::LV2_LOG__Note; } -/// UriBound for a debuging message. -pub struct TraceClass; -unsafe impl UriBound for TraceClass { +/// URID marker. The corresponding URID is used to log a debbuging trace on the host. +pub struct Trace; +unsafe impl UriBound for Trace { const URI: &'static [u8] = lv2_sys::LV2_LOG__Trace; } -/// Uribound for an error message. -pub struct WarningClass; -unsafe impl UriBound for WarningClass { +/// URID marker. The corresponding URID is used to log a warning on the host. +pub struct Warning; +unsafe impl UriBound for Warning { const URI: &'static [u8] = lv2_sys::LV2_LOG__Warning; } -/// Marker trait for Uribound type representing nature of a log message. -pub unsafe trait EntryType {} +/// Trait for URID marker. Plugin implementers shouldn't care about it. +/// +/// # Safety +/// +/// This trait is used to check at compile time if an URID indicate the nature of a log message, +/// Plugin implementers should not implement it. +pub unsafe trait Entry {} -unsafe impl EntryType for ErrorClass {} -unsafe impl EntryType for NoteClass {} -unsafe impl EntryType for TraceClass {} -unsafe impl EntryType for WarningClass {} +unsafe impl Entry for Error {} +unsafe impl Entry for Note {} +unsafe impl Entry for Trace {} +unsafe impl Entry for Warning {} /// Returned if an error occured when sending a log to the host. #[derive(PartialEq, Eq, Clone, Copy, Debug)] @@ -51,7 +51,7 @@ impl fmt::Display for PrintError { write!(f, "An error occured when sending a message to the host") } } -impl Error for PrintError {} +impl error::Error for PrintError {} //replace the lv2_sys::Log_Log to avoid checking if function pointers are null #[repr(C)] @@ -103,7 +103,7 @@ unsafe impl<'a> Feature for Log<'a> { impl<'a> Log<'a> { /// Send a log message to the host. /// - /// The `entry_type` parameter is an URID representing the kind of log message. There are four + /// The `entry` parameter is an URID representing the kind of log message. There are four /// kind of message: /// * **note:** an informative message. /// * **warning:** a warning message. @@ -112,15 +112,11 @@ impl<'a> Log<'a> { /// operation, but the host may implement an option to display them for debugging purposes. /// This entry type is special in that it may be written to in a real-time thread. It is /// assumed that if debug tracing is enabled, real-time considerations are not a concern. - pub fn print_cstr( - &self, - entry_type: URID, - message: &CStr, - ) -> Result<(), PrintError> { + pub fn print_cstr(&self, entry: URID, message: &CStr) -> Result<(), PrintError> { let res = unsafe { (self.internal.printf)( self.internal.handle, - entry_type.get(), + entry.get(), "%s\0" as *const _ as *const c_char, message.as_ptr(), ) @@ -133,15 +129,13 @@ impl<'a> Log<'a> { } } -/// A URID cache containing all log properties. +/// A URID cache containing all usefull log properties. #[derive(URIDCollection, Debug)] pub struct LogURIDCollection { - pub entry_class: URID, - pub error_class: URID, - pub note_class: URID, - pub trace_class: URID, - pub warning_class: URID, - //pub log: URID>, + pub error_class: URID, + pub note_class: URID, + pub trace_class: URID, + pub warning_class: URID, } #[cfg(test)] @@ -153,7 +147,7 @@ mod tests { internal: &*(0xDEFEC8 as *const LogInternal), } }; - let urid = unsafe { URID::::new_unchecked(42) }; + let urid = unsafe { URID::::new_unchecked(42) }; let message = CStr::from_bytes_with_nul(b"message\0").unwrap(); let _ = fake_logger.print_cstr(urid, message); From 826aeb08d32bf81cb4d7b4e29f3559938aed9255 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Fri, 20 Aug 2021 01:14:59 +0200 Subject: [PATCH 21/25] ooops, log is not rt-safe but is valid in any threading class --- log/src/lib.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 9ba5bbbd..73f28b75 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -88,15 +88,10 @@ unsafe impl<'a> Feature for Log<'a> { // * i shouldn't be used in context where rt is a concern, that mean is audiothreadclass in // practice, but it's acceptable to use it for debugging purpose // So, at this time, i just giving access to it instanciation class - unsafe fn from_feature_ptr(feature: *const c_void, class: ThreadingClass) -> Option { - match class { - ThreadingClass::Audio => { - panic!("The log feature is not allowed in the audio threading class") - } - _ => (feature as *const LogInternal) - .as_ref() - .map(|internal| Self { internal }), - } + unsafe fn from_feature_ptr(feature: *const c_void, _class: ThreadingClass) -> Option { + (feature as *const LogInternal) + .as_ref() + .map(|internal| Self { internal }) } } From f0a47aaeec9f5d4243f943c6d629874254b1f63a Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Fri, 20 Aug 2021 01:31:04 +0200 Subject: [PATCH 22/25] oops, forgot to remove some _class suffix --- log/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index 73f28b75..addcfb5a 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -127,10 +127,10 @@ impl<'a> Log<'a> { /// A URID cache containing all usefull log properties. #[derive(URIDCollection, Debug)] pub struct LogURIDCollection { - pub error_class: URID, - pub note_class: URID, - pub trace_class: URID, - pub warning_class: URID, + pub error: URID, + pub note: URID, + pub trace: URID, + pub warning: URID, } #[cfg(test)] From 99e12ccb65ffa8e612651de15bd94da121128279 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Fri, 20 Aug 2021 03:09:03 +0200 Subject: [PATCH 23/25] use a pointer replacement. --- log/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index addcfb5a..c6fb2000 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -63,11 +63,12 @@ struct LogInternal { fmt: *const c_char, ... ) -> c_int, + //placeholder, not useable yet vprintf: unsafe extern "C" fn( handle: lv2_sys::LV2_Log_Handle, type_: lv2_sys::LV2_URID, fmt: *const c_char, - ap: *mut lv2_sys::__va_list_tag, + ap: *mut core::ffi::c_void, //should be *mut ffi::VaList but it's not yet stable ) -> c_int, } From ed9613bd87a4cfbe0f90db53eb6a2070a753a533 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Sat, 21 Aug 2021 18:20:52 +0200 Subject: [PATCH 24/25] complete and rework the log crate doc --- log/src/lib.rs | 132 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 25 deletions(-) diff --git a/log/src/lib.rs b/log/src/lib.rs index c6fb2000..f10f9d97 100644 --- a/log/src/lib.rs +++ b/log/src/lib.rs @@ -1,3 +1,83 @@ +//! Logging library allowing LV2 plugins to print log message through host. +//! +//! This crate allow plugins to print log message through the host. Different log levels are +//! defined by URI and passed as a lv2 URID. The core of this crate is the [Log +//! Feature](struct.Log.html). +//! +//! # Example +//! +//! This following plugin log an error message each time the input control is switched on. +//! +//! Note: Logging an error is not real-time safe. This following plugin should not ask +//! `hardRTCapable` in its .ttl files. +//! +//! ``` +//! use core::any::Any; +//! use lv2_core::feature::*; +//! use lv2_core::prelude::*; +//! use lv2_log::*; +//! use lv2_urid::*; +//! use std::ffi::CStr; +//! use urid::*; +//! +//! #[derive(URIDCollection)] +//! struct LoggerUrids { +//! error: URID, +//! } +//! +//! #[derive(PortCollection)] +//! struct Ports { +//! toggle: InputPort, +//! } +//! #[derive(FeatureCollection)] +//! pub struct InitFeatures<'a> { +//! map: LV2Map<'a>, +//! } +//! +//! #[derive(FeatureCollection)] +//! pub struct AudioFeatures<'a> { +//! log: Log<'a>, +//! } +//! +//! #[repr(C)] +//! #[uri("urn:rust-lv2-test:logger")] +//! struct logger { +//! urids: LoggerUrids, +//! last_toggle: bool, +//! } +//! +//! impl Plugin for logger { +//! type Ports = Ports; +//! type InitFeatures = InitFeatures<'static>; +//! type AudioFeatures = AudioFeatures<'static>; +//! +//! fn new(_plugin_info: &PluginInfo, features: &mut Self::InitFeatures) -> Option { +//! let urids: LoggerUrids = features.map.populate_collection()?; +//! Some(Self { +//! urids, +//! last_toggle: false, +//! }) +//! } +//! +//! fn run(&mut self, ports: &mut Ports, features: &mut Self::AudioFeatures, _: u32) { +//! let log = &features.log; +//! let toggle = *ports.toggle > 0.0; +//! if self.last_toggle != toggle && toggle { +//! let message = CStr::from_bytes_with_nul(b"error run message\n\0").unwrap(); +//! let _ = log.print_cstr(self.urids.error, message); +//! } +//! self.last_toggle = toggle; +//! } +//! +//! fn extension_data(_uri: &Uri) -> Option<&'static dyn Any> { +//! None +//! //match_extensions![uri, WorkerDescriptor] +//! } +//! } +//! +//! lv2_descriptors!(logger); +//! ``` + use lv2_core::feature::{Feature, ThreadingClass}; use std::error; use std::ffi::CStr; @@ -5,50 +85,50 @@ use std::fmt; use std::os::raw::*; //get all common c_type use urid::*; -/// URID marker. The corresponding URID is used to log an error on the host. +/// URID marker. The corresponding URID is used to log an error message on the host. pub struct Error; unsafe impl UriBound for Error { const URI: &'static [u8] = lv2_sys::LV2_LOG__Error; } -/// URID marker. The corresponding URID is used to log an informative on the host. +/// URID marker. The corresponding URID is used to log an informative message on the host. pub struct Note; unsafe impl UriBound for Note { const URI: &'static [u8] = lv2_sys::LV2_LOG__Note; } -/// URID marker. The corresponding URID is used to log a debbuging trace on the host. +/// URID marker. The corresponding URID is used to log a debugging trace on the host. pub struct Trace; unsafe impl UriBound for Trace { const URI: &'static [u8] = lv2_sys::LV2_LOG__Trace; } -/// URID marker. The corresponding URID is used to log a warning on the host. +/// URID marker. The corresponding URID is used to log a warning message on the host. pub struct Warning; unsafe impl UriBound for Warning { const URI: &'static [u8] = lv2_sys::LV2_LOG__Warning; } -/// Trait for URID marker. Plugin implementers shouldn't care about it. -/// -/// # Safety +/// Trait for URID marker. URID with a marker implementing this can be used to indicate the logging +/// level. /// -/// This trait is used to check at compile time if an URID indicate the nature of a log message, -/// Plugin implementers should not implement it. -pub unsafe trait Entry {} +/// Plugin implementers can implement this on custom URID marker to define and use additional +/// logging level. +// +pub trait Entry: UriBound {} -unsafe impl Entry for Error {} -unsafe impl Entry for Note {} -unsafe impl Entry for Trace {} -unsafe impl Entry for Warning {} +impl Entry for Error {} +impl Entry for Note {} +impl Entry for Trace {} +impl Entry for Warning {} -/// Returned if an error occured when sending a log to the host. +/// Returned if an error occurred when sending a log to the host. #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct PrintError; impl fmt::Display for PrintError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "An error occured when sending a message to the host") + write!(f, "An error occurred when sending a message to the host") } } impl error::Error for PrintError {} @@ -72,7 +152,9 @@ struct LogInternal { ) -> c_int, } -/// The Log feature. +/// Feature allowing to print log message through the host. +/// +/// #[repr(transparent)] pub struct Log<'a> { internal: &'a LogInternal, @@ -83,12 +165,6 @@ unsafe impl<'a> UriBound for Log<'a> { } unsafe impl<'a> Feature for Log<'a> { - // Note: this feature can be used in any threading class but: - // * i have a doubt about it's thread safety, can we assume the host provide this thread safety - // since this feature can be used anywhere ?. - // * i shouldn't be used in context where rt is a concern, that mean is audiothreadclass in - // practice, but it's acceptable to use it for debugging purpose - // So, at this time, i just giving access to it instanciation class unsafe fn from_feature_ptr(feature: *const c_void, _class: ThreadingClass) -> Option { (feature as *const LogInternal) .as_ref() @@ -100,7 +176,7 @@ impl<'a> Log<'a> { /// Send a log message to the host. /// /// The `entry` parameter is an URID representing the kind of log message. There are four - /// kind of message: + /// standard kind of message: /// * **note:** an informative message. /// * **warning:** a warning message. /// * **error:** an error message. @@ -108,6 +184,12 @@ impl<'a> Log<'a> { /// operation, but the host may implement an option to display them for debugging purposes. /// This entry type is special in that it may be written to in a real-time thread. It is /// assumed that if debug tracing is enabled, real-time considerations are not a concern. + /// + /// # Real-Time safety + /// + /// This function is not real-time safe. Except for logging debugging trace, it should not be + /// used in real-time context. That means `HardRTCapable` plugins should not call this function in + /// their `run()` context. pub fn print_cstr(&self, entry: URID, message: &CStr) -> Result<(), PrintError> { let res = unsafe { (self.internal.printf)( @@ -125,7 +207,7 @@ impl<'a> Log<'a> { } } -/// A URID cache containing all usefull log properties. +/// A URID cache containing all useful log properties. #[derive(URIDCollection, Debug)] pub struct LogURIDCollection { pub error: URID, From 5134b894659743a40b8d4e2ae8237c9453f04703 Mon Sep 17 00:00:00 2001 From: Yruama_Lairba Date: Sat, 21 Aug 2021 18:42:06 +0200 Subject: [PATCH 25/25] fix example test (missing dev dependencie) --- log/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/log/Cargo.toml b/log/Cargo.toml index f77c6a3a..4d38ace2 100644 --- a/log/Cargo.toml +++ b/log/Cargo.toml @@ -10,3 +10,6 @@ edition = "2018" lv2-sys = "2.0.0" lv2-core = "3.0.0" urid = "0.1.0" + +[dev-dependencies] +lv2-urid = "2.1.0" # for doc example