Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
  • abdsaber000/vlc
  • falbrechtskirchinger/vlc
  • b.sullender/vlc
  • hulxv/vlc
  • zyad-ayad/vlc
  • shocknovaa/vlc
  • gremlinflat/vlc
  • Pratham24D/vlc
  • hmaarrfk/vlc
412 results
Show changes
Commits on Source (2)
  • Alexandre Janniaux's avatar
    vlcrs-core: add tracer capability bindings · 3a3b5d67
    Alexandre Janniaux authored
    This commit allows rust code to use the tracer API, through the trace!()
    macro, and also exposes a TracerCapability and TracerModuleLoader to
    create new tracer modules in Rust.
    3a3b5d67
  • Alexandre Janniaux's avatar
    logger: add telegraf tracer · e8e46b0d
    Alexandre Janniaux authored
    The tracer is designed to send the metrics towards a telegraf server
    using this kind of configuration:
    
        [[inputs.socket_listener]]
        service_address = "tcp://localhost:8094"
    
    The telegraf server can then forward the metrics towards an influxdb
    server for monitoring or directly to grafana live server[^1] for
    introspection.
    
    The influxdb database can also be used to query the metrics after
    they've been indexed.
    
    The application using the tracer can use the VLC_TELEGRAF_ENDPOINT
    environment variable (eg. VLC_TELEGRAF_ENDPOINT=tcp://127.0.0.1:8094)
    to set where the tracer will output the traces to.
    
    A bunch of notes and improvement left for later:
    
     - Unsafe code is still used for accessing the fields data since an
       union is used and union access is unsafe. It could probably be
       wrapped from the binding implementation.
    
     - There is no way to specify the address using the configuration
       since vlc_variable is not bound to the Rust bindings and no
       unsafe extern "C" code...
    e8e46b0d
......@@ -4,6 +4,7 @@ members = [
"src/rust/vlcrs-macros",
"src/rust/vlcrs-messages",
"src/rust/vlcrs-utils",
"modules/logger/telegraf-rs/"
]
resolver = "2"
......@@ -12,5 +13,5 @@ version = "4.0.0"
license = "LGPL-2.1-or-later"
[workspace.dependencies]
vlcrs-core = { path = "./vlcrs-core" }
vlcrs-macros = { path = "./vlcrs-macros" }
vlcrs-core = { path = "src/rust/vlcrs-core" }
vlcrs-macros = { path = "src/rust/vlcrs-macros" }
......@@ -30,3 +30,21 @@ libemscripten_logger_plugin_la_SOURCES = logger/emscripten.c
if HAVE_EMSCRIPTEN
logger_LTLIBRARIES += libemscripten_logger_plugin.la
endif
AM_V_LTCARGO = $(AM_V_LTCARGO_$(V))
AM_V_LTCARGO_ = $(AM_V_LTCARGO_$(AM_DEFAULT_VERBOSITY))
AM_V_LTCARGO__0 = $(AM_V_LTCARGO_0)
AM_V_LTCARGO_0 = @echo " CARGO $(@)";
libtelegraf_rs.la: $(libtelegraf_rs_plugin_la_SOURCES)
$(AM_V_LTCARGO)$(LIBTOOL_CARGO) $(abs_srcdir)/logger/telegraf-rs $@
CLEANFILES += libtelegraf_rs.la
libtelegraf_rs_plugin_la_SOURCES = \
logger/telegraf-rs/Cargo.toml \
logger/telegraf-rs/src/lib.rs
libtelegraf_rs_plugin_la_LIBADD = libtelegraf_rs.la
if HAVE_RUST
logger_LTLIBRARIES += libtelegraf_rs_plugin.la
endif
[package]
name = "telegraf-rs"
version.workspace = true
edition = "2021"
license = "LGPL-2.1-or-later"
[dependencies]
vlcrs-core.workspace = true
vlcrs-macros.workspace = true
telegraf = "=0.6.0"
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(vlc_static_plugins)'] }
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) 2024-2025 Alexandre Janniaux <ajanni@videolabs.io>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
use std::{cell::UnsafeCell, ffi::CStr, sync::Mutex};
use telegraf::{Client, IntoFieldData, Point};
use vlcrs_core::tracer::{sys::vlc_tracer_value_type, TracerCapability, TracerModuleLoader};
use vlcrs_macros::module;
struct TraceField(vlcrs_core::tracer::TraceField);
impl IntoFieldData for TraceField {
fn field_data(&self) -> telegraf::FieldData {
match self.0.kind() {
vlc_tracer_value_type::String => unsafe {
let value = CStr::from_ptr(self.0.value().string);
telegraf::FieldData::Str(value.to_str().unwrap().to_string())
},
vlc_tracer_value_type::Integer => unsafe {
telegraf::FieldData::Number(self.0.value().integer)
},
vlc_tracer_value_type::Double => unsafe {
telegraf::FieldData::Float(self.0.value().double)
},
_ => unreachable!(),
}
}
}
struct TelegrafTracer {
endpoint: Mutex<UnsafeCell<telegraf::Client>>,
}
impl TracerCapability for TelegrafTracer {
fn open(_obj: &mut vlcrs_core::object::Object) -> Option<impl TracerCapability>
where
Self: Sized,
{
let endpoint_address =
std::env::var("VLC_TELEGRAF_ENDPOINT").unwrap_or(String::from("tcp://localhost:8094"));
let endpoint = Client::new(&endpoint_address)
.map(UnsafeCell::new)
.map(Mutex::new)
.unwrap();
Some(Self { endpoint })
}
fn trace(&self, _tick: vlcrs_core::tracer::Tick, entries: &'_ vlcrs_core::tracer::Trace) {
if !entries
.into_iter()
.any(|e| e.kind() != vlcrs_core::tracer::sys::vlc_tracer_value_type::String)
{
/* We cannot support events for now. */
return;
}
let tags: Vec<(String, String)> = entries
.into_iter()
.filter(|e| e.kind() == vlcrs_core::tracer::sys::vlc_tracer_value_type::String)
.map(|entry| unsafe {
let value = CStr::from_ptr(entry.value().string);
(
String::from(entry.key()),
String::from(value.to_str().unwrap()),
)
})
.collect();
let record: Vec<(String, Box<dyn IntoFieldData + 'static>)> = entries
.into_iter()
.filter(|e| e.kind() != vlcrs_core::tracer::sys::vlc_tracer_value_type::String)
.map(|entry| {
(
String::from(entry.key()),
Box::new(TraceField(entry)) as Box<dyn IntoFieldData>,
)
})
.collect();
let p = Point::new(
String::from("measurement"),
tags,
record,
None, //Some(tick.0 as u64),
);
let mut endpoint = self.endpoint.lock().unwrap();
if let Err(err) = endpoint.get_mut().write_point(&p) {
match err {
telegraf::TelegrafError::IoError(e) => eprintln!("TelegrafTracer: IO Error: {}", e),
telegraf::TelegrafError::ConnectionError(s) => {
eprintln!("telegraf tracer: connection error: {}", s)
}
telegraf::TelegrafError::BadProtocol(_) => todo!(),
}
}
}
}
module! {
type: TelegrafTracer (TracerModuleLoader),
capability: "tracer" @ 0,
category: ADVANCED_MISC,
description: "Tracer module forwarding the traces to a Telegraf endpoint",
shortname: "Telegraf tracer",
shortcuts: ["telegraf"],
}
......@@ -6,3 +6,6 @@ license.workspace = true
[dependencies]
vlcrs-messages = { path = "../vlcrs-messages" }
[dev-dependencies]
vlcrs-macros.workspace = true
#![deny(unsafe_op_in_unsafe_fn)]
#![feature(extern_types)]
#![feature(associated_type_defaults)]
#![feature(allocator_api)]
#![feature(c_size_t)]
//! The `vlcrs-core` crate.
......@@ -11,6 +12,25 @@
//! If you need a vlc core C API that is not ported or wrapped yet here,
//! then do so first instead of bypassing this crate.
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) 2024 Alexandre Janniaux <ajanni@videolabs.io>
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software Foundation,
// Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.#![deny(unsafe_op_in_unsafe_fn)]
pub mod plugin;
pub mod object;
pub mod tracer;
/// SPDX-License-Identifier: LGPL-2.1-or-later
/// Copyright (C) 2024-2025 Alexandre Janniaux <ajanni@videolabs.io>
///
/// This program is free software; you can redistribute it and/or modify it
/// under the terms of the GNU Lesser General Public License as published by
/// the Free Software Foundation; either version 2.1 of the License, or
/// (at your option) any later version.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU Lesser General Public License for more details.
///
/// You should have received a copy of the GNU Lesser General Public License
/// along with this program; if not, write to the Free Software Foundation,
/// Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
use std::{
cell::UnsafeCell,
ffi::{c_char, c_void, CStr},
mem::MaybeUninit,
ptr::NonNull,
};
use crate::{object::Object, plugin::ModuleProtocol};
pub mod sys;
pub use sys::{Trace, TraceField};
pub struct Tick(pub i64);
///
/// Trait representing the module capability for implementing tracers.
///
/// A type implementing the [TracerCapability] trait can be exposed to
/// a [vlcrs_macros::module!] manifest using the
/// [TracerModuleLoader] type loader, which will expose it as a "tracer"
/// capability for VLC core.
///
/// Note that this trait *requires* [Sync] since the tracer is used
/// from the C code in multiple threads at the same time.
///
/// [Sync] is automatically implemented by types using only [Sync]
/// types, and is unsafe to implement. It means that the following
/// implementation would not be possible without unsafe:
///
/// ```compile_fail
/// use std::cell::Cell;
/// use vlcrs_core::object::Object;
/// use vlcrs_core::tracer::{Tick, TracerCapability, Trace};
/// struct Module { last_trace_tick: Cell<Tick>, }
/// impl TracerCapability for Module {
/// fn open(obj: &mut Object) -> Option<impl TracerCapability> {
/// Some(Self{ last_trace_tick: Cell::from(Tick(0)) })
/// }
///
/// fn trace(&self, tick: Tick, entries: &Trace) {
/// let mut state = self.last_trace_tick.get_mut();
/// *state = tick;
/// }
/// }
/// ````
///
/// As it will fail with the following error:
///
/// ```no_build
/// test: vlcrs-core/src/tracer/mod.rs - tracer::TracerCapability (line 31)
/// error[E0277]: `Cell<Tick>` cannot be shared between threads safely
/// --> vlcrs-core/src/tracer/mod.rs:36:27
/// |
/// 8 | impl TracerCapability for Module {
/// | ^^^^^^ `Cell<Tick>` cannot be shared between threads safely
/// |
/// = help: within `Module`, the trait `Sync` is not implemented for `Cell<Tick>`, which is required by `Module: Sync`
/// = note: if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`
/// note: required because it appears within the type `Module`
/// ````
///
/// Instead, proper concurrency handling must be implemented inside the
/// object so that it becomes Sync and can be used in the multiples threads.
///
pub trait TracerCapability: Sync {
fn open(obj: &mut Object) -> Option<impl TracerCapability>
where
Self: Sized;
fn trace(&self, tick: Tick, entries: &Trace);
}
#[allow(non_camel_case_types)]
pub type TracerCapabilityActivate =
unsafe extern "C" fn(
obj: &mut Object,
opaque: &mut MaybeUninit<*mut c_void>,
) -> Option<&'static sys::vlc_tracer_operations>;
extern "C" fn tracer_trace(opaque: *const c_void, tick: sys::vlc_tick, entries: sys::Trace) {
{
let tracer: &dyn TracerCapability =
unsafe { &**(opaque as *const Box<dyn TracerCapability>) };
tracer.trace(Tick(tick), &entries);
}
}
extern "C" fn tracer_destroy(opaque: *mut c_void) {
let tracer: *mut Box<dyn TracerCapability> = opaque as *mut _;
let _ = unsafe { Box::from_raw(tracer) };
}
const TRACER_OPERATIONS: sys::vlc_tracer_operations = sys::vlc_tracer_operations {
trace: tracer_trace,
destroy: tracer_destroy,
};
extern "C" fn activate_tracer<T: TracerCapability>(
obj: &mut Object,
opaque: &mut MaybeUninit<*mut c_void>,
) -> Option<&'static sys::vlc_tracer_operations> {
if let Some(instance) = T::open(obj) {
let wrapper: Box<dyn TracerCapability> = Box::try_new(instance).ok()?;
let sys = Box::into_raw(Box::try_new(wrapper).ok()?);
opaque.write(sys as *mut _);
return Some(&TRACER_OPERATIONS);
}
None
}
///
/// Loader type for the "tracer" capability, using the
/// [TracerCapability] trait.
///
/// This is an implementation of the [ModuleProtocol] type for the
/// [TracerCapability] trait, exposing modules from the declaration
/// ([`vlcrs_macros::module!`]) of the manifest as a "tracer"
/// capability for VLC core.
///
/// ```
/// use vlcrs_core::tracer::{Tick, TracerCapability, TracerModuleLoader, Trace};
/// use vlcrs_core::object::Object;
/// use vlcrs_macros::module;
/// struct CustomTracer {}
///
/// // Empty implementation
/// impl TracerCapability for CustomTracer {
/// fn open(obj: &mut Object) -> Option<impl TracerCapability> {
/// Some(Self{})
/// }
/// fn trace(&self, _tick: Tick, _entries: &Trace) {}
/// }
///
/// module!{
/// type: CustomTracer (TracerModuleLoader),
/// capability: "tracer" @ 0,
/// category: ADVANCED_MISC,
/// description: "Custom tracer implementation",
/// shortname: "Custom tracer",
/// shortcuts: ["customtracer"],
///}
/// ````
pub struct TracerModuleLoader;
impl<T> ModuleProtocol<T> for TracerModuleLoader
where
T: TracerCapability,
{
type Activate = TracerCapabilityActivate;
fn activate_function() -> Self::Activate {
activate_tracer::<T>
}
}
///
/// Wrapper around a vlc_tracer implementation from VLC core.
///
/// Exposes the public API for using tracers from VLC core.
///
pub struct Tracer {
tracer: UnsafeCell<NonNull<sys::vlc_tracer>>,
}
impl Tracer {
///
/// Request a new instance of a tracer from LibVLC.
///
pub fn create(obj: &Object, name: &CStr) -> Option<Tracer> {
let name = name.as_ptr() as *const c_char;
// SAFETY: sys::vlc_tracer_Create() is safe as long as name is
// null-terminated (given by CStr) and Object is valid,
// which is given by requiring a reference.
let tracer: NonNull<sys::vlc_tracer> = unsafe { sys::vlc_tracer_Create(obj, name)? };
Some(Self {
tracer: UnsafeCell::new(tracer),
})
}
///
/// Register the new point at time [tick] with the metadata [entries].
///
pub fn trace(&self, tick: Tick, entries: Trace) {
unsafe {
// SAFETY: TODO
let tracer = *self.tracer.get();
// SAFETY: the pointer `tracer` is guaranteed to be non-null and
// nobody else has reference to it.
sys::vlc_tracer_TraceWithTs(tracer, tick.0, entries);
}
}
}
#[macro_export]
macro_rules! trace {
($tracer: ident, $ts: expr, $($key:ident = $value:expr)*) => {};
}
#![allow(rustdoc::bare_urls)]
#![allow(rustdoc::broken_intra_doc_links)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
/// SPDX-License-Identifier: LGPL-2.1-or-later
/// Copyright (C) 2024-2025 Alexandre Janniaux <ajanni@videolabs.io>
///
/// This program is free software; you can redistribute it and/or modify it
/// under the terms of the GNU Lesser General Public License as published by
/// the Free Software Foundation; either version 2.1 of the License, or
/// (at your option) any later version.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU Lesser General Public License for more details.
///
/// You should have received a copy of the GNU Lesser General Public License
/// along with this program; if not, write to the Free Software Foundation,
/// Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
use std::{
ffi::{c_char, c_double, c_void, CStr},
ptr::NonNull,
};
use crate::object::Object;
pub type vlc_tick = i64;
#[repr(C)]
#[non_exhaustive]
#[doc = "Tracer message values"]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum vlc_tracer_value_type {
Integer = 0,
Double = 1,
String = 2,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union vlc_tracer_value {
pub integer: i64,
pub double: c_double,
pub string: *const c_char,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct vlc_tracer_entry {
pub key: *const c_char,
pub value: vlc_tracer_value,
pub kind: vlc_tracer_value_type,
}
#[repr(C)]
pub struct vlc_tracer_trace {
pub entries: NonNull<vlc_tracer_entry>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct vlc_tracer {
_unused: [u8; 0],
}
#[derive(PartialEq, Copy, Clone)]
#[repr(transparent)]
pub struct Trace {
pub entries: NonNull<vlc_tracer_trace>,
}
#[derive(PartialEq, Copy, Clone, Debug)]
#[repr(transparent)]
pub struct TraceField {
pub entry: NonNull<vlc_tracer_entry>,
}
impl TraceField {
pub fn key(&self) -> &str {
unsafe {
let key = CStr::from_ptr(self.entry.read().key);
key.to_str().unwrap()
}
}
pub fn kind(&self) -> vlc_tracer_value_type {
unsafe { self.entry.read().kind }
}
pub fn value(&self) -> vlc_tracer_value {
unsafe { self.entry.read().value }
}
}
pub struct TraceIterator {
current_field: NonNull<vlc_tracer_entry>,
}
impl IntoIterator for Trace {
type Item = TraceField;
type IntoIter = TraceIterator;
fn into_iter(self) -> Self::IntoIter {
TraceIterator {
current_field: unsafe { self.entries.read().entries },
}
}
}
impl Iterator for TraceIterator {
type Item = TraceField;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
if self.current_field.read().key.is_null() {
return None;
}
let output = Some(TraceField {
entry: self.current_field,
});
self.current_field = self.current_field.add(1);
output
}
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct vlc_tracer_operations {
pub trace: extern "C" fn(opaque: *const c_void, ts: vlc_tick, entries: Trace),
pub destroy: extern "C" fn(*mut c_void),
}
extern "C" {
pub fn vlc_tracer_Create(parent: &Object, name: *const c_char) -> Option<NonNull<vlc_tracer>>;
pub fn vlc_tracer_TraceWithTs(tracer: NonNull<vlc_tracer>, tick: vlc_tick, entries: Trace);
}
#[cfg(test)]
mod test {
#[test]
fn test_trace_interop() {
use super::*;
let entries = [
vlc_tracer_entry {
kind: vlc_tracer_value_type::String,
value: vlc_tracer_value {
string: c"value1".as_ptr(),
},
key: c"test1".as_ptr(),
},
vlc_tracer_entry {
kind: vlc_tracer_value_type::Integer,
value: vlc_tracer_value { integer: 0 },
key: std::ptr::null(),
},
];
let trace_field = TraceField {
entry: NonNull::from(&entries[0]),
};
assert_eq!(trace_field.kind(), vlc_tracer_value_type::String);
assert_eq!(trace_field.key(), "test1");
let trace_field = TraceField {
entry: NonNull::from(&entries[1]),
};
assert_eq!(trace_field.kind(), vlc_tracer_value_type::Integer);
let trace = vlc_tracer_trace {
entries: NonNull::from(&entries[0]),
};
let trace = Trace {
entries: NonNull::from(&trace),
};
let mut iterator = trace.into_iter();
let first = iterator.next().expect("First field must be valid");
assert_eq!(first.kind(), vlc_tracer_value_type::String);
assert_eq!(first.key(), "test1");
unsafe {
assert_eq!(CStr::from_ptr(first.value().string), c"value1");
}
let second = iterator.next();
assert_eq!(second, None);
}
}