dmap 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +4 -3
- data/Rakefile +1 -1
- data/lib/dmap.rb +13 -20
- metadata +1 -1
data/README.rdoc
CHANGED
@@ -24,11 +24,12 @@ We all love examples, so here's an example of how to use this module:
|
|
24
24
|
# => <MSRV: [<MINM: "I'm a string!">]>
|
25
25
|
|
26
26
|
# Or write out what you want in code:
|
27
|
-
|
28
|
-
|
27
|
+
d = DMAP::Element.new("msrv",[DMAP::Element.new('minm',"I'm a string!")])
|
28
|
+
p d
|
29
29
|
# => <MSRV: [<MINM: "I'm a string!">]>
|
30
30
|
|
31
|
-
# All DMAP elements act like their Ruby counterparts
|
31
|
+
# All DMAP elements act like their Ruby counterparts
|
32
|
+
# (I've ballsed this up a little, functions taking blocks are playing up):
|
32
33
|
d.push(DMAP::Element.new('asdm'))
|
33
34
|
|
34
35
|
# They can also be pre-populated with data of an appropriate type
|
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.
|
8
|
+
gem.version = "0.1.4"
|
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"
|
data/lib/dmap.rb
CHANGED
@@ -9,8 +9,7 @@ module DMAP
|
|
9
9
|
# Represents any DMAP tag and its content.
|
10
10
|
# Will have methods appropriate to the dmap specified
|
11
11
|
class Element
|
12
|
-
attr_reader :
|
13
|
-
attr_reader :name
|
12
|
+
attr_reader :tag
|
14
13
|
attr_reader :real_class
|
15
14
|
|
16
15
|
# Accepts a string or an IO. The first four bytes (in either case) should be the
|
@@ -25,7 +24,6 @@ module DMAP
|
|
25
24
|
# Assume we have an IO object, if this fails then we probably have a string instead
|
26
25
|
begin
|
27
26
|
@tag = tag_or_dmap.read(4).upcase
|
28
|
-
@unparsed_content = true
|
29
27
|
@io = tag_or_dmap if new_content.nil?
|
30
28
|
rescue NoMethodError
|
31
29
|
@tag = tag_or_dmap[0..3].upcase
|
@@ -144,7 +142,7 @@ module DMAP
|
|
144
142
|
original_new
|
145
143
|
begin
|
146
144
|
# Lets assume its an io
|
147
|
-
@dmap_length = array_or_io.read(4).unpack("N")[0]
|
145
|
+
@dmap_length = array_or_io.read(4).unpack("N")[0]
|
148
146
|
@dmap_io = array_or_io
|
149
147
|
@dmap_start = @dmap_io.tell
|
150
148
|
@unparsed_data = true
|
@@ -152,7 +150,11 @@ module DMAP
|
|
152
150
|
rescue NoMethodError
|
153
151
|
begin
|
154
152
|
array_or_io.each do |element|
|
155
|
-
|
153
|
+
if element.is_a? DMAP::Element
|
154
|
+
self.push element
|
155
|
+
else
|
156
|
+
raise "Thisneeds to be a DMAP::Element. #{element.inspect}"
|
157
|
+
end
|
156
158
|
end
|
157
159
|
rescue NoMethodError
|
158
160
|
end
|
@@ -208,6 +210,8 @@ module DMAP
|
|
208
210
|
end
|
209
211
|
|
210
212
|
# Allows people to specify a integer and the size of the binary representation required
|
213
|
+
#
|
214
|
+
# If you create one with a wanted_box_size that's not 1,2,4,8 you'll run into trouble elsewhere (most likely)
|
211
215
|
class MeasuredInteger
|
212
216
|
attr_reader :value
|
213
217
|
attr_accessor :box_size, :binary, :signed
|
@@ -223,22 +227,20 @@ module DMAP
|
|
223
227
|
# current value.
|
224
228
|
def box_size=(wanted_box_size)
|
225
229
|
# Find the smallest number of bytes needed to express this number
|
226
|
-
@box_size = [wanted_box_size || 0,(Math.log(@value) / 2.07944154167984).ceil].max rescue
|
230
|
+
@box_size = [wanted_box_size || 0,(Math.log(@value) / 2.07944154167984).ceil].max rescue 1 # For when value = 0
|
227
231
|
end
|
228
232
|
|
229
233
|
def to_dmap
|
230
234
|
case @box_size
|
231
|
-
when 1,2,4
|
235
|
+
when 1,2,4,8
|
232
236
|
[@box_size,@value].pack("N"<<MeasuredInteger.pack_code(@box_size,@signed))
|
233
|
-
when 8
|
234
|
-
[@box_size,@value / 65536,@value % 65536].pack((@signed) ? "Nll" : "NNN") # FIXME: How do you do signed version :S
|
235
237
|
else
|
236
238
|
raise "I don't know how to unpack an integer #{@box_size} bytes long"
|
237
239
|
end
|
238
240
|
end
|
239
241
|
|
240
242
|
def self.pack_code(length,signed)
|
241
|
-
out = {1=>"C",2=>"S",4=>"N"}[length]
|
243
|
+
out = {1=>"C",2=>"S",4=>"N",8=>"Q"}[length] # FIXME: Lower case N won't work!
|
242
244
|
out.downcase if signed
|
243
245
|
return out
|
244
246
|
end
|
@@ -426,13 +428,4 @@ module DMAP
|
|
426
428
|
CEJS = [:signed, 'com.apple.itunes.jukebox-score']
|
427
429
|
ASDM = [:time, 'daap.songdatemodified']
|
428
430
|
AESF = [:number, 'com.apple.itunes.itms-storefrontid']
|
429
|
-
end
|
430
|
-
|
431
|
-
d = DMAP::Element.new("msrv",[DMAP::Element.new('minm',"I'm a string!")])
|
432
|
-
p d
|
433
|
-
# All DMAP elements act like their Ruby counterparts:
|
434
|
-
d.push(DMAP::Element.new('asdm'))
|
435
|
-
# They can also be pre-populated with data of an appropriate type
|
436
|
-
d.push(DMAP::Element.new('astm',123))
|
437
|
-
p d
|
438
|
-
# => <MSRV: [<MINM: "I'm a string!">, <ASDM: Fri Nov 06 11:18:29 +0000 2009>, <ASTM: 123>]>
|
431
|
+
end
|