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.
Files changed (81) hide show
  1. data/README +63 -0
  2. data/doc/classes/Net/DAAP/Client.html +251 -0
  3. data/doc/classes/Net/DAAP/Client.src/M000003.html +20 -0
  4. data/doc/classes/Net/DAAP/Client.src/M000004.html +25 -0
  5. data/doc/classes/Net/DAAP/Client.src/M000005.html +33 -0
  6. data/doc/classes/Net/DAAP/Client.src/M000006.html +37 -0
  7. data/doc/classes/Net/DAAP/Client.src/M000007.html +20 -0
  8. data/doc/classes/Net/DAAP/Client.src/M000008.html +24 -0
  9. data/doc/classes/Net/DAAP/DAAPv2.html +165 -0
  10. data/doc/classes/Net/DAAP/DAAPv2.src/M000015.html +30 -0
  11. data/doc/classes/Net/DAAP/DAAPv2.src/M000016.html +21 -0
  12. data/doc/classes/Net/DAAP/DAAPv3.html +178 -0
  13. data/doc/classes/Net/DAAP/DAAPv3.src/M000017.html +30 -0
  14. data/doc/classes/Net/DAAP/DAAPv3.src/M000018.html +23 -0
  15. data/doc/classes/Net/DAAP/DMAP.html +189 -0
  16. data/doc/classes/Net/DAAP/DMAP.src/M000012.html +20 -0
  17. data/doc/classes/Net/DAAP/DMAP.src/M000013.html +18 -0
  18. data/doc/classes/Net/DAAP/DMAP.src/M000014.html +24 -0
  19. data/doc/classes/Net/DAAP/Database.html +224 -0
  20. data/doc/classes/Net/DAAP/Database.src/M000009.html +25 -0
  21. data/doc/classes/Net/DAAP/Database.src/M000010.html +21 -0
  22. data/doc/classes/Net/DAAP/Database.src/M000011.html +35 -0
  23. data/doc/classes/Net/DAAP/Playlist.html +192 -0
  24. data/doc/classes/Net/DAAP/Playlist.src/M000001.html +24 -0
  25. data/doc/classes/Net/DAAP/Playlist.src/M000002.html +30 -0
  26. data/doc/classes/Net/DAAP/Song.html +208 -0
  27. data/doc/classes/Net/DAAP/Song.src/M000019.html +27 -0
  28. data/doc/classes/Net/DAAP/Song.src/M000020.html +19 -0
  29. data/doc/classes/Net/DAAP.html +168 -0
  30. data/doc/classes/Net.html +127 -0
  31. data/doc/created.rid +1 -0
  32. data/doc/files/CHANGELOG.html +110 -0
  33. data/doc/files/LICENSE.html +531 -0
  34. data/doc/files/README.html +176 -0
  35. data/doc/files/lib/net/daap/database_rb.html +101 -0
  36. data/doc/files/lib/net/daap/dmap_rb.html +101 -0
  37. data/doc/files/lib/net/daap/playlist_rb.html +101 -0
  38. data/doc/files/lib/net/daap/song_rb.html +101 -0
  39. data/doc/files/lib/net/daap_rb.html +114 -0
  40. data/doc/fr_class_index.html +35 -0
  41. data/doc/fr_file_index.html +34 -0
  42. data/doc/fr_method_index.html +46 -0
  43. data/doc/index.html +24 -0
  44. data/doc/rdoc-style.css +208 -0
  45. data/lib/CVS/Entries +1 -0
  46. data/lib/CVS/Repository +1 -0
  47. data/lib/CVS/Root +1 -0
  48. data/lib/net/CVS/Entries +2 -0
  49. data/lib/net/CVS/Repository +1 -0
  50. data/lib/net/CVS/Root +1 -0
  51. data/lib/net/daap/CVS/Entries +5 -0
  52. data/lib/net/daap/CVS/Repository +1 -0
  53. data/lib/net/daap/CVS/Root +1 -0
  54. data/lib/net/daap/database.rb +69 -0
  55. data/lib/net/daap/dmap.rb +575 -0
  56. data/lib/net/daap/playlist.rb +36 -0
  57. data/lib/net/daap/song.rb +27 -0
  58. data/lib/net/daap.rb +234 -0
  59. data/test/CVS/Entries +4 -0
  60. data/test/CVS/Repository +1 -0
  61. data/test/CVS/Root +1 -0
  62. data/test/data/CVS/Entries +1 -0
  63. data/test/data/CVS/Repository +1 -0
  64. data/test/data/CVS/Root +1 -0
  65. data/test/data/mt-daapd/079aca35773150da9fd98db10c7fd0c0.txt +0 -0
  66. data/test/data/mt-daapd/2972f65088b42a06b5d3ca089d71791d.txt +0 -0
  67. data/test/data/mt-daapd/440c2217e6207c54c317c296f71f9769.txt +0 -0
  68. data/test/data/mt-daapd/4d1ce9f941cbd823ed06f1f1baa5a3b9.txt +0 -0
  69. data/test/data/mt-daapd/7bded8b540fd082f102d25e181b47bc4.txt +0 -0
  70. data/test/data/mt-daapd/CVS/Entries +11 -0
  71. data/test/data/mt-daapd/CVS/Repository +1 -0
  72. data/test/data/mt-daapd/CVS/Root +1 -0
  73. data/test/data/mt-daapd/b3e894b87111bdba88e4765967f4b45a.txt +0 -0
  74. data/test/data/mt-daapd/d56b699830e77ba53855679cb1d252da.txt +0 -0
  75. data/test/data/mt-daapd/e61ce3062cb76770658896b778ad06cd.txt +0 -0
  76. data/test/data/mt-daapd/e9a8e709c2116651157182f130207048.txt +0 -0
  77. data/test/data/mt-daapd/f9073959a0afacebfab7e3bf19c2714a.txt +0 -0
  78. data/test/tc_client.rb +148 -0
  79. data/test/tc_protocol.rb +49 -0
  80. data/test/ts_daap.rb +6 -0
  81. 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
@@ -0,0 +1,4 @@
1
+ /tc_client.rb/1.1.1.1/Wed Dec 7 23:25:52 2005//
2
+ /tc_protocol.rb/1.1.1.1/Wed Dec 7 23:25:52 2005//
3
+ /ts_daap.rb/1.1.1.1/Wed Dec 7 23:25:52 2005//
4
+ D/data////
@@ -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
@@ -0,0 +1 @@
1
+ :ext:aaronp@rubyforge.org:/var/cvs/daapclient
@@ -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
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
@@ -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
data/test/ts_daap.rb ADDED
@@ -0,0 +1,6 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), "..", "lib")
2
+
3
+ require 'test/unit'
4
+ require 'tc_client'
5
+ require 'tc_protocol'
6
+