feat: 支持设置音量。

This commit is contained in:
2023-05-07 18:18:34 +08:00
parent 9109518822
commit 2c5ac11579
8 changed files with 238 additions and 9 deletions

View File

@ -5,8 +5,9 @@ mod ambient_light;
mod display;
mod led_color;
mod rpc;
pub mod screenshot;
mod screenshot;
mod screenshot_manager;
mod volume;
use ambient_light::{Border, ColorCalibration, LedStripConfig, LedStripConfigGroup};
use display::{DisplayManager, DisplayState};
@ -18,6 +19,7 @@ use screenshot_manager::ScreenshotManager;
use serde::{Deserialize, Serialize};
use serde_json::to_string;
use tauri::{http::ResponseBuilder, regex, Manager};
use volume::VolumeManager;
#[derive(Serialize, Deserialize)]
#[serde(remote = "DisplayInfo")]
@ -223,6 +225,8 @@ async fn main() {
let _mqtt = MqttRpc::global().await;
let _volume = VolumeManager::global().await;
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![
greet,

View File

@ -45,6 +45,8 @@ impl Board {
let display_setting_request_sender = board_message_channels
.display_setting_request_sender
.clone();
let volume_setting_request_sender =
board_message_channels.volume_setting_request_sender.clone();
loop {
match socket.try_recv(&mut buf) {
@ -60,6 +62,8 @@ impl Board {
if let Err(err) = result {
error!("send display setting request to channel failed: {:?}", err);
}
} else if buf[0] == 4 {
let result = volume_setting_request_sender.send(buf[1] as f32 / 100.0);
}
}
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {

View File

@ -6,6 +6,7 @@ use super::DisplaySettingRequest;
pub struct BoardMessageChannels {
pub display_setting_request_sender: Arc<broadcast::Sender<DisplaySettingRequest>>,
pub volume_setting_request_sender: Arc<broadcast::Sender<f32>>,
}
impl BoardMessageChannels {
@ -19,8 +20,12 @@ impl BoardMessageChannels {
let (display_setting_request_sender, _) = broadcast::channel(16);
let display_setting_request_sender = Arc::new(display_setting_request_sender);
let (volume_setting_request_sender, _) = broadcast::channel(16);
let volume_setting_request_sender = Arc::new(volume_setting_request_sender);
Self {
display_setting_request_sender,
volume_setting_request_sender,
}
}
}

View File

@ -3,9 +3,9 @@ use std::{collections::HashMap, sync::Arc, time::Duration};
use futures::future::join_all;
use mdns_sd::{ServiceDaemon, ServiceEvent};
use paris::{error, info, warn};
use tokio::sync::{watch, OnceCell, RwLock, broadcast};
use tokio::sync::{watch, OnceCell, RwLock};
use super::{Board, BoardInfo, DisplaySettingRequest};
use super::{Board, BoardInfo};
#[derive(Debug, Clone)]
pub struct UdpRpc {

View File

@ -0,0 +1,101 @@
use std::{
mem,
sync::{Arc, RwLock},
};
use coreaudio::{
audio_unit::macos_helpers::get_default_device_id,
sys::{
kAudioHardwareServiceDeviceProperty_VirtualMasterVolume, kAudioObjectPropertyScopeOutput,
AudioObjectHasProperty, AudioObjectPropertyAddress, AudioObjectSetPropertyData,
},
};
use paris::error;
use tokio::sync::OnceCell;
use crate::rpc::BoardMessageChannels;
pub struct VolumeManager {
current_volume: Arc<RwLock<f32>>,
handler: Option<tokio::task::JoinHandle<()>>,
}
impl VolumeManager {
pub async fn global() -> &'static Self {
static VOLUME_MANAGER: OnceCell<VolumeManager> = OnceCell::const_new();
VOLUME_MANAGER
.get_or_init(|| async { Self::create() })
.await
}
pub fn create() -> Self {
let mut instance = Self {
current_volume: Arc::new(RwLock::new(0.0)),
handler: None,
};
instance.subscribe_volume_setting_request();
instance
}
fn subscribe_volume_setting_request(&mut self) {
let handler = tokio::spawn(async {
let channels = BoardMessageChannels::global().await;
let mut request_rx = channels.volume_setting_request_sender.subscribe();
while let Ok(volume) = request_rx.recv().await {
if let Err(err) = Self::set_volume(volume) {
error!("failed to set volume: {}", err);
}
}
});
self.handler = Some(handler);
}
fn set_volume(volume: f32) -> anyhow::Result<()> {
log::debug!("set volume: {}", volume);
let device_id = get_default_device_id(false);
if device_id.is_none() {
anyhow::bail!("default audio output device is not found.");
}
let device_id = device_id.unwrap();
let address = AudioObjectPropertyAddress {
mSelector: kAudioHardwareServiceDeviceProperty_VirtualMasterVolume,
mScope: kAudioObjectPropertyScopeOutput,
mElement: 0,
};
log::debug!("device id: {}", device_id);
log::debug!("address: {:?}", address);
if 0 == unsafe { AudioObjectHasProperty(device_id, &address) } {
anyhow::bail!("Can not get audio property");
}
let size = mem::size_of::<f32>() as u32;
let result = unsafe {
AudioObjectSetPropertyData(
device_id,
&address,
0,
std::ptr::null(),
size,
&volume as *const f32 as *const std::ffi::c_void,
)
};
if result != 0 {
anyhow::bail!("Can not set audio property");
}
Ok(())
}
}

View File

@ -0,0 +1,3 @@
mod manager;
pub use manager::*;