Home of the Squeezebox™ & Transporter® network music players.
Page 1 of 2 12 LastLast
Results 1 to 10 of 16
  1. #1
    Senior Member
    Join Date
    Mar 2010
    Posts
    114

    Sending IR commands in response to Squeezebox events

    As discussed in the lirc rpi gpio IR support for picoreplayer thread, this place is intended for discussion of a comprehensive solution for the task of triggering IR commands in response to player events. Based on the conceptual work of ahebrank, I've written a small daemon in Micropython that gets the current player ID from the server by player name (instead of hardcoding the MAC address) and then listens for events affecting that player.

    Currently, only power 0 and power 1 are supported, but this could easily extended to mixer volume <value>. Indeed, I've tested the CLI with my player and with the VolumeLock plugin enabled, I still get the mixer volume events like this:

    Code:
    <playerid> mixer volume 95
    <playerid> mixer volume 100
    <playerid> mixer volume 90
    <playerid> mixer volume 100
    <playerid> mixer volume 85
    <playerid> mixer volume 100
    <playerid> mixer volume 80
    <playerid> mixer volume 100
    <playerid> mixer volume 105
    This means that every volume change is followed by an immediate reset to the fixed level. Accounting for that and translating these to a number of steps should be possible (and will be my next task).

    Currently, the daemon is configured by a JSON file (for which the path must be given as the first argument on the command line). It allows multiple IR commands per triggering event, with customizable delay between them, but the syntax is not very flexible. Here's an example configuration file:

    Code:
    {
    	"IRSEND": "/usr/local/bin/irsend",
    	"REMOTE": "<LIRCDRemote>",
    	"EVENTS": {
    		"POWER_ON": [
    			{
    				"DELAY": 0,
    				"CODE": "<Command1>"
    			},
    			{
    				"DELAY": 1000,
    				"CODE": "<Command2>"
    			}
    		],
    		"POWER_OFF": [
    			{
    				"DELAY": 0,
    				"CODE": "<Command3>"
    			}
    		]
    	},
    	"SERVER": {
    		"HOST": "<HostName>",
    		"PORT": 9090,
    		"RESTART_DELAY": 30
    	},
    	"PLAYER_NAME": "<PlayerName>"
    }
    I'd like to make integration into pCP as easy as possible - is there a way to get the set player name from the command line, so that it does not have to be configured explicitly? Anything else to think of?

  2. #2
    As written in the other thread, I was looking for a similar solution. My initial approach was a bit different from yours though. I think the hard part here is catching the LMS events and preventing them from being executed by the player/software/squeezelite since our project should take care of that. Sending the actual commands would then be rather trivial. I'd therefore like to vote for a more generic approach that implements the first part and delegates handling of the commands to an external script. I think that would be the most flexible approach.

    A few more thoughts:

    I think the parameters we should definitely handle are volume and power. Others might be interested in more parameters like sound settings so we should keep this extensible if it can be done without too much effort but I'd say we focus on power and volume first.

    Possible power handling capabilities are IMHO: turn on, turn off, toggle power, report current power status. I'd also add "guess current power status" as a script might be able to tell whether an external amp is turned on but not whether it's set to the correct source.

    Possible volume handling capabilities are: set absolute volume, increase/decrease volume, report current volume. In the case of relative volume only we should think about how to represent the current volume in LMS. I'd like to have the option to choose between a fixed volume and a limited range to give some indication at least.

    As for the implementation I see three possibilies:

    • An external script. I suspect with that approach it would be somewhat hard to prevent the commands to be passed through to the player. At least I have no idea how to do that.
    • An LMS plugin. Might be the most flexible but possibly the hardest solution. Also, I'm not sure whether LMS has the capabilty to adjust its internal volume representation without sending it to the player as well.
    • A patch for squeezelite. This would probably be the most straightforward approach but would limit the solution to squeezelite based players. I'm not sure that's a bad thing though as I guess the original devices should have that problem sorted out already.


    Quote Originally Posted by pputzer View Post
    is there a way to get the set player name from the command line, so that it does not have to be configured explicitly? Anything else to think of?
    You could either use pgrep -laf to get it from the squeezelite command line or grep it out of /usr/local/etc/pcp/pcp.cfg.

    BTW I'm all for pCP integration but I think we should find a solution that works at least on other squeezelite based players as well.

  3. #3
    Senior Member
    Join Date
    Mar 2010
    Posts
    114
    Quote Originally Posted by Manul View Post
    As written in the other thread, I was looking for a similar solution. My initial approach was a bit different from yours though. I think the hard part here is catching the LMS events and preventing them from being executed by the player/software/squeezelite since our project should take care of that. Sending the actual commands would then be rather trivial. I'd therefore like to vote for a more generic approach that implements the first part and delegates handling of the commands to an external script. I think that would be the most flexible approach.
    There is no way to catch LMS events and prevent the player from acting on them without an LMS plugin. Allowing the use of separate scripts as "handlers" sounds like a good idea, but I'd like to keep the simple case (using IR remote control commands) simple from a configuration standpoint. Having both possibilities should not be too hard, though.

    Quote Originally Posted by Manul View Post
    I think the parameters we should definitely handle are volume and power. Others might be interested in more parameters like sound settings so we should keep this extensible if it can be done without too much effort but I'd say we focus on power and volume first.
    Yes, certainly.

    Quote Originally Posted by Manul View Post
    Possible power handling capabilities are IMHO: turn on, turn off, toggle power, report current power status. I'd also add "guess current power status" as a script might be able to tell whether an external amp is turned on but not whether it's set to the correct source.
    I'm not sure how you'd want to handle the back channel (querying, amplifier feedback)? I don't really see a way to do that. POWER_TOGGLE does not need to be handled IMHO, because you can simple use the same script/command for both POWER_ON and POWER_OFF.

    Quote Originally Posted by Manul View Post
    Possible volume handling capabilities are: set absolute volume, increase/decrease volume, report current volume. In the case of relative volume only we should think about how to represent the current volume in LMS. I'd like to have the option to choose between a fixed volume and a limited range to give some indication at least.
    I would not want to keep a separate state in the daemon, because eventually it would be out of sync and burn down spectacularly. Resetting the player to a fixed volume (instead of having VolumeLock do that) should be possible. However, why don't you want the digital volume at line level (100 %)? That would be best if you handle volume settings in the amplifier, no matter whether that's done digital or analog. You could still increase the volume of the amp via events, as it happily reports 105 % when you try to increase volume from the fixed 100 %.

    Quote Originally Posted by Manul View Post
    As for the implementation I see three possibilies:

    • An external script. I suspect with that approach it would be somewhat hard to prevent the commands to be passed through to the player. At least I have no idea how to do that.
    • An LMS plugin. Might be the most flexible but possibly the hardest solution. Also, I'm not sure whether LMS has the capabilty to adjust its internal volume representation without sending it to the player as well.
    • A patch for squeezelite. This would probably be the most straightforward approach but would limit the solution to squeezelite based players. I'm not sure that's a bad thing though as I guess the original devices should have that problem sorted out already.
    If you want to prevent the player from acting on events, than yes, patching squeezelite would seem to be the way to go. I'm not sure if this is the right direction, though. Why do you need that feature specifically?

    Quote Originally Posted by Manul View Post
    You could either use pgrep -laf to get it from the squeezelite command line or grep it out of /usr/local/etc/pcp/pcp.cfg.

    BTW I'm all for pCP integration but I think we should find a solution that works at least on other squeezelite based players as well.
    Sure. But I'd like to make pCP integration as easy as possible, so hardcoding the player name in a config file is not the best solution.

  4. #4
    Quote Originally Posted by Manul View Post
    As written in the other thread, I was looking for a similar solution. My initial approach was a bit different from yours though. I think the hard part here is catching the LMS events and preventing them from being executed by the player/software/squeezelite since our project should take care of that. Sending the actual commands would then be rather trivial. I'd therefore like to vote for a more generic approach that implements the first part and delegates handling of the commands to an external script. I think that would be the most flexible approach.
    Have you played with DenonSerial? "delegates handling of the commands to an external script" pretty much describes its "Network Address" or "Remote System" modes, in which it either sends ASCII text like "PWON" to a TCP connection or via "denonserial" CLI notifications. The external script could either bind to a TCP port for "Network Address" mode or use the CLI to "listen" or "subscribe" for notifications in "Remote System" mode. "Remote System" is likely better for you. Denon AVRs, like Squeezeboxes, take discrete volume commands so the external script would need to maintain an internal representation of the current volume in order to know how to interpret the discrete levels.

    I think your biggest challenge *should* be the amp and SB virtual volumes getting far out of sync, e.g. LMS thinks the player volume is 100% but somebody has actually turned the amp volume rather low. (With an old-school SB Classic, I expect you could act on IR remote control codes even if LMS thought no player volume change was appropriate, but for Touch & Jivelite & web or app control UIs you're likely to get "stuck" when LMS thinks the volume is 100 or 0.) I think you'd want the normal LMS 0-100 range to correspond to more IR commands than would be needed to take the amp from silent to full volume, so you could always turn the SB/LMS virtual volume down to 0 to reset the amp and then turn it back up.
    owner of the stuff at https://tuxreborn.netlify.com/
    (which used to reside at www.tux.org/~peterw/)
    Note: The best way to reach me is email or PM, as I don't spend much time on the forums.
    Free plugins: AllQuiet Auto Dim/AutoDisplay BlankSaver ContextMenu DenonSerial
    FuzzyTime KidsPlay KitchenTimer PlayLog PowerCenter/BottleRocket SaverSwitcher
    SettingsManager SleepFade StatusFirst SyncOptions VolumeLock

  5. #5
    Quote Originally Posted by pputzer View Post
    I'm not sure how you'd want to handle the back channel (querying, amplifier feedback)? I don't really see a way to do that.
    FWIW, the Denon RS232 protocol has several query commands =, e.g. "PW?" queries whether amp is in On or Standby mode. In its Network Address (TCP) mode, DenonSerial by default periodically polls the amp for changes. IIRC it doesn't do that for Remote System players because it's assumed they could use the CLI to inform LMS; its polling is meant to give LMS a way of detecting that somebody turned the physical knobs on the amp. And I think CLI is the answer here -- if the amp daemon knows something happened, it can ask LMS what it thinks, and use the CLI to correct LMS when it's wrong.

    Manul, I think you could almost get there w/ the external handler using the CLI listen/subscribe and VolumeLock's "Set current volume as maximum" set high, like 99. You'd always interpret a 'mixer volume 99' notification as indication to send an IR volume up command to the amp (not 100, as when you try to increase the volume past max you'll see two mixer volume commands: the attempt, followed by VolumeLock reasserting the discrete maximum). What you would probably also need is a way to configure VolumeLock with a *minimum* volume for that player so the LMS UIs would always give you an option to go quieter. You might also like a way to configure VolumeLock not to display the "Volume level is capped" messages. I have little interest in writing a UI for such settings, but modifying it to respect new preferences set via the 'playerpref' CLI seems like it should be easy (or of course you could copy my code and just manually edit it, would just take a couple lines of code to hard-code a minimum volume and disable that Volume is capped message).
    owner of the stuff at https://tuxreborn.netlify.com/
    (which used to reside at www.tux.org/~peterw/)
    Note: The best way to reach me is email or PM, as I don't spend much time on the forums.
    Free plugins: AllQuiet Auto Dim/AutoDisplay BlankSaver ContextMenu DenonSerial
    FuzzyTime KidsPlay KitchenTimer PlayLog PowerCenter/BottleRocket SaverSwitcher
    SettingsManager SleepFade StatusFirst SyncOptions VolumeLock

  6. #6
    Senior Member
    Join Date
    Mar 2010
    Posts
    114
    Quote Originally Posted by peterw View Post
    FWIW, the Denon RS232 protocol has several query commands =, e.g. "PW?" queries whether amp is in On or Standby mode. In its Network Address (TCP) mode, DenonSerial by default periodically polls the amp for changes. IIRC it doesn't do that for Remote System players because it's assumed they could use the CLI to inform LMS; its polling is meant to give LMS a way of detecting that somebody turned the physical knobs on the amp. And I think CLI is the answer here -- if the amp daemon knows something happened, it can ask LMS what it thinks, and use the CLI to correct LMS when it's wrong.
    Yes, but than it's still the daemon polling, not some other device querying the player state.

  7. #7
    Senior Member
    Join Date
    Mar 2010
    Posts
    114
    If anyone would like to try out the new version, I've added VOLUME_RAISE and VOLUME_LOWER events to my daemon. At the moment it doesn't work to well with my amp because a single volume change IR code does not do much. I'll see if allowing for the SEND_START/SEND_STOP parameters of irsend (or simple repeating the SEND_ONCE) will improve this.


    Gesendet von iPad mit Tapatalk
    Last edited by pputzer; 2019-05-19 at 00:44. Reason: irsend parameters incorrect

  8. #8
    Quote Originally Posted by pputzer View Post
    There is no way to catch LMS events and prevent the player from acting on them without an LMS plugin.
    As you mention later, I think patching the player would be another way. It's probably not possible from an external script though – although I'm not even sure of that: Preventing the player from acting might be impossible but immediately sending another command that negates the first one might be a possibility.

    Quote Originally Posted by pputzer View Post
    Allowing the use of separate scripts as "handlers" sounds like a good idea, but I'd like to keep the simple case (using IR remote control commands) simple from a configuration standpoint. Having both possibilities should not be too hard, though.
    If that's the simple case. I do want to send IR commands to 2 of my amps as well but I'm using WiFi to IR gateways for that, so even though I'll also be sending IR commands, the actual code for that would look quite different from yours.

    Quote Originally Posted by pputzer View Post
    I'm not sure how you'd want to handle the back channel (querying, amplifier feedback)? I don't really see a way to do that.
    I'm not sure I understand the problem you see. I have the abovementiond 2 amps connected to WiFi enabled power sockets that can report current amperage. That way I'm able to at least reliably tell whether the amp is on or in standby.

    Quote Originally Posted by pputzer View Post
    POWER_TOGGLE does not need to be handled IMHO, because you can simple use the same script/command for both POWER_ON and POWER_OFF.
    Which would probably sooner or later end up with the amp's actual power state being out of sync with what LMS thinks. I see no way around that though, so if all we have is a power toggle command it's probably better to not handle power at all. Thus I agree we wouldn't need to handle power toggle.

    Quote Originally Posted by pputzer View Post
    I would not want to keep a separate state in the daemon, because eventually it would be out of sync and burn down spectacularly. Resetting the player to a fixed volume (instead of having VolumeLock do that) should be possible.
    Welk, I think it might be nice to at least have an indication of how the volume changed since the start. I might be wrong on that though, that's why I'd prefer to have both options.

    Quote Originally Posted by pputzer View Post
    However, why don't you want the digital volume at line level (100 %)? That would be best if you handle volume settings in the amplifier, no matter whether that's done digital or analog. You could still increase the volume of the amp via events, as it happily reports 105 % when you try to increase volume from the fixed 100 %.
    Two reasons: In one case, the output is analog and might be distorting at 100%. Therefore I'd like to set a lower fixed level for that. The other reason would be to level the volume with that of other sources like a CD player.

    Quote Originally Posted by pputzer View Post
    If you want to prevent the player from acting on events, than yes, patching squeezelite would seem to be the way to go. I'm not sure if this is the right direction, though. Why do you need that feature specifically?
    Because I only want one volume to change: That of the amp. Thus I think I'll need to keep squeezelite's fingers from the alsa controls.

    Quote Originally Posted by pputzer View Post
    Sure. But I'd like to make pCP integration as easy as possible, so hardcoding the player name in a config file is not the best solution.
    That was not a suggestion but my observation on what I think pCP does.

    Quote Originally Posted by peterw View Post
    Have you played with DenonSerial?
    Not really, no. I had a look or two at the code to (try to) understand its inner works but since I need a more generic solution and didn't think DenonSerial would help me much there, I haven't actually played around with it. I'll give it a go though.

    Quote Originally Posted by peterw View Post
    "delegates handling of the commands to an external script" pretty much describes its "Network Address" or "Remote System" modes, in which it either sends ASCII text like "PWON" to a TCP connection or via "denonserial" CLI notifications. The external script could either bind to a TCP port for "Network Address" mode or use the CLI to "listen" or "subscribe" for notifications in "Remote System" mode. "Remote System" is likely better for you.
    That does indeed sound like it might be (most of) what I need already. The same might be true for @pputzer as well, if I understand his plans correctly. Actually, one of the amps I want to control is a Denon AVR so handling all 3 amps with the same plugin would make a lot of sense.

    Quote Originally Posted by peterw View Post
    I think your biggest challenge *should* be the amp and SB virtual volumes getting far out of sync,
    They will definitely. My plan was to limit the range in LMS to, say, 5 to 95 so it would always allow volume changes. The idea is that the displayed volume in LMS would at least give an indication on where the actual volume might be compared to the start. As written above, this might not work at all and be utter nonsense but I'd like to at least try it out.

    Quote Originally Posted by peterw View Post
    You might also like a way to configure VolumeLock not to display the "Volume level is capped" messages. I have little interest in writing a UI for such settings, but modifying it to respect new preferences set via the 'playerpref' CLI seems like it should be easy (or of course you could copy my code and just manually edit it, would just take a couple lines of code to hard-code a minimum volume and disable that Volume is capped message).
    I'll definitely play around with it and let you know how it went.
    Last edited by Manul; 2019-05-19 at 09:36.

  9. #9
    Senior Member
    Join Date
    Aug 2012
    Location
    Austria
    Posts
    926
    This plugin should be of interest.
    Various SW: Web Interface | Playlist Editor / Generator | Music Classification | Similar Music | Announce | EventTrigger | LMSlib2go | ...
    Various HowTos: build a self-contained LMS | Bluetooth/ALSA | Control LMS with any device | ...

  10. #10
    Senior Member
    Join Date
    Mar 2010
    Posts
    114
    Quote Originally Posted by Manul View Post
    As you mention later, I think patching the player would be another way. It's probably not possible from an external script though ľ although I'm not even sure of that: Preventing the player from acting might be impossible but immediately sending another command that negates the first one might be a possibility.
    Should be possible, but you'll have round-trip time, and you'd have take care to prevent feedback loops (server sends info to daemon, daemon "counteracts" the setting, server sends a new info to daemon ...).

    Quote Originally Posted by Manul View Post
    If that's the simple case. I do want to send IR commands to 2 of my amps as well but I'm using WiFi to IR gateways for that, so even though I'll also be sending IR commands, the actual code for that would look quite different from yours.
    I'd say that controlling two amps via an additional gateway module is certainly not the "simple" use case, but I get your point. Maybe simplifying the codebase to only trigger scripts instead of allowing direct configuration of IR commands is better (also in regard to the change away from LIRC in pCP 5.0). What would a minimal viable product for your situation look like?

    Quote Originally Posted by Manul View Post
    I'm not sure I understand the problem you see. I have the abovementiond 2 amps connected to WiFi enabled power sockets that can report current amperage. That way I'm able to at least reliably tell whether the amp is on or in standby.
    You earlier wrote that you'd like the daemon to allow queries. I had interpreted that as you'd like the amp (or some other external device) query the state of the player. Maybe that was a misunderstanding.

    Quote Originally Posted by Manul View Post
    Welk, I think it might be nice to at least have an indication of how the volume changed since the start. I might be wrong on that though, that's why I'd prefer to have both options.
    Yes, volume is something we need to keep track of (the daemon in its current form already does) to be able to interpret directional change (LMS only transmits percentage values).

    Quote Originally Posted by Manul View Post
    Two reasons: In one case, the output is analog and might be distorting at 100%. Therefore I'd like to set a lower fixed level for that. The other reason would be to level the volume with that of other sources like a CD player.
    The leveling issue is valid (though with modern RPi DACs it should be done in the overlay settings). (I don't get how analog output would distort at 100% if the amps volume was not set too high in the first place.)

    Quote Originally Posted by Manul View Post
    Because I only want one volume to change: That of the amp. Thus I think I'll need to keep squeezelite's fingers from the alsa controls.
    By default (i.e. without an explicit "Control" setting), Squeezelite uses only internal volume and does not touch the Alsa mixer ľ at least that's what I read from the documentation.

    Quote Originally Posted by Roland0 View Post
    This plugin should be of interest.
    Thank you, that looks interesting. I gather that the commands are run on the LMS server itself, though? We'd still need a daemon on the player to act on the events?

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •