Songs with nil file
Closed this issue · 6 comments
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
?
Does the file get listed correctly in another player, for example MPC, the official frontend for MPD?
Probably best if you add some sort of log out puts response.inspect
after this line so that we can see what the data coming from MPD looks like for that specific file.
Interesting results. When I use where
, I get back a valid Song
with file
:
bb = M.where(title:'Bang Bang')
# p response
"file: gavin/\xE7\xBE\xA4\xE6\x98\x9F/Kill Bill_ Vol.1/01 Bang Bang (My Baby Shot Me Down).mp3\nLast-Modified: 2008-06-01T03:16:00Z\nTime: 160\nArtist: Nancy Sinatra\nAlbumArtist: \xE7\xBE\xA4\xE6\x98\x9F\nTitle: Bang Bang (My Baby Shot Me Down)\nAlbum: Kill Bill: Vol.1\nTrack: 1\nDate: 2003\nGenre: Soundtrack\n"
bb.length #=> 1
bb.first.file #=> "gavin/群星/Kill Bill_ Vol.1/01 Bang Bang (My Baby Shot Me Down).mp3"
However, when I use songs
instead I get the nil
:
ss = M.songs.select{ |f| f.title[/Bang Bang/] }
# (p response moved to below)
ss.length #=> 1
ss.first.file #=> nil
The last ~500 bytes of the response.inspect
end with data including the file name:
"…ate: 1977\nDisc: 1/1\ndirectory: gavin/\xE7\xBE\xA4\xE6\x98\x9F\nLast-Modified: 2009-01-04T00:25:22Z\ndirectory: gavin/\xE7\xBE\xA4\xE6\x98\x9F/Kill Bill_ Vol.1\nLast-Modified: 2009-01-04T00:25:22Z\nfile: gavin/\xE7\xBE\xA4\xE6\x98\x9F/Kill Bill_ Vol.1/01 Bang Bang (My Baby Shot Me Down).mp3\nLast-Modified: 2008-06-01T03:16:00Z\nTime: 160\nArtist: Nancy Sinatra\nAlbumArtist: \xE7\xBE\xA4\xE6\x98\x9F\nTitle: Bang Bang (My Baby Shot Me Down)\nAlbum: Kill Bill: Vol.1\nTrack: 1\nDate: 2003\nGenre: Soundtrack\n"
The above includes the only instances of "Bang Bang" in the entire 4.8MB response text.
@archseer To help debug, the full response is available at:
https://gist.github.com/Phrogz/a8c46afc3aac50a1182b
The encoding for the response string is ASCII-8BIT.
Looks like this could be related to #38
When you use where
ruby-mpd sends :findadd
or :find
. When you call songs
it sends :listallinfo
.
Found it (and I have a fix that I need to package up). The problem is that listallinfo
includes directories in the results (and starts off with them). Here are the first few lines of the response:
directory: bijan
Last-Modified: 2016-01-22T16:23:13Z
file: bijan/CabinFeverSessionsDec13_Fubari_Janis.mp3
Last-Modified: 2016-01-13T17:13:19Z
Time: 11256
The code in parse_response
tries to handle this by stripping out Directory
(and Playlist
) lines:
string = filter_lines(string, [:directory, :playlist])
However, this leaves the Last-Modified:
line as the first line. Then, make_chunks
splits the results based on Last-Modified:
instead of the desired file:
separator. And things go downhill.
I'm getting rid of filter_lines
—because this is the only case where it's used, and it's very inefficient, and doesn't work as desired—and replacing it with:
string.gsub! /^(?:directory|playlist): .+?\n(?:last-modified: .+?\n)?/i, ''
With this one-line change @mpd.songs
works correctly.