Initial music-player crate

This commit is contained in:
mars 2022-09-24 12:54:55 -06:00
parent 81bd65cf29
commit 2ba24a85dc
3 changed files with 239 additions and 1 deletions

View File

@ -1,6 +1,7 @@
[workspace]
members = [
"crates/egui",
"crates/music-player",
"crates/sao-ui-rs",
"crates/script",
"crates/types",
@ -23,4 +24,4 @@ slab = "0.4"
wasmtime = "0.38"
[dependencies.font-kit]
version = "0.11"
version = "*"

View File

@ -0,0 +1,11 @@
[package]
name = "canary-music-player"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1"
canary = { path = "../../" }
glium = "0.32"
mpris = "2.0.0-rc3"
ouroboros = "^0.15"

View File

@ -0,0 +1,226 @@
use canary::ScriptInstance;
use glium::{glutin, Display, Surface};
use glutin::event::{Event, WindowEvent};
use glutin::event_loop::{ControlFlow, EventLoop};
use mpris::{PlayerFinder, ProgressTracker};
use ouroboros::self_referencing;
#[derive(Copy, Clone)]
pub struct Vertex {
pub position: [f32; 2],
pub color: [f32; 4],
}
glium::implement_vertex!(Vertex, position, color);
impl From<&canary::MeshVertex> for Vertex {
fn from(v: &canary::MeshVertex) -> Self {
Self {
position: [v.position.x, v.position.y],
color: [v.color.r, v.color.g, v.color.b, v.color.a],
}
}
}
const VERTEX_SHADER_SRC: &str = r#"
#version 330
in vec2 position;
in vec4 color;
out vec4 frag_color;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
frag_color = color;
}
"#;
const FRAGMENT_SHADER_SRC: &str = r#"
#version 330
in vec4 frag_color;
out vec4 fb_color;
void main() {
fb_color = frag_color;
}
"#;
#[self_referencing]
pub struct Player {
player: mpris::Player,
#[borrows(player)]
#[covariant]
tracker: ProgressTracker<'this>,
}
impl Player {
pub fn from_player(player: mpris::Player) -> Self {
PlayerBuilder {
player,
tracker_builder: |player| player.track_progress(100).unwrap(),
}
.build()
}
pub fn tick(&mut self) -> bool {
self.with_tracker_mut(|tracker| {
let tick = tracker.tick();
if tick.progress_changed {
println!(
"{:?}/{:?}",
tick.progress.position(),
tick.progress.length()
);
}
if tick.track_list_changed {
println!("{:#?}", tick.progress.metadata());
}
tick.player_quit
})
}
}
pub struct App {
display: Display,
program: glium::Program,
player_finder: PlayerFinder,
player: Option<Player>,
script: canary::WasmtimeScript<canary::ScriptAbiImpl>,
panel: canary::PanelId,
}
impl App {
pub fn new(module_path: &str, display: Display) -> Self {
let program =
glium::Program::from_source(&display, VERTEX_SHADER_SRC, FRAGMENT_SHADER_SRC, None)
.unwrap();
let runtime = canary::WasmtimeRuntime::new().unwrap();
let abi = Default::default();
let module = std::fs::read(module_path).unwrap();
let mut script = runtime.load_module(abi, &module).unwrap();
let panel = script.bind_panel(vec![]);
Self {
display,
program,
player_finder: PlayerFinder::new().expect("Could not connect to D-Bus"),
player: None,
script,
panel,
}
}
pub fn update(&mut self) {
self.display.gl_window().window().request_redraw();
/*let disconnected = if let Some(player) = self.player.as_mut() {
player.tick()
} else {
match self.player_finder.find_active() {
Ok(player) => {
println!("Connected to MPRIS");
self.player = Some(Player::from_player(player));
}
Err(e) => eprintln!("PlayerFinder: {:?}", e),
}
false
};
if disconnected {
println!("Disconnected from MPRIS");
self.player = None;
}*/
self.script.update(self.panel, 0.01667);
}
pub fn draw(&mut self) {
let mut target = self.display.draw();
target.clear_color(0.0, 0.0, 0.0, 0.0);
self.script.draw(self.panel, |commands| {
let mut joined_vs: Vec<Vertex> = Vec::new();
let mut joined_is = Vec::new();
for command in commands.iter() {
match command {
canary::DrawCommand::Mesh { vertices, indices } => {
let voff = joined_vs.len() as canary::MeshIndex;
joined_vs.extend(vertices.iter().map(Vertex::from));
joined_is.extend(indices.iter().map(|i| i + voff));
}
_ => unimplemented!(),
}
}
let vertex_buffer = glium::VertexBuffer::new(&self.display, &joined_vs).unwrap();
let index_buffer = glium::IndexBuffer::new(
&self.display,
glium::index::PrimitiveType::TrianglesList,
&joined_is,
)
.unwrap();
let params = glium::DrawParameters {
blend: glium::Blend::alpha_blending(),
..Default::default()
};
target
.draw(
&vertex_buffer,
&index_buffer,
&self.program,
&glium::uniforms::EmptyUniforms,
&params,
)
.unwrap();
});
target.finish().unwrap();
}
}
fn main() {
let args: Vec<String> = std::env::args().collect();
let module_path = args
.get(1)
.expect("Please pass a path to a Canary script!")
.to_owned();
let event_loop = EventLoop::new();
let wb = glutin::window::WindowBuilder::new();
let cb = glutin::ContextBuilder::new();
let display = glium::Display::new(wb, cb, &event_loop).unwrap();
let mut app = App::new(&module_path, display);
event_loop.run(move |ev, _, control_flow| {
*control_flow = ControlFlow::Poll;
match ev {
Event::WindowEvent { event, .. } => match event {
WindowEvent::CloseRequested => {
*control_flow = ControlFlow::Exit;
return;
}
_ => return,
},
Event::MainEventsCleared => {
app.update();
}
Event::RedrawRequested(_) => {
app.draw();
}
_ => {}
}
});
}