Control volume with custom scripts

Cool stuff you can do with MPD. A place for you to put your hacks and patches, or be inspired by others'.

Control volume with custom scripts

Postby nkk64 » July 14th, 2016, 2:47 pm

Well my setup is like this: nettop with mpd server using alsa ---> usb DAC ---> Integrated Amp

Integrated Amp is attached also directly to nettop through its RS232 comm port. I use that to send commands to Amp (like volume up/down, wake/standby).

Currently I ssh to nettop and use moc player to play music. In Moc configuration files you can define keyboard shortcuts to execute shell commands so that when I press e.g. '>' it runs custom script (that sends vol up command to Amp comm port).

But now I want to control playback using my smartphone and I'm looking for mpd server / smartphone client.

So what I need is to run custom scripts on server when I press volume up or down on client.

Unfortunately I don't think I can write my own mixer though it seems the way to go .
Any ideas?

Nick
Last edited by nkk64 on July 15th, 2016, 1:16 pm, edited 1 time in total.
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby max » July 15th, 2016, 12:47 pm

You can use the "null" mixer and a client listening for mixer events.
max
Forum team
 
Posts: 512
Joined: January 15th, 2013, 3:43 pm

Re: Control volume with custom scripts

Postby nkk64 » July 15th, 2016, 1:15 pm

Thank you max.

Google search returned link to this project: MPD Event Listener - PHP

https://sourceforge.net/projects/mpdeve ... rce=navbar

Will try this weekend
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » July 25th, 2016, 7:39 pm

You can use the "null" mixer and a client listening for mixer events.


Actually, I wrote an application that does exactly that (well almost): Synchronator.

In short: by activating the Alsa dummy soundcard you can enable MPD volume control without actually touching the actual audiosignal. Synchronator in turn listens for mixer events on that mixer and sends the appropriate commands to the amp via serial, tcp, or i2c. The advantage of this setup, you can run other audio applications that make use of the same approach simultaneously, e.g. Shairport, Squeezelite.

In addition, I created a http interface to provide control over other options the amp might have (power, input, etc).

Currently configuration files exist for Arcam, Cambridge Audio, NAD, Lyngdorf, Dynaudio, Classe, among others. This should work for many more (most?) controllable amplifiers though.

As for the OP, it seems the amp only understands relative volume commands (up/down). That is a bit problematic since there is the 0-100 volume range in MPD. I fixed that by resetting the volume level to 50 once the 25/75 barriers are reached. This way you can always go further up down and control the amp any way you like. This works quite well, but only if the client regularly updates the volume level from the MPD server.

For the source, installation and configuration manuals, sample config files, you can check:
https://github.com/therealmuffin/synchronator

Any question can be directed here or there, whatever one prefers.

Hope this helps in your quest,

Kind regards,

Maarten
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby nkk64 » July 28th, 2016, 4:14 pm

Thank you Maarten, indeed your project looks like what I need.

Well, installation and configuration went without problems. Upon running I got "Failed to open lock file" but creating /var/run/synchronizer folder did help.

Now synchronator runs and log looks like:

synchronator[3797]: Checking presence and validity of required variables:
synchronator[3797]: [OK] sync_2way: FALSE
synchronator[3797]: [OK] diff_commands: FALSE
synchronator[3797]: [OK] query.interval: 1
synchronator[3797]: [OK] volume.curve: linear
synchronator[3797]: [OK] volume.discrete: FALSE
synchronator[3797]: [OK] volume.multiplier: 1
synchronator[3797]: [OK] data_type: ascii
Main.ronator[3797]: [OK] header.[0]:
synchronator[3797]: [OK] tail.[0]:
synchronator[3797]: [OK] event_delimiter.[0]: =
synchronator[3797]: [OK] volume.header.[0]: Volume
synchronator[3797]: [OK] volume.tail.[0]:
synchronator[3797]: [OK] volume.min: -
synchronator[3797]: [OK] volume.plus: +
Main.Power??[3797]: [OK] query.trigger.[0]:
synchronator[3797]: [OK] interface: serial
synchronator[3797]: [OK] serial_port: /dev/ttyUSB0
synchronator[3797]: [OK] serial_parity: FALSE
synchronator[3797]: [OK] serial_even: TRUE
synchronator[3797]: [OK] serial_2stop: TRUE
synchronator[3797]: [OK] serial_baud: 115200
synchronator[3797]: [OK] serial_bits: 8
synchronator[3797]: Alsa volume range, min, max: 150, -50, 100
synchronator[3797]: Trigger written to serial port
synchronator[3797]: Trigger written to serial port
synchronator[3797]: Volume level mutation (int. initiated): ext. level: 29.00
synchronator[3797]: Volume level mutation (int. initiated): ext. level: 32.00


However volume is not changed. Mine is nad 356bee and commands look like those of 375bee.
if I configure port using:

stty -F /dev/ttyUSB0 115200 -icrnl -ixon -opost -isig -icanon -iexten

after that I can increase volume by executing
echo 'Main.Volume+' > /dev/ttyUSB0

or put amp into standby:
echo 'Main.Power=Off' > /dev/ttyUSB0

I suspect problem with synchronator is with port configuration. I use USB to PL2303 Serial Port.

Now if I enable
sync_2way=TRUE in conf file then I see lines like:

synchronator[3882]: Detected incoming event (header): On
(Power)
synchronator[3882]: Leftovers in buffer (bytes read, #leftovers): (5, 0)
synchronator[3882]: Trigger written to serial port
synchronator[3882]: Leftovers in buffer (bytes read, #leftovers):
(1, 1)
synchronator[3882]: Leftovers in buffer (bytes read, #leftovers):
Main.Power= (12, 13)
synchronator[3882]: Detected incoming event (header): On
(Power)
synchronator[3882]: Leftovers in buffer (bytes read, #leftovers): (4, 0)
synchronator[3882]: Volume level mutation (int. initiated): ext. level: 68.00
synchronator[3882]: Volume level mutation (int. initiated): ext. level: 71.00
synchronator[3882]: Volume level mutation (int. initiated): ext. level: 72.00
synchronator[3882]: Volume level mutation (int. initiated): ext. level: 74.00
synchronator[3882]: Volume level mutation (int. initiated): ext. level: 75.00
synchronator[3882]: Mixer volume level: 76
synchronator[3882]: Volume level mutation (int. initiated): ext. level: 50.00
synchronator[3882]: Mixer volume level: 78


and again, volume is not actually changed.
Any ideas?

Nick
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » July 29th, 2016, 7:43 pm

Hello Nick,

While I did test Synchronator with your amp, at some point I thought it was a good idea to set the event_delimiter to "=" in the NAD C375 config file apparently. This breaks the volume command formation, resulting in e.g. Main.Volume=+ .

Conclusion, I've added the C375 config file quite a bit to get rid of the event_delimiter for outgoing commands while retaining it for incoming commands (since it is needed to properly differentiate between the commands and values...)

The port configuration seems fine since it does recognize the incoming 'Main.Power=On' command.... so it shows in the output you copied. Synchronator wouldn't if the configuration wasn't correct

In short, download the new config file from github and give it a try. From the output I'm getting it should work fine right now.... if it doesn't please post back and we'll see how to fix that. Any suggestions on functionality and/or behaviour are also welcome! I haven't tested Synchronator too heavily with relative volume commands in real life .

Kind regards, Maarten
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby nkk64 » July 30th, 2016, 7:16 am

Hi Maarten,

Thank you for prompt reply and fix. It works now!

I'm going out of town for ten days and so will not be able to play much with it soon.
As for suggestions I think it would have been helpful if synchronator did log actual commands it sends - that way I'd have understood why it did not work from the very beginning :D

Btw there is a project Mopidy and a plugin for it mopidy-nad. Development of that plugin is abandoned and currently you'll have to dive into python source code to make it work, but I liked their idea of calibrating volume comntrol. Here is how it could have been applied to synchronator: The number of volume positions of my NAD amp is known to be X=80 (I can count if necessary - X will become to be config parameter for various amps). So upon running synchronator you just run 'Main.Volume-' X times so you are sure that vol regulator now is at zero position. All you have to do in your code is to map 0-X range to 0%-100% range of mpd clients. This way you'll avoid that weird volume indicator jumps to 50%. Downside is that if someone adjusts volume manually one will have to restart synchronator.

There is one more thing I'll have to solve. Good amps are power hungry even if they are idling (under 40w in my case). So I have to find way to put my NAD into standby (<0.5w). Unfortunately there seems no mute event in MPD so that I can not think how I can send standby/wake up commands (Main.Power=On/Off) based on MPD events. I think better way is to dive into linux's power management internals... Some udev rules maybe...

Thank you again, Maarten

Regards
Nick
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » August 1st, 2016, 6:48 pm

nkk64 wrote:Hi Maarten,
As for suggestions I think it would have been helpful if synchronator did log actual commands it sends - that way I'd have understood why it did not work from the very beginning :D


Thanks for the suggestion, you're quite right. However, special characters such as new line/carriage return and hex data (instead of ascii) tend to create blank or unreadable terminal output. Fixing that would require converting those characters which increase Synchronator's footprint which I don't like. With a different approach of logging that could change, but the drawbacks of the current approach aren't large enough (yet).

nkk64 wrote:Btw there is a project Mopidy and a plugin for it mopidy-nad. Development of that plugin is abandoned and currently you'll have to dive into python source code to make it work, but I liked their idea of calibrating volume comntrol. Here is how it could have been applied to synchronator: The number of volume positions of my NAD amp is known to be X=80 (I can count if necessary - X will become to be config parameter for various amps). So upon running synchronator you just run 'Main.Volume-' X times so you are sure that vol regulator now is at zero position. All you have to do in your code is to map 0-X range to 0%-100% range of mpd clients. This way you'll avoid that weird volume indicator jumps to 50%. Downside is that if someone adjusts volume manually one will have to restart synchronator.


That's an interesting approach, hadn't thought of that. If you're willing to test it I can implement that. I'm not giving any timeframe on that though, but can I report here when there is something to test.

As for the manual volume adjustments: a possible fix could be that setting the volume to zero via MPD triggers the volume calibration. That process would take a few seconds (I guess) and can not be disrupted... so MPD volume control would be disfunctional for that period. Another option is, twice to zero in a second to trigger a calibration (I doubt that action can be triggered by accident).

nkk64 wrote:There is one more thing I'll have to solve. Good amps are power hungry even if they are idling (under 40w in my case). So I have to find way to put my NAD into standby (<0.5w). Unfortunately there seems no mute event in MPD so that I can not think how I can send standby/wake up commands (Main.Power=On/Off) based on MPD events. I think better way is to dive into linux's power management internals... Some udev rules maybe...


Synchronator has an http interface (via a php script) and can be controlled via command line. In some MPD clients you can set a http trigger for start/stop events, e.g. Mpod, Mpad. For other clients you may file a feature request. That could be one solution. Another option is to loop a bash/python script to watch the status of mpd and to trigger a command accordingly. I would suggest a grace period for the standby command to prevent turning off/on the amp too frequently, e.g. set the amp in standby only after no activity for say 5-10 minutes.
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby nkk64 » August 4th, 2016, 11:42 am

Muffinman wrote:
That's an interesting approach, hadn't thought of that. If you're willing to test it I can implement that. I'm not giving any timeframe on that though, but can I report here when there is something to test.


I'll gladly test. I've also added myself to watchers of your synchronator github project.

Muffinman wrote:
As for the manual volume adjustments: a possible fix could be that setting the volume to zero via MPD triggers the volume calibration. That process would take a few seconds (I guess) and can not be disrupted... so MPD volume control would be disfunctional for that period. Another option is, twice to zero in a second to trigger a calibration (I doubt that action can be triggered by accident).


I like the idea of recalibrating when volume is set to zero. That will be easier to use and implement too compared to zeroing volume twice.

Btw I also like that in this approach volume will be zeroed when synchronator starts. Sometimes someone may dust off volume regulator when amp is in standby and accidentally set it near to max. Even if my speakers will survive, I doubt my ears will :D

As for power management, I'd prefer client-independent approach. I.e. I'd rather dig into linux power events or, like you suggested, mpd status watching direction. Will report here if I find something reliable.
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby nkk64 » August 4th, 2016, 11:48 am

Just an idea: One can use setting vol to zero twice in a second to put amp into idle. Also will have to send power=on command any time vol regulator leaves zero position - not a big deal, just occasional redundant command I believe.
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » August 16th, 2016, 9:16 pm

I've implemented the suggested approach. As far as I can tell from what I see flowing out of my serial port it should work fine. I'd say, give it a try.

For the configuration options read the section "additional non-descrete specific options" in the volume section of the configuration manual. You might want to experiment a bit with the 'timeout' setting to prevent overloading the amp with volume data. The configuration file with the MAVC suffix should work for your amp.

https://github.com/therealmuffin/synchronator/blob/master/CONFIG_MANUAL.md#additional-non-discrete-specific-options

I did implement a double zero approach to reinitialize volume. However, you can set the interval to zero effectively resetting the volume level every time volume reaches zero.

In addition, with this additional functionality it seems almost logical to also implement LIRC for IR control. I can not test it (I don't have an IR blaster). nkk64 won't test it because rs232 is preferred over IR. However, anyone else willing to test, please do!!

Give it a try and see how it works....

Kind regards
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby nkk64 » August 17th, 2016, 12:23 pm

Thank you Maarten, I'll play with it next week - when I'm back at home.

Unfortunately I'll not be able to test IR control for the simple reason that either IR receiver of my amp or remote are damaged.

Meanwhile, as promised, let me report on the way I found to handle power management thing. Here is a script that uses expect shell and allows to run some shell scripts when MPD player's play/pause/stop events are fired:

http://erion.elmasllari.com/automated-s ... i-and-mpd/

I modified it a bit and use MPD stop event to put Amp into standby (if I just want to stop playing music I can use Pause) and wake up Amp on Play event - but only if state has changed - i.e. clicking play multiple times will invoke wake up script only once. The only logic change was that when checking if the state has changed you have to pause a bit before checking for final state because replacing playlist while playing fires two events "stop - play" so you have to avoid sending poweroff-poweron.

Btw similar approach can be adopted to create expect shell script that reacts on mixer events - volume up/down.

Best regards,
Nick
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » August 18th, 2016, 8:47 pm

nkk64 wrote:Btw similar approach can be adopted to create expect shell script that reacts on mixer events - volume up/down.


Thanks for the link, never heard of the utility Expect. That seems like a very handy and easy to use tool. However, for proper volume level synchronization I suspect the setup can get quite cpu inefficient. Nonetheless, if I had known of this tool I certainly would have given it a try before writing Synchronator. It would have been very hard to get the same functionality as I now have though.

Kind regards, Maarten
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby nkk64 » August 23rd, 2016, 6:53 am

Wow, I tried it with default setting and it works like a charm.

As I mentioned somewhere above after installation on my ubuntu 16.04 system I had to manually create /var/run/synchronator folder - otherwise synchronator throws file not found error. Would be nice if it created the folder (if absent) without user intervention or at least mention it in install guide - had to seach for error source in source code.

Both with Theremin (OS X client) and MPDroid (android client) default values are OK so I did not start playing with offsets or multipler/divisors.

Recalibration works too - pause while MPD volume is not responsive is a bit too long, but you should not mess with vol control and you'll not need recalibration at all.

The only setting I changed was query interval - just to have less trigger lines in log. I dont quite understand functionality of that trigger. Seems it allows synchronator to know about selected source on amp and also about power state. If that's right, here is how one could use it:

I start synchronator when system starts. That means MPD is running but amp is still in standby state. So volume calibration will fail. Amp is waked up only upon the first Play event and this is a good moment to calibrate volume. So if synchronator can detect that amp was off when it (synchronator) started it could also delay volume calibration until Play event is fired for the 1st time. Ideally synchronator could control Amp state like that expect shell script I described. But it's not an ideal world, is it? :D

Thank you for the effort you are putting into synchronator. Maybe some day I'll try matching it with my Marantz receiver. I bet protocol is identical to that of Denon.

Best wishes,

Nick
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » August 28th, 2016, 9:02 pm

nkk64 wrote:Wow, I tried it with default setting and it works like a charm.

Very good to hear!!

nkk64 wrote:As I mentioned somewhere above after installation on my ubuntu 16.04 system I had to manually create /var/run/synchronator folder - otherwise synchronator throws file not found error. Would be nice if it created the folder (if absent) without user intervention or at least mention it in install guide - had to seach for error source in source code.

That's usually handled by the init.d or systemd script. I did improve the error message to give the needed info to fix the issue. Thanks for the report on that!

nkk64 wrote:Both with Theremin (OS X client) and MPDroid (android client) default values are OK so I did not start playing with offsets or multipler/divisors.

These settings are only valid (and of any use) for true absolute volume controlled amps and ignored otherwise. So it wouldn't do anything anyways in your case..

nkk64 wrote:Recalibration works too - pause while MPD volume is not responsive is a bit too long, but you should not mess with vol control and you'll not need recalibration at all.

I'm not sure I understand what you mean. Volume control is indeed unresponsive during calibration. Calibration must take as long as it needs to be to go from max volume to zero. If it takes longer than that perhaps the range setting is too high (and thus sending more volume down commands than necessary). The right value is a matter of trial and error (or manual?). The same goes for the timeout between volume commands send. If it is set too high, calibration will also take longer than necessary.

nkk64 wrote:The only setting I changed was query interval - just to have less trigger lines in log. I dont quite understand functionality of that trigger. Seems it allows synchronator to know about selected source on amp and also about power state. If that's right, here is how one could use it:

The trigger allows Synchronator to record the state of the amp (power, input, etc). This can be nice for the http interface or other applications. In addition Synchronator can reply the status if the setup requires it (not relevant in your case). Anyhow, once the configuration is done, I would recommend running Synchronator in minimal verbose. Under normal circumstances there is no need for detailed logging.

nkk64 wrote:I start synchronator when system starts. That means MPD is running but amp is still in standby state. So volume calibration will fail.

Ok, good point, hadn't thought of that. I made some changes on that. When Synchronator detects the amp is powered up (from a previously unknown state or standby), it will initialize volume. All you need to do is set a 'default' volume level in the volume section of your config file (in your case scale 0-100, e.g. default=10). You can also trigger reinitialization from command line

nkk64 wrote:Amp is waked up only upon the first Play event and this is a good moment to calibrate volume. So if synchronator can detect that amp was off when it (synchronator) started it could also delay volume calibration until Play event is fired for the 1st time. Ideally synchronator could control Amp state like that expect shell script I described. But it's not an ideal world, is it? :D

Actually, Synchronator can control the Amp state. What it doesn't do is watch MPD status. I believe there are more flexible/better ways to implement that, e.g. Expect. Once Expect is triggered it can send the appropriate trigger to Synchronator and done (volume, input, reinit volume, etc). In that sense Expect can work as a complement to Synchronator. An example script can be found in the scripts folder.

Kind regards, Maarten
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby nkk64 » August 29th, 2016, 5:59 pm

Hi Maarten,

Introducing default volume level is a very good idea - one will not have to manually adjust level after recalibration every time.

An example script can be found in the scripts folder.


Are you sure you did upload it there? Scripts folder was last updated 2 months ago.

Best wishes,

Nick
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm

Re: Control volume with custom scripts

Postby Muffinman » August 29th, 2016, 6:43 pm

nkk64 wrote:Are you sure you did upload it there? Scripts folder was last updated 2 months ago.


Yes, it is in scripts/triggers folder. The readme file gives a bit more information.

Kind regards, Maarten
Muffinman
 
Posts: 12
Joined: July 25th, 2016, 7:12 pm

Re: Control volume with custom scripts

Postby matt_garman » November 13th, 2016, 9:55 pm

I have been playing with synchronator on my server with only the dummy soundcard. Works as expected.

How do I actually configure MPD to use the dummy mixer? From the synchronator docs:
in mpd.conf: add to audio_output with type 'alsa':
mixer_type "hardware"
mixer_device "hw:Dummy"
mixer_control "Master"


When I add those params to /etc/mpd.conf, I get these errors:
Code: Select all
Nov 13 15:11 : config: option 'mixer_control' on line 53 was not recognized
Nov 13 15:11 : config: option 'mixer_device' on line 54 was not recognized
Nov 13 15:11 : config: option 'mixer_index' on line 55 was not recognized


Do I not have a new enough mpd version? I'm using version 0.19.12.

Thanks!
matt_garman
 
Posts: 2
Joined: November 13th, 2016, 9:50 pm

Re: Control volume with custom scripts

Postby nkk64 » November 14th, 2016, 6:34 am

Well I have MPD 0.19.1 on my raspberry PI and alsa section that I successfully use for my USB DAC in mpd.conf looks like:

audio_output {
type "alsa"
name "ustars"
device "hw:1,0"
mixer_type "hardware"
mixer_device "hw:Dummy"
mixer_control "Master"
}
nkk64
 
Posts: 10
Joined: July 14th, 2016, 2:22 pm


Return to Tips, Tricks, and Hacks

Who is online

Users browsing this forum: No registered users and 1 guest

cron