class DACPClient::Client
The Client
class handles communication with the server
Constants
- DEFAULT_HEADERS
Attributes
guid[W]
host[R]
hsgid[RW]
name[R]
port[R]
session_id[R]
Public Class Methods
new(name, host = 'localhost', port = 3689)
click to toggle source
# File lib/dacpclient/client.rb, line 39 def initialize(name, host = 'localhost', port = 3689) @name = name @host = host @port = port @session_id = nil @hsgid = nil @media_revision = 1 setup_connection end
Public Instance Methods
albums(db = default_db)
click to toggle source
# File lib/dacpclient/client.rb, line 278 def albums(db = default_db) url = "databases/#{db.item_id}/groups" meta = 'dmap.itemname,dmap.itemid,dmap.persistentid,daap.songartist,daap.songalbumartist' query = "('daap.songartist!:'+('com.apple.itunes.extended-media-kind:1','com.apple.itunes.extended-media-kind:32'))" do_action(url, meta: meta, type: 'music', :'group-type' => 'albums', sort: 'artist', :'include-sort-headers' => 1, query: query, clean_url: true, model: Albums).items end
artists(db = default_db)
click to toggle source
# File lib/dacpclient/client.rb, line 271 def artists(db = default_db) url = "databases/#{db.item_id}/groups" meta = 'dmap.itemname,dmap.itemid,dmap.persistentid,daap.songartist,daap.groupalbumcount,daap.songartistid' query = "('daap.songartist!:'+('com.apple.itunes.extended-media-kind:1','com.apple.itunes.extended-media-kind:32'))" do_action(url, meta: meta, type: 'music', :'group-type' => 'artists', sort: 'album', :'include-sort-headers' => 1, query: query, clean_url: true, model: Artists).items end
artwork(database, id, width = 320, height = 320)
click to toggle source
# File lib/dacpclient/client.rb, line 229 def artwork(database, id, width = 320, height = 320) url = "databases/#{database}/items/#{id}/extra_data/artwork" do_action(url, { mw: width, mh: height }, clean_url: true) end
clear_queue()
click to toggle source
# File lib/dacpclient/client.rb, line 195 def clear_queue do_action('playqueue-edit', command: 'clear') end
content_codes()
click to toggle source
# File lib/dacpclient/client.rb, line 106 def content_codes do_action('content-codes', clean_url: true) end
ctrl_int()
click to toggle source
# File lib/dacpclient/client.rb, line 180 def ctrl_int do_action('ctrl-int', clean_url: true) end
cue(command, query, index = 0)
click to toggle source
# File lib/dacpclient/client.rb, line 149 def cue(command, query, index = 0) do_action(:cue, command: command, query: query, index: index) end
databases()
click to toggle source
# File lib/dacpclient/client.rb, line 203 def databases meta = %w(dmap.itemname dmap.itemcount dmap.itemid dmap.persistentid daap.baseplaylist com.apple.itunes.special-playlist com.apple.itunes.smart-playlist com.apple.itunes.saved-genius dmap.parentcontainerid dmap.editcommandssupported).join(',') do_action('databases', clean_url: true, meta: meta, model: Databases) end
default_db()
click to toggle source
# File lib/dacpclient/client.rb, line 221 def default_db databases.items.find { |item| item.default_db == 1 } end
default_playlist(db = default_db)
click to toggle source
# File lib/dacpclient/client.rb, line 225 def default_playlist(db = default_db) playlists(db).find(&:base_playlist?) end
guid()
click to toggle source
# File lib/dacpclient/client.rb, line 62 def guid return @guid unless @guid.nil? d = Digest::SHA2.hexdigest(@name) d[0..15].upcase end
list_queue()
click to toggle source
# File lib/dacpclient/client.rb, line 199 def list_queue do_action('playqueue-contents', model: PlayQueue) end
login()
click to toggle source
# File lib/dacpclient/client.rb, line 78 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()
click to toggle source
# File lib/dacpclient/client.rb, line 184 def logout do_action(:logout) @media_revision = 1 @session_id = nil end
now_playing_artwork(width = 320, height = 320)
click to toggle source
# File lib/dacpclient/client.rb, line 234 def now_playing_artwork(width = 320, height = 320) do_action(:nowplayingartwork, mw: width, mh: height) end
pair(pin)
click to toggle source
# File lib/dacpclient/client.rb, line 68 def pair(pin) pairingserver = PairingServer.new(name, guid) pairingserver.pin = pin pairingserver.start end
pair_and_login(pin = nil)
click to toggle source
# File lib/dacpclient/client.rb, line 90 def pair_and_login(pin = nil) login rescue DACPForbiddenError, Faraday::ConnectionFailed => e pin = 4.times.map { Random.rand(10) } if pin.nil? if e.instance_of? DACPForbiddenError message = e.result.status else message = e end warn "#{message} error: Cannot login, starting pairing process" warn "Pincode: #{pin}" @host = pair(pin).host setup_connection retry end
playlists(db = default_db)
click to toggle source
# File lib/dacpclient/client.rb, line 211 def playlists(db = default_db) meta = %w(dmap.itemname dmap.itemcount dmap.itemid dmap.persistentid daap.baseplaylist com.apple.itunes.special-playlist com.apple.itunes.smart-playlist com.apple.itunes.saved-genius dmap.parentcontainerid dmap.editcommandssupported).join(',') do_action("databases/#{db.item_id}/containers", clean_url: true, meta: meta, model: Playlists).items end
playspec(playlist, db = default_db)
click to toggle source
# File lib/dacpclient/client.rb, line 153 def playspec(playlist, db = default_db) dbspec = "'dmap.persistentid:0x#{db.persistent_id.to_s(16)}'" cspec = "'dmap.persistentid:0x#{playlist.persistent_id.to_s(16)}'" # don't worry about playing item's from playlists yet.. # container-item-spec='dmap.containeritemid:%s' do_action(:playspec, database_spec: dbspec, container_spec: cspec) end
position()
click to toggle source
# File lib/dacpclient/client.rb, line 119 def position response = do_action(:getproperty, properties: 'dacp.playingtime') response.cast? ? (response['cast'] - response['cant']) : 0 end
queue(id)
click to toggle source
# File lib/dacpclient/client.rb, line 190 def queue(id) do_action('playqueue-edit', command: 'add', query: "\'dmap.itemid:#{id}\'") end
repeat()
click to toggle source
# File lib/dacpclient/client.rb, line 162 def repeat response = do_action(:getproperty, properties: 'dacp.repeatstate') response[:carp] end
repeat=(repeatstate)
click to toggle source
# File lib/dacpclient/client.rb, line 167 def repeat=(repeatstate) set_property('dacp.repeatstate', repeatstate) end
search(search, type = nil, db = default_db, container = default_playlist(default_db))
click to toggle source
# File lib/dacpclient/client.rb, line 238 def search(search, type = nil, db = default_db, container = default_playlist(default_db)) 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(',') q = '(' + q + ')' if queries.length > 1 meta = %w(dmap.itemname dmap.itemid com.apple.itunes.has-chapter-data 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 daap.songhasbeenplayed daap.songbookmark com.apple.itunes.is-hd-video daap.songlongcontentdescription daap.songtime daap.songuserplaycount daap.songartist com.apple.itunes.content-rating daap.songdatereleased com.apple.itunes.movie-info-xml daap.songalbumartist com.apple.itunes.extended-media-kind).join(',') url = "databases/#{db.item_id}/containers/#{container.item_id}/items" do_action(url, query: q, type: 'music', sort: 'album', meta: meta, :'include-sort-headers' => 1, clean_url: true) end
seek(ms)
click to toggle source
# File lib/dacpclient/client.rb, line 115 def seek(ms) set_property('dacp.playingtime', ms) end
Also aliased as: position=
serverinfo()
click to toggle source
# File lib/dacpclient/client.rb, line 74 def serverinfo do_action('server-info', clean_url: true) end
shuffle()
click to toggle source
# File lib/dacpclient/client.rb, line 171 def shuffle response = do_action(:getproperty, properties: 'dmcp.shufflestate') response[:cash] end
shuffle=(shufflestate)
click to toggle source
# File lib/dacpclient/client.rb, line 176 def shuffle=(shufflestate) set_property('dmcp.shufflestate', shufflestate) end
status(wait = false)
click to toggle source
# File lib/dacpclient/client.rb, line 126 def status(wait = false) revision = wait ? @media_revision : 1 result = do_action(:playstatusupdate, :'revision-number' => revision, model: Status) @media_revision = result.media_revision result rescue Faraday::Error::TimeoutError => e if wait retry else raise e end end
track_length()
click to toggle source
# File lib/dacpclient/client.rb, line 110 def track_length response = do_action(:getproperty, properties: 'dacp.playingtime') response.cast? ? response['cast'] : 0 end
volume()
click to toggle source
# File lib/dacpclient/client.rb, line 140 def volume response = do_action(:getproperty, properties: 'dmcp.volume') response[:cmvo] end
volume=(volume)
click to toggle source
# File lib/dacpclient/client.rb, line 145 def volume=(volume) set_property('dmcp.volume', volume) end
Private Instance Methods
do_action(action, params = {})
click to toggle source
# File lib/dacpclient/client.rb, line 298 def do_action(action, params = {}) clean_url = params.delete(:clean_url) || false model = params.delete(:model) action = '/' + action.to_s unless @session_id.nil? params['session-id'] = @session_id.to_s action = '/ctrl-int/1' + action unless clean_url end params['hsgid'] = @hsgid unless @hsgid.nil? params = filter_param_keys(params) result = @client.get do |request| request.options.params_encoder = Faraday::FlatterParamsEncoder request.url action request.params = params request.headers.merge!(DEFAULT_HEADERS) end parse_result result, model end
filter_param_keys(params)
click to toggle source
# File lib/dacpclient/client.rb, line 320 def filter_param_keys(params) Hash[params.map { |k, v| [k.to_s.tr('_', '-'), v] }] end
parse_result(result, model)
click to toggle source
# File lib/dacpclient/client.rb, line 324 def parse_result(result, model) if !result.success? fail DACPForbiddenError, result elsif result.headers['Content-Type'] == 'application/x-dmap-tagged' && result.body.length > 0 res = DMAPParser::Parser.parse(result.body) model ? model.new(res) : res else result.body end end
set_property(property, value)
click to toggle source
# File lib/dacpclient/client.rb, line 294 def set_property(property, value) do_action(:setproperty, property => value) end
setup_connection()
click to toggle source
# File lib/dacpclient/client.rb, line 287 def setup_connection @uri = URI::HTTP.build(host: @host, port: @port) Faraday::Utils.default_params_encoder = Faraday::FlatterParamsEncoder @client = Faraday.new(@uri.to_s) @client.use FaradayMiddleware::Gzip end