dacpclient 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,86 +1,40 @@
1
- require 'dacpclient/tagdefinitions'
1
+ require 'dacpclient/tag_definitions'
2
2
  require 'dacpclient/dmapconverter'
3
3
 
4
4
  require 'stringio'
5
5
  module DACPClient
6
- module DMAPParser
7
- # The DMAPParser class parses DMAP responses
8
- class Parser
9
-
10
- def self.parse(response)
11
- return nil if response.nil? || response.length < 8
12
- response = StringIO.new(response)
13
- ret = TagContainer.new
14
- key = response.read(4)
15
- ret.type = Types.find { |a| a.tag == key }
16
- response.read(4) # ignore length for now
17
- ret.value = parse_container(response)
18
- ret
19
- end
20
-
21
- private
6
+ # The DMAPParser class parses DMAP responses
7
+ class DMAPParser
8
+ def self.parse(response)
9
+ return nil if response.nil? || response.length < 8
10
+ response = StringIO.new(response)
11
+ ret = TagContainer.new
12
+ key = response.read(4)
13
+ ret.type = TagDefinition[key]
14
+ response.read(4) # ignore length for now
15
+ ret.value = parse_container(response)
16
+ ret
17
+ end
22
18
 
23
- def self.parse_container(response)
24
- values = []
19
+ private
25
20
 
26
- until response.eof?
27
- key = response.read(4)
28
- length = DMAPConverter.bin_to_int(response.read(4))
29
- data = response.read(length)
30
- tag = Types.find { |a| a.tag.to_s == key }
31
- # puts "#{key} (#{length}): #{data.inspect}"
32
- p data if !tag.nil? && tag.tag.to_s == 'msas'
33
- values << if !tag.nil?
34
- case tag.type
35
- when :container
36
- data = StringIO.new(data)
37
- TagContainer.new(tag, parse_container(data))
38
- when :byte
39
- Tag.new(tag, DMAPConverter.bin_to_byte(data))
40
- when :uint16, :short
41
- Tag.new(tag, DMAPConverter.bin_to_short(data))
42
- when :uint32
43
- Tag.new(tag, DMAPConverter.bin_to_int(data))
44
- when :uint64
45
- Tag.new(tag, DMAPConverter.bin_to_long(data))
46
- when :bool
47
- Tag.new(tag, DMAPConverter.bin_to_bool(data))
48
- when :hex
49
- Tag.new(tag, DMAPConverter.bin_to_hex(data))
50
- when :string
51
- Tag.new(tag, data)
52
- when :date
53
- Tag.new tag, Time.at(DMAPConverter.bin_to_int(data))
54
- when :version
55
- Tag.new tag, DMAPConverter.bin_to_version(data)
56
- else
57
- warn "Unknown type #{tag.type}"
58
- Tag.new(tag, parseunknown(data))
59
- end
60
- else
61
- # puts "Unknown key #{key}"
62
- tag = TagDefinition.new(key, :unknown,
63
- "unknown (#{data.bytesize})")
64
- Tag.new(tag, parseunknown(data))
65
- end
66
- end
67
- values
68
- end
21
+ def self.parse_container(response)
22
+ values = []
69
23
 
70
- def self.parseunknown(data)
71
- if data =~ /[^\x20-\x7e]/ # non-readable characters
72
- if data.bytesize == 1
73
- return DMAPConverter.bin_to_byte(data)
74
- elsif data.bytesize == 2
75
- return DMAPConverter.bin_to_short(data)
76
- elsif data.bytesize == 4
77
- return DMAPConverter.bin_to_int(data)
78
- elsif data.bytesize == 8
79
- return DMAPConverter.bin_to_long(data)
80
- end
24
+ until response.eof?
25
+ key = response.read(4)
26
+ length = DMAPConverter.bin_to_int(response.read(4))
27
+ data = response.read(length)
28
+ tag = TagDefinition[key] ||
29
+ TagDefinition.new(key, :unknown, "unknown (#{data.bytesize})")
30
+ if tag.type == :container
31
+ data = StringIO.new(data)
32
+ values << TagContainer.new(tag, parse_container(data))
33
+ else
34
+ values << Tag.new(tag, DMAPConverter.decode(tag.type, data))
81
35
  end
82
- data
83
36
  end
37
+ values
84
38
  end
85
39
  end
86
- end
40
+ end
@@ -1,50 +1,35 @@
1
1
  require 'socket'
2
2
  require 'dnssd'
3
3
  require 'digest'
4
+ require 'gserver'
4
5
  module DACPClient
5
6
  # The pairingserver handles pairing with iTunes
6
- class PairingServer
7
+ class PairingServer < GServer
7
8
  attr_accessor :pin, :device_type
8
- def initialize(name, host, port = 1024)
9
- @name = name
9
+
10
+ MDNS_TYPE = '_touch-remote._tcp'.freeze
11
+
12
+ def initialize(client, host, port = 1024)
13
+ @name = client.name
10
14
  @port = port
11
15
  @host = host
12
- @pair = Client.get_guid(@name)
16
+ @pair = client.get_guid
13
17
  @pin = [0, 0, 0, 0]
14
18
  @device_type = 'iPod'
19
+ super port, host
15
20
  end
16
21
 
17
22
  def start
18
- # puts "Pairing started (pincode=#{@pin.join})"
19
-
20
- pairing_string = generate_pairing_string(@pair, @name, @device_type)
21
-
22
- expected = PairingServer.generate_pin_challenge(@pair, @pin)
23
- server = TCPServer.open(@host, @port)
24
- type = '_touch-remote._tcp'
25
- @service = DNSSD.register!(@name, type, 'local', @port, text_record)
23
+ @pairing_string = generate_pairing_string(@pair, @name, @device_type)
24
+ @expected = PairingServer.generate_pin_challenge(@pair, @pin)
25
+ @service = DNSSD.register!(@name, MDNS_TYPE, 'local', @port, text_record)
26
26
 
27
- while (client = server.accept)
28
- get = client.gets
29
- code = get.match(/pairingcode=([^&]*)/)[1]
27
+ super
28
+ join
30
29
 
31
- if code == expected
32
- client.print "HTTP/1.1 200 OK\r\n"
33
- client.print "Content-Length: #{pairing_string.length}\r\n\r\n"
34
- client.print pairing_string
35
- # puts 'Pairing succeeded :)'
36
- client.close
37
- @service.stop
38
- break
39
- else
40
- # puts 'Wrong pincode entered'
41
- client.print "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"
42
- end
43
- client.close
44
- end
45
- server.close
30
+ @service.stop
46
31
 
47
- sleep 1 # sleep so iTunes accepts our login
32
+ sleep 0.5 # sleep so iTunes accepts our login
48
33
  end
49
34
 
50
35
  def self.generate_pin_challenge(pair, pin)
@@ -52,17 +37,31 @@ module DACPClient
52
37
  Digest::MD5.hexdigest(pair + pin_string).upcase
53
38
  end
54
39
 
40
+ def serve(client)
41
+ code = client.gets.match(/pairingcode=([^&]*)/)[1]
42
+ correct = code == @expected
43
+ if correct
44
+ client.print "HTTP/1.1 200 OK\r\n" +
45
+ "Content-Length: #{@pairing_string.length}\r\n\r\n"
46
+ client.print @pairing_string
47
+ else
48
+ client.print "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"
49
+ end
50
+ client.close
51
+ stop if correct
52
+ end
53
+
55
54
  private
56
55
 
57
56
  def text_record
58
- DNSSD::TextRecord.new({
57
+ DNSSD::TextRecord.new(
59
58
  'DvNm' => @name,
60
59
  'Revm' => '10000',
61
60
  'DvTy' => @device_type,
62
61
  'RemN' => 'Remote',
63
62
  'txtvers' => '1',
64
63
  'Pair' => @pair
65
- })
64
+ )
66
65
  end
67
66
 
68
67
  def generate_pairing_string(pair, name, device_type)
@@ -73,4 +72,4 @@ module DACPClient
73
72
  end.to_dmap
74
73
  end
75
74
  end
76
- end
75
+ end
@@ -0,0 +1,21 @@
1
+ module DACPClient
2
+ Tag = Struct.new(:type, :value) do
3
+ def to_s
4
+ "#<#{self.class.name} #{type}>"
5
+ end
6
+
7
+ def inspect(level = 0)
8
+ "#{' ' * level}#{type}: #{value}"
9
+ end
10
+
11
+ def to_dmap
12
+ value = self.value
13
+ if type.type == :container
14
+ value = value.reduce('') { |a, e| a + e.to_dmap }
15
+ else
16
+ value = DMAPConverter.encode(type.type, value)
17
+ end
18
+ type.tag.to_s + [value.length].pack('N') + value
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,49 @@
1
+ module DACPClient
2
+ # The TagContainer class is a Tag which contains other Tags
3
+ class TagContainer < Tag
4
+ def initialize(type = nil, value = [])
5
+ super type, value
6
+ end
7
+
8
+ def inspect(level = 0)
9
+ "#{' ' * level}#{type}:\n" + value.reduce('') do |a, e|
10
+ a + e.inspect(level + 1).chomp + "\n"
11
+ end
12
+ end
13
+
14
+ def get_value(key)
15
+ return value[key] if key.is_a? Fixnum
16
+
17
+ key = key.to_s
18
+ val = value.find { |e| e.type.tag == key }
19
+ val = value.find { |e| e.type.name == key } if val.nil?
20
+
21
+ if val.type.type == :container
22
+ val
23
+ elsif !val.nil?
24
+ val.value
25
+ end
26
+ end
27
+
28
+ alias_method :[], :get_value
29
+
30
+ def has?(key)
31
+ key = key.to_s
32
+ val = value.find { |e| e.type.tag == key }
33
+ val = value.find { |e| e.type.name == key } if val.nil?
34
+ !val.nil?
35
+ end
36
+
37
+ def method_missing(method, *arguments, &block)
38
+ if has?(method)
39
+ get_value(method)
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def to_a
46
+ value
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ require 'dacpclient/tag'
2
+ require 'dacpclient/tag_container'
3
+
4
+ module DACPClient
5
+ # The TagDefinition class describes the tags
6
+ TagDefinition = Struct.new(:tag, :type, :name) do
7
+ def inspect
8
+ "#{tag} (#{name}: #{type})"
9
+ end
10
+
11
+ def to_s
12
+ "#{tag} (#{name}: #{type})"
13
+ end
14
+
15
+ class << self
16
+ def find(key)
17
+ @@tags[key.to_s]
18
+ end
19
+
20
+ def tag(*args, &block)
21
+ @@tags ||= Hash.new(nil)
22
+ definition = new(*args, &block).freeze
23
+ @@tags[definition.tag.to_s] = definition
24
+ end
25
+
26
+ alias_method :[], :find
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,167 @@
1
+ require 'dacpclient/tag_definition'
2
+ module DACPClient
3
+ # Sources:
4
+ # https://github.com/chendo/dmap-ng/blob/master/lib/dmap/tag_definitions.rb
5
+ # https://code.google.com/p/ytrack/wiki/DMAP
6
+ # https://code.google.com/p/tunesremote-se/wiki/ContentCodes
7
+ # https://raw.github.com/mattstevens/dmap-parser/master/dmap_parser.c
8
+ # /content-codes
9
+ class TagDefinition
10
+ tag 'mcon', :container, 'dmap.container'
11
+ tag 'msrv', :container, 'dmap.serverinforesponse'
12
+ tag 'msml', :container, 'dmap.msml'
13
+ tag 'mccr', :container, 'dmap.contentcodesresponse'
14
+ tag 'mdcl', :container, 'dmap.dictionary'
15
+ tag 'mlog', :container, 'dmap.loginresponse'
16
+ tag 'mupd', :container, 'dmap.updateresponse'
17
+ tag 'avdb', :container, 'daap.serverdatabases'
18
+ tag 'mlcl', :container, 'dmap.listing'
19
+ tag 'mlit', :container, 'dmap.listingitem'
20
+ tag 'mbcl', :container, 'dmap.bag'
21
+ tag 'adbs', :container, 'daap.returndatabasesongs'
22
+ tag 'aply', :container, 'daap.databaseplaylists'
23
+ tag 'apso', :container, 'daap.playlistsongs'
24
+ tag 'mudl', :container, 'dmap.deletedidlisting'
25
+ tag 'abro', :container, 'daap.databasebrowse'
26
+ tag 'abal', :container, 'daap.browsealbumlisting'
27
+ tag 'abar', :container, 'daap.browseartistlisting'
28
+ tag 'abcp', :container, 'daap.browsecomposerlisting'
29
+ tag 'abgn', :container, 'daap.browsegenrelisting'
30
+ tag 'prsv', :container, 'daap.resolve'
31
+ tag 'arif', :container, 'daap.resolveinfo'
32
+ tag 'casp', :container, 'dacp.speakers'
33
+ tag 'caci', :container, 'dacp.controlint'
34
+ tag 'cmpa', :container, 'dacp.pairinganswer'
35
+ tag 'cacr', :container, 'dacp.cacr'
36
+ tag 'cmcp', :container, 'dmcp.controlprompt'
37
+ tag 'cmgt', :container, 'dmcp.getpropertyresponse'
38
+ tag 'cmst', :container, 'dmcp.status'
39
+ tag 'agal', :container, 'daap.albumgrouping'
40
+ tag 'minm', :string, 'dmap.itemname'
41
+ tag 'msts', :string, 'dmap.statusstring'
42
+ tag 'mcna', :string, 'dmap.contentcodesname'
43
+ tag 'asal', :string, 'daap.songalbum'
44
+ tag 'asaa', :string, 'daap.songalbumartist'
45
+ tag 'asar', :string, 'daap.songartist'
46
+ tag 'ascm', :string, 'daap.songcomment'
47
+ tag 'asfm', :string, 'daap.songformat'
48
+ tag 'aseq', :string, 'daap.songeqpreset'
49
+ tag 'asgn', :string, 'daap.songgenre'
50
+ tag 'asdt', :string, 'daap.songdescription'
51
+ tag 'asul', :string, 'daap.songdataurl'
52
+ tag 'ceWM', :string, 'com.apple.itunes.welcome-message'
53
+ tag 'ascp', :string, 'daap.songcomposer'
54
+ tag 'assu', :string, 'daap.sortartist'
55
+ tag 'assa', :string, 'daap.sortalbum'
56
+ tag 'agrp', :string, 'daap.songgrouping'
57
+ tag 'cann', :string, 'daap.nowplayingtrack'
58
+ tag 'cana', :string, 'daap.nowplayingartist'
59
+ tag 'canl', :string, 'daap.nowplayingalbum'
60
+ tag 'cang', :string, 'daap.nowplayinggenre'
61
+ tag 'cmnm', :string, 'dacp.devicename'
62
+ tag 'cmty', :string, 'dacp.devicetype'
63
+ tag 'cmpg', :hex, 'dacp.pairingguid' # hex string
64
+ tag 'mper', :uint64, 'dmap.persistentid'
65
+ tag 'canp', :uint64, 'dacp.nowplaying'
66
+ tag 'cmpy', :uint64, 'dacp.passguid'
67
+ tag 'mstt', :uint32, 'dmap.status' # http status??
68
+ tag 'mcnm', :uint32, 'dmap.contentcodesnumber'
69
+ tag 'miid', :uint32, 'dmap.itemid'
70
+ tag 'mcti', :uint32, 'dmap.containeritemid'
71
+ tag 'mpco', :uint32, 'dmap.parentcontainerid'
72
+ tag 'mimc', :uint32, 'dmap.itemcount'
73
+ tag 'mrco', :uint32, 'dmap.returnedcount'
74
+ tag 'mtco', :uint32, 'dmap.containercount'
75
+ tag 'mstm', :uint32, 'dmap.timeoutinterval'
76
+ tag 'msdc', :uint32, 'dmap.databasescount'
77
+ tag 'msma', :uint32, 'dmap.speakermachineaddress'
78
+ tag 'mlid', :uint32, 'dmap.sessionid'
79
+ tag 'assr', :uint32, 'daap.songsamplerate'
80
+ tag 'assz', :uint32, 'daap.songsize'
81
+ tag 'asst', :uint32, 'daap.songstarttime'
82
+ tag 'assp', :uint32, 'daap.songstoptime'
83
+ tag 'astm', :uint32, 'daap.songtime'
84
+ tag 'msto', :uint32, 'dmap.utcoffset'
85
+ tag 'cmsr', :uint32, 'dmcp.mediarevision'
86
+ tag 'caas', :uint32, 'dacp.albumshuffle'
87
+ tag 'caar', :uint32, 'dacp.albumrepeat'
88
+ tag 'cant', :uint32, 'dacp.remainingtime'
89
+ tag 'cmmk', :uint32, 'dmcp.mediakind'
90
+ tag 'cast', :uint32, 'dacp.tracklength'
91
+ tag 'asai', :uint32, 'daap.songalbumid'
92
+ tag 'aeNV', :uint32, 'com.apple.itunes.norm-volume'
93
+ tag 'cmvo', :uint32, 'dmcp.volume'
94
+ tag 'mcty', :uint16, 'dmap.contentcodestype'
95
+ tag 'asbt', :uint16, 'daap.songsbeatsperminute'
96
+ tag 'asbr', :uint16, 'daap.songbitrate'
97
+ tag 'asdc', :uint16, 'daap.songdisccount'
98
+ tag 'asdn', :uint16, 'daap.songdiscnumber'
99
+ tag 'astc', :uint16, 'daap.songtrackcount'
100
+ tag 'astn', :uint16, 'daap.songtracknumber'
101
+ tag 'asyr', :uint16, 'daap.songyear'
102
+ tag 'ated', :uint16, 'daap.supportsextradata'
103
+ tag 'asgr', :uint16, 'daap.supportsgroups'
104
+ tag 'mikd', :byte, 'dmap.itemkind'
105
+ tag 'casu', :byte, 'dacp.su'
106
+ tag 'msau', :byte, 'dmap.authenticationmethod'
107
+ tag 'mstu', :byte, 'dmap.updatetype'
108
+ tag 'asrv', :byte, 'daap.songrelativevolume'
109
+ tag 'asur', :byte, 'daap.songuserrating'
110
+ tag 'asdk', :byte, 'daap.songdatakind'
111
+ tag 'caps', :byte, 'dacp.playstatus'
112
+ tag 'cash', :byte, 'dacp.shufflestate'
113
+ tag 'carp', :byte, 'dacp.repeatstate'
114
+ tag 'muty', :byte, 'dmap.updatetype'
115
+ tag "f\215ch", :byte, 'dmap.haschildcontainers'
116
+ tag 'msas', :byte, 'dmap.authenticationschemes'
117
+ tag 'cavs', :bool, 'dacp.visualizer'
118
+ tag 'cafs', :bool, 'dacp.fullscreen'
119
+ tag 'ceGS', :bool, 'com.apple.itunes.genius-selectable'
120
+ tag 'mslr', :bool, 'dmap.loginrequired'
121
+ tag 'msal', :bool, 'dmap.supportsautologout'
122
+ tag 'msup', :bool, 'dmap.supportsupdate'
123
+ tag 'mspi', :bool, 'dmap.supportspersistenids'
124
+ tag 'msex', :bool, 'dmap.supportsextensions'
125
+ tag 'msbr', :bool, 'dmap.supportsbrowse'
126
+ tag 'msqy', :bool, 'dmap.supportsquery'
127
+ tag 'msix', :bool, 'dmap.supportsindex'
128
+ tag 'msrs', :bool, 'dmap.supportsresolve'
129
+ tag 'asco', :bool, 'daap.songcompliation'
130
+ tag 'asdb', :bool, 'daap.songdisabled'
131
+ tag 'abpl', :bool, 'daap.baseplaylist'
132
+ tag 'aeSP', :bool, 'com.apple.itunes.smart-playlist'
133
+ tag 'aePP', :bool, 'com.apple.itunes.is-podcast-playlist'
134
+ tag 'aePS', :bool, 'com.apple.itunes.special-playlist'
135
+ tag 'aeSG', :bool, 'com.apple.itunes.saved-genius'
136
+ tag 'aeFP', :bool, 'com.apple.itunes.req-fplay'
137
+ tag 'aeHV', :bool, 'com.apple.itunes.has-video'
138
+ tag 'caia', :bool, 'dacp.isavailiable'
139
+ tag 'caip', :bool, 'dacp.isplaying'
140
+ tag 'ceVO', :bool, 'com.apple.itunes.voting-enabled'
141
+ tag 'aeSV', :version, 'com.apple.itunes.music-sharing-version'
142
+ tag 'mpro', :version, 'dmap.protocolversion'
143
+ tag 'apro', :version, 'daap.protocolversion'
144
+ tag 'musr', :version, 'dmap.serverrevision'
145
+ tag 'mstc', :date, 'dmap.utc-time'
146
+ tag 'asda', :date, 'daap.songdateadded'
147
+ tag 'asdm', :date, 'daap.songdatemodified'
148
+ tag 'ceJC', :bool, 'com.apple.itunes.jukebox-client-vote'
149
+ tag 'ceJI', :bool, 'com.apple.itunes.jukebox-current'
150
+ tag 'ceJS', :uint16, 'com.apple.itunes.jukebox-score'
151
+ tag 'ceJV', :bool, 'com.apple.itunes.jukebox-vote'
152
+ tag 'ceQR', :container, 'com.apple.itunes.playqueue-contents-response'
153
+ tag 'ceQS', :container, 'com.apple.itunes.playqueue-contents-???'
154
+ tag 'ceQs', :uint64, 'com.apple.itunes.playqueue-id'
155
+ tag 'ceQa', :string, 'com.apple.itunes.playqueue-album'
156
+ tag 'ceQg', :string, 'com.apple.itunes.playqueue-genre'
157
+ tag 'ceQn', :string, 'com.apple.itunes.playqueue-name'
158
+ tag 'ceQr', :string, 'com.apple.itunes.playqueue-artist'
159
+ tag 'msml', :container, 'msml'
160
+ tag 'aeGs', :bool, 'com.apple.itunes.can-be-genius-seed'
161
+ tag 'aprm', :short, 'daap.playlistrepeatmode'
162
+ tag 'apsm', :short, 'daap.playlistshufflemode'
163
+ tag 'cmpr', :version, 'dmcp.protocolversion'
164
+ tag 'capr', :version, 'dacp.protocolversion'
165
+ tag 'ppro', :version, 'unknown.version'
166
+ end
167
+ end
@@ -1,4 +1,4 @@
1
1
  # The DACPClient module
2
2
  module DACPClient
3
- VERSION = '0.1.1'
4
- end
3
+ VERSION = '0.2.0'
4
+ end
data/lib/dacpclient.rb CHANGED
@@ -1 +1 @@
1
- require 'dacpclient/client'
1
+ require 'dacpclient/client'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dacpclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jurriaan Pruis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-13 00:00:00.000000000 Z
11
+ date: 2013-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dnssd
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.8
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.8
41
+ - !ruby/object:Gem::Dependency
42
+ name: plist
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.0
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: yard
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +94,48 @@ dependencies:
66
94
  - - '>='
67
95
  - !ruby/object:Gem::Version
68
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 5.2.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 5.2.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.15.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 0.15.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rake
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
69
139
  description: A DACP (iTunes Remote protocol) client
70
140
  email:
71
141
  - email@jurriaanpruis.nl
@@ -85,12 +155,16 @@ files:
85
155
  - bin/dacpclient
86
156
  - dacpclient.gemspec
87
157
  - lib/dacpclient.rb
158
+ - lib/dacpclient/bonjour.rb
88
159
  - lib/dacpclient/client.rb
89
160
  - lib/dacpclient/dmapbuilder.rb
90
161
  - lib/dacpclient/dmapconverter.rb
91
162
  - lib/dacpclient/dmapparser.rb
92
163
  - lib/dacpclient/pairingserver.rb
93
- - lib/dacpclient/tagdefinitions.rb
164
+ - lib/dacpclient/tag.rb
165
+ - lib/dacpclient/tag_container.rb
166
+ - lib/dacpclient/tag_definition.rb
167
+ - lib/dacpclient/tag_definitions.rb
94
168
  - lib/dacpclient/version.rb
95
169
  homepage: https://github.com/jurriaan/ruby-dacpclient
96
170
  licenses:
@@ -104,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
178
  requirements:
105
179
  - - '>='
106
180
  - !ruby/object:Gem::Version
107
- version: 1.9.3
181
+ version: 2.0.0
108
182
  required_rubygems_version: !ruby/object:Gem::Requirement
109
183
  requirements:
110
184
  - - '>='
@@ -112,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
186
  version: '0'
113
187
  requirements: []
114
188
  rubyforge_project:
115
- rubygems_version: 2.0.5
189
+ rubygems_version: 2.1.11
116
190
  signing_key:
117
191
  specification_version: 4
118
192
  summary: A DACP (iTunes Remote protocol) client