diff --git a/README.md b/README.md index 368527f..1d0e77d 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,4 @@ Mixrs will create a unix socket at `/tmp/mixrs` and listen for instructions. Ins |6|PlayPauseCurrent|Tells the current sink input to toggle its `playing` state.
*Behavior varies based on the current sink input's player*| |7|PlayNext|Tells the current sink input to play the next item (e.g. the next song).
*Behavior varies based on the current sink input's player*| |8|PlayPrevious|Tells the current sink input to play the previous item (e.g. the previous song).
*Behavior varies based on the current sink input's player*| +|9|GetCurrentOutput|Gets information about the currently selected sink input and sends it through the requesting unix socket| diff --git a/src/instructions.rs b/src/instructions.rs index 4d8efb2..812f11e 100644 --- a/src/instructions.rs +++ b/src/instructions.rs @@ -9,6 +9,7 @@ pub enum MixerInstruction { PlayPauseCurrent, PlayNext, PlayPrevious, + GetCurrentOutput, } impl MixerInstruction { @@ -23,6 +24,7 @@ impl MixerInstruction { 6 => Some(MixerInstruction::PlayPauseCurrent), 7 => Some(MixerInstruction::PlayNext), 8 => Some(MixerInstruction::PlayPrevious), + 9 => Some(MixerInstruction::GetCurrentOutput), _ => None, } } diff --git a/src/mixer.rs b/src/mixer.rs index f5d6266..d4a17c5 100644 --- a/src/mixer.rs +++ b/src/mixer.rs @@ -4,8 +4,8 @@ use std::{ borrow::{Borrow, BorrowMut}, collections::HashMap, fs, - io::Read, - os::unix::net::UnixListener, + io::{Read, Write}, + os::unix::net::{UnixListener, UnixStream}, path::Path, sync::{ mpsc::{channel, Receiver, Sender}, @@ -124,7 +124,7 @@ impl Mixer { .create_socket_listener() .expect("Error creating unix socket listener"); - let (mixer_tx, mixer_rx) = channel::(); + let (mixer_tx, mixer_rx) = channel::<(MixerInstruction, UnixStream)>(); thread::spawn(move || { for client in listener.incoming() { @@ -134,7 +134,7 @@ impl Mixer { stream.read_to_end(&mut buf).expect("Error reading stream"); match MixerInstruction::from_u8(buf[0]) { - Some(ix) => mixer_tx.send(ix).unwrap(), + Some(ix) => mixer_tx.send((ix, stream)).unwrap(), None => println!("Invalid instruction: {}", buf[0]), } } @@ -181,7 +181,7 @@ impl Mixer { loop { match mixer_rx.try_recv() { - Ok(ix) => match ix { + Ok((ix, stream)) => match ix { MixerInstruction::SelectNext => self.select_next(), MixerInstruction::SelectPrevious => self.select_previous(), MixerInstruction::ToggleMuteCurrent => self.toggle_mute_current(), @@ -191,6 +191,7 @@ impl Mixer { MixerInstruction::PlayPauseCurrent => self.play_pause_current(), MixerInstruction::PlayNext => self.play_next_current(), MixerInstruction::PlayPrevious => self.play_previous_current(), + MixerInstruction::GetCurrentOutput => self.get_current_output(stream), }, Err(_) => (), } @@ -495,7 +496,10 @@ impl Mixer { let _ = send_notification_with_progress( &format!( "({}/{}) {}: {}%", - index + 1, sink_inputs_length, ¤t_sink.name, current_sink_volume_percent + index + 1, + sink_inputs_length, + ¤t_sink.name, + current_sink_volume_percent ), current_sink_volume_percent, ); @@ -560,6 +564,31 @@ impl Mixer { Err(_) => (), }; } + + pub fn get_current_output(&self, mut stream: UnixStream) { + let index_lock = self.selected_index.lock().unwrap(); + + let Some(index) = *index_lock else { + return; + }; + + drop(index_lock); + + let Some(sink_index) = self.sink_inputs.keys().nth(index) else { + return; + }; + + let Some(sink_input) = self.sink_inputs.get(sink_index) else { + return; + }; + + let _ = stream.write_all( + sink_input + .get_output_data(index, self.sink_inputs.len(), *sink_index) + .as_bytes(), + ); + let _ = stream.shutdown(std::net::Shutdown::Both); + } } pub fn iterate_mainloop(mainloop: &mut pulse::mainloop::standard::Mainloop) { diff --git a/src/pulseaudio/mod.rs b/src/pulseaudio/mod.rs index 0b83a91..6255d66 100644 --- a/src/pulseaudio/mod.rs +++ b/src/pulseaudio/mod.rs @@ -29,4 +29,17 @@ impl SinkInputMixerData { pub fn get_volume_percent(&self) -> u8 { total_volume_to_percentage(self.volume) } + + /// Formats the sink input data to a string separating fields by new lines + pub fn get_output_data( + &self, + selection_index: usize, + sink_count: usize, + sink_index: u32, + ) -> String { + format!( + "selection: {}/{sink_count}\nid: {sink_index}\nname: {}\nvolume: {}\nvolume_percentage: {}\nmuted: {}\n", + selection_index + 1, self.name, self.volume, self.get_volume_percent(), self.muted + ) + } }