lib/sonos/endpoint/a_v_transport.rb in sonos-0.3.5 vs lib/sonos/endpoint/a_v_transport.rb in sonos-0.3.6

- old
+ new

@@ -46,10 +46,16 @@ state: body[:current_transport_state], speed: body[:current_speed], } end + # Returns true if the player is not in a paused or stopped state + def is_playing? + state = get_player_state[:state] + !['PAUSED_PLAYBACK', 'STOPPED'].include?(state) + end + # Pause the currently playing track. def pause parse_response send_transport_message('Pause') end @@ -75,11 +81,11 @@ # Play the previous track. def previous parse_response send_transport_message('Previous') end - + def line_in(speaker) set_av_transport_uri('x-rincon-stream:' + speaker.uid.sub('uuid:', '')) end # Seeks to a given timestamp in the current track @@ -88,37 +94,44 @@ # Must be sent in the format of HH:MM:SS timestamp = Time.at(seconds).utc.strftime('%H:%M:%S') parse_response send_transport_message('Seek', "<Unit>REL_TIME</Unit><Target>#{timestamp}</Target>") end + # Seeks the playlist selection to the provided index + def select_track(index) + parse_response send_transport_message('Seek', "<Unit>TRACK_NR</Unit><Target>#{index}</Target>") + end + # Clear the queue def clear_queue - parse_response parse_response send_transport_message('RemoveAllTracksFromQueue') + parse_response send_transport_message('RemoveAllTracksFromQueue') end # Save queue def save_queue(title) parse_response send_transport_message('SaveQueue', "<Title>#{title}</Title><ObjectID></ObjectID>") end # Adds a track to the queue # @param[String] uri Uri of track # @param[String] didl Stanza of DIDL-Lite metadata (generally created by #add_spotify_to_queue) + # @param[Integer] position Optional queue insertion position. Leaving this blank inserts at the end. # @return[Integer] Queue position of the added track - def add_to_queue(uri, didl = '') - response = send_transport_message('AddURIToQueue', "<EnqueuedURI>#{uri}</EnqueuedURI><EnqueuedURIMetaData>#{didl}</EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>1</EnqueueAsNext>") + def add_to_queue(uri, didl = '', position = 0) + response = send_transport_message('AddURIToQueue', "<EnqueuedURI>#{uri}</EnqueuedURI><EnqueuedURIMetaData>#{didl}</EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>#{position}</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>1</EnqueueAsNext>") # TODO yeah, this error handling is a bit soft. For consistency's sake :) pos = response.xpath('.//FirstTrackNumberEnqueued').text if pos.length != 0 pos.to_i end end # Adds a Spotify track to the queue along with extra data for better metadata retrieval # @param[Hash] opts Various options (id, user, region and type) + # @param[Integer] position Optional queue insertion position. Leaving this blank inserts at the end. # @return[Integer] Queue position of the added track(s) - def add_spotify_to_queue(opts = {}) + def add_spotify_to_queue(opts = {}, position = 0) opts = { :id => '', :user => nil, :region => nil, :type => 'track' @@ -151,13 +164,52 @@ uri = "x-sonos-spotify:spotify%3a#{opts[:type]}%3a#{opts[:id]}" else return nil end - add_to_queue(uri, didl_metadata) + add_to_queue(uri, didl_metadata, position) end + # Add an Rdio object to the queue (album or track), anything else can only + # be streamed (play now). + # @param[Hash] opts Various options (album/track keys, username and type) + # @param[Integer] position Optional queue insertion position. Leaving this blank inserts at the end. + # @return[Integer] Queue position of the added track(s) + def add_rdio_to_queue(opts = {}, position = 0) + opts = { + :username => nil, + :album => nil, + :track => nil, + :type => 'track', + :format => 'mp3' # can be changed, but only 'mp3' is valid. + }.merge(opts) + + return nil if opts[:username].nil? + + # Both tracks and albums require the album key. And tracks need a track + # key of course. + return nil if opts[:album].nil? + return nil if opts[:type] == 'track' and opts[:track].nil? + + # In order for valid DIDL we'll pass an empty :track for albums. + opts[:track] = '' if opts[:type] == 'album' + + didl_metadata = "&lt;DIDL-Lite xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:upnp=&quot;urn:schemas-upnp-org:metadata-1-0/upnp/&quot; xmlns:r=&quot;urn:schemas-rinconnetworks-com:metadata-1-0/&quot; xmlns=&quot;urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/&quot;&gt;&lt;item id=&quot;00030020_t%3a%3a#{opts[:track]}%3a%3aa%3a%3a#{opts[:album]}&quot; parentID=&quot;0004006c_a%3a%3a#{opts[:album]}&quot; restricted=&quot;true&quot;&gt;&lt;dc:title&gt;&lt;/dc:title&gt;&lt;upnp:class&gt;object.item.audioItem.musicTrack&lt;/upnp:class&gt;&lt;desc id=&quot;cdudn&quot; nameSpace=&quot;urn:schemas-rinconnetworks-com:metadata-1-0/&quot;&gt;SA_RINCON2823_#{opts[:username]}&lt;/desc&gt;&lt;/item&gt;&lt;/DIDL-Lite&gt;" + + case opts[:type] + when /track/ + uri = "x-sonos-http:_t%3a%3a#{opts[:track]}%3a%3aa%3a%3a#{opts[:album]}.#{opts[:format]}?sid=11&amp;flags=32" + when /album/ + type_id = '0004006c_a' + uri = "x-rincon-cpcontainer:#{type_id}%3a%3a#{opts[:album]}" + else + return nil + end + + add_to_queue(uri, didl_metadata, position) + end + # Removes a track from the queue # @param[String] object_id Track's queue ID def remove_from_queue(object_id) parse_response send_transport_message('RemoveTrackFromQueue', "<ObjectID>#{object_id}</ObjectID><UpdateID>0</UpdateID></u:RemoveTrackFromQueue>") end @@ -176,9 +228,22 @@ # Ungroup from its current group. # Trying to call this on a stereo pair slave will fail. def ungroup parse_response send_transport_message('BecomeCoordinatorOfStandaloneGroup') + end + + # Set a sleep timer up to 23:59:59 + # E.g. '00:11:00' for 11 minutes. + # @param duration [String] Duration of timer or nil to clear. + def set_sleep_timer(duration) + if duration.nil? + duration = '' + elsif duration.gsub(':', '').to_i > 235959 + duration = '23:59:59' + end + + parse_response send_transport_message('ConfigureSleepTimer', "<NewSleepTimerDuration>#{duration}</NewSleepTimerDuration>") end private # Play a stream.