about summary refs log tree commit diff stats
path: root/pkgs/by-name/mp/mpdpopm/src/messanges/mod.rs
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-01-31 16:29:24 +0100
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2026-01-31 16:29:24 +0100
commit9741228b51856902f3791b43012b2ae792cf3f5d (patch)
tree4fa1b571cf9c5a9bed725249a5557563ef53d035 /pkgs/by-name/mp/mpdpopm/src/messanges/mod.rs
parentpkgs/mpdpopm: Change the default config to be the new json format (diff)
downloadnixos-config-9741228b51856902f3791b43012b2ae792cf3f5d.zip
pkgs/mpdpopm: Add a (basic) dj mode
Diffstat (limited to '')
-rw-r--r--pkgs/by-name/mp/mpdpopm/src/messanges/mod.rs110
1 files changed, 110 insertions, 0 deletions
diff --git a/pkgs/by-name/mp/mpdpopm/src/messanges/mod.rs b/pkgs/by-name/mp/mpdpopm/src/messanges/mod.rs
new file mode 100644
index 00000000..c5320dd9
--- /dev/null
+++ b/pkgs/by-name/mp/mpdpopm/src/messanges/mod.rs
@@ -0,0 +1,110 @@
+use anyhow::{Context, Result, anyhow, bail, ensure};
+use clap::{Parser, Subcommand};
+use shlex::Shlex;
+use tracing::info;
+
+use crate::{
+    clients::{Client, IdleClient},
+    dj::{Dj, algorithms::Discovery},
+};
+
+pub const COMMAND_CHANNEL: &str = "unwoundstack.com:commands";
+
+#[derive(Parser)]
+struct Commands {
+    #[command(subcommand)]
+    command: SubCommand,
+}
+
+#[derive(Parser)]
+enum SubCommand {
+    Dj {
+        #[command(subcommand)]
+        command: DjCommand,
+    },
+}
+
+#[derive(Subcommand)]
+enum DjCommand {
+    Start {},
+    Stop {},
+}
+
+pub(crate) struct MessageQueue {
+    dj: Option<Dj<Discovery>>,
+}
+
+impl MessageQueue {
+    pub(crate) fn new() -> Self {
+        Self { dj: None }
+    }
+
+    pub(crate) async fn advance_dj(&mut self, client: &mut Client) -> Result<()> {
+        if let Some(dj) = self.dj.as_mut() {
+            dj.add_track(client).await?;
+        }
+
+        Ok(())
+    }
+
+    /// Read messages off the commands channel & dispatch 'em
+    pub(crate) async fn check_messages(
+        &mut self,
+        client: &mut Client,
+        idle_client: &mut IdleClient,
+    ) -> Result<()> {
+        let m = idle_client
+            .get_messages()
+            .await
+            .context("Failed to `get_messages` from client")?;
+
+        for (chan, msgs) in m {
+            ensure!(chan == COMMAND_CHANNEL, "Unknown channel: `{}`", chan);
+
+            for msg in msgs {
+                self.process(client, msg).await?;
+            }
+        }
+
+        Ok(())
+    }
+
+    /// Process a single command
+    pub(crate) async fn process(&mut self, client: &mut Client, msg: String) -> Result<()> {
+        let split = {
+            let mut shl = Shlex::new(&msg);
+            let res: Vec<_> = shl.by_ref().collect();
+
+            if shl.had_error {
+                bail!("Failed to parse command '{msg}'")
+            }
+
+            assert_eq!(shl.line_no, 1, "A unexpected newline appeared");
+            assert!(!res.is_empty());
+
+            let mut base = vec!["base".to_owned()];
+            base.extend(res);
+            base
+        };
+
+        let args = Commands::parse_from(split);
+
+        match args.command {
+            SubCommand::Dj { command } => match command {
+                DjCommand::Start {} => {
+                    info!("Dj started");
+                    self.dj = Some(Dj::new(Discovery::new()));
+                    self.advance_dj(client).await?;
+                }
+                DjCommand::Stop {} => {
+                    self.dj
+                        .take()
+                        .ok_or_else(|| anyhow!("Tried to disable already disabled dj mode"))?;
+                    info!("Dj stopped");
+                }
+            },
+        }
+
+        Ok(())
+    }
+}