Class: DACPClient::Client
- Inherits:
-
Object
- Object
- DACPClient::Client
- Defined in:
- lib/dacpclient/client.rb
Overview
The Client class handles communication with the server
Constant Summary collapse
- HOME_SHARING_HOST =
'https://homesharing.itunes.apple.com'- HOME_SHARING_PATH =
'/WebObjects/MZHomeSharing.woa/wa/getShareIdentifiers'- DEFAULT_HEADERS =
{ 'Viewer-Only-Client' => '1', # 'Accept-Encoding' => 'gzip', 'Connection' => 'keep-alive', 'User-Agent' => 'RubyDACPClient/' + VERSION }.freeze
Instance Attribute Summary collapse
-
#guid ⇒ Object
Returns the value of attribute guid.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#hsgid ⇒ Object
Returns the value of attribute hsgid.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#port ⇒ Object
readonly
Returns the value of attribute port.
-
#session_id ⇒ Object
readonly
Returns the value of attribute session_id.
Instance Method Summary collapse
- #artwork(database, id, width = 320, height = 320) ⇒ Object
- #clear_queue ⇒ Object
- #content_codes ⇒ Object
- #ctrl_int ⇒ Object
- #databases ⇒ Object
- #default_db ⇒ Object
- #default_playlist(db) ⇒ Object
-
#initialize(name, host = 'localhost', port = 3689) ⇒ Client
constructor
A new instance of Client.
- #list_queue ⇒ Object
- #login ⇒ Object
- #logout ⇒ Object
- #now_playing_artwork(width = 320, height = 320) ⇒ Object
- #pair(pin) ⇒ Object
- #pair_and_login(pin = nil) ⇒ Object
- #playlists(db) ⇒ Object
- #position ⇒ Object
- #queue(id) ⇒ Object
- #repeat ⇒ Object
- #repeat=(repeatstate) ⇒ Object
- #search(db, container, search, type = nil) ⇒ Object
- #seek(ms) ⇒ Object (also: #position=)
- #serverinfo ⇒ Object
- #setup_home_sharing(user, password) ⇒ Object
- #shuffle ⇒ Object
- #shuffle=(shufflestate) ⇒ Object
- #status(wait = false) ⇒ Object
- #track_length ⇒ Object
- #volume ⇒ Object
- #volume=(volume) ⇒ Object
Constructor Details
#initialize(name, host = 'localhost', port = 3689) ⇒ Client
Returns a new instance of Client.
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/dacpclient/client.rb', line 28 def initialize(name, host = 'localhost', port = 3689) @client = Net::HTTP.new(host, port) @name = name @host = host @port = port @session_id = nil @hsgid = nil @mediarevision = 1 @uri = URI::HTTP.build(host: @host, port: @port) @client = Faraday.new(url: @uri.to_s) end |
Instance Attribute Details
#guid ⇒ Object
Returns the value of attribute guid.
15 16 17 |
# File 'lib/dacpclient/client.rb', line 15 def guid @guid end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
16 17 18 |
# File 'lib/dacpclient/client.rb', line 16 def host @host end |
#hsgid ⇒ Object
Returns the value of attribute hsgid.
15 16 17 |
# File 'lib/dacpclient/client.rb', line 15 def hsgid @hsgid end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
16 17 18 |
# File 'lib/dacpclient/client.rb', line 16 def name @name end |
#port ⇒ Object (readonly)
Returns the value of attribute port.
16 17 18 |
# File 'lib/dacpclient/client.rb', line 16 def port @port end |
#session_id ⇒ Object (readonly)
Returns the value of attribute session_id.
16 17 18 |
# File 'lib/dacpclient/client.rb', line 16 def session_id @session_id end |
Instance Method Details
#artwork(database, id, width = 320, height = 320) ⇒ Object
203 204 205 206 |
# File 'lib/dacpclient/client.rb', line 203 def artwork(database, id, width = 320, height = 320) url = "databases/#{database}/items/#{id}/extra_data/artwork" do_action(url, { mw: width, mh: height }, true) end |
#clear_queue ⇒ Object
179 180 181 |
# File 'lib/dacpclient/client.rb', line 179 def clear_queue do_action('playqueue-edit', command: 'clear') end |
#content_codes ⇒ Object
104 105 106 |
# File 'lib/dacpclient/client.rb', line 104 def content_codes do_action('content-codes', {}, true) end |
#ctrl_int ⇒ Object
164 165 166 |
# File 'lib/dacpclient/client.rb', line 164 def ctrl_int do_action('ctrl-int', {}, true) end |
#databases ⇒ Object
187 188 189 |
# File 'lib/dacpclient/client.rb', line 187 def databases do_action('databases', {}, true) end |
#default_db ⇒ Object
195 196 197 |
# File 'lib/dacpclient/client.rb', line 195 def default_db databases[:mlcl].to_a.find { |item| item.mdbk == 1 } end |
#default_playlist(db) ⇒ Object
199 200 201 |
# File 'lib/dacpclient/client.rb', line 199 def default_playlist(db) @client.playlists(72).mlcl.to_a.find { |item| item.abpl } end |
#list_queue ⇒ Object
183 184 185 |
# File 'lib/dacpclient/client.rb', line 183 def list_queue do_action('playqueue-contents') end |
#login ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/dacpclient/client.rb', line 82 def login response = nil if @hsgid.nil? pairing_guid = '0x' + guid response = do_action(:login, 'pairing-guid' => pairing_guid) else response = do_action(:login, 'hasFP' => '1') end @session_id = response[:mlid] response end |
#logout ⇒ Object
168 169 170 171 172 |
# File 'lib/dacpclient/client.rb', line 168 def logout do_action(:logout) @mediarevision = 1 @session_id = nil end |
#now_playing_artwork(width = 320, height = 320) ⇒ Object
208 209 210 |
# File 'lib/dacpclient/client.rb', line 208 def (width = 320, height = 320) do_action(:nowplayingartwork, mw: width, mh: height) end |
#pair(pin) ⇒ Object
72 73 74 75 76 |
# File 'lib/dacpclient/client.rb', line 72 def pair(pin) pairingserver = PairingServer.new(self, '0.0.0.0', 1024) pairingserver.pin = pin pairingserver.start end |
#pair_and_login(pin = nil) ⇒ Object
94 95 96 97 98 99 100 101 102 |
# File 'lib/dacpclient/client.rb', line 94 def pair_and_login(pin = nil) login rescue DACPForbiddenError => e pin = 4.times.map { Random.rand(10) } if pin.nil? warn "#{e.result.status} error: Cannot login, starting pairing process" warn "Pincode: #{pin}" pair(pin) retry end |
#playlists(db) ⇒ Object
191 192 193 |
# File 'lib/dacpclient/client.rb', line 191 def playlists(db) do_action("databases/#{db}/containers", {}, true) end |
#position ⇒ Object
117 118 119 120 |
# File 'lib/dacpclient/client.rb', line 117 def position response = do_action(:getproperty, properties: 'dacp.playingtime') response.cast? ? (response['cast'] - response['cant']) : 0 end |
#queue(id) ⇒ Object
174 175 176 177 |
# File 'lib/dacpclient/client.rb', line 174 def queue(id) do_action('playqueue-edit', command: 'add', query: "\'dmap.itemid:#{id}\'") end |
#repeat ⇒ Object
146 147 148 149 |
# File 'lib/dacpclient/client.rb', line 146 def repeat response = do_action(:getproperty, properties: 'dacp.repeatstate') response[:carp] end |
#repeat=(repeatstate) ⇒ Object
151 152 153 |
# File 'lib/dacpclient/client.rb', line 151 def repeat=(repeatstate) do_action(:setproperty, 'dacp.repeatstate' => repeatstate) end |
#search(db, container, search, type = nil) ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/dacpclient/client.rb', line 212 def search(db, container, search, type = nil) search = URI.escape(search) types = { title: 'dmap.itemname', artist: 'daap.songartist', album: 'daap.songalbum', genre: 'daap.songgenre', composer: 'daap.songcomposer' } queries = [] type = types.keys if type.nil? Array(type).each do |t| queries << "'#{types[t]}:#{search}'" end q = queries.join(',') = %w(dmap.itemname dmap.itemid daap.songartist daap.songalbumartist daap.songalbum com.apple.itunes.cloud-id dmap.containeritemid com.apple.itunes.has-video com.apple.itunes.itms-songid com.apple.itunes.extended-media-kind dmap.downloadstatus daap.songdisabled).join(',') url = "databases/#{db}/containers/#{container}/items" do_action(url, { type: 'music', sort: 'album', query: q, meta: }, true) end |
#seek(ms) ⇒ Object Also known as: position=
113 114 115 |
# File 'lib/dacpclient/client.rb', line 113 def seek(ms) do_action(:setproperty, 'dacp.playingtime' => ms) end |
#serverinfo ⇒ Object
78 79 80 |
# File 'lib/dacpclient/client.rb', line 78 def serverinfo do_action('server-info', {}, true) end |
#setup_home_sharing(user, password) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/dacpclient/client.rb', line 53 def setup_home_sharing(user, password) hs_client = Faraday.new(url: HOME_SHARING_HOST) result = hs_client.post do |request| request.url HOME_SHARING_PATH request.headers['Content-Type'] = 'text/xml' request.headers.merge!(DEFAULT_HEADERS) request.body = { 'appleId' => user, 'guid' => 'empty', 'password' => password }.to_plist end response = Plist.parse_xml(result.body) @hsgid = response['sgid'] end |
#shuffle ⇒ Object
155 156 157 158 |
# File 'lib/dacpclient/client.rb', line 155 def shuffle response = do_action(:getproperty, properties: 'dmcp.shufflestate') response[:cash] end |
#shuffle=(shufflestate) ⇒ Object
160 161 162 |
# File 'lib/dacpclient/client.rb', line 160 def shuffle=(shufflestate) do_action(:setproperty, 'dmcp.shufflestate' => shufflestate) end |
#status(wait = false) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/dacpclient/client.rb', line 124 def status(wait = false) revision = wait ? @mediarevision : 1 result = do_action(:playstatusupdate, 'revision-number' => revision) @mediarevision = result[:cmsr] result rescue Faraday::Error::TimeoutError => e if wait retry else raise e end end |
#track_length ⇒ Object
108 109 110 111 |
# File 'lib/dacpclient/client.rb', line 108 def track_length response = do_action(:getproperty, properties: 'dacp.playingtime') response.cast? ? response['cast'] : 0 end |
#volume ⇒ Object
137 138 139 140 |
# File 'lib/dacpclient/client.rb', line 137 def volume response = do_action(:getproperty, properties: 'dmcp.volume') response[:cmvo] end |
#volume=(volume) ⇒ Object
142 143 144 |
# File 'lib/dacpclient/client.rb', line 142 def volume=(volume) do_action(:setproperty, 'dmcp.volume' => volume) end |