dacpclient 0.2.6 → 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
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.2.6
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jurriaan Pruis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-28 00:00:00.000000000 Z
11
+ date: 2014-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: dmapparser
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.18.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.18.1
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: yard
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +142,14 @@ dependencies:
114
142
  requirements:
115
143
  - - "~>"
116
144
  - !ruby/object:Gem::Version
117
- version: 0.17.0
145
+ version: 0.18.0
118
146
  type: :development
119
147
  prerelease: false
120
148
  version_requirements: !ruby/object:Gem::Requirement
121
149
  requirements:
122
150
  - - "~>"
123
151
  - !ruby/object:Gem::Version
124
- version: 0.17.0
152
+ version: 0.18.0
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: rake
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -155,15 +183,17 @@ files:
155
183
  - bin/dacpclient
156
184
  - dacpclient.gemspec
157
185
  - lib/dacpclient.rb
186
+ - lib/dacpclient/browser.rb
158
187
  - lib/dacpclient/client.rb
159
- - lib/dacpclient/dmapbuilder.rb
160
- - lib/dacpclient/dmapconverter.rb
161
- - lib/dacpclient/dmapparser.rb
188
+ - lib/dacpclient/faraday/flatter_params_encoder.rb
189
+ - lib/dacpclient/model.rb
190
+ - lib/dacpclient/models/pair_info.rb
191
+ - lib/dacpclient/models/play_queue.rb
192
+ - lib/dacpclient/models/play_queue_item.rb
193
+ - lib/dacpclient/models/playlist.rb
194
+ - lib/dacpclient/models/playlists.rb
195
+ - lib/dacpclient/models/status.rb
162
196
  - lib/dacpclient/pairingserver.rb
163
- - lib/dacpclient/tag.rb
164
- - lib/dacpclient/tag_container.rb
165
- - lib/dacpclient/tag_definition.rb
166
- - lib/dacpclient/tag_definitions.rb
167
197
  - lib/dacpclient/version.rb
168
198
  homepage: https://github.com/jurriaan/ruby-dacpclient
169
199
  licenses:
@@ -185,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
215
  version: '0'
186
216
  requirements: []
187
217
  rubyforge_project:
188
- rubygems_version: 2.2.0
218
+ rubygems_version: 2.2.2
189
219
  signing_key:
190
220
  specification_version: 4
191
221
  summary: A DACP (iTunes Remote protocol) client
@@ -1,43 +0,0 @@
1
- module DACPClient
2
- # This class provides a DSL to create DMAP responses
3
- class DMAPBuilder
4
- attr_reader :result
5
-
6
- def initialize
7
- @dmap_stack = []
8
- end
9
-
10
- def self.method_missing(method, *args, &block)
11
- new.send(method, *args, &block)
12
- end
13
-
14
- def build_container(tag , &block)
15
- unless tag.type == :container
16
- fail "Tag #{method} is not a container type"
17
- end
18
- @dmap_stack << TagContainer.new(tag)
19
- instance_eval(&block)
20
- if @dmap_stack.length > 1
21
- @dmap_stack.last.value << @dmap_stack.pop
22
- else
23
- return @result = @dmap_stack.pop
24
- end
25
- end
26
-
27
- def method_missing(method, *args, &block)
28
- tag = TagDefinition[method]
29
- return super if tag.nil?
30
-
31
- if block_given?
32
- build_container(tag, &block)
33
- else
34
- if @dmap_stack.length > 0
35
- args = args.size > 1 ? args : args.first
36
- @dmap_stack.last.value << Tag.new(tag, args)
37
- else
38
- fail 'Cannot build DMAP without a valid container'
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,119 +0,0 @@
1
- module DACPClient
2
- # The DMAPConverter class converts between binary and ruby formats
3
- class DMAPConverter
4
- class << self
5
- def date_to_bin(data)
6
- int_to_bin(value.to_i)
7
- end
8
-
9
- def bin_to_byte(data)
10
- data.unpack('C').first
11
- end
12
-
13
- def bin_to_long(data)
14
- (bin_to_int(data[0..3]) << 32) + bin_to_int(data[4..7])
15
- end
16
-
17
- def bin_to_int(data)
18
- data.unpack('N').first
19
- end
20
-
21
- def bin_to_short(data)
22
- data.unpack('n').first
23
- end
24
-
25
- def bin_to_bool(data)
26
- data == "\x01"
27
- end
28
-
29
- def bin_to_version(data)
30
- data.unpack('nCC').join '.'
31
- end
32
-
33
- def bin_to_hex(data)
34
- data.bytes.reduce('') { |a, e| a + sprintf('%02X', e) }
35
- end
36
-
37
- def bin_to_date(data)
38
- Time.at(bin_to_int(data))
39
- end
40
-
41
- def bool_to_bin(data)
42
- (data ? 1 : 0).chr
43
- end
44
-
45
- def int_to_bin(data)
46
- [data.to_i].pack 'N'
47
- end
48
-
49
- def byte_to_bin(data)
50
- [data.to_i].pack 'C'
51
- end
52
-
53
- def long_to_bin(data)
54
- [data >> 32, data & 0xfffffff].pack 'NN'
55
- end
56
-
57
- def short_to_bin(data)
58
- [data.to_i].pack 'n'
59
- end
60
-
61
- def version_to_bin(data)
62
- data.split('.').pack 'nCC'
63
- end
64
-
65
- def hex_to_bin(data)
66
- [data].pack 'H*'
67
- end
68
-
69
- def decode_unknown(data)
70
- if data =~ /[^\x20-\x7e]/ # non-readable characters
71
- if data.bytesize == 1
72
- return DMAPConverter.bin_to_byte(data)
73
- elsif data.bytesize == 2
74
- return DMAPConverter.bin_to_short(data)
75
- elsif data.bytesize == 4
76
- return DMAPConverter.bin_to_int(data)
77
- elsif data.bytesize == 8
78
- return DMAPConverter.bin_to_long(data)
79
- end
80
- end
81
- data
82
- end
83
-
84
- def bin_to_string(data)
85
- data
86
- end
87
- alias_method :string_to_bin, :bin_to_string
88
-
89
- alias_method :uint16_to_bin, :short_to_bin
90
- alias_method :uint32_to_bin, :int_to_bin
91
- alias_method :uint64_to_bin, :long_to_bin
92
-
93
- alias_method :bin_to_uint16, :bin_to_short
94
- alias_method :bin_to_uint32, :bin_to_int
95
- alias_method :bin_to_uint64, :bin_to_long
96
- alias_method :bin_to_unknown, :decode_unknown
97
-
98
- def decode(type, data)
99
- decode_method = ('bin_to_' + type.to_s).to_sym
100
- if respond_to? decode_method
101
- send(decode_method, data)
102
- else
103
- warn "Decoder: Unknown type #{type}"
104
- decode_unknown(data)
105
- end
106
- end
107
-
108
- def encode(type, data)
109
- encode_method = (type.to_s + '_to_bin').to_sym
110
- if respond_to? encode_method
111
- send(encode_method, data)
112
- else
113
- warn "Encoder: Unknown type #{type}"
114
- data
115
- end
116
- end
117
- end
118
- end
119
- end
@@ -1,40 +0,0 @@
1
- require 'dacpclient/tag_definitions'
2
- require 'dacpclient/dmapconverter'
3
-
4
- require 'stringio'
5
- module DACPClient
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
18
-
19
- private
20
-
21
- def self.parse_container(response)
22
- values = []
23
-
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))
35
- end
36
- end
37
- values
38
- end
39
- end
40
- end
@@ -1,21 +0,0 @@
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
@@ -1,51 +0,0 @@
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 method =~ /(.*)\?$/
39
- has?($1)
40
- elsif has?(method)
41
- get_value(method)
42
- else
43
- super
44
- end
45
- end
46
-
47
- def to_a
48
- value
49
- end
50
- end
51
- end
@@ -1,29 +0,0 @@
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
@@ -1,167 +0,0 @@
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