Physical volume controls are a MUST - how to add to plexamp?

I am continuing work on my Raspberry Pi 5 headless plexamp player with use of HiFiBerry DAC8X, with asound.conf configured to output in a 4.0 configuration (downmixing 5.1 to 4.0 by creating a phantom center in the fronts, and dropping the LFE).

Since this will be feeding a poweramp set to a stationary level, volume will need to be adjusted on the output of the Pi.

I’ve added a rotary control, and have it setup that the Pi recognizes it’s input.

I would expect programming very simple input commands to adjust the volume up or down should be pretty basic, simple, straightforward stuff - but it has unfolded into a complete and total nightmare. I do not understand why so many obstructions have been placed in the way of a simple command.

Plexamp has a good starting point with a volume control built into the app - but navigating a touch screen to a kinda hidden volume control is not an ideal method to simply adjust the volume up and down, so it should be possible for this volume control to accept inputs from the Pi to adjust it, to allow the addition of a simple knob. This seems to not be the case - all efforts AI has made to create a script to do this result in 404 not found errors, and all calls for AI to research further to find documented methods to make such commands result in it suggesting there is no documentation on how to do this, which suggests that plexamp may not even be setup to allow simple requests like this.

I hope this isn’t the case, as this would be quite an oversight to not allow something as simple as a volume knob in an audio player.

Alternately, it approached it on the system level - but this has been a total nightmare as well, it is not finding any system ways to adjust the volume either, nor documentation for a verified method, which results in hours of AI overconfident guesswork presented as proven solutions, that produce frustrating error after frustrating error.

Does anyone around here have any proven method of adding a simple volume control to a plexamp player, please?

“AI” is quite terrible sometimes, all you had to do was watch the Plexamp log while you controlled the volume remotely.

HttpServer: [10.0.0.105] GET /player/playback/setParameters volume=27&commandID=123973&type=music

AI is quite terrible and amazing all at once. I’m an old school PC support troubleshooter. I know nothing of coding, and failed at it when I attempted to pursue it in college - I just didn’t have the mindset to boil down complex tasks to a few simple lines of code. I know what to ask for, I don’t know how to code it. On the one hand, AI has taken my requests, and built me completely automated processes to rip perfectly gapless and normalized leveled multichannel flac files from SACDs - push a button, and it does it all. That has empowered me to take on things that require coding. On the other hand - it takes a simple task like adding a volume control, and turns it into a multi-hour process of troubleshooting an error message that leads down rabbit holes of manually updating firmwares.

However - after steering Grok a bit and getting out of the firmware weeds, I got stuck on scripts that couldn’t access the volume controls, and then had to wait 2 hours to ask Grok why.

So I took it to co-pilot, and it wrote me this:

#!/usr/bin/python3
import lgpio
import requests
import time
import signal
import sys

KY-040 GPIO pins

CLK = 17 # Rotary encoder CLK pin
DT = 18 # Rotary encoder DT pin
SW = 27 # Button pin (not used in phase 1)

Plexamp API settings

PLEXAMP_URL = “http://localhost:32500/player/playback/setParameters
API_TOKEN = “” # Replace with your Plexamp token
PLAYER_ID = “75ccacad-fdd9-4054-9d65-94d3c3972e48” # Use discovered player identifier
VOLUME_STEP = 5 # Volume change per rotation (0-100 scale)

Initialize GPIO

h = lgpio.gpiochip_open(0)
lgpio.gpio_claim_input(h, CLK)
lgpio.gpio_claim_input(h, DT)
lgpio.gpio_claim_input(h, SW, lgpio.SET_PULL_UP)

Set Plexamp volume

def set_volume(volume):
volume = max(0, min(100, volume)) # Clamp volume between 0-100
try:
response = requests.get(
f"{PLEXAMP_URL}?volume={volume}&commandID=9999&type=music",
headers={
“X-Plex-Token”: API_TOKEN,
“X-Plex-Target-Client-Identifier”: PLAYER_ID,
}
)
response.raise_for_status()
print(f"Volume set to: {volume}%“)
except requests.RequestException as e:
print(f"Error setting volume: {e}”)

Handle rotary encoder

def handle_rotary():
last_clk = lgpio.gpio_read(h, CLK)
volume = 50 # Default starting volume
while True:
clk = lgpio.gpio_read(h, CLK)
dt = lgpio.gpio_read(h, DT)
if clk != last_clk and clk == 0: # Detect rotation event
if dt != clk and volume < 100: # Increase volume, but don’t exceed 100%
volume += VOLUME_STEP
elif dt == clk and volume > 0: # Decrease volume, but don’t go below 0%
volume -= VOLUME_STEP
set_volume(volume) # Adjust Plexamp volume
last_clk = clk
time.sleep(0.01) # Debounce timing

Cleanup on exit

def signal_handler(sig, frame):
lgpio.gpiochip_close(h)
print(“\nExiting…”)
sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

Main execution

print(“KY-040 volume control ready. Rotate to adjust volume.”)
try:
handle_rotary()
except KeyboardInterrupt:
signal_handler(None, None)

This script “works”, except for the side effect of breaking all audio output. Which makes “works” not a good word to describe it.

Once I run it, sound is immediately muted. However - turning the knob does show volume moving up and down between 0 to 100 percent, and viewing the now muted playback that continues in plexamp shows the volume slider is moving.

Restarting plexamp does not resolve the situation, which suggests the problem lies outside of plexamp, it is still sending audio to - something that has been disrupted by this script. Only a reboot resets things to a working state again.

I realize at this point I’m reporting on something that has been proven to be outside of plexamp - but to anyone out there that this makes sense to, any suggestions would be greatly appreciated.

And thanks again, @elan, for your response on this - you’ve been great.

(Note you do not need an API_TOKEN to call the player endpoints)

1 Like

Seems AI, being informed of the exact hardware I am using, proceeded to instruct me to use GPIO pins that are documented as needed by the DAC8X. It’s only after I specifically asked Co-pilot how to troubleshoot pin interference one by one, that we found the pin that was causing problems - and which point it responded something including information about that being in the range of pins that are used by the DAC8X. Which…it’s like…if you can determine that after a test, why couldn’t you determine that before? Although to be fair, it was Grok that started us on the path of the pins we’re using, Co-pilot just never verified that. Although, I suppose I never asked it to. Anyways - progress is being made again. And I did feed your tips to the AI to further help guide it along to tweaking the script.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.