sonos 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Changelog.markdown CHANGED
@@ -1,3 +1,10 @@
1
+ ### Version 0.1.1 — Unreleased
2
+
3
+ * **Feature:** Queue
4
+ * **Feature:** Clear Queue
5
+ * **Feature:** Save Queue
6
+ * **Feature:** Device Description URL
7
+
1
8
  ### Version 0.1.0 — December 24, 2012
2
9
 
3
10
  * **Feature:** Stop
@@ -0,0 +1,55 @@
1
+ module Sonos
2
+ module ContentDirectory
3
+ CONTENT_DIRECTORY_ENDPOINT = '/MediaServer/ContentDirectory/Control'
4
+ CONTENT_DIRECTORY_XMLNS = 'urn:schemas-upnp-org:service:ContentDirectory:1'
5
+
6
+ # Get the current queue
7
+ def queue(starting_index = 0, requested_count = 100)
8
+ name = 'Browse'
9
+ action = "#{CONTENT_DIRECTORY_XMLNS}##{name}"
10
+ message = %Q{<u:#{name} xmlns:u="#{CONTENT_DIRECTORY_XMLNS}"><ObjectID>Q:0</ObjectID><BrowseFlag>BrowseDirectChildren</BrowseFlag><Filter>dc:title,res,dc:creator,upnp:artist,upnp:album,upnp:albumArtURI</Filter><StartingIndex>#{starting_index}</StartingIndex><RequestedCount>#{requested_count}</RequestedCount><SortCriteria></SortCriteria></u:Browse>}
11
+ result = content_directory_client.call name, soap_action: action, message: message
12
+ body = result.body[:browse_response]
13
+
14
+ hash = {
15
+ total: body[:total_matches].to_i,
16
+ items: parse_items(body[:result])
17
+ }
18
+
19
+ # Paginate
20
+ # TODO: This is ugly and inflexible
21
+ if starting_index == 0
22
+ start = starting_index
23
+ while hash[:items].count < hash[:total]
24
+ start += requested_count
25
+ hash[:items] += browse(start, requested_count)[:items]
26
+ end
27
+ end
28
+
29
+ hash
30
+ end
31
+
32
+ private
33
+
34
+ def content_directory_client
35
+ @content_directory_client ||= Savon.client endpoint: "http://#{self.ip}:#{PORT}#{CONTENT_DIRECTORY_ENDPOINT}", namespace: NAMESPACE
36
+ end
37
+
38
+ def parse_items(string)
39
+ result = []
40
+ doc = Nokogiri::XML(string)
41
+ doc.css('item').each do |item|
42
+ res = item.css('res').first
43
+ result << {
44
+ title: item.xpath('dc:title').inner_text,
45
+ artist: item.xpath('dc:creator').inner_text,
46
+ album: item.xpath('upnp:album').inner_text,
47
+ album_art: "http://#{self.ip}:#{PORT}#{item.xpath('upnp:albumArtURI').inner_text}",
48
+ duration: res['duration'],
49
+ id: res.inner_text
50
+ }
51
+ end
52
+ result
53
+ end
54
+ end
55
+ end
data/lib/sonos/speaker.rb CHANGED
@@ -2,12 +2,14 @@ require 'savon'
2
2
  require 'sonos/transport'
3
3
  require 'sonos/rendering'
4
4
  require 'sonos/device'
5
+ require 'sonos/content_directory'
5
6
 
6
7
  module Sonos
7
8
  class Speaker
8
9
  include Transport
9
10
  include Rendering
10
11
  include Device
12
+ include ContentDirectory
11
13
 
12
14
  attr_reader :ip, :zone_name, :zone_icon, :uid, :serial_number, :software_version, :hardware_version, :mac_address
13
15
 
@@ -18,6 +20,11 @@ module Sonos
18
20
  get_status
19
21
  end
20
22
 
23
+ # URL for giant dump of device information
24
+ def device_description_url
25
+ "http://#{self.ip}:#{PORT}/xml/device_description.xml"
26
+ end
27
+
21
28
  private
22
29
 
23
30
  # Get information about the speaker.
@@ -52,6 +52,19 @@ module Sonos
52
52
  send_transport_message('Previous')
53
53
  end
54
54
 
55
+ # Clear the queue
56
+ def clear_queue
57
+ send_transport_message('RemoveAllTracksFromQueue')
58
+ end
59
+
60
+ # Save queue
61
+ def save_queue(title)
62
+ name = 'SaveQueue'
63
+ action = "#{TRANSPORT_XMLNS}##{name}"
64
+ message = %Q{<u:#{name} xmlns:u="#{TRANSPORT_XMLNS}"><InstanceID>0</InstanceID><Title>#{title}</Title><ObjectID></ObjectID></u:#{name}>}
65
+ transport_client.call(name, soap_action: action, message: message)
66
+ end
67
+
55
68
  private
56
69
 
57
70
  # Play a stream.
data/lib/sonos/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sonos
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
data/sonos.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Sonos::VERSION
9
9
  gem.authors = ['Sam Soffes']
10
10
  gem.email = ['sam@soff.es']
11
- gem.description = 'Sonos Controller'
12
- gem.summary = 'Control Sonos speakers with Ruby'
11
+ gem.description = 'Control Sonos speakers with Ruby'
12
+ gem.summary = gem.description
13
13
  gem.homepage = 'https://github.com/soffes/sonos'
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sonos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,7 +27,7 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 2.0.2
30
- description: Sonos Controller
30
+ description: Control Sonos speakers with Ruby
31
31
  email:
32
32
  - sam@soff.es
33
33
  executables: []
@@ -41,6 +41,7 @@ files:
41
41
  - Rakefile
42
42
  - Readme.markdown
43
43
  - lib/sonos.rb
44
+ - lib/sonos/content_directory.rb
44
45
  - lib/sonos/device.rb
45
46
  - lib/sonos/rendering.rb
46
47
  - lib/sonos/speaker.rb
@@ -61,7 +62,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
61
62
  version: '0'
62
63
  segments:
63
64
  - 0
64
- hash: -1995798408343589310
65
+ hash: -921214504657487484
65
66
  required_rubygems_version: !ruby/object:Gem::Requirement
66
67
  none: false
67
68
  requirements:
@@ -70,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
71
  version: '0'
71
72
  segments:
72
73
  - 0
73
- hash: -1995798408343589310
74
+ hash: -921214504657487484
74
75
  requirements: []
75
76
  rubyforge_project:
76
77
  rubygems_version: 1.8.23