2个版本

0.1.1 2020年10月23日
0.1.0 2020年3月27日

#13#lv2


lv2 中使用

MIT/Apache

1MB
15K SLoC

Rust-LV2的库,用于实现LV2 Worker扩展。

一个工作调度库,允许具有实时能力的LV2插件执行非实时操作。这是 rust-lv2 的一部分,一个用于创建LV2插件的 Rust 编写的安全、快速和易于使用的框架,用于音频处理。

文档

原始LV2 API(用C语言编程)由"LV2书籍"进行文档编制。这本书正在与rust-lv2的开发一起翻译成Rust(链接)(链接),并描述了如何正确使用rust-lv2

许可证

根据您选择以下任一许可证进行许可

任选。


lib.rs:

一个工作调度库,允许实时能力的LV2插件执行非实时操作。

此crate允许插件在另一个线程中安排必须执行的工作。插件可以使用此接口安全地执行非实时安全的工作,并在运行上下文中接收结果。一个典型用例是从磁盘读取和缓存数据的采样器。有关详细信息,请参阅LV2 Worker规范

示例

use std::any::Any;
use lv2_core::feature::*;
use lv2_core::prelude::*;
use urid::*;
use lv2_worker::*;

#[derive(PortCollection)]
struct Ports {}

/// Requested features
#[derive(FeatureCollection)]
struct AudioFeatures<'a> {
    ///host feature allowing to schedule some work
    schedule: Schedule<'a, EgWorker>,
}

//custom datatype
struct WorkMessage {
    cycle: usize,
    task: usize,
}

/// A plugin that do some work in another thread
struct EgWorker {
    // The schedule handler needs to know the plugin type in order to access the `WorkData` type.
    cycle: usize,
    end_cycle: usize,
}

/// URI identifier
unsafe impl UriBound for EgWorker {
    const URI: &'static [u8] = b"urn:rust-lv2-more-examples:eg-worker-rs\0";
}

impl Plugin for EgWorker {
    type Ports = Ports;
    type InitFeatures = ();
    type AudioFeatures = AudioFeatures<'static>;

    fn new(_plugin_info: &PluginInfo, _features: &mut Self::InitFeatures) -> Option<Self> {
        Some(Self {
            cycle: 0,
            end_cycle: 1,
        })
    }

    fn run(&mut self, _ports: &mut Ports, features: &mut Self::AudioFeatures, _: u32) {
        self.cycle += 1;
        let cycle = self.cycle;
        println!("cycle {} started", cycle);
        for task in 0..10 {
            let work = WorkMessage { cycle, task };
            // schedule some work, passing some data and check for error
            if let Err(e) = features.schedule.schedule_work(work) {
                eprintln!("Can't schedule work: {}", e);
            }
        }
    }

    fn extension_data(uri: &Uri) -> Option<&'static dyn Any> {
        match_extensions![uri, WorkerDescriptor<Self>]
    }
}

/// Implementing the extension.
impl Worker for EgWorker {
    // data type sent by the schedule handler and received by the `work` method.
    type WorkData = WorkMessage;
    // data type sent by the response handler and received by the `work_response` method.
    type ResponseData = String;
    fn work(
        //response handler need to know the plugin type.
        response_handler: &ResponseHandler<Self>,
        data: Self::WorkData,
    ) -> Result<(), WorkerError> {
        println!("work received: cycle {}, task {}", data.cycle, data.task);
        if data.task >= 5 {
            if let Err(e) = response_handler.respond(format!(
                "response to cycle {}, task {}",
                data.cycle, data.task
            )) {
                eprintln!("Can't respond: {}", e);
            }
        };
        Ok(())
    }

    fn work_response(
        &mut self,
        data: Self::ResponseData,
        _features: &mut Self::AudioFeatures,
    ) -> Result<(), WorkerError> {
        println!("work_response received: {}", data);
        Ok(())
    }

    fn end_run(&mut self, _features: &mut Self::AudioFeatures) -> Result<(), WorkerError> {
        println!("cycle {} ended", self.end_cycle);
        self.end_cycle += 1;
        Ok(())
    }
}

依赖项

~1.5MB
~34K SLoC