archseer / ruby-mpd Goto Github PK
View Code? Open in Web Editor NEWruby-mpd is a powerful object-oriented Music Player Daemon library, forked from librmpd.
License: GNU General Public License v2.0
ruby-mpd is a powerful object-oriented Music Player Daemon library, forked from librmpd.
License: GNU General Public License v2.0
not sure if this is ruby-mpd related, but i didnt find a clue yet, maybe you can enlighten me
basically i have this code for handling the connection
def self.connect_mpd
@mpd = MPD.new 'localhost', 6600, {callbacks: true} if @mpd == nil
unless @mpd.connected?
Rails.logger.info "Connecting to MPD . . ."
@mpd.connect
sleep 0.3
@mpd.on :song do |song|
Rails.logger.info "!!!!!!!!!!!!!! #{Time.now.to_s} MPD_SONG change: #{song.title} - #{song.artist} !!!"
end
end
end
this block gets fired about every minute(or even more) and works fine basically
After a few hours(about 6-8) the callback just stops firing, but the connection to mpd is still there, application continuing to work normally. No clues about dropped connection in mpd.log
connection_timeout is set to 3600 in mpd.conf
using ruby-mpd 0.31, MPD 0.18, local only
any tips what could be wrong?
mpc
has a feature to insert a song at a specific position, is this available here as well?
Given the (ugly) situation of a file with a backslash in the name, MPD requires the backslash to be escaped. Right now only double-quotes are backslash-escaped inside the double quoted param.
When using a song callback as such:
@mpd.on :song do |current|
puts current.inspect
end
it only works when a new file starts to play, which is a problem with radio streams, for two reasons.
#<MPD::Song:0x00000002a30c58 @data={:pos=>0, :id=>703}, @time=nil, @file="http://streamer.strobe.fm/", @title=nil, @artist=nil, @album=nil, @albumartist=nil>
But, it would generate something like this if the callback detected the metadata changing:
#<MPD::Song:0x000000019a9628 @data={:name=>"Strobe.FM", :pos=>0, :id=>703}, @time=nil, @file="http://streamer.strobe.fm/", @title="Goo Goo Dolls - Caught In The Storm", @artist=nil, @album=nil, @albumartist=nil>
The only thing I can think of is that the callback checks if the id changed, (notice the id is 703 in both of those arrays, because it's still the same stream) but it doesn't change when using radio streams. I guess the best way to check this would be to check if anything in the array changed.
Obviously my diagnosis could be entirely wrong, I'm not that good with ruby, but that's my theory.
The playlist now has a song with a file but no other data. How can I detect if this is a valid song with no metadata, or an invalid song?
I'm currently using the heuristic of checking to see if song.time.nil?
. It would be nice to have something like MPD::Song#valid?
to see if the song instance is grounded in reality and able to be used.
I have a DB that's currently at 17k songs (and growing). Some search terms can produce a lot of results, like:
@mpd.where file:'.'
@mpd.where any:'e'
Calls like this take 1.3 seconds on the server before they return. In my interface I then go on to truncate the results to the first 500. I'd like to be able to:
@mpd.where {file:'.'}, {limit:500}
and have the results limited for me.
I realize that this requires MPD support. I've posted a feature request on the MPD forum.
(FWIW, I also tried modifying build_songs_list
in parser.rb
to accept an optional limit, to reduce the number of songs created in the map. Reducing the map set from 16883 songs to 500 songs only reduced the time from 1.27s to 1.23s, a negligible savings.)
A silly edge case, but:
begin; @mpd.song_with_id(1); rescue MPD::Error=>e; puts e; end
#=> [playlistid] No such song
begin; @mpd.song_with_id(-1); rescue MPD::Error=>e; puts e; end
#=> [playlistid] Number too large: -1
begin; @mpd.song_with_id('cat'); rescue MPD::Error=>e; puts e; end
#=> [playlistid] Integer expected: cat
begin; @mpd.song_with_id(nil); rescue MPD::Error=>e; puts e; end
NoMethodError: undefined method `delete' for true:TrueClass
from /var/lib/gems/2.1.0/gems/ruby-mpd-0.3.3/lib/ruby-mpd/song.rb:13:in `initialize'
from /var/lib/gems/2.1.0/gems/ruby-mpd-0.3.3/lib/ruby-mpd/plugins/queue.rb:81:in `new'
from /var/lib/gems/2.1.0/gems/ruby-mpd-0.3.3/lib/ruby-mpd/plugins/queue.rb:81:in `song_with_id'
...
Ideally, if I
@mpd.on :updating_db do |job_id|
puts "Updating DB #{job_id.inspect}"
end
@mpd.update
I should get something like
Updating DB 1
Updating DB nil
so that I can tell when the update has ended, but that doesn't happen at all. Instead the callback is only executed when updating_db
appears.
Here's the relevant status change:
{:volume=>96, :repeat=>false, :random=>false, :single=>false, :consume=>false, :playlist=>5002, :playlistlength=>4999, :mixrampdb=>0.0, :state=>:play, :song=>0, :songid=>5000, :time=>[5, 244], :elapsed=>4.574, :bitrate=>1202, :audio=>[44100, 16, 2], :updating_db=>1, :nextsong=>1, :nextsongid=>5001}
{:volume=>96, :repeat=>false, :random=>false, :single=>false, :consume=>false, :playlist=>5002, :playlistlength=>4999, :mixrampdb=>0.0, :state=>:play, :song=>0, :songid=>5000, :time=>[6, 244], :elapsed=>5.619, :bitrate=>1224, :audio=>[44100, 16, 2], :nextsong=>1, :nextsongid=>5001}
As you can see, updating_db
simply disappears when the update has completed, which is fine, but I should also get an event.
my_song.track_length #=> 11256
my_song.length #=> "187:36"
I'd prefer/expect that show "M:SS" when below one hour, and "H:MM:SS" when above one hour, e.g. "3:07:36"
for the above.
mpd 0.17.0 added some new-ish support for SoundCloud URLs.
In a Ruby script, I can execute
`mpc load soundcloud://track/121108619`
To queue a new URL. With this library, the following does not work:
mpd.load "soundcloud://track/121108619"
The error is:
MPD::ConnectionError (Broken pipe (got disconnected)):
Note that this should be load
, not add
, because MPD considers these to be playlists.
On my live music server:
@mpd.add( song ) # takes about 40ms
`mpc add "#{song.file}"` # takes about 5ms
This may seem trivial, but when dynamically generating the queue with 100 songs this is the difference between waiting 4 seconds versus half a second.
I wonder if this is the @mutex.synchronize
slowing me down; I'll be looking at ways to speed up the batch adding of many songs.
I tried using your gem today, and I get the following error when I try to run any commands. Seems that the regex in the make_chunks command returns Nil, and that's causing an error in the match command that exits the entire program.
/home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd/parser.rb:129:in `make_chunks': undefined method `[]' for nil:NilClass (NoMethodError)
from /home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd/parser.rb:155:in `build_response'
from /home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd/parser.rb:147:in `parse_response'
from /home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd.rb:195:in `block in send_command'
from /home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd.rb:191:in `synchronize'
from /home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd.rb:191:in `send_command'
from /home/pi/.rvm/gems/ruby-2.2.1/gems/ruby-mpd-0.3.3/lib/ruby-mpd/plugins/controls.rb:29:in `play'
from radio.rb:10:in `block in <main>'
from radio.rb:5:in `loop'
from radio.rb:5:in `<main>'
There are a few new commands and features in .18 that aren't implemented:
http://git.musicpd.org/cgit/master/mpd.git/plain/NEWS?h=release-0.18
:toggleoutput
is pretty straightforward but :readcomments
is not. :readcomments
returns a hash of additional arbitrary tags on the song file. I'd like to implement it but I wanted to see if you had any comment on how it should be done.
The last 4 items already work.
As the README.md states, version 0.3.0 should introduce some kind of 'reconnect mechanism'. As far as is can see, there is no such mechanism. If the server decides to time out the connection of a ruby-mpd client object, #connected?
doesn't report the timed out connection as well as #ping
and any call that requires a working connection returns true or throws different exceptions as calls to the sockets #gets
function return nil. The only way to detect, that the server closed the connection due to a timeout would be to check #eof?
on the socket.
At the moment i'm working on an implementation of the #callback_thread
that uses a blocking #gets
version of the mpd idle
command and as a result of my implementation, not even having callbacks enabled prevents the connection from timing out as there are no frequent polling any more. That is why i stumbled about it.
Am i missing something or is this the intended way the ruby-mpd gem should work?
Just wanted to see if I glanced right over this, or if it isn't documented. How can I connect to an MPD server that has a password?
mpc like toggle command seems to be unsupported, would be a good addition.
"mpc toggle Toggles Play/Pause, plays if stopped"
When I'm adding a lot of songs one by one (which as far as I can see can't be done any other way), the :playlist
callback gets fired multiple times, which is correct. But it would be nice to be able to temporarily disable callbacks for potentially long operations, like this:
class MPD
def no_callbacks(&block)
# pause callback thread (or stop it)
yield
# resume callback thread (or restart it)
end
end
mpd.no_callbacks do
# add many songs here
end
# :playlist callback gets fired here
This way, my client would get the updated playlist when it's finished and wouldn't have to process multiple incomplete updates. At the end of the provided block, the callback thread would resume as usual and emit all changed keys. This requires that the callback cannot only be stopped, but also resumed (or stopped and then restarted).
Any feedback would be appreciated!
RubyGems.org doesn't report a license for your gem. This is because it is not specified in the gemspec of your last release.
via e.g.
spec.license = 'MIT'
# or
spec.licenses = ['MIT', 'GPL-2']
Including a license in your gemspec is an easy way for rubygems.org and other tools to check how your gem is licensed. As you can imagine, scanning your repository for a LICENSE file or parsing the README, and then attempting to identify the license or licenses is much more difficult and more error prone. So, even for projects that already specify a license, including a license in your gemspec is a good practice. See, for example, how rubygems.org uses the gemspec to display the rails gem license.
There is even a License Finder gem to help companies/individuals ensure all gems they use meet their licensing needs. This tool depends on license information being available in the gemspec. This is an important enough issue that even Bundler now generates gems with a default 'MIT' license.
I hope you'll consider specifying a license in your gemspec. If not, please just close the issue with a nice message. In either case, I'll follow up. Thanks for your time!
Appendix:
If you need help choosing a license (sorry, I haven't checked your readme or looked for a license file), GitHub has created a license picker tool. Code without a license specified defaults to 'All rights reserved'-- denying others all rights to use of the code.
Here's a list of the license names I've found and their frequencies
p.s. In case you're wondering how I found you and why I made this issue, it's because I'm collecting stats on gems (I was originally looking for download data) and decided to collect license metadata,too, and make issues for gemspecs not specifying a license as a public service :). See the previous link or my blog post about this project for more information.
Using MPD 0.19.1 on Debian 8, Ruby 2.1.5p273
require 'ruby-mpd'
mpd = MPD.new
mpd.status # NoMethodError: undefined method `[]' for nil:NilClass from /var/lib/gems/2.1.0/gems/ruby-mpd-0.3.3/lib/ruby-mpd/parser.rb:129:in `make_chunks'
mpd.status # works
Any idea why I would always get an empty string when using mpd.songs. When using ympd it shows a database, and mpd stats even report back that it has songs. I can do mpd.albums and mpd.artists and it gives the exepcted output but songs is empty. Is it that I have too many songs?
mpd.stats
=> {:uptime=>2930, :playtime=>0, :artists=>2169, :albums=>1772, :songs=>201361, :db_playtime=>29261847, :db_update=>2016-02-01 23:44:27 +0100}
First of all, thanks for this library. It's been terrific for scripting with.
I just came across the bug in #62, but the last release was back in 2015 (and the fix was in 2016). Is it possible to get a new release pushed to RubyGems so that I (and others) don't have to vendor/monkeypatch this in?
Thanks!
If a playlist has an internet radio or an erroneous file the .songs method throws the exception:
TypeError: no implicit conversion of Symbol into String
I would expect the the method to return a list of song objects as stated in the playlist. Perhaps some checks could be made for interet radio. Or perhaps return nil for those songs which do not exist. Or worst case provide an error indicating which playlist and file produce the error. In my case, the playlist has two good files and just one bad, and it took me a while to track down the problem.
To confirm just echo some erronous fileames or an internet radio url into an .m3u file in mpd's playlist directory and parse it with ruby-mpd. Heres the trace:
from ...gem/ruby/2.0.0/gems/ruby-mpd-0.2.2/lib/ruby-mpd/song.rb:12:in `initialize'
from ...gem/ruby/2.0.0/gems/ruby-mpd-0.2.2/lib/ruby-mpd/playlist.rb:25:in `new'
from ...gem/ruby/2.0.0/gems/ruby-mpd-0.2.2/lib/ruby-mpd/playlist.rb:25:in `block in songs'
from ...gem/ruby/2.0.0/gems/ruby-mpd-0.2.2/lib/ruby-mpd/playlist.rb:25:in `map'
from ...gem/ruby/2.0.0/gems/ruby-mpd-0.2.2/lib/ruby-mpd/playlist.rb:25:in `songs'
I recently into strange behavior regarding the time field and streams. If I add a youtube stream to mpd, mpd seems to first have no idea of the time (mpc reports it as 0:00/0:00) and then as it parses it mpd starts correctly reporting the time. ruby-mpd always reports the time as nil, even when mpc is correctly reporting the time. I am thinking the ruby-mpd might not be getting the latest information? But I'm a bit lost as to where the issue lies. Here is an example of what I am talking about:
Youtube video I have been using for testing (happens to all videos): https://www.youtube.com/watch?v=Q1JxHz_9LBI
I have been obtaining the stream using youtube-dl --prefer-insecure -i -f140 -q --no-warnings -ge https://www.youtube.com/watch?v=Q1JxHz_9LBI via my mumble bot.
Immediately after adding the stream, nothing is playing yet
brick@treef ~/mumblecop (hg)-[default] % mpc
Stanchinsky - Piano Sonata in E-flat minor
[playing] #1/1 0:00/0:00 (0%)
volume: n/a repeat: off random: off single: off consume: on \
Stream starts playing through mpd
brick@treef ~/mumblecop (hg)-[default] % mpc
Stanchinsky - Piano Sonata in E-flat minor
[playing] #1/1 0:17/9:46 (2%)
volume: n/a repeat: off random: off single: off consume: on
brick@treef ~/mumblecop (hg)-[default] % irb
irb(main):001:0> require 'ruby-mpd'
=> true
irb(main):002:0> a = MPD.new
=> #<MPD:0x00000002593268 @hostname="localhost", @port=6600, @options={:callbacks=>false}, @password=nil, @socket=nil, @version=nil, @tags=nil, @mutex=#<Mutex:0x00000002593150>, @callbacks={}>
irb(main):003:0> a.connect
=> true
irb(main):004:0> a.current_song
=> #<MPD::Song:0x000000025767f8 @mpd=#<MPD:0x00000002593268 @hostname="localhost", @port=6600, @options={:callbacks=>false}, @password=nil, @socket=#<TCPSocket:fd 9>, @version="0.19.0", @tags=nil, @mutex=#<Mutex:0x00000002593150>, @callbacks={}>, @data={:pos=>0, :id=>35}, @time=nil, @file="http://r9---sn-ab5e6m7e.googlevideo.com/videoplayback?id=4352711f3ffd2c12&itag=140&source=youtube&pl=17&mm=31&mn=sn-ab5e6m7e&mv=m&ms=au&nh=EAI&ratebypass=yes&mime=audio/mp4&gir=yes&clen=9300109&lmt=1390341494585760&dur=585.514&mt=1438116453&sver=3&signature=81FD1414A77EFE2FDCE2CDB9F2E7B6215AE56704.19EB9387CC5F4D701538CEA4779088190B7E8797&key=dg_yt0&upn=5RvJtqAhGo0&fexp=901816,9407150,9407813,9408710,9415365,9415387,9415430,9415485,9416126,9416217,9416324,9417279,9417878&ip=96.252.105.91&ipbits=0&expire=1438138113&sparams=ip,ipbits,expire,id,itag,source,pl,mm,mn,mv,ms,nh,ratebypass,mime,gir,clen,lmt,dur", @title="Stanchinsky - Piano Sonata in E-flat minor ", @artist=nil, @album=nil, @albumartist=nil>
ruby-mpd returns time as nil.
Any thoughts? I will try digging more into the source. I'm guessing that when the song object is initialized the time is nil but when mpd updates it ruby-mpd doesn't read the updated value, but I'm not sure how it works behind the scenes. But on second thought I guess I must be wrong because I have been adding the title after adding the stream and ruby-mpd is correctly reading the song. So... I'll keep looking :)
I'm working on Dockerizing an application that uses ruby-mpd
. I include a small set of Creative Commons mp3s as a kind of "database seed". I noticed that @mpd.songs.count
was always 1 greater than the actual count of my library.
using some Dirty Ruby Tricks(tm), I've traced it as follows:
[1] pry(main)> @mpd = MPD.new ENV['MPD_HOST'], ENV['MPD_PORT']
=> #<MPD:0x0000000584e6d0
@callbacks={},
@hostname="127.0.0.1",
@mutex=#<Mutex:0x0000000584e590>,
@options={:callbacks=>false},
@password=nil,
@port="6600",
@socket=nil,
@tags=nil,
@version=nil>
[2] pry(main)> @mpd.connect
=> true
[3] pry(main)> unless ENV['MPD_PASS'].nil?
[3] pry(main)* @mpd.password ENV['MPD_PASS']
[3] pry(main)* end
=> nil
[4] pry(main)>
[5] pry(main)>
[6] pry(main)>
[7] pry(main)>
[8] pry(main)> @mpd.send('socket').puts 'listallinfo'
=> nil
[9] pry(main)> response = @mpd.send('handle_server_response')
=> "directory: test_library\nLast-Modified: 2015-08-04T20:01:23Z\nfile: test_library/Indian_Summer-212174.mp3\nLast-Modified: 2009-04-04T13:04:47Z\nTime: 286\nArtist: canton\nTitle: Indian Summer\nAlbum: http://www.cantonbecker.com\nfile: test_library/Map_of_the_Cosmos-184608.mp3\nLast-Modified: 2009-03-16T01:37:52Z\nTime: 395\nArtist: canton\nTitle: Map of the Cosmos\nAlbum: http://www.cantonbecker.com\n"
[10] pry(main)>
[11] pry(main)> response.lines
=> ["directory: test_library\n",
"Last-Modified: 2015-08-04T20:01:23Z\n",
"file: test_library/Indian_Summer-212174.mp3\n",
"Last-Modified: 2009-04-04T13:04:47Z\n",
"Time: 286\n",
"Artist: canton\n",
"Title: Indian Summer\n",
"Album: http://www.cantonbecker.com\n",
"file: test_library/Map_of_the_Cosmos-184608.mp3\n",
"Last-Modified: 2009-03-16T01:37:52Z\n",
"Time: 395\n",
"Artist: canton\n",
"Title: Map of the Cosmos\n",
"Album: http://www.cantonbecker.com\n"]
[12] pry(main)> response.lines.reject {|line| line =~ /(#{[:directory, :playlist].join('|')}):/i}
=> ["Last-Modified: 2015-08-04T20:01:23Z\n",
"file: test_library/Indian_Summer-212174.mp3\n",
"Last-Modified: 2009-04-04T13:04:47Z\n",
"Time: 286\n",
"Artist: canton\n",
"Title: Indian Summer\n",
"Album: http://www.cantonbecker.com\n",
"file: test_library/Map_of_the_Cosmos-184608.mp3\n",
"Last-Modified: 2009-03-16T01:37:52Z\n",
"Time: 395\n",
"Artist: canton\n",
"Title: Map of the Cosmos\n",
"Album: http://www.cantonbecker.com\n"]
note statements 11 and 12. MPD::Parser#filter_lines
removes the "directory" line, but leaves behind the "Last-Modified" line associated with the directory. this later on manifests as a bizarre, inconsistent song list:
[13] pry(main)> @mpd.songs
=> [#<MPD::Song:0x000000049a5930
@album=nil,
@albumartist=nil,
@artist=nil,
@data={:"last-modified"=>2015-08-04 20:01:23 UTC},
@file="test_library/Indian_Summer-212174.mp3",
@mpd=
#<MPD:0x0000000584e6d0
@callbacks={},
@hostname="127.0.0.1",
@mutex=#<Mutex:0x0000000584e590>,
@options={:callbacks=>false},
@password=nil,
@port="6600",
@socket=#<TCPSocket:fd 10>,
@tags=nil,
@version="0.19.0">,
@time=nil,
@title=nil>,
#<MPD::Song:0x000000049a58b8
@album="http://www.cantonbecker.com",
@albumartist=nil,
@artist="canton",
@data={:"last-modified"=>2009-04-04 13:04:47 UTC},
@file="test_library/Map_of_the_Cosmos-184608.mp3",
@mpd=
#<MPD:0x0000000584e6d0
@callbacks={},
@hostname="127.0.0.1",
@mutex=#<Mutex:0x0000000584e590>,
@options={:callbacks=>false},
@password=nil,
@port="6600",
@socket=#<TCPSocket:fd 10>,
@tags=nil,
@version="0.19.0">,
@time=[nil, 286],
@title="Indian Summer">,
#<MPD::Song:0x000000049a5868
@album="http://www.cantonbecker.com",
@albumartist=nil,
@artist="canton",
@data={:"last-modified"=>2009-03-16 01:37:52 UTC},
@file=nil,
@mpd=
#<MPD:0x0000000584e6d0
@callbacks={},
@hostname="127.0.0.1",
@mutex=#<Mutex:0x0000000584e590>,
@options={:callbacks=>false},
@password=nil,
@port="6600",
@socket=#<TCPSocket:fd 10>,
@tags=nil,
@version="0.19.0">,
@time=[nil, 395],
@title="Map of the Cosmos">]
3 songs where there should be 2, one with a nil
@file
variable, another with a nil
@time
variable.
I have no idea what a fix would/should look like. I think I've spent all of today's brain juices tracing the issue this far.
as an additional exhibit, here's a data structure that has obviously weird behavior in :"last-modified"
and :time
. I didn't trace it fully, but I assume this data structure will eventually become an array of MPD::Song
objects. the mis-matched columns likely causes malformed objects to be created.
[15] pry(main)> @mpd.send('parse_response', 'listallinfo', response)
=> {:directory=>"test_library",
:"last-modified"=>[23, 1, 20, 4, 8, 2015, 2, 216, false, "UTC", 2009-04-04 13:04:47 UTC, 2009-03-16 01:37:52 UTC],
:file=>["test_library/Indian_Summer-212174.mp3", "test_library/Map_of_the_Cosmos-184608.mp3"],
:time=>[nil, 286, [nil, 395]],
:artist=>["canton", "canton"],
:title=>["Indian Summer", "Map of the Cosmos"],
:album=>["http://www.cantonbecker.com", "http://www.cantonbecker.com"]}
Hey Blaz @archseer,
I’ve seen that you’ve incremented the version number in ruby-mpd but and released on Rubygems but in fact the code has not been tagged. Given that I’ve migrated the codebase onto Bundler, I thought I’d share with you what I do, it may be useful:
I use rake release
after changing version.rb
, this rake task comes from Bundler and it properly tags the codebase, pushes it up and then releases the gem onto Rubygems. So all release stuff can be done using a single command in the terminal.
Hopefully this will help.
— Attila
A Song
may have @time==nil
if the song is not valid. This may occur if a playlist has songs added to it that have then been removed from the queue (or if a playlist file is hand-edited to add broken entries).
When this is the case, asking for song.track_length
errors, because the implementation is just @time.last
.
Though rarely a good idea, it's possible for filenames to have double-quotes in them. In this case, the MPD protocol expects the name to be double-quoted, with double-quotes inside escaped with backslashes. For example, given a song test/"Suddenly".mp3
:
# telnet to MPD
add test/"Suddenly".mp3
ACK [2@0] {add} Invalid unquoted character
add "test/"Suddenly".mp3"
ACK [2@0] {add} Space expected after closing '"'
add "test/\"Suddenly\".mp3"
OK
Several spots in the codebase just wrap a uri in quotes without escaping embedded quotes.
require "pp"
require "ruby-mpd"
mpd = MPD.new
mpd.connect
begin
playlist = MPD::Playlist.new(mpd, "Example")
playlist.add("http://uk1.internet-radio.com:8106/listen.pls")
pp playlist.songs
ensure
mpd.disconnect
end
Files inside Playlist 'Example' do not exist!
[]
I've checked the code and found this implementation of MPD::Playlist#songs
:
# Lists the songs in the playlist. Playlist plugins are supported.
# @return [Array<MPD::Song>] songs in the playlist.
def songs
result = @mpd.send_command(:listplaylistinfo, @name)
result.map do |hash|
if hash[:file] && !hash[:file].match(/^(https?:\/\/)?/)[0].empty?
Song.new(@mpd, {:file => hash[:file], :time => [0]})
else
Song.new(@mpd, hash)
end
end
rescue TypeError
puts "Files inside Playlist '#{@name}' do not exist!"
return []
rescue NotFound
return [] # we rescue in the case the playlist doesn't exist.
end
The problem is, that result
looks like this:
[ "http://uk1.internet-radio.com:8106/listen.pls" ]
But the code requires result
to look like this:
[ { :file => "http://uk1.internet-radio.com:8106/listen.pls" } ]
Edit: I am using MPD 0.18.0
Whenever I call #where
with the add
flag true, it crashes with the following error:
/usr/lib/ruby/gems/1.9.1/gems/ruby-mpd-0.3.1/lib/ruby-mpd/parser.rb:112:in `build_songs_list': undefined method `map' for true:TrueClass (NoMethodError)
from /usr/lib/ruby/gems/1.9.1/gems/ruby-mpd-0.3.1/lib/ruby-mpd/plugins/database.rb:95:in `where'
from MusicBot.rb:117:in `search'
from MusicBot.rb:191:in `parse_input'
from MusicBot.rb:55:in `block in <main>'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:145:in `call'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:145:in `block in run_callbacks'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:145:in `each'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:145:in `run_callbacks'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:136:in `read'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:130:in `block (2 levels) in spawn_thread'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:130:in `loop'
from /usr/lib/ruby/gems/1.9.1/gems/mumble-ruby-1.0.2/lib/mumble-ruby/client.rb:130:in `block in spawn_thread'
This also happens when I am calling #where
from irb, and regardless of the value of the strict
option. Also, it should be noted that mpd does indeed add the query into the queue, but ruby-mpd crashes.
By looking at the source, you say that #where
should return true whenever the add
option is true and it seems like #build_song_list
can't handle the return from #send_command
.
I think that this is unintentional behavior, as half of the examples that are given on how to use #where
use the add option.
I have tested and reproduced the bug on debian squeeze with mpd 0.17.6 and ruby 1.9.3 and on arch with mpd 0.18.9 with ruby 2.1.1
Hey,
I wasn't sure if this was a bug or I'm not using the library correctly. I noticed that the first song I add doesn't show up in the queue until I add a 2nd song. I took a screenshot of the irb session so you could see what I'm talking about. Let me know if it's a bug, I wouldn't mind putting in a fix for it if you wanted some help. Also thank you very much for putting this gem together. It's been great fun working with it.
mpd.set_sticker 'song', song, 'added-by', 'phrogz'
#=> true
mpd.list_stickers 'song', song
#=> "added-by=phrogz"
mpd.get_sticker 'song', song, 'added-by'
#=> "added-by=phrogz"
I would expect list_stickers
to return a Hash, e.g. { 'added-by' => 'phrogz' }
I would expect get_sticker
to return a String, e.g. "phrogz"
s = M.where(genre:'(123)').first
s.genre #=> "(123)"
s.file #=> "Beelzebubs/Foster Street/08 Comfortably Numb.mp3"
phrogz$ eyeD3 "Beelzebubs/Foster Street/08 Comfortably Numb.mp3" | grep genre
track: 8 genre: A Cappella (id 123)
I'd like to get the genre name, not the id, in my Song
instances. Is this possible?
When using the add command (in a queue) with a valid stream URL (both m3u or mp3), this error is shown : [] No database .
How can I fix that ?
Just imported my song library. There are many Song
s returned with no file
.
[ M.stats[:songs], M.songs.length, M.songs.reject(&:file).length ]
#=> [17103, 22892, 5789]
Some of them are real zombies:
M.songs.reject(&:file).first
#=> #<MPD::Song:0x000000028e18e8 @mpd=…, @data={:"last-modified"=>2015-11-08 07:57:01 UTC}, @time=nil, @file=nil, @title=nil, @artist=nil, @album=nil, @albumartist=nil>
Some of them are files that exist on disk (perhaps the Unicode characters in the path are tricky?):
M.songs.reject(&:file).last
#=> #<MPD::Song:0x00000003704178 @mpd=…, @data={:"last-modified"=>2008-06-01 03:16:00 UTC, :track=>1, :date=>2003, :genre=>"Soundtrack"}, @time=[nil, 160], @file=nil, @title="Bang Bang (My Baby Shot Me Down)", @artist="Nancy Sinatra", @album="Kill Bill: Vol.1", @albumartist="群星">
Dir['**/*'].grep /Bang Bang/
#=> ["群星/Kill Bill_ Vol.1/01 Bang Bang (My Baby Shot Me Down).mp3"]
puts `ls -l "群星/Kill Bill_ Vol.1/"`
#=> total 3744
#=> -rw-r--r-- 1 gkistner gkistner 3833856 May 31 2008 01 Bang Bang (My Baby Shot Me Down).mp3
How do I fix it so that all songs have a file
?
hi, thank you for this gem
i got error when try to move song in playlist
there are not enough params (songid and songpos) in @mpd.send_command
def move(songid, songpos)
- @mpd.send_command :playlistmove, @name
+ @mpd.send_command :playlistmove, @name, songid, songpos
end
It doesn't mean anything if I pass path to the directories call or not. I always get full list of directories.
Maybe, https://github.com/archSeer/ruby-mpd/blob/master/lib/ruby-mpd/plugins/database.rb#L125 should pass path to the files call
I've put a question on Stack Exchange Code Review:
http://codereview.stackexchange.com/q/120345/3060
In short, I am writing tests for the command_lists functionality and expected results for ugly edge cases. I welcome any opinions on a better way to simulate MPD getting and sending information.
The two changes I plan to make beyond what I put there are:
Some of my songs come back from the server with multiple genres applied:
$ telnet 0 6600
Trying 0.0.0.0...
Connected to 0.
Escape character is '^]'.
OK MPD 0.19.0
search file "pull me under"
file: doza/Dream Theater/Images and Words/01 Pull Me Under.mp3
Last-Modified: 2012-11-11T16:44:44Z
Time: 493
Artist: Dream Theater
AlbumArtist: Dream Theater
Title: Pull Me Under
Album: Images and Words
Track: 1
Date: 1992
Genre: Rock
Genre: Rock
Composer: Dream Theater; Kevin Moore
This results in an array in the genre
metadata:
song = @mpd.where(file:'pull me under').first
p song.instance_variable_get(:@data)[:genre]
#=> ["Rock", "Rock"]
This causes some code in the new genre resolver to fail when asking for song.genre
.
/var/lib/gems/2.1.0/gems/ruby-mpd-0.3.3/lib/ruby-mpd/song.rb:264:in `[]': no implicit conversion of Regexp into Integer (TypeError)
The information.rb
plugin has an idle
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.
My UI uses the name of a playlist as the unique identifier. When I want to fetch a playlist with this name I must currently use one of the following:
playlist = @mpd.playlists.find{ |pl| pl.name==playlistname }
playlist = MPD::Playlist.new( @mpd, playlist:playlistname )
Using find
feels gross because it instantiates all the playlists (maybe a great many) when I only need one. Using new
feels gross because if I mistakenly ask for a playlist that does not exist it will be created.
I'd prefer to be able to do something like:
playlist = @mpd.playlist( playlistname )
Does that seem reasonable?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.