Comments (4)
https://github.com/archSeer/ruby-mpd#idle
from ruby-mpd.
https://github.com/archSeer/ruby-mpd#idle
To implement idle, what is needed is a lock that prevents sending commands to the daemon while waiting for the response (except
noidle
). An intermediate solution would be to queue the commands to send them later, when idle has returned the response.
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 idle
spawn another connection in another thread, ideally with an idleloop
style option that allows the thread and connection to be re-used indefinitely if desired.
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 EventMachine.defer
to spawn a thread for each of these, and executing mpc idle
. I use Faye to send updates to all clients when a change occurs. It's working well at first glance, but I'd rather not shell to mpc when I have ruby-mpd
.
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
from ruby-mpd.
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.
from ruby-mpd.
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)?
from ruby-mpd.
Related Issues (20)
- Detect invalid songs
- Instantiate a playlist by name
- song_with_id( nil ) causes error
- Getting stickers does not parse the values HOT 1
- .songs returns empty array despite reporting 200k songs HOT 4
- Adding songs to the queue is slow HOT 7
- Song with multiple genres causes runtime error
- Song filename with double-quotes causes errors
- Song#length does not handle multi-hour songs well
- track_length errors when a song has no time
- Error adding song with backslash in name
- Discussion: how to best test complex interactions? HOT 2
- Correct way of handling timeouts? HOT 3
- Cannot fetch songs for playlist (TypeError)
- First command causes error HOT 1
- Add toggle command (mpc like) HOT 1
- Error when attempting to play stream
- New release?
- Insert at position HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ruby-mpd.