-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support idle
#53
Comments
That's not how I'd do it. Idle is ~useless to me if I can't do anything else once I invoke it. I'd implement idle by having each call to Some background on how I'm using idle, in case it helps shape the reason for my argument above: My (web-based) music player shows the currently-playing song, progress, volume, and a list of all available playlists, and the "up next" live playlist. I want these to be exactly up-to-date. I could have the web browser poll the web server, and have the web server poll MPD at high frequency. Turns out to be an ugly amount of network traffic and high server CPU usage. (There are currently over 17k songs in the music database. When all of them are added to the up-next queue, it takes several seconds to ask MPD for the current list.) I could use ruby-mpd callbacks. However, polling the MPD server at 5Hz for changes seems ugly. I worry that it will also be CPU intensive (though I've not yet tried it.) Instead, I want to write: # Starts idling on another (identical) connection under another thread.
# Invokes the block once the idle command returns.
# The continuous:true option causes the idle command to be immediately re-issued
# in the same thread/connection (for convenience and minimal thread thrash).
@mpd.idle_until( 'stored_playlist', continuous:true ){ update_playlists }
@mpd.idle_until( 'playlist database', continuous:true ){ update_upnext }
@mpd.idle_until( 'player mixer options', continuous:true ){ update_status } Right now I'm using def initialize
@mpd = MPD.new( ENV['MPD_HOST'], ENV['MPD_PORT'] )
@mpd.connect
@faye = Faye::Client.new("http://#{ENV['RB3JAY_HOST']}:#{ENV['RB3JAY_PORT']}/faye")
watch_for_changes
end
def watch_for_changes
watch_status
watch_playlists
watch_upnext
end
def watch_status
# TODO: replace fast status updates with client-side "dead-reckoning"
# of progress while playing; notify only for play/pause/song changes.
# Run at higher than 1Hz so that the progress bar updates ~smoothly.
EM.add_periodic_timer(0.25) do
if (info=mpd_status) != @last_status
send_status( @last_status=info )
end
end
end
def watch_playlists
EM.defer(
->( ){ idle_until 'stored_playlist' },
->(_){ send_playlists; watch_playlists }
)
end
def watch_upnext
EM.defer(
->( ){ idle_until 'playlist', 'database' },
->(_){ send_next; watch_upnext }
)
end
def idle_until(*events)
`mpc -h #{ENV['MPD_HOST']} -p #{ENV['MPD_PORT']} idle #{events.join(' ')}`
end
def mpd_status
@mpd.status
end
def send_status( info=mpd_status )
@faye.publish '/status', info
end
def up_next
@mpd.queue.slice(0,ENV['RB3JAY_LISTLIMIT'].to_i).map(&:details)
end
def send_next( songs=up_next )
@faye.publish '/next', songs
end
def playlists
@mpd.playlists.map(&:name).grep(/^(?!user-)/).sort
end
def send_playlists( lists=playlists )
@faye.publish '/playlists', playlists
end |
I haven't actively been using this library in the past 2 years so I'm unlikely to work on such features, however I will be more than happy to accept pull requests. |
Both are good to know. I'll see what I can do. Any suggestion on how to spec or test what I described above (another thread waiting on idle from MPD)? |
The
information.rb
plugin has anidle
command, but it is currently commented out.I'd like to be able to watch for changes. As it is I'll have to use background threads shelling out to
mpc idle
to implement the same functionality.The text was updated successfully, but these errors were encountered: