diff --git a/assets/encoders/headphonesBig.svg b/assets/encoders/headphonesBig.svg
new file mode 100644
index 0000000..6c804b5
--- /dev/null
+++ b/assets/encoders/headphonesBig.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/encoders/headphonesBigMuted.svg b/assets/encoders/headphonesBigMuted.svg
new file mode 100644
index 0000000..eb880e7
--- /dev/null
+++ b/assets/encoders/headphonesBigMuted.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/encoders/microphoneBig.svg b/assets/encoders/microphoneBig.svg
new file mode 100644
index 0000000..4aff504
--- /dev/null
+++ b/assets/encoders/microphoneBig.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/encoders/microphoneBigMuted.svg b/assets/encoders/microphoneBigMuted.svg
new file mode 100644
index 0000000..7d3e5d6
--- /dev/null
+++ b/assets/encoders/microphoneBigMuted.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/manifest.json b/assets/manifest.json
index 27f19aa..9a3916c 100644
--- a/assets/manifest.json
+++ b/assets/manifest.json
@@ -94,6 +94,9 @@
"Icon": "actions/volumeControl",
"Tooltip": "Control the volume levels of audio input and output devices",
"Controllers": ["Keypad", "Encoder"],
+ "Encoder": {
+ "layout": "$B1"
+ },
"PropertyInspectorPath": "pi/volumecontrol.html",
"DisableAutomaticStates": true,
"States": [{ "Image": "actions/volumeControl" }]
diff --git a/src/actions/voice_settings/audio_device_utils.rs b/src/actions/voice_settings/audio_device_utils.rs
index 3e805fd..a1049ea 100644
--- a/src/actions/voice_settings/audio_device_utils.rs
+++ b/src/actions/voice_settings/audio_device_utils.rs
@@ -56,6 +56,7 @@ pub struct AudioDeviceWrapper {
pub device_id: String,
pub volume: f32,
pub available_devices: Vec,
+ pub enable: bool,
}
impl From for SetVoiceSettingsArgs {
diff --git a/src/actions/voice_settings/volume_control.rs b/src/actions/voice_settings/volume_control.rs
index 793c9a3..f0ca215 100644
--- a/src/actions/voice_settings/volume_control.rs
+++ b/src/actions/voice_settings/volume_control.rs
@@ -1,6 +1,7 @@
use super::audio_device_utils::{AudioDeviceType, AudioDeviceWrapper, get_audio_device_settings};
use super::update_voice_setting;
+use discord_ipc_rust::models::send::commands::SetVoiceSettingsArgs;
use openaction::{Action, ActionUuid, Instance, OpenActionResult, async_trait};
use serde::{Deserialize, Serialize};
@@ -32,6 +33,55 @@ impl Default for VolumeControlSettings {
}
}
+const MUTED_ICON: &str = include_str!("../../../assets/encoders/microphoneBigMuted.svg");
+const UNMUTED_ICON: &str = include_str!("../../../assets/encoders/microphoneBig.svg");
+const DEAFEN_ICON: &str = include_str!("../../../assets/encoders/headphonesBigMuted.svg");
+const UNDEAFEN_ICON: &str = include_str!("../../../assets/encoders/headphonesBig.svg");
+
+async fn update_feedback(
+ instance: &Instance,
+ settings: &VolumeControlSettings,
+) -> OpenActionResult<()> {
+ let device_type = &settings.device_type;
+ let Some(device_settings) = get_audio_device_settings(device_type).await else {
+ log::error!(
+ "Failed to obtain voice settings for {:?} device",
+ device_type
+ );
+ instance.show_alert().await?;
+ return Ok(());
+ };
+
+ let icon = match (device_type, device_settings.enable) {
+ (AudioDeviceType::Input, true) => UNMUTED_ICON,
+ (AudioDeviceType::Input, false) => MUTED_ICON,
+ (AudioDeviceType::Output, true) => UNDEAFEN_ICON,
+ (AudioDeviceType::Output, false) => DEAFEN_ICON,
+ };
+
+ let value = device_type.to_linear(device_settings.volume) as i32;
+ let indicator_value = match device_type {
+ AudioDeviceType::Input => value,
+ AudioDeviceType::Output => value / 2,
+ };
+
+ let title = match device_type {
+ AudioDeviceType::Input => "Microphone",
+ AudioDeviceType::Output => "Headphones",
+ };
+
+ instance
+ .set_feedback(&serde_json::json!({
+ "title": title,
+ "icon": icon,
+ "value": format!("{}%", value),
+ "indicator": {
+ "value": indicator_value
+ }
+ }))
+ .await
+}
+
async fn adjust_volume(
instance: &Instance,
device_type: &AudioDeviceType,
@@ -69,6 +119,22 @@ impl Action for VolumeControlAction {
const UUID: ActionUuid = "me.amankhanna.oadiscord.volumecontrol";
type Settings = VolumeControlSettings;
+ async fn will_appear(
+ &self,
+ instance: &Instance,
+ settings: &Self::Settings,
+ ) -> OpenActionResult<()> {
+ update_feedback(instance, settings).await
+ }
+
+ async fn did_receive_settings(
+ &self,
+ instance: &Instance,
+ settings: &Self::Settings,
+ ) -> OpenActionResult<()> {
+ update_feedback(instance, settings).await
+ }
+
async fn key_up(&self, instance: &Instance, settings: &Self::Settings) -> OpenActionResult<()> {
let value = match settings.action_type {
VolumeControlActionType::Increase => settings.step_size as f32,
@@ -85,6 +151,49 @@ impl Action for VolumeControlAction {
.await
}
+ async fn dial_up(
+ &self,
+ instance: &Instance,
+ settings: &Self::Settings,
+ ) -> OpenActionResult<()> {
+ let device_type = &settings.device_type;
+ let Some(device_settings) = get_audio_device_settings(device_type).await else {
+ log::error!(
+ "Failed to obtain voice settings for {:?} device",
+ device_type
+ );
+ instance.show_alert().await?;
+ return Ok(());
+ };
+
+ match device_type {
+ AudioDeviceType::Input => {
+ let new_mute = device_settings.enable;
+ update_voice_setting(
+ instance,
+ SetVoiceSettingsArgs {
+ mute: Some(new_mute),
+ ..Default::default()
+ },
+ 0,
+ )
+ .await
+ }
+ AudioDeviceType::Output => {
+ let new_deaf = device_settings.enable;
+ update_voice_setting(
+ instance,
+ SetVoiceSettingsArgs {
+ deaf: Some(new_deaf),
+ ..Default::default()
+ },
+ 0,
+ )
+ .await
+ }
+ }
+ }
+
async fn dial_rotate(
&self,
instance: &Instance,
@@ -93,7 +202,6 @@ impl Action for VolumeControlAction {
_pressed: bool,
) -> OpenActionResult<()> {
let delta = (settings.step_size as f32) * ticks as f32;
-
adjust_volume(instance, &settings.device_type, delta, false).await
}
}
diff --git a/src/rpc_events.rs b/src/rpc_events.rs
index b0efed5..cd1e6da 100644
--- a/src/rpc_events.rs
+++ b/src/rpc_events.rs
@@ -160,6 +160,7 @@ async fn apply_voice_state(settings: discord_ipc_rust::models::shared::voice::Vo
device_id: input.device_id,
volume: input.volume,
available_devices: input.available_devices,
+ enable: !mute && !deaf,
});
}
@@ -171,9 +172,14 @@ async fn apply_voice_state(settings: discord_ipc_rust::models::shared::voice::Vo
device_id: output.device_id,
volume: output.volume,
available_devices: output.available_devices,
+ enable: !deaf,
});
}
+ for instance in visible_instances(crate::actions::VolumeControlAction::UUID).await {
+ let _ = instance.get_settings().await;
+ }
+
for instance in visible_instances(crate::actions::SetAudioDeviceAction::UUID).await {
let _ = crate::actions::voice_settings::set_audio_device::send_available_devices_to_pi(
&instance,