daapclient 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +63 -0
- data/doc/classes/Net/DAAP/Client.html +251 -0
- data/doc/classes/Net/DAAP/Client.src/M000003.html +20 -0
- data/doc/classes/Net/DAAP/Client.src/M000004.html +25 -0
- data/doc/classes/Net/DAAP/Client.src/M000005.html +33 -0
- data/doc/classes/Net/DAAP/Client.src/M000006.html +37 -0
- data/doc/classes/Net/DAAP/Client.src/M000007.html +20 -0
- data/doc/classes/Net/DAAP/Client.src/M000008.html +24 -0
- data/doc/classes/Net/DAAP/DAAPv2.html +165 -0
- data/doc/classes/Net/DAAP/DAAPv2.src/M000015.html +30 -0
- data/doc/classes/Net/DAAP/DAAPv2.src/M000016.html +21 -0
- data/doc/classes/Net/DAAP/DAAPv3.html +178 -0
- data/doc/classes/Net/DAAP/DAAPv3.src/M000017.html +30 -0
- data/doc/classes/Net/DAAP/DAAPv3.src/M000018.html +23 -0
- data/doc/classes/Net/DAAP/DMAP.html +189 -0
- data/doc/classes/Net/DAAP/DMAP.src/M000012.html +20 -0
- data/doc/classes/Net/DAAP/DMAP.src/M000013.html +18 -0
- data/doc/classes/Net/DAAP/DMAP.src/M000014.html +24 -0
- data/doc/classes/Net/DAAP/Database.html +224 -0
- data/doc/classes/Net/DAAP/Database.src/M000009.html +25 -0
- data/doc/classes/Net/DAAP/Database.src/M000010.html +21 -0
- data/doc/classes/Net/DAAP/Database.src/M000011.html +35 -0
- data/doc/classes/Net/DAAP/Playlist.html +192 -0
- data/doc/classes/Net/DAAP/Playlist.src/M000001.html +24 -0
- data/doc/classes/Net/DAAP/Playlist.src/M000002.html +30 -0
- data/doc/classes/Net/DAAP/Song.html +208 -0
- data/doc/classes/Net/DAAP/Song.src/M000019.html +27 -0
- data/doc/classes/Net/DAAP/Song.src/M000020.html +19 -0
- data/doc/classes/Net/DAAP.html +168 -0
- data/doc/classes/Net.html +127 -0
- data/doc/created.rid +1 -0
- data/doc/files/CHANGELOG.html +110 -0
- data/doc/files/LICENSE.html +531 -0
- data/doc/files/README.html +176 -0
- data/doc/files/lib/net/daap/database_rb.html +101 -0
- data/doc/files/lib/net/daap/dmap_rb.html +101 -0
- data/doc/files/lib/net/daap/playlist_rb.html +101 -0
- data/doc/files/lib/net/daap/song_rb.html +101 -0
- data/doc/files/lib/net/daap_rb.html +114 -0
- data/doc/fr_class_index.html +35 -0
- data/doc/fr_file_index.html +34 -0
- data/doc/fr_method_index.html +46 -0
- data/doc/index.html +24 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/CVS/Entries +1 -0
- data/lib/CVS/Repository +1 -0
- data/lib/CVS/Root +1 -0
- data/lib/net/CVS/Entries +2 -0
- data/lib/net/CVS/Repository +1 -0
- data/lib/net/CVS/Root +1 -0
- data/lib/net/daap/CVS/Entries +5 -0
- data/lib/net/daap/CVS/Repository +1 -0
- data/lib/net/daap/CVS/Root +1 -0
- data/lib/net/daap/database.rb +69 -0
- data/lib/net/daap/dmap.rb +575 -0
- data/lib/net/daap/playlist.rb +36 -0
- data/lib/net/daap/song.rb +27 -0
- data/lib/net/daap.rb +234 -0
- data/test/CVS/Entries +4 -0
- data/test/CVS/Repository +1 -0
- data/test/CVS/Root +1 -0
- data/test/data/CVS/Entries +1 -0
- data/test/data/CVS/Repository +1 -0
- data/test/data/CVS/Root +1 -0
- data/test/data/mt-daapd/079aca35773150da9fd98db10c7fd0c0.txt +0 -0
- data/test/data/mt-daapd/2972f65088b42a06b5d3ca089d71791d.txt +0 -0
- data/test/data/mt-daapd/440c2217e6207c54c317c296f71f9769.txt +0 -0
- data/test/data/mt-daapd/4d1ce9f941cbd823ed06f1f1baa5a3b9.txt +0 -0
- data/test/data/mt-daapd/7bded8b540fd082f102d25e181b47bc4.txt +0 -0
- data/test/data/mt-daapd/CVS/Entries +11 -0
- data/test/data/mt-daapd/CVS/Repository +1 -0
- data/test/data/mt-daapd/CVS/Root +1 -0
- data/test/data/mt-daapd/b3e894b87111bdba88e4765967f4b45a.txt +0 -0
- data/test/data/mt-daapd/d56b699830e77ba53855679cb1d252da.txt +0 -0
- data/test/data/mt-daapd/e61ce3062cb76770658896b778ad06cd.txt +0 -0
- data/test/data/mt-daapd/e9a8e709c2116651157182f130207048.txt +0 -0
- data/test/data/mt-daapd/f9073959a0afacebfab7e3bf19c2714a.txt +0 -0
- data/test/tc_client.rb +148 -0
- data/test/tc_protocol.rb +49 -0
- data/test/ts_daap.rb +6 -0
- metadata +148 -0
data/lib/net/daap.rb
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'digest/m4p'
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
require 'net/daap/dmap'
|
|
5
|
+
require 'net/daap/song'
|
|
6
|
+
require 'net/daap/playlist'
|
|
7
|
+
require 'net/daap/database'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module Net
|
|
11
|
+
# = Synopsis
|
|
12
|
+
# The DAAP library is used for browsing an iTunes share.
|
|
13
|
+
# Make sure that Digest::M4P is installed before using this library.
|
|
14
|
+
#
|
|
15
|
+
# == Example
|
|
16
|
+
# require 'rubygems'
|
|
17
|
+
# require 'net/daap'
|
|
18
|
+
#
|
|
19
|
+
# daap = Net::DAAP::Client.new('localhost')
|
|
20
|
+
# daap.connect do |dsn|
|
|
21
|
+
#
|
|
22
|
+
# daap.databases do |db|
|
|
23
|
+
# puts "All songs in the database"
|
|
24
|
+
# db.songs do |song|
|
|
25
|
+
# puts "#{song.artist} - #{song.name}"
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# puts "Songs for each playlist"
|
|
29
|
+
# db.playlists do |pl|
|
|
30
|
+
# puts "Playlist name: #{pl.name}"
|
|
31
|
+
# pl.songs do |song|
|
|
32
|
+
# puts "#{song.artist} - #{song.name}"
|
|
33
|
+
# File::open("dl/#{song.artist} - #{song.name}.#{song.format}", "w") do |f|
|
|
34
|
+
# f << song.get
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
37
|
+
# end
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
40
|
+
#
|
|
41
|
+
module DAAP
|
|
42
|
+
|
|
43
|
+
# = Synopsis
|
|
44
|
+
# The Client class interacts with the iTunes server to fetch lists of songs,
|
|
45
|
+
# databases, and playlists. Each Client class can have many Database,
|
|
46
|
+
# and each Database can have many Playlist, and many Song. See DAAP for a
|
|
47
|
+
# code example.
|
|
48
|
+
class Client
|
|
49
|
+
attr_reader :dmap
|
|
50
|
+
|
|
51
|
+
# Create a new Client and pass in the host where the client will connect.
|
|
52
|
+
def initialize(server_host)
|
|
53
|
+
@server_host = server_host
|
|
54
|
+
@server_port = 3689
|
|
55
|
+
@debug = 0
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Connects to the iTunes server. This method should be called right after
|
|
59
|
+
# construction. See DAAP for an example.
|
|
60
|
+
def connect(&connection)
|
|
61
|
+
@http_client = Net::HTTP.start(@server_host, @server_port)
|
|
62
|
+
find_validator
|
|
63
|
+
@dmap = Net::DAAP::DMAP.new(:daap => self)
|
|
64
|
+
load_server_info
|
|
65
|
+
@connected = 1
|
|
66
|
+
yield @dsn
|
|
67
|
+
disconnect
|
|
68
|
+
@connected = 0
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Returns the databases found on the iTunes server.
|
|
72
|
+
def databases
|
|
73
|
+
return error("Not connected, can't fetch databases") unless @connected
|
|
74
|
+
|
|
75
|
+
listings = @dmap.find(do_get("databases"),
|
|
76
|
+
"daap.serverdatabases/dmap.listing")
|
|
77
|
+
# FIXME check the value of listing
|
|
78
|
+
@databases = []
|
|
79
|
+
unpack_listing(listings) do |value|
|
|
80
|
+
if block_given?
|
|
81
|
+
yield Database.new( :db_info => value,
|
|
82
|
+
:daap => self )
|
|
83
|
+
else
|
|
84
|
+
@databases << Database.new( :db_info => value,
|
|
85
|
+
:daap => self )
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
@databases
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def do_get(request)
|
|
92
|
+
debug("do_get")
|
|
93
|
+
url = String.new('/' + request)
|
|
94
|
+
if @session_id
|
|
95
|
+
url += url =~ /\?/ ? "&" : "?"
|
|
96
|
+
url += "session-id=#{@session_id}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if @revision && request != "logout"
|
|
100
|
+
url += "&revision-number=#{@revision}"
|
|
101
|
+
end
|
|
102
|
+
debug(url)
|
|
103
|
+
|
|
104
|
+
res = @http_client.get(url, request_headers(url))
|
|
105
|
+
|
|
106
|
+
content_type = res.header['content-type']
|
|
107
|
+
if request !~ /(?:\/items\/\d+\.|logout)/ && content_type !~ /dmap/
|
|
108
|
+
raise "Broken response"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
res.body
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def get_song(request)
|
|
115
|
+
@request_id = 1 unless @request_id
|
|
116
|
+
@request_id += 1 if @request_id
|
|
117
|
+
do_get(request)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def unpack_listing(listing, &func)
|
|
121
|
+
listing.each do |item|
|
|
122
|
+
record = Hash.new
|
|
123
|
+
item[1].each do |pair_ref|
|
|
124
|
+
record[pair_ref[0]] = pair_ref[1]
|
|
125
|
+
end
|
|
126
|
+
yield record
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
def disconnect
|
|
132
|
+
do_get("logout")
|
|
133
|
+
end
|
|
134
|
+
def load_server_info
|
|
135
|
+
flat_list = @dmap.flat_list(do_get("server-info"))
|
|
136
|
+
@dsn = flat_list['/dmap.serverinforesponse/dmap.itemname']
|
|
137
|
+
|
|
138
|
+
debug("Connected to share '#{@dsn}'")
|
|
139
|
+
@session_id = @dmap.find(do_get("login"),
|
|
140
|
+
"dmap.loginresponse/dmap.sessionid")
|
|
141
|
+
debug("My id is #{@session_id}")
|
|
142
|
+
@dsn
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def request_headers(url)
|
|
146
|
+
headers = Hash.new
|
|
147
|
+
headers['Client-DAAP-Version'] = "3.0"
|
|
148
|
+
headers['Client-DAAP-Access-Index'] = "2"
|
|
149
|
+
headers['Client-DAAP-Request-ID'] = @request_id.to_s if @request_id
|
|
150
|
+
headers['Client-DAAP-Validation'] =
|
|
151
|
+
@validator.validate(url, 2, @request_id) if @validator
|
|
152
|
+
|
|
153
|
+
headers
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def find_validator
|
|
157
|
+
res = @http_client.get('/server-info')
|
|
158
|
+
server = res.header['daap-server']
|
|
159
|
+
|
|
160
|
+
if server =~ /^iTunes\/4.2/
|
|
161
|
+
@validator = DAAPv2.new
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
if server =~ /^iTunes/
|
|
165
|
+
@validator = DAAPv3.new
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def debug(message)
|
|
170
|
+
if @debug == 1
|
|
171
|
+
print "DEBUG: "
|
|
172
|
+
p message
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# This class is used for generating a Client-DAAP-Validation header for iTunes
|
|
178
|
+
# version 4.2 servers.
|
|
179
|
+
class DAAPv2
|
|
180
|
+
def initialize
|
|
181
|
+
@seeds = []
|
|
182
|
+
(0..255).each do |i|
|
|
183
|
+
string = String.new
|
|
184
|
+
string += (i & 0x80) != 0 ? "Accept-Language" : "user-agent"
|
|
185
|
+
string += (i & 0x40) != 0 ? "max-age" : "Authorization"
|
|
186
|
+
string += (i & 0x20) != 0 ? "Client-DAAP-Version" : "Accept-Encoding"
|
|
187
|
+
string += (i & 0x10) != 0 ? "daap.protocolversion": "daap.songartist"
|
|
188
|
+
string += (i & 0x08) != 0 ? "daap.songcomposer" : "daap.songdatemodified"
|
|
189
|
+
string += (i & 0x04) != 0 ? "daap.songdiscnumber" : "daap.songdisabled"
|
|
190
|
+
string += (i & 0x02) != 0 ? "playlist-item-spec" : "revision-number"
|
|
191
|
+
string += (i & 0x01) != 0 ? "session-id" : "content-codes"
|
|
192
|
+
@seeds << Digest::MD5.new(string).to_s.upcase
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
# Returns a validation header based on MD5
|
|
196
|
+
def validate(path, select = 2, req_id = nil)
|
|
197
|
+
string = path.dup
|
|
198
|
+
string += "Copyright 2003 Apple Computer, Inc."
|
|
199
|
+
string += @seeds[select]
|
|
200
|
+
return Digest::MD5.new(string).to_s.upcase
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# This class is used for generating a Client-DAAP-Validation header for iTunes
|
|
205
|
+
# servers newer than 4.2, or something.
|
|
206
|
+
class DAAPv3
|
|
207
|
+
attr_reader :seeds
|
|
208
|
+
def initialize
|
|
209
|
+
@seeds = []
|
|
210
|
+
(0..255).each do |i|
|
|
211
|
+
string = String.new
|
|
212
|
+
string += (i & 0x40) != 0 ? "eqwsdxcqwesdc" : "op[;lm,piojkmn"
|
|
213
|
+
string += (i & 0x20) != 0 ? "876trfvb 34rtgbvc" : "=-0ol.,m3ewrdfv"
|
|
214
|
+
string += (i & 0x10) != 0 ? "87654323e4rgbv " : "1535753690868867974342659792"
|
|
215
|
+
string += (i & 0x08) != 0 ? "Song Name" : "DAAP-CLIENT-ID:"
|
|
216
|
+
string += (i & 0x04) != 0 ? "111222333444555" : "4089961010"
|
|
217
|
+
string += (i & 0x02) != 0 ? "playlist-item-spec" : "revision-number"
|
|
218
|
+
string += (i & 0x01) != 0 ? "session-id" : "content-codes"
|
|
219
|
+
string += (i & 0x80) != 0 ? "IUYHGFDCXWEDFGHN" : "iuytgfdxwerfghjm"
|
|
220
|
+
@seeds << Digest::M4P.new(string).to_s.upcase
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
# Returns a validation header using a custom MD5 called Digest::M4P
|
|
224
|
+
def validate(path, select = 2, req_id = nil)
|
|
225
|
+
string = String.new
|
|
226
|
+
string += path
|
|
227
|
+
string += "Copyright 2003 Apple Computer, Inc."
|
|
228
|
+
string += @seeds[select]
|
|
229
|
+
string += req_id.to_s if req_id != nil
|
|
230
|
+
Digest::M4P.new(string).to_s.upcase
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
data/test/CVS/Entries
ADDED
data/test/CVS/Repository
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
daap/test
|
data/test/CVS/Root
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:ext:aaronp@rubyforge.org:/var/cvs/daapclient
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
D/mt-daapd////
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
daap/test/data
|
data/test/data/CVS/Root
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:ext:aaronp@rubyforge.org:/var/cvs/daapclient
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/079aca35773150da9fd98db10c7fd0c0.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
2
|
+
/2972f65088b42a06b5d3ca089d71791d.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
3
|
+
/440c2217e6207c54c317c296f71f9769.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
4
|
+
/4d1ce9f941cbd823ed06f1f1baa5a3b9.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
5
|
+
/7bded8b540fd082f102d25e181b47bc4.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
6
|
+
/b3e894b87111bdba88e4765967f4b45a.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
7
|
+
/d56b699830e77ba53855679cb1d252da.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
8
|
+
/e61ce3062cb76770658896b778ad06cd.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
9
|
+
/e9a8e709c2116651157182f130207048.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
10
|
+
/f9073959a0afacebfab7e3bf19c2714a.txt/1.1.1.1/Wed Dec 7 23:25:52 2005//
|
|
11
|
+
D
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
daap/test/data/mt-daapd
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:ext:aaronp@rubyforge.org:/var/cvs/daapclient
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/test/tc_client.rb
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'net/daap'
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
class MyTest < Net::DAAP::Client
|
|
6
|
+
def connect
|
|
7
|
+
@dmap = Net::DAAP::DMAP.new(:daap => self)
|
|
8
|
+
load_server_info
|
|
9
|
+
@connected = 1
|
|
10
|
+
@dsn
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def find_validator
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def do_get(request)
|
|
17
|
+
contents = nil
|
|
18
|
+
md5 = Digest::MD5.new(request)
|
|
19
|
+
File::open("data/mt-daapd/" + md5.to_s + ".txt", "r") do |file|
|
|
20
|
+
contents = file.read
|
|
21
|
+
end
|
|
22
|
+
contents
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class DAAPClient_Test < Test::Unit::TestCase
|
|
27
|
+
def setup
|
|
28
|
+
@daap = MyTest.new('localhost')
|
|
29
|
+
@daap.connect
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_connect
|
|
33
|
+
daap = MyTest.new('localhost')
|
|
34
|
+
dsn = daap.connect
|
|
35
|
+
assert_equal("apatterson", dsn)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_songs
|
|
39
|
+
songs = @daap.databases[0].songs
|
|
40
|
+
songs_hash = Hash.new
|
|
41
|
+
songs.each do |song|
|
|
42
|
+
songs_hash[song.id] = { :size => song.size, :album => song.album,
|
|
43
|
+
:name => song.name, :artist => song.artist, :format => song.format,
|
|
44
|
+
:persistentid => song.persistentid, :itemid => song.id }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
hash =
|
|
48
|
+
{2327300=>{:itemid=>2327300, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4654199, :name=>"Myxomatosis (Judge, Jury & Executioner)", :persistentid=>2327300},
|
|
49
|
+
2327243=>{:itemid=>2327243, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>3723264, :name=>"Myxomatosis", :persistentid=>2327243},
|
|
50
|
+
2327281=>{:itemid=>2327281, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>5950405, :name=>"A Punch Up At A Wedding (No No No No No No No No)", :persistentid=>2327281},
|
|
51
|
+
2327234=>{:itemid=>2327234, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>4759552, :name=>"A Punch-Up At The Wedding", :persistentid=>2327234},
|
|
52
|
+
2327272=>{:itemid=>2327272, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>7673398, :name=>"Paranoid Android", :persistentid=>2327272},
|
|
53
|
+
2327253=>{:itemid=>2327253, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>3284376, :name=>"I will (Los Angeles version)", :persistentid=>2327253},
|
|
54
|
+
2327225=>{:itemid=>2327225, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>3190784, :name=>"2+2=5", :persistentid=>2327225},
|
|
55
|
+
2327301=>{:itemid=>2327301, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>6455593, :name=>"Backdrifts (Honeymoon Is Over)", :persistentid=>2327301},
|
|
56
|
+
2327282=>{:itemid=>2327282, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4037702, :name=>"Scatterbrain (As Dead As Leaves)", :persistentid=>2327282},
|
|
57
|
+
2327273=>{:itemid=>2327273, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>5236170, :name=>"Karma Police", :persistentid=>2327273},
|
|
58
|
+
2327311=>{:itemid=>2327311, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4030394, :name=>"A Wolf At The Door (It Girl. Rag Doll)", :persistentid=>2327311},
|
|
59
|
+
2327254=>{:itemid=>2327254, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>6443033, :name=>"Skttrbrain (Four Tet remix)", :persistentid=>2327254},
|
|
60
|
+
2327302=>{:itemid=>2327302, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>2393022, :name=>"I Will (No Man's Land)", :persistentid=>2327302},
|
|
61
|
+
2327245=>{:itemid=>2327245, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>5212004, :name=>"Gagging Order", :persistentid=>2327245},
|
|
62
|
+
2327283=>{:itemid=>2327283, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4833826, :name=>"A Wolf At The Door", :persistentid=>2327283},
|
|
63
|
+
2327226=>{:itemid=>2327226, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>4134912, :name=>"Sail To The Moon", :persistentid=>2327226},
|
|
64
|
+
2327264=>{:itemid=>2327264, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>2350164, :name=>"Fitter Happier", :persistentid=>2327264},
|
|
65
|
+
2327312=>{:itemid=>2327312, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>2868372, :name=>"I Will", :persistentid=>2327312},
|
|
66
|
+
2327246=>{:itemid=>2327246, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>5130084, :name=>"I am Citizen Insane", :persistentid=>2327246},
|
|
67
|
+
2327284=>{:itemid=>2327284, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4785551, :name=>"2 + 2 = 5", :persistentid=>2327284},
|
|
68
|
+
2327322=>{:itemid=>2327322, :album=>"I Might Be Wrong: Live Recordings", :format=>"mp3", :artist=>"Radiohead", :size=>5953983, :name=>"The National Anthem", :persistentid=>2327322},
|
|
69
|
+
2327227=>{:itemid=>2327227, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>3223552, :name=>"A Wolf At The Door", :persistentid=>2327227},
|
|
70
|
+
2327265=>{:itemid=>2327265, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>4616547, :name=>"Electioneering", :persistentid=>2327265},
|
|
71
|
+
2327303=>{:itemid=>2327303, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>6475455, :name=>"There There (The Boney King Of Nowhere)", :persistentid=>2327303},
|
|
72
|
+
2327294=>{:itemid=>2327294, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>7122152, :name=>"We Suck Young Blood", :persistentid=>2327294},
|
|
73
|
+
2327237=>{:itemid=>2327237, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>3229696, :name=>"Scatterbrain", :persistentid=>2327237},
|
|
74
|
+
2327247=>{:itemid=>2327247, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>3349578, :name=>"Fog. (Again) - Live", :persistentid=>2327247},
|
|
75
|
+
2327285=>{:itemid=>2327285, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>5170908, :name=>"Sail To The Moon (Brush The Cobwebs Of The Sky)", :persistentid=>2327285},
|
|
76
|
+
2327323=>{:itemid=>2327323, :album=>"I Might Be Wrong: Live Recordings", :format=>"mp3", :artist=>"Radiohead", :size=>6263793, :name=>"Dollars And Cents", :persistentid=>2327323},
|
|
77
|
+
2327228=>{:itemid=>2327228, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>3225600, :name=>"Go To Sleep", :persistentid=>2327228},
|
|
78
|
+
2327266=>{:itemid=>2327266, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>5691739, :name=>"Airbag", :persistentid=>2327266},
|
|
79
|
+
2327295=>{:itemid=>2327295, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>6240049, :name=>"Sit Down. Stand Up", :persistentid=>2327295},
|
|
80
|
+
2327314=>{:itemid=>2327314, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>6463866, :name=>"Where I End And You Begin", :persistentid=>2327314},
|
|
81
|
+
2327324=>{:itemid=>2327324, :album=>"I Might Be Wrong: Live Recordings", :format=>"mp3", :artist=>"Radiohead", :size=>5300405, :name=>"Idioteque", :persistentid=>2327324},
|
|
82
|
+
2327229=>{:itemid=>2327229, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>5179392, :name=>"There There", :persistentid=>2327229},
|
|
83
|
+
2327267=>{:itemid=>2327267, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>5707428, :name=>"Climbing Up The Walls", :persistentid=>2327267},
|
|
84
|
+
2327305=>{:itemid=>2327305, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4840722, :name=>"Scatterbrain", :persistentid=>2327305},
|
|
85
|
+
2327248=>{:itemid=>2327248, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>4547728, :name=>"I Am A Wicked Child", :persistentid=>2327248},
|
|
86
|
+
2327286=>{:itemid=>2327286, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>4836960, :name=>"Go To Sleep", :persistentid=>2327286},
|
|
87
|
+
2327258=>{:itemid=>2327258, :album=>"2+2=5 CD's", :format=>"mp3", :artist=>"Radiohead", :size=>4930333, :name=>"Remyxomatosis", :persistentid=>2327258},
|
|
88
|
+
2327315=>{:itemid=>2327315, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>3990668, :name=>"2+2=5 (The Lukewarm)", :persistentid=>2327315},
|
|
89
|
+
2327230=>{:itemid=>2327230, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>5163008, :name=>"Backdrifts", :persistentid=>2327230},
|
|
90
|
+
2327268=>{:itemid=>2327268, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>5299397, :name=>"Exit Music (For A Film)", :persistentid=>2327268},
|
|
91
|
+
2327249=>{:itemid=>2327249, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>7450123, :name=>"Remyxomatosis (Cristian Vogel RMX)", :persistentid=>2327249},
|
|
92
|
+
2327287=>{:itemid=>2327287, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>7767272, :name=>"There There", :persistentid=>2327287},
|
|
93
|
+
2327325=>{:itemid=>2327325, :album=>"I Might Be Wrong: Live Recordings", :format=>"mp3", :artist=>"Radiohead", :size=>4552253, :name=>"Like Spinning Plates", :persistentid=>2327325},
|
|
94
|
+
2327240=>{:itemid=>2327240, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>1912832, :name=>"I Will", :persistentid=>2327240},
|
|
95
|
+
2327316=>{:itemid=>2327316, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>5581763, :name=>"Myxomatosis", :persistentid=>2327316},
|
|
96
|
+
2327221=>{:itemid=>2327221, :album=>"There there", :format=>"mp3", :artist=>"Radiohead", :size=>5777028, :name=>"Where bluebirds fly.", :persistentid=>2327221},
|
|
97
|
+
2327259=>{:itemid=>2327259, :album=>"2+2=5 CD's", :format=>"mp3", :artist=>"Radiohead", :size=>7425967, :name=>"There There (demo)", :persistentid=>2327259},
|
|
98
|
+
2327297=>{:itemid=>2327297, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>5389293, :name=>"Where I End And You Begin (The Sky Is Falling In)", :persistentid=>2327297},
|
|
99
|
+
2327269=>{:itemid=>2327269, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>5195935, :name=>"Lucky", :persistentid=>2327269},
|
|
100
|
+
2327307=>{:itemid=>2327307, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>7137199, :name=>"A Punchup At A Wedding", :persistentid=>2327307},
|
|
101
|
+
2327250=>{:itemid=>2327250, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>11222064, :name=>"There there (First demo)", :persistentid=>2327250},
|
|
102
|
+
2327231=>{:itemid=>2327231, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>4749312, :name=>"We Suck Young Blood", :persistentid=>2327231},
|
|
103
|
+
2327260=>{:itemid=>2327260, :album=>"2+2=5 CD's", :format=>"mp3", :artist=>"Radiohead", :size=>4263688, :name=>"Skttrbrain (Four Tet RMX)", :persistentid=>2327260},
|
|
104
|
+
2327298=>{:itemid=>2327298, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>5937853, :name=>"We Suck Young Blood (Your Time Is Up)", :persistentid=>2327298},
|
|
105
|
+
2327251=>{:itemid=>2327251, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>5786001, :name=>"Paperbag Writer", :persistentid=>2327251},
|
|
106
|
+
2327232=>{:itemid=>2327232, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>3393536, :name=>"The Gloaming", :persistentid=>2327232},
|
|
107
|
+
2327270=>{:itemid=>2327270, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>6494227, :name=>"The Tourist", :persistentid=>2327270},
|
|
108
|
+
2327280=>{:itemid=>2327280, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>6201806, :name=>"Sail To The Moon", :persistentid=>2327280},
|
|
109
|
+
2327261=>{:itemid=>2327261, :album=>"2+2=5 CD's", :format=>"mp3", :artist=>"Radiohead", :size=>2158009, :name=>"I will (LA version)", :persistentid=>2327261},
|
|
110
|
+
2327299=>{:itemid=>2327299, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>5089617, :name=>"The Gloaming", :persistentid=>2327299},
|
|
111
|
+
2327242=>{:itemid=>2327242, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>4311040, :name=>"Where I End And You Begin", :persistentid=>2327242},
|
|
112
|
+
2327271=>{:itemid=>2327271, :album=>"OK Computer", :format=>"mp3", :artist=>"Radiohead", :size=>5989015, :name=>"Let Down", :persistentid=>2327271},
|
|
113
|
+
2327233=>{:itemid=>2327233, :album=>"Hail To The Theif", :format=>"mp3", :artist=>"Radiohead", :size=>4161536, :name=>"Sit Down, Stand Up", :persistentid=>2327233},
|
|
114
|
+
2327252=>{:itemid=>2327252, :album=>"Radiohead - HTTT Era B-Sides", :format=>"m4a", :artist=>"Radiohead", :size=>6588253, :name=>"Where Bluebirds Fly", :persistentid=>2327252},
|
|
115
|
+
2327290=>{:itemid=>2327290, :album=>"Hail To The Thief", :format=>"mp3", :artist=>"Radiohead", :size=>7743448, :name=>"Backdrifts", :persistentid=>2327290}}
|
|
116
|
+
assert_equal(hash, songs_hash)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_databases
|
|
120
|
+
# There should be only one database
|
|
121
|
+
assert(true, @daap.databases.length == 1)
|
|
122
|
+
db = @daap.databases[0]
|
|
123
|
+
assert_equal(1, db.persistentid)
|
|
124
|
+
assert_equal('apatterson', db.name)
|
|
125
|
+
assert_equal(4, db.containercount)
|
|
126
|
+
assert_equal(1, db.id)
|
|
127
|
+
assert_equal(68, db.itemcount)
|
|
128
|
+
assert_equal(68, db.songs.length)
|
|
129
|
+
assert(true, db.songs.length == db.itemcount)
|
|
130
|
+
assert_equal(4, db.playlists.length)
|
|
131
|
+
assert(true, db.playlists.length == db.containercount)
|
|
132
|
+
|
|
133
|
+
#@daap.databases.each do |db|
|
|
134
|
+
# puts "All songs in the database"
|
|
135
|
+
# db.songs.each do |song|
|
|
136
|
+
# #puts "#{song.artist} - #{song.name}"
|
|
137
|
+
# end
|
|
138
|
+
#
|
|
139
|
+
# puts "Songs for each playlist"
|
|
140
|
+
# db.playlists.each do |pl|
|
|
141
|
+
# puts "Playlist name: #{pl.name}"
|
|
142
|
+
# pl.songs.each do |song|
|
|
143
|
+
# #puts "#{song.artist} - #{song.name}"
|
|
144
|
+
# end
|
|
145
|
+
# end
|
|
146
|
+
#end
|
|
147
|
+
end
|
|
148
|
+
end
|
data/test/tc_protocol.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'net/daap'
|
|
3
|
+
require 'digest/md5'
|
|
4
|
+
|
|
5
|
+
class DAAPProtocol_Test < Test::Unit::TestCase
|
|
6
|
+
def test_v3
|
|
7
|
+
proto = Net::DAAP::DAAPv3.new
|
|
8
|
+
assert_equal("434EED05046099EA7938EDEE2805E3E8",
|
|
9
|
+
proto.validate("/content-codes", 2))
|
|
10
|
+
assert_equal("77BE0B44D0D6ED1268381859B133B4B9",
|
|
11
|
+
proto.validate("/server-info", 2))
|
|
12
|
+
assert_equal("E3B047FF11C1F845093E898495A585E2",
|
|
13
|
+
proto.validate("/login", 2))
|
|
14
|
+
assert_equal("34370BBBDFC2980C568862AD40DD1F40",
|
|
15
|
+
proto.validate("/databases?session-id=10", 2))
|
|
16
|
+
assert_equal("24BF5D60319039401EE2D8B9FEA571FD",
|
|
17
|
+
proto.validate("/databases/1/items?type=music&meta=dmap.itemid,dmap.itemname,dmap.persistentid,daap.songalbum,daap.songartist,daap.songformat,daap.songsize&session-id=10", 2))
|
|
18
|
+
assert_equal("1A01D5DE1936B3E0B1A1D30D1FE6556C",
|
|
19
|
+
proto.validate("/databases/1/containers?meta=dmap.itemid,dmap.itemname,dmap.persistentid,com.apple.itunes.smart-playlist&session-id=10", 2))
|
|
20
|
+
assert_equal("3B9A624D4CF25AE764F8F241C3BCE362",
|
|
21
|
+
proto.validate("/logout?session-id=10", 2))
|
|
22
|
+
assert_equal("2530C0BC46579EE229338099E0A36CDD",
|
|
23
|
+
proto.validate("/databases/1/items/2327251.m4a?session-id=11", 2, 1))
|
|
24
|
+
assert_equal("B287AD7370CE0F06325F477A591CE488",
|
|
25
|
+
proto.validate("/databases/1/items/2327271.mp3?session-id=11", 2, 2))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_v2
|
|
29
|
+
proto = Net::DAAP::DAAPv2.new
|
|
30
|
+
assert_equal("4FDEE34A22CDA1490A7577750AAF367C",
|
|
31
|
+
proto.validate("/content-codes", 2))
|
|
32
|
+
assert_equal("91DE0B5A5A0C0ACF43228778CC974397",
|
|
33
|
+
proto.validate("/server-info", 2))
|
|
34
|
+
assert_equal("84EF8C938B20B66F5D32FE560E7968ED",
|
|
35
|
+
proto.validate("/login", 2))
|
|
36
|
+
assert_equal("7ECA31ED40E5D4D481156CB6A324A2B7",
|
|
37
|
+
proto.validate("/databases?session-id=15", 2))
|
|
38
|
+
assert_equal("D64E9194DF3242B283944AEC337A4FB1",
|
|
39
|
+
proto.validate("/databases/1/items?type=music&meta=dmap.itemid,dmap.itemname,dmap.persistentid,daap.songalbum,daap.songartist,daap.songformat,daap.songsize&session-id=15", 2))
|
|
40
|
+
assert_equal("44D944FFF6045A1A89FAF91CDB894230",
|
|
41
|
+
proto.validate("/databases/1/containers?meta=dmap.itemid,dmap.itemname,dmap.persistentid,com.apple.itunes.smart-playlist&session-id=15", 2))
|
|
42
|
+
assert_equal("52CD3E871A06BBE4B9BC28B07A7D8F97",
|
|
43
|
+
proto.validate("/databases/1/items/2327251.m4a?session-id=15", 2))
|
|
44
|
+
assert_equal("D4973EACAD71DE9183EE431D74C8436A",
|
|
45
|
+
proto.validate("/databases/1/items/2327271.mp3?session-id=15", 2))
|
|
46
|
+
assert_equal("6DB9B14FAB5A7198B485349B40BB188A",
|
|
47
|
+
proto.validate("/logout?session-id=15", 2))
|
|
48
|
+
end
|
|
49
|
+
end
|