dmap 0.1.6 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/Rakefile +1 -1
  2. data/lib/dmap.rb +214 -205
  3. metadata +2 -2
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "dmap"
8
- gem.version = "0.1.6"
8
+ gem.version = "0.2.1"
9
9
  gem.summary = %Q{Parses Apple's DMAP strings (4-byte serialization method)}
10
10
  gem.description = %Q{Apple uses a system of serialization (I think its called dmap…) where a 4-byte string tells of the information following, both its type and what it represents. Its used in the DAAP (Protocol), QuickTime mov structure and doubtless many other places.}
11
11
  gem.email = "jphastings@gmail.com"
@@ -20,18 +20,18 @@ module DMAP
20
20
  #
21
21
  # NB. if you specify `content` while passing a dmap tag you will overwrite anything
22
22
  # that was in the dmap!
23
- def initialize(tag_or_dmap,new_content = nil)
23
+ def initialize(tag_or_dmap,new_content = nil)
24
24
  # Assume we have an IO object, if this fails then we probably have a string instead
25
25
  begin
26
- @tag = tag_or_dmap.read(4).upcase
26
+ @tag = tag_or_dmap.read(4)
27
27
  @io = tag_or_dmap if new_content.nil?
28
28
  rescue NoMethodError
29
- @tag = tag_or_dmap[0..3].upcase
29
+ @tag = tag_or_dmap[0..3]
30
30
  end
31
31
 
32
32
  # Find out the details of this tag
33
33
  begin
34
- type,@name = DMAP.const_get(@tag)
34
+ @name,type = DMAP::TAGS[@tag.to_sym]
35
35
  rescue NameError
36
36
  raise NameError, "I don't know how to interpret the tag '#{@tag}'. Please extend the DMAP module!"
37
37
  end
@@ -62,7 +62,12 @@ module DMAP
62
62
 
63
63
  # Adds the tag to a request to create the dmap
64
64
  def to_dmap
65
- "#{@tag.downcase}#{@real_class.to_dmap}"
65
+ begin
66
+ "#{@tag.downcase}#{@real_class.to_dmap}"
67
+ rescue
68
+ warn("Error while putting #{@tag} to dmap")
69
+ raise
70
+ end
66
71
  end
67
72
 
68
73
  private
@@ -79,27 +84,43 @@ module DMAP
79
84
  @real_class = Array.new(content || @io || [])
80
85
  end
81
86
 
82
- def parse_number(content,signed = false)
87
+ def parse_byte(content)
83
88
  begin
84
- if not content.nil? and content.is_a? Numeric
85
- @real_class = MeasuredInteger.new(content,nil,signed)
86
- elsif not content.nil? and (content[0].is_a? Numeric and content[1].is_a? Numeric)
87
- @real_class = MeasuredInteger.new(content[0],content[1],signed)
88
- else
89
- box_size = @io.read(4).unpack("N")[0]
90
- case box_size
91
- when 1,2,4
92
- num = @io.read(box_size).unpack(MeasuredInteger.pack_code(box_size,signed))[0]
93
- when 8
94
- num = @io.read(box_size).unpack("NN")
95
- num = num[0]*65536 + num[1]
96
- else
97
- raise "I don't know how to unpack an integer #{box_size} bytes long"
98
- end
99
- @real_class = MeasuredInteger.new(num,box_size,signed)
100
- end
89
+ @real_class = MeasuredInteger.new(@io.read(@io.read(4).unpack("N")[0]).unpack("C")[0],1,false)
101
90
  rescue NoMethodError
102
- @real_class = MeasuredInteger.new(0,0,signed)
91
+ @real_class = MeasuredInteger.new(content || 0,1,false)
92
+ end
93
+ end
94
+
95
+ def parse_short(content)
96
+ begin
97
+ @real_class = MeasuredInteger.new(@io.read(@io.read(4).unpack("N")[0]).unpack("n")[0],2,false)
98
+ rescue NoMethodError
99
+ @real_class = MeasuredInteger.new(content || 0,2,false)
100
+ end
101
+ end
102
+
103
+ def parse_integer(content)
104
+ begin
105
+ @real_class = MeasuredInteger.new(@io.read(@io.read(4).unpack("N")[0]).unpack("N")[0],4,false) # Use L?
106
+ rescue NoMethodError
107
+ @real_class = MeasuredInteger.new(content || 0,4,false)
108
+ end
109
+ end
110
+
111
+ def parse_long(content)
112
+ begin
113
+ @real_class = MeasuredInteger.new(@io.read(@io.read(4).unpack("N")[0]).unpack("Q")[0],8,false)
114
+ rescue NoMethodError
115
+ @real_class = MeasuredInteger.new(content || 0,8,false)
116
+ end
117
+ end
118
+
119
+ def parse_signed_integer(content)
120
+ begin
121
+ @real_class = MeasuredInteger.new(@io.read(@io.read(4).unpack("N")[0]).unpack("l")[0],4,true)
122
+ rescue NoMethodError
123
+ @real_class = MeasuredInteger.new(content || 0,4,true)
103
124
  end
104
125
  end
105
126
 
@@ -107,9 +128,9 @@ module DMAP
107
128
  def parse_version(content)
108
129
  begin
109
130
  # FIXME: Are version numbers x.y ?
110
- @real_class = Version.new(@io.read(@io.read(4).unpack("N")[0]).unpack("nn").join("."))
131
+ @real_class = Version.new(@io.read(@io.read(4).unpack("N")[0]).unpack("CCCC").join("."))
111
132
  rescue NoMethodError
112
- @real_class = Version.new(content || "1.0")
133
+ @real_class = Version.new(content || "0.1.0.0")
113
134
  end
114
135
  end
115
136
 
@@ -120,10 +141,6 @@ module DMAP
120
141
  @real_class = Time.now
121
142
  end
122
143
  end
123
-
124
- def parse_signed(content)
125
- parse_number(content,true)
126
- end
127
144
  end
128
145
 
129
146
  # We may not always want to parse an entire DMAP in one go, here we extend Array so that
@@ -150,7 +167,6 @@ module DMAP
150
167
  @dmap_io = array_or_io
151
168
  @dmap_start = @dmap_io.tell
152
169
  @unparsed_data = true
153
- parse_dmap if @@parse_immediately
154
170
  rescue NoMethodError
155
171
  begin
156
172
  array_or_io.each do |element|
@@ -165,6 +181,7 @@ module DMAP
165
181
  @unparsed_data = false
166
182
  end
167
183
 
184
+ parse_dmap if @@parse_immediately
168
185
  end
169
186
 
170
187
  [:==, :===, :=~, :clone, :display, :dup, :enum_for, :eql?, :equal?, :hash, :to_a, :to_enum, :each, :length].each do |method_name|
@@ -220,56 +237,46 @@ module DMAP
220
237
  attr_reader :value
221
238
  attr_accessor :box_size, :binary, :signed
222
239
 
223
- def initialize(value,wanted_box_size = nil,signed = false)
224
- @value = value
225
- @binary = (box_size == 1)
226
- self.box_size = wanted_box_size
240
+ def initialize(value,box_size = 1,signed = false)
241
+ @value = value.to_i
242
+ @box_size = box_size
227
243
  @signed = signed
228
244
  end
229
245
 
230
- # Will set the box size to the largest value of the one you specify and the maximum needed for the
231
- # current value.
232
- def box_size=(wanted_box_size)
233
- # Find the smallest number of bytes needed to express this number
234
- @box_size = [wanted_box_size || 0,(Math.log((Math.log(@value) / 2.07944154167984).ceil)/0.693147180559945).ceil].max rescue 1 # For when value = 0
235
- end
236
-
237
- def to_dmap
246
+ def to_dmap # TODO: Tidy me
238
247
  case @box_size
239
248
  when 1,2,4,8
240
- [@box_size,@value].pack("N"<<MeasuredInteger.pack_code(@box_size,@signed))
249
+ [@box_size,@value].pack("N"<<pack_code)
241
250
  else
242
251
  raise "I don't know how to unpack an integer #{@box_size} bytes long"
243
252
  end
244
253
  end
245
254
 
246
- def self.pack_code(length,signed)
247
- out = {1=>"C",-1=>"c",2=>"n",4=>"N",8=>"Q",-8=>"q"}[length * (signed ? -1 : 1)] # FIXME: pack codes for all signed cases
248
- return out
255
+ def pack_code
256
+ {1=>"C",-1=>"c",2=>"n",4=>"N",8=>"Q",-8=>"q"}[@box_size * (@signed ? -1 : 1)] # FIXME: pack codes for all signed cases
249
257
  end
250
258
 
251
259
  def inspect
252
- # This is a bit of a guess, no change to the data, just helps inspection
253
- return (@value == 1) ? "true" : "false" if @binary
254
260
  @value
255
261
  end
256
262
  end
257
263
 
258
264
  # A class to store version numbers
259
265
  class Version
260
- def initialize(version = "1.0")
261
- @major,@minor = (version.to_s<<".0").split(".").collect{|n| n.to_i }
262
- if @major > 63 or @minor > 63
263
- raise RangeError "Neither major nor minor version numbers can be above 63. Surely that's enough?"
266
+ attr_accessor :maximus,:major,:minor,:minimus
267
+ def initialize(version = "0.1.0.0")
268
+ @maximus,@major,@minor,@minimus = (version.to_s<<".0.0.0").split(".").collect{|n| n.to_i }
269
+ if @maximus > 255 or @major > 255 or @minor > 255 or @minimus > 255
270
+ raise RangeError "None of the version points can be above 255. Surely that's enough?"
264
271
  end
265
272
  end
266
273
 
267
274
  def to_dmap
268
- "\000\000\000\004"<<[@major,@minor].pack("nn")
275
+ "\000\000\000\004"<<[@maximus,@major,@minor,@minimus].pack("CCCC")
269
276
  end
270
277
 
271
278
  def inspect
272
- "v#{@major}.#{@minor}"
279
+ "v#{@maximus}.#{@major}.#{@minor}.#{@minimus}"
273
280
  end
274
281
  end
275
282
 
@@ -287,154 +294,156 @@ module DMAP
287
294
  end
288
295
  end
289
296
 
290
- #F�CH = [:number, 'dmap.haschildcontainers']
291
- ABAL = [:list, 'daap.browsealbumlisting']
292
- ABAR = [:list, 'daap.browseartistlisting']
293
- ABCP = [:list, 'daap.browsecomposerlisting']
294
- ABGN = [:list, 'daap.browsegenrelisting']
295
- ABPL = [:number, 'daap.baseplaylist']
296
- ABRO = [:list, 'daap.databasebrowse']
297
- ADBS = [:list, 'daap.databasesongs']
298
- AEAI = [:number, 'com.apple.itunes.itms-artistid']
299
- AECI = [:number, 'com.apple.itunes.itms-composerid']
300
- AECR = [:string, 'com.apple.itunes.content-rating']
301
- AEEN = [:string, 'com.apple.itunes.episode-num-str']
302
- AEES = [:number, 'com.apple.itunes.episode-sort']
303
- AEFP = [:number, 'com.apple.itunes.req-fplay']
304
- AEGD = [:number, 'com.apple.itunes.gapless-enc-dr']
305
- AEGE = [:number, 'com.apple.itunes.gapless-enc-del']
306
- AEGH = [:number, 'com.apple.itunes.gapless-heur']
307
- AEGI = [:number, 'com.apple.itunes.itms-genreid']
308
- AEGR = [:number, 'com.apple.itunes.gapless-resy']
309
- AEGU = [:number, 'com.apple.itunes.gapless-dur']
310
- AEHD = [:number, 'com.apple.itunes.is-hd-video']
311
- AEHV = [:number, 'com.apple.itunes.has-video']
312
- AEMK = [:number, 'com.apple.itunes.mediakind']
313
- AENN = [:string, 'com.apple.itunes.network-name']
314
- AENV = [:number, 'com.apple.itunes.norm-volume']
315
- AEPC = [:number, 'com.apple.itunes.is-podcast']
316
- AEPI = [:number, 'com.apple.itunes.itms-playlistid']
317
- AEPP = [:number, 'com.apple.itunes.is-podcast-playlist']
318
- AEPS = [:number, 'com.apple.itunes.special-playlist']
319
- AESF = [:number, 'com.apple.itunes.itms-storefrontid']
320
- AESG = [:number, 'com.apple.itunes.saved-genius']
321
- AESI = [:number, 'com.apple.itunes.itms-songid']
322
- AESN = [:string, 'com.apple.itunes.series-name']
323
- AESP = [:number, 'com.apple.itunes.smart-playlist']
324
- AESU = [:number, 'com.apple.itunes.season-num']
325
- AESV = [:number, 'com.apple.itunes.music-sharing-version']
326
- AGRP = [:string, 'daap.songgrouping']
327
- APLY = [:list, 'daap.databaseplaylists']
328
- APRM = [:number, 'daap.playlistrepeatmode']
329
- APRO = [:version,'daap.protocolversion']
330
- APSM = [:number, 'daap.playlistshufflemode']
331
- APSO = [:list, 'daap.playlistsongs']
332
- ARIF = [:list, 'daap.resolveinfo']
333
- ARSV = [:list, 'daap.resolve']
334
- ASAA = [:string, 'daap.songalbumartist']
335
- ASAI = [:number, 'daap.songalbumid']
336
- ASAL = [:string, 'daap.songalbum']
337
- ASAR = [:string, 'daap.songartist']
338
- ASBK = [:number, 'daap.bookmarkable']
339
- ASBO = [:number, 'daap.songbookmark']
340
- ASBR = [:number, 'daap.songbitrate']
341
- ASBT = [:number, 'daap.songbeatsperminute']
342
- ASCD = [:number, 'daap.songcodectype']
343
- ASCM = [:string, 'daap.songcomment']
344
- ASCN = [:string, 'daap.songcontentdescription']
345
- ASCO = [:number, 'daap.songcompilation']
346
- ASCP = [:string, 'daap.songcomposer']
347
- ASCR = [:number, 'daap.songcontentrating']
348
- ASCS = [:number, 'daap.songcodecsubtype']
349
- ASCT = [:string, 'daap.songcategory']
350
- ASDA = [:time, 'daap.songdateadded']
351
- ASDB = [:number, 'daap.songdisabled']
352
- ASDC = [:number, 'daap.songdisccount']
353
- ASDK = [:number, 'daap.songdatakind']
354
- ASDM = [:time, 'daap.songdatemodified']
355
- ASDN = [:number, 'daap.songdiscnumber']
356
- ASDP = [:time, 'daap.songdatepurchased']
357
- ASDR = [:time, 'daap.songdatereleased']
358
- ASDT = [:string, 'daap.songdescription']
359
- ASED = [:number, 'daap.songextradata']
360
- ASEQ = [:string, 'daap.songeqpreset']
361
- ASFM = [:string, 'daap.songformat']
362
- ASGN = [:string, 'daap.songgenre']
363
- ASGP = [:number, 'daap.songgapless']
364
- ASHP = [:number, 'daap.songhasbeenplayed']
365
- ASKY = [:string, 'daap.songkeywords']
366
- ASLC = [:string, 'daap.songlongcontentdescription']
367
- ASLS = [:number, 'daap.songlongsize']
368
- ASPU = [:string, 'daap.songpodcasturl']
369
- ASRV = [:signed, 'daap.songrelativevolume']
370
- ASSA = [:string, 'daap.sortartist']
371
- ASSC = [:string, 'daap.sortcomposer']
372
- ASSL = [:string, 'daap.sortalbumartist']
373
- ASSN = [:string, 'daap.sortname']
374
- ASSP = [:number, 'daap.songstoptime']
375
- ASSR = [:number, 'daap.songsamplerate']
376
- ASSS = [:string, 'daap.sortseriesname']
377
- ASST = [:number, 'daap.songstarttime']
378
- ASSU = [:string, 'daap.sortalbum']
379
- ASSZ = [:number, 'daap.songsize']
380
- ASTC = [:number, 'daap.songtrackcount']
381
- ASTM = [:number, 'daap.songtime']
382
- ASTN = [:number, 'daap.songtracknumber']
383
- ASUL = [:string, 'daap.songdataurl']
384
- ASUR = [:number, 'daap.songuserrating']
385
- ASYR = [:number, 'daap.songyear']
386
- ATED = [:number, 'daap.supportsextradata']
387
- AVDB = [:list, 'daap.serverdatabases']
388
- CEJC = [:signed, 'com.apple.itunes.jukebox-client-vote']
389
- CEJI = [:number, 'com.apple.itunes.jukebox-current']
390
- CEJS = [:signed, 'com.apple.itunes.jukebox-score']
391
- CEJV = [:number, 'com.apple.itunes.jukebox-vote']
392
- MBCL = [:list, 'dmap.bag']
393
- MCCR = [:list, 'dmap.contentcodesresponse']
394
- MCNA = [:string, 'dmap.contentcodesname']
395
- MCNM = [:number, 'dmap.contentcodesnumber']
396
- MCON = [:list, 'dmap.container']
397
- MCTC = [:number, 'dmap.containercount']
398
- MCTI = [:number, 'dmap.containeritemid']
399
- MCTY = [:number, 'dmap.contentcodestype']
400
- MDCL = [:list, 'dmap.dictionary']
401
- MEDS = [:number, 'dmap.editcommandssupported']
402
- MIID = [:number, 'dmap.itemid']
403
- MIKD = [:number, 'dmap.itemkind']
404
- MIMC = [:number, 'dmap.itemcount']
405
- MINM = [:string, 'dmap.itemname']
406
- MLCL = [:list, 'dmap.listing']
407
- MLID = [:number, 'dmap.sessionid']
408
- MLOG = [:list, 'dmap.loginresponse']
409
- MPCO = [:number, 'dmap.parentcontainerid']
410
- MPER = [:number, 'dmap.persistentid']
411
- MPRO = [:version,'dmap.protocolversion']
412
- MRCO = [:number, 'dmap.returnedcount']
413
- MSAL = [:number, 'dmap.supportsautologout']
414
- MSAS = [:number, 'dmap.authenticationschemes']
415
- MSAU = [:number, 'dmap.authenticationmethod']
416
- MSBR = [:number, 'dmap.supportsbrowse']
417
- MSDC = [:number, 'dmap.databasescount']
418
- MSED = [:number, 'unknown_msed']
419
- MSEX = [:number, 'dmap.supportsextensions']
420
- MSIX = [:number, 'dmap.supportsindex']
421
- MSLR = [:number, 'dmap.loginrequired']
422
- MSMA = [:number, 'unknown_msma']
423
- MSML = [:list, 'unknown_msml']
424
- MSPI = [:number, 'dmap.supportspersistentids']
425
- MSQY = [:number, 'dmap.supportsquery']
426
- MSRS = [:number, 'dmap.supportsresolve']
427
- MSRV = [:list, 'dmap.serverinforesponse']
428
- MSTC = [:time, 'dmap.utctime']
429
- MSTM = [:number, 'dmap.timeoutinterval']
430
- MSTO = [:signed, 'dmap.utcoffset']
431
- MSTS = [:string, 'dmap.statusstring']
432
- MSTT = [:number, 'dmap.status']
433
- MSUP = [:number, 'dmap.supportsupdate']
434
- MTCO = [:number, 'dmap.specifiedtotalcount']
435
- MUDL = [:list, 'dmap.deletedidlisting']
436
- MUPD = [:list, 'dmap.updateresponse']
437
- MUSR = [:number, 'dmap.serverrevision']
438
- MUTY = [:number, 'dmap.updatetype']
439
- MLIT = [:list, 'dmap.listingitem']
297
+ TAGS = {
298
+ :abal => ['daap.browsealbumlisting', :list],
299
+ :abar => ['daap.browseartistlisting', :list],
300
+ :abcp => ['daap.browsecomposerlisting', :list],
301
+ :abgn => ['daap.browsegenrelisting', :list],
302
+ :abpl => ['daap.baseplaylist', :byte],
303
+ :abro => ['daap.databasebrowse', :list],
304
+ :adbs => ['daap.databasesongs', :list],
305
+ :aeAI => ['com.apple.itunes.itms-artistid', :integer],
306
+ :aeCI => ['com.apple.itunes.itms-composerid', :integer],
307
+ :aeCR => ['com.apple.itunes.content-rating', :string],
308
+ :aeEN => ['com.apple.itunes.episode-num-str', :string],
309
+ :aeES => ['com.apple.itunes.episode-sort', :integer],
310
+ :aeFP => ['com.apple.itunes.req-fplay', :byte],
311
+ :aeGU => ['com.apple.itunes.gapless-dur', :long],
312
+ :aeGD => ['com.apple.itunes.gapless-enc-dr', :integer],
313
+ :aeGE => ['com.apple.itunes.gapless-enc-del', :integer],
314
+ :aeGH => ['com.apple.itunes.gapless-heur', :integer],
315
+ :aeGI => ['com.apple.itunes.itms-genreid', :integer],
316
+ :aeGR => ['com.apple.itunes.gapless-resy', :long],
317
+ :aeHD => ['com.apple.itunes.is-hd-video', :byte],
318
+ :aeHV => ['com.apple.itunes.has-video', :byte],
319
+ :aeMK => ['com.apple.itunes.mediakind', :byte],
320
+ :aeNN => ['com.apple.itunes.network-name', :string],
321
+ :aeNV => ['com.apple.itunes.norm-volume', :integer],
322
+ :aePC => ['com.apple.itunes.is-podcast', :byte],
323
+ :aePI => ['com.apple.itunes.itms-playlistid', :integer],
324
+ :aePP => ['com.apple.itunes.is-podcast-playlist', :byte],
325
+ :aePS => ['com.apple.itunes.special-playlist', :byte],
326
+ :aeSU => ['com.apple.itunes.season-num', :integer],
327
+ :aeSF => ['com.apple.itunes.itms-storefrontid', :integer],
328
+ :aeSG => ['com.apple.itunes.saved-genius', :byte],
329
+ :aeSI => ['com.apple.itunes.itms-songid', :integer],
330
+ :aeSN => ['com.apple.itunes.series-name', :string],
331
+ :aeSP => ['com.apple.itunes.smart-playlist', :byte],
332
+ :aeSV => ['com.apple.itunes.music-sharing-version', :integer],
333
+ :agrp => ['daap.songgrouping', :string],
334
+ :aply => ['daap.databaseplaylists', :list],
335
+ :aprm => ['daap.playlistrepeatmode', :byte],
336
+ :apro => ['daap.protocolversion', :version],
337
+ :apsm => ['daap.playlistshufflemode', :byte],
338
+ :apso => ['daap.playlistsongs', :list],
339
+ :arif => ['daap.resolveinfo', :list],
340
+ :arsv => ['daap.resolve', :list],
341
+ :asaa => ['daap.songalbumartist', :string],
342
+ :asai => ['daap.songalbumid', :long],
343
+ :asal => ['daap.songalbum', :string],
344
+ :asar => ['daap.songartist', :string],
345
+ :asbk => ['daap.bookmarkable', :byte],
346
+ :asbo => ['daap.songbookmark', :integer],
347
+ :asbr => ['daap.songbitrate', :short],
348
+ :asbt => ['daap.songbeatsperminute', :short],
349
+ :ascd => ['daap.songcodectype', :integer],
350
+ :ascm => ['daap.songcomment', :string],
351
+ :ascn => ['daap.songcontentdescription', :string],
352
+ :asco => ['daap.songcompilation', :byte],
353
+ :ascp => ['daap.songcomposer', :string],
354
+ :ascr => ['daap.songcontentrating', :byte],
355
+ :ascs => ['daap.songcodecsubtype', :integer],
356
+ :asct => ['daap.songcategory', :string],
357
+ :asda => ['daap.songdateadded', :time],
358
+ :asdb => ['daap.songdisabled', :byte],
359
+ :asdc => ['daap.songdisccount', :short],
360
+ :asdk => ['daap.songdatakind', :byte],
361
+ :asdm => ['daap.songdatemodified', :time],
362
+ :asdn => ['daap.songdiscnumber', :short],
363
+ :asdp => ['daap.songdatepurchased', :time],
364
+ :asdr => ['daap.songdatereleased', :time],
365
+ :asdt => ['daap.songdescription', :string],
366
+ :ased => ['daap.songextradata', :short],
367
+ :aseq => ['daap.songeqpreset', :string],
368
+ :asfm => ['daap.songformat', :string],
369
+ :asgn => ['daap.songgenre', :string],
370
+ :asgp => ['daap.songgapless', :byte],
371
+ :ashp => ['daap.songhasbeenplayed', :byte],
372
+ :asky => ['daap.songkeywords', :string],
373
+ :aslc => ['daap.songlongcontentdescription', :string],
374
+ :asls => ['daap.songlongsize', :long],
375
+ :aspu => ['daap.songpodcasturl', :string],
376
+ :asrv => ['daap.songrelativevolume', :signed_byte],
377
+ :assu => ['daap.sortalbum', :string],
378
+ :assa => ['daap.sortartist', :string],
379
+ :assc => ['daap.sortcomposer', :string],
380
+ :assl => ['daap.sortalbumartist', :string],
381
+ :assn => ['daap.sortname', :string],
382
+ :assp => ['daap.songstoptime', :integer],
383
+ :assr => ['daap.songsamplerate', :integer],
384
+ :asss => ['daap.sortseriesname', :string],
385
+ :asst => ['daap.songstarttime', :integer],
386
+ :assz => ['daap.songsize', :integer],
387
+ :astc => ['daap.songtrackcount', :short],
388
+ :astm => ['daap.songtime', :integer],
389
+ :astn => ['daap.songtracknumber', :short],
390
+ :asul => ['daap.songdataurl', :string],
391
+ :asur => ['daap.songuserrating', :byte],
392
+ :asyr => ['daap.songyear', :short],
393
+ :ated => ['daap.supportsextradata', :short],
394
+ :avdb => ['daap.serverdatabases', :list],
395
+ :ceJC => ['com.apple.itunes.jukebox-client-vote', :signed_byte],
396
+ :ceJI => ['com.apple.itunes.jukebox-current', :integer],
397
+ :ceJS => ['com.apple.itunes.jukebox-score', :signed_short],
398
+ :ceJV => ['com.apple.itunes.jukebox-vote', :integer],
399
+ :"f\215ch" => ['dmap.haschildcontainers', :byte],
400
+ :mbcl => ['dmap.bag', :list],
401
+ :mccr => ['dmap.contentcodesresponse', :list],
402
+ :mcna => ['dmap.contentcodesname', :string],
403
+ :mcnm => ['dmap.contentcodesnumber', :integer],
404
+ :mcon => ['dmap.container', :list],
405
+ :mctc => ['dmap.containercount', :integer],
406
+ :mcti => ['dmap.containeritemid', :integer],
407
+ :mcty => ['dmap.contentcodestype', :short],
408
+ :mdcl => ['dmap.dictionary', :list],
409
+ :meds => ['dmap.editcommandssupported', :integer],
410
+ :miid => ['dmap.itemid', :integer],
411
+ :mikd => ['dmap.itemkind', :byte],
412
+ :mimc => ['dmap.itemcount', :integer],
413
+ :minm => ['dmap.itemname', :string],
414
+ :mlcl => ['dmap.listing', :list],
415
+ :mlid => ['dmap.sessionid', :integer],
416
+ :mlit => ['dmap.listingitem', :list],
417
+ :mlog => ['dmap.loginresponse', :list],
418
+ :mpco => ['dmap.parentcontainerid', :integer],
419
+ :mper => ['dmap.persistentid', :long],
420
+ :mpro => ['dmap.protocolversion', :version],
421
+ :mrco => ['dmap.returnedcount', :integer],
422
+ :msau => ['dmap.authenticationmethod', :byte],
423
+ :msal => ['dmap.supportsautologout', :byte],
424
+ :msas => ['dmap.authenticationschemes', :integer],
425
+ :msbr => ['dmap.supportsbrowse', :byte],
426
+ :msdc => ['dmap.databasescount', :integer],
427
+ :msed => ['unknown_msed', :byte], # TODO: Figure out what these are for
428
+ :msex => ['dmap.supportsextensions', :byte],
429
+ :msix => ['dmap.supportsindex', :byte],
430
+ :mslr => ['dmap.loginrequired', :byte],
431
+ :msma => ['unknown_msma', :long],
432
+ :msml => ['unknown_msml', :list],
433
+ :mspi => ['dmap.supportspersistentids', :byte],
434
+ :msqy => ['dmap.supportsquery', :byte],
435
+ :msrs => ['dmap.supportsresolve', :byte],
436
+ :msrv => ['dmap.serverinforesponse', :list],
437
+ :mstc => ['dmap.utctime', :time],
438
+ :mstm => ['dmap.timeoutinterval', :integer],
439
+ :msto => ['dmap.utcoffset', :signed_integer],
440
+ :msts => ['dmap.statusstring', :string],
441
+ :mstt => ['dmap.status', :integer],
442
+ :msup => ['dmap.supportsupdate', :byte],
443
+ :mtco => ['dmap.specifiedtotalcount', :integer],
444
+ :mudl => ['dmap.deletedidlisting', :list],
445
+ :mupd => ['dmap.updateresponse', :list],
446
+ :musr => ['dmap.serverrevision', :integer],
447
+ :muty => ['dmap.updatetype', :byte],
448
+ }
440
449
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dmap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Hastings-Spital
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-06 00:00:00 +00:00
12
+ date: 2009-11-07 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency