Open ben-willmore opened 5 years ago
I did a bit more investigation. As far as I can see, the MPD protocol doesn't support "only", and so this is actually implemented in mpc here (line 159 onward). I don't fully understand the code but it does seems to be looping from 1 to the highest output ID, leading to problems if the output IDs are large. I guess MPC is assuming that output IDs will always be small numbers, and that assumption is broken by forked-daapd.
I guess this could be fixed in forked-daapd by remapping the output IDs that are provided to mpc, but perhaps it is not a big deal.
I worked around this with a bash script which disables all outputs, then enables the desired one:
function disableall() {
/usr/bin/mpc outputs | sed "s|.*(\(.*\)).*|\1|" | while read -r output; do
/usr/bin/mpc disable "${output}"
done
}
disableall
/usr/bin/mpc enable "${1}"
I can't see any evidence elsewhere that forked-daapd is maintaining a huge list of outputs, so my idea that this might be related to performance issues is probably wrong.
Thanks for the report and the excellent investigation. It sounds like you have found the cause and the possible fix. The mpd part of forked-daapd is maintained by @chme so he will decide if this should be changed.
I think, the best way to address this, would be to always save the outputs to the database. Right now it is only done at shutdown. This would allow to have an autoincrement key, that could be used as the output id for mpd clients.
This might also allow to get the current outputs without blocking the player thread by reading them always from the database.
Yes, sounds like a good solution!
@beniamino38 I had a similar patch solution which I merged with yours. It enables me to type only part of the speaker name to enable (which could have conflicts, so caveat emptor). I also changed your loop to only repeat for each enabled speaker. (Note that the last 2 lines are the entirety of my spkon bash script.)
function disableall() { /usr/bin/mpc outputs | grep enabled | sed "s|.((.)).*|\1|" | while read -r output; do /usr/bin/mpc disable "${output}" done }
disableall
spk=$1 mpc enable `mpc outputs |grep -i $spk |awk {'print $2'}`
On my network, I have two forked-daapd servers and a few speakers. The forked-daapd servers can see the speakers correctly:
I can turn the speakers on (and off) correctly:
However, if I try to select a single speaker, the command takes a long time to return, and usually fails with a timeout:
If I look in the forked-daapd debug log while this is happening, I see tens of thousands of lines like:
It looks like forked-daapd is incorrectly maintaining a list of tens of thousands of outputs (I have no idea where these come from) and trying to turn each one off individually, which takes a long time to achieve. I wonder if this may be related to other performance issues I have noticed.