mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2025-02-07 02:59:28 +00:00
Handle playback volume
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
3b7f0c5793
commit
0f75905cc8
@ -20,11 +20,18 @@ pub struct PCMInfo {
|
||||
pub be: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Volume {
|
||||
pub mute: bool,
|
||||
pub volume: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AudioOutEvent {
|
||||
Init { id: u64, info: PCMInfo },
|
||||
Fini { id: u64 },
|
||||
SetEnabled { id: u64, enabled: bool },
|
||||
SetVolume { id: u64, volume: Volume },
|
||||
Write { id: u64, data: Vec<u8> },
|
||||
}
|
||||
|
||||
@ -33,6 +40,7 @@ pub enum AudioInEvent {
|
||||
Init { id: u64, info: PCMInfo },
|
||||
Fini { id: u64 },
|
||||
SetEnabled { id: u64, enabled: bool },
|
||||
SetVolume { id: u64, volume: Volume },
|
||||
Read { id: u64 },
|
||||
}
|
||||
|
||||
@ -119,6 +127,17 @@ impl<E: 'static + EventSender<Event = AudioOutEvent>> AudioOutListener<E> {
|
||||
self.send(AudioOutEvent::SetEnabled { id, enabled })
|
||||
}
|
||||
|
||||
/// SetVolume method
|
||||
fn set_volume(&mut self, id: u64, mute: bool, volume: serde_bytes::ByteBuf) {
|
||||
self.send(AudioOutEvent::SetVolume {
|
||||
id,
|
||||
volume: Volume {
|
||||
mute,
|
||||
volume: volume.into_vec(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// Write method
|
||||
fn write(&mut self, id: u64, data: serde_bytes::ByteBuf) {
|
||||
self.send(AudioOutEvent::Write {
|
||||
@ -191,6 +210,17 @@ impl<E: 'static + EventSender<Event = AudioInEvent>> AudioInListener<E> {
|
||||
self.send(AudioInEvent::SetEnabled { id, enabled })
|
||||
}
|
||||
|
||||
/// SetVolume method
|
||||
fn set_volume(&mut self, id: u64, mute: bool, volume: serde_bytes::ByteBuf) {
|
||||
self.send(AudioInEvent::SetVolume {
|
||||
id,
|
||||
volume: Volume {
|
||||
mute,
|
||||
volume: volume.into_vec(),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/// Read method
|
||||
fn read(&mut self, id: u64, size: u64) -> Vec<u8> {
|
||||
dbg!((id, size));
|
||||
|
@ -20,6 +20,7 @@ glib = { git = "https://github.com/gtk-rs/gtk-rs", optional = true }
|
||||
derivative = "2.2.0"
|
||||
gst = { package = "gstreamer", version = "0.16.7" }
|
||||
gst-app = { package = "gstreamer-app", version = "0.16.5" }
|
||||
gst-audio = { package = "gstreamer-audio", version = "0.16.5" }
|
||||
|
||||
[dependencies.gtk]
|
||||
package = "gtk4"
|
||||
|
@ -1,13 +1,15 @@
|
||||
use gst::prelude::*;
|
||||
|
||||
use qemu_display_listener::{Audio, PCMInfo};
|
||||
use gst_audio::StreamVolumeExt;
|
||||
use std::thread::{self, JoinHandle};
|
||||
use std::{collections::HashMap, error::Error};
|
||||
|
||||
use qemu_display_listener::{Audio, PCMInfo};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct OutStream {
|
||||
pipeline: gst::Pipeline,
|
||||
src: gst_app::AppSrc,
|
||||
sink: gst::Element,
|
||||
}
|
||||
|
||||
fn pcminfo_as_caps(info: &PCMInfo) -> String {
|
||||
@ -44,23 +46,28 @@ impl OutStream {
|
||||
.unwrap()
|
||||
.dynamic_cast::<gst_app::AppSrc>()
|
||||
.unwrap();
|
||||
|
||||
Ok(Self { pipeline, src })
|
||||
let sink = pipeline.get_by_name("sink").unwrap();
|
||||
Ok(Self {
|
||||
pipeline,
|
||||
src,
|
||||
sink,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GstAudio {
|
||||
thread: JoinHandle<()>,
|
||||
out_thread: JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl GstAudio {
|
||||
pub fn new(audio: Audio) -> Result<Self, Box<dyn Error>> {
|
||||
gst::init()?;
|
||||
|
||||
// TODO audio.listen_in() for capture.
|
||||
let rx = audio.listen_out()?;
|
||||
let mut out = HashMap::new();
|
||||
let thread = thread::spawn(move || loop {
|
||||
let out_thread = thread::spawn(move || loop {
|
||||
match rx.recv() {
|
||||
Ok(event) => {
|
||||
use qemu_display_listener::AudioOutEvent::*;
|
||||
@ -95,6 +102,28 @@ impl GstAudio {
|
||||
eprintln!("Stream was not setup yet: {}", id);
|
||||
}
|
||||
}
|
||||
SetVolume { id, volume } => {
|
||||
if let Some(s) = out.get(&id) {
|
||||
if let Some(stream_vol) = s
|
||||
.pipeline
|
||||
.get_by_interface(gst_audio::StreamVolume::static_type())
|
||||
{
|
||||
let stream_vol = stream_vol
|
||||
.dynamic_cast::<gst_audio::StreamVolume>()
|
||||
.unwrap();
|
||||
stream_vol.set_mute(volume.mute);
|
||||
if let Some(vol) = volume.volume.first() {
|
||||
let vol = *vol as f64 / 255f64;
|
||||
stream_vol
|
||||
.set_volume(gst_audio::StreamVolumeFormat::Cubic, vol);
|
||||
}
|
||||
} else {
|
||||
eprintln!("Volume not implemented for this pipeline");
|
||||
}
|
||||
} else {
|
||||
eprintln!("Stream was not setup yet: {}", id);
|
||||
}
|
||||
}
|
||||
Write { id, data } => {
|
||||
if let Some(s) = out.get(&id) {
|
||||
let b = gst::Buffer::from_slice(data);
|
||||
@ -108,6 +137,6 @@ impl GstAudio {
|
||||
Err(e) => eprintln!("Audio thread error: {}", e),
|
||||
}
|
||||
});
|
||||
Ok(Self { thread })
|
||||
Ok(Self { out_thread })
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user