char/char-rtc-obs
git clone https://git.t4t.associates/char/char-rtc-obs
eeaf4aa
main
1use env_logger:: filter::{ Builder , Filter }; 2use log::{ Level , Log }; 3use std::{ ffi:: CStr , sync:: atomic:: AtomicBool , sync:: atomic:: Ordering }; 4 5static DEBUG_WHIP : AtomicBool =AtomicBool :: new ( false ); 6 7pub ( crate ) fn debug_whip () ->bool { 8DEBUG_WHIP . load ( Ordering :: Relaxed ) 9} 10 11/// cbindgen:ignore 12mod obs{ 13use std:: os:: raw:: c_char; 14use std:: os:: raw:: c_int; 15 16# [ repr ( C )] 17# [ derive ( Debug )] 18pub ( super ) struct obs_cmdline_args { 19pub ( super ) argc : c_int , 20pub ( super ) argv : * const * const c_char , 21} 22 23# [ link ( name = "libobs" )] 24extern "C" { 25pub ( super ) fn blog ( log_level : i32 , format : * const c_char , ...); 26pub ( super ) fn obs_get_cmdline_args () ->obs_cmdline_args ; 27} 28} 29 30pub struct OBSLogger { 31log_filter : Filter , 32} 33 34impl OBSLogger { 35pub fn install () { 36// Pull our RUST_LOG in case they are using that 37let mut log_filter: String = std:: env:: var ( "RUST_LOG" ). unwrap_or_else ( |_|"INFO" . into ()); 38 39unsafe { 40let raw_args = obs:: obs_get_cmdline_args (); 41let mut args = std:: slice:: from_raw_parts ( raw_args. argv , raw_args. argc as usize ) 42. iter () 43. map ( |arg|CStr :: from_ptr ( * arg). to_string_lossy ()); 44 45while let Some ( arg) = args. next () { 46match arg. as_ref () { 47"--debug-webrtc-whip" =>{ 48DEBUG_WHIP . store ( true , Ordering :: Relaxed ); 49} 50"--debug-webrtc-filter" =>{ 51if let Some ( filter) = args. next () { 52 log_filter = filter. into (); 53} 54} 55 _ =>{} 56} 57} 58let mut filter_builder =Builder :: new (); 59 log:: set_boxed_logger ( Box :: new ( Self { 60log_filter : filter_builder. parse ( & log_filter). build (), 61})) 62. expect ( "Logger already set" ); 63 64 log:: set_max_level ( log:: LevelFilter :: Trace ); 65} 66} 67} 68 69impl Log for OBSLogger { 70fn enabled ( & self , metadata : & log:: Metadata ) ->bool { 71self . log_filter . enabled ( metadata) 72} 73 74fn log ( & self , record : & log:: Record ) { 75if !self . log_filter . matches ( record) { 76return ; 77} 78 79let level = record. level (); 80let log_level =match level{ 81Level :: Trace =>( 300 , "[T] " ), 82Level :: Debug =>( 300 , "[D] " ), 83Level :: Info =>( 300 , "" ), 84Level :: Warn =>( 200 , "" ), 85Level :: Error =>( 100 , "" ), 86}; 87 88let message_prefix =format! ( 89"{}[{}:{}]" , 90 log_level. 1 , 91if record. target (). is_empty () { 92 record. module_path (). unwrap_or ( "unk" ) 93} else { 94 record. target () 95}, 96 record. line (). unwrap_or ( 0 ), 97); 98 99const MAX_CHUNK_SIZE : usize =3500 ; 100 101let message_chars = record. args (). to_string (). chars (). collect ::< Vec < char >>(); 102let chunks = message_chars. chunks ( MAX_CHUNK_SIZE ); 103let chunks_len = chunks. len (); 104for ( index, chunk) in chunks. enumerate () { 105unsafe { 106let chunk = chunk. iter (). cloned (). collect ::< String >(); 107if chunks_len ==1 { 108 obs:: blog ( 109 log_level. 0 , 110format! ( "{message_prefix}: {chunk}\0" ). as_ptr () as * const i8 , 111); 112} else { 113 obs:: blog ( 114 log_level. 0 , 115format! ( 116"{message_prefix}: MULTIPART [{}/{chunks_len}] {chunk}\0" , 117 index +1 , 118) 119. as_ptr () as * const i8 , 120); 121} 122} 123} 124} 125 126fn flush ( & self ) {} 127}