sonos 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.markdown +7 -0
- data/lib/sonos/content_directory.rb +55 -0
- data/lib/sonos/speaker.rb +7 -0
- data/lib/sonos/transport.rb +13 -0
- data/lib/sonos/version.rb +1 -1
- data/sonos.gemspec +2 -2
- metadata +5 -4
data/Changelog.markdown
CHANGED
@@ -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.
|
data/lib/sonos/transport.rb
CHANGED
@@ -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
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
|
12
|
-
gem.summary =
|
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.
|
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
|
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: -
|
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: -
|
74
|
+
hash: -921214504657487484
|
74
75
|
requirements: []
|
75
76
|
rubyforge_project:
|
76
77
|
rubygems_version: 1.8.23
|