sonos 0.3.0 → 0.3.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ded5809db9b6874541a783058f58e2675f042092
4
+ data.tar.gz: 16b0167e929a9d328f1420ef41bd38576a34bf85
5
+ SHA512:
6
+ metadata.gz: 7ccf9e8e83d533d33205b57620a0ec7d1de4d81f69faeff100469fe75a9cfed7d56f3ea6093a6f50bfb6c2c803ccf86f88b5e99684fe2ad2c35a00605056f32f
7
+ data.tar.gz: cdeaed6716f84e1a399c9d8e9049d8f482d717b5e801d14df9feeb71f85b04960116c4aa5dadc8b1d76265c821caa39a7bff607723a0e9da6d74e7dbbfa7ea24
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.0.0-p195
data/Readme.markdown CHANGED
@@ -53,6 +53,8 @@ speaker.volume
53
53
  speaker.volume = 70
54
54
  speaker.volume -= 10
55
55
  speaker.queue
56
+ speaker.add_to_queue 'http://assets.samsoff.es/music/Airports.mp3'
57
+ speaker.remove_from_queue(speaker.queue[:items].last[:queue_id])
56
58
  speaker.save_queue 'Jams'
57
59
  speaker.clear_queue
58
60
  ```
@@ -91,7 +93,6 @@ You can also run `sonos pause_all` to pause all your Sonos groups.
91
93
  * Set repeat mode
92
94
  * Search music library
93
95
  * Browse music library
94
- * Add songs to queue
95
96
  * Skip to song in queue
96
97
  * Alarm clock
97
98
  * Sleep timer
data/lib/sonos/cli.rb CHANGED
@@ -22,6 +22,24 @@ module Sonos
22
22
  system.pause_all
23
23
  end
24
24
 
25
+ desc 'play_all', 'Resumes playing all Sonos speaker groups'
26
+ def play_all
27
+ system.play_all
28
+ end
29
+
30
+ desc 'groups', 'List all Sonos groups'
31
+ def groups
32
+ system.groups.each do |group|
33
+ puts group.master_speaker.name.ljust(20) + group.master_speaker.ip
34
+
35
+ group.slave_speakers.each do |speaker|
36
+ puts speaker.name.rjust(10).ljust(20) + speaker.ip
37
+ end
38
+
39
+ puts "\n"
40
+ end
41
+ end
42
+
25
43
  private
26
44
 
27
45
  def system
@@ -14,7 +14,7 @@ module Sonos::Device
14
14
  elsif Speaker.model_numbers.include?(model_number)
15
15
  Speaker.new(ip, data)
16
16
  else
17
- raise ArgumentError.new("#{self.data[:model_number]} not supported")
17
+ raise ArgumentError.new("#{data[:model_number]} not supported")
18
18
  end
19
19
  end
20
20
 
@@ -6,7 +6,7 @@ module Sonos::Device
6
6
  # Used for Zone Bridge
7
7
  class Bridge < Base
8
8
 
9
- MODEL_NUMBERS = ['ZB100']
9
+ MODEL_NUMBERS = ['ZB100','ZP80']
10
10
 
11
11
  attr_reader :icon
12
12
 
@@ -17,12 +17,15 @@ module Sonos
17
17
  MULTICAST_ADDR = '239.255.255.250'
18
18
  MULTICAST_PORT = 1900
19
19
  DEFAULT_TIMEOUT = 1
20
+ DEFAULT_IP = nil
20
21
 
21
22
  attr_reader :timeout
22
23
  attr_reader :first_device_ip
24
+ attr_reader :default_ip
23
25
 
24
- def initialize(timeout = DEFAULT_TIMEOUT)
26
+ def initialize(timeout = DEFAULT_TIMEOUT,default_ip = DEFAULT_IP)
25
27
  @timeout = timeout
28
+ @default_ip = default_ip
26
29
  initialize_socket
27
30
  end
28
31
 
@@ -61,7 +64,8 @@ module Sonos
61
64
  end
62
65
  end
63
66
  rescue Timeout::Error => ex
64
- nil
67
+ puts "Timeout error; switching to the default IP"
68
+ return @default_ip
65
69
  end
66
70
  end
67
71
 
@@ -11,6 +11,9 @@ module Sonos::Endpoint::AVTransport
11
11
  body = response.body[:get_position_info_response]
12
12
  doc = Nokogiri::XML(body[:track_meta_data])
13
13
 
14
+ # No music
15
+ return nil if doc.children.length == 0
16
+
14
17
  art_path = doc.xpath('//upnp:albumArtURI').inner_text
15
18
 
16
19
  # TODO: No idea why this is necessary. Maybe its a Nokogiri thing
@@ -20,6 +23,7 @@ module Sonos::Endpoint::AVTransport
20
23
  title: doc.xpath('//dc:title').inner_text,
21
24
  artist: doc.xpath('//dc:creator').inner_text,
22
25
  album: doc.xpath('//upnp:album').inner_text,
26
+ info: doc.xpath('//r:streamContent').inner_text,
23
27
  queue_position: body[:track],
24
28
  track_duration: body[:track_duration],
25
29
  current_position: body[:rel_time],
@@ -28,13 +32,17 @@ module Sonos::Endpoint::AVTransport
28
32
  }
29
33
  end
30
34
 
35
+ def has_music?
36
+ !now_playing.nil?
37
+ end
38
+
31
39
  # Pause the currently playing track.
32
40
  def pause
33
41
  send_transport_message('Pause')
34
42
  end
35
43
 
36
44
  # Play the currently selected track or play a stream.
37
- # @param [String] optional uri of the track to play. Leaving this blank, plays the current track.
45
+ # @param [String] uri Optional uri of the track to play. Leaving this blank, plays the current track.
38
46
  def play(uri = nil)
39
47
  # Play a song from the uri
40
48
  set_av_transport_uri(uri) and return if uri
@@ -78,6 +86,24 @@ module Sonos::Endpoint::AVTransport
78
86
  send_transport_message('SaveQueue', "<Title>#{title}</Title><ObjectID></ObjectID>")
79
87
  end
80
88
 
89
+ # Adds a track to the queue
90
+ # @param[String] uri Uri of track
91
+ # @return[Integer] Queue position of the added track
92
+ def add_to_queue(uri)
93
+ response = send_transport_message('AddURIToQueue', "<EnqueuedURI>#{uri}</EnqueuedURI><EnqueuedURIMetaData></EnqueuedURIMetaData><DesiredFirstTrackNumberEnqueued>0</DesiredFirstTrackNumberEnqueued><EnqueueAsNext>1</EnqueueAsNext>")
94
+ # TODO yeah, this error handling is a bit soft. For consistency's sake :)
95
+ pos = response.xpath('.//FirstTrackNumberEnqueued').text
96
+ if pos.length != 0
97
+ pos.to_i
98
+ end
99
+ end
100
+
101
+ # Removes a track from the queue
102
+ # @param[String] object_id Track's queue ID
103
+ def remove_from_queue(object_id)
104
+ send_transport_message('RemoveTrackFromQueue', "<ObjectID>#{object_id}</ObjectID><UpdateID>0</UpdateID></u:RemoveTrackFromQueue>")
105
+ end
106
+
81
107
  # Join another speaker's group.
82
108
  # Trying to call this on a stereo pair slave will fail.
83
109
  def join(master)
@@ -96,7 +122,7 @@ module Sonos::Endpoint::AVTransport
96
122
  send_transport_message('BecomeCoordinatorOfStandaloneGroup')
97
123
  end
98
124
 
99
- private
125
+ private
100
126
 
101
127
  # Play a stream.
102
128
  def set_av_transport_uri(uri)
@@ -28,7 +28,7 @@ module Sonos::Endpoint::ContentDirectory
28
28
  hash
29
29
  end
30
30
 
31
- private
31
+ private
32
32
 
33
33
  def content_directory_client
34
34
  @content_directory_client ||= Savon.client endpoint: "http://#{self.ip}:#{Sonos::PORT}#{CONTENT_DIRECTORY_ENDPOINT}", namespace: Sonos::NAMESPACE
@@ -40,10 +40,11 @@ private
40
40
  doc.css('item').each do |item|
41
41
  res = item.css('res').first
42
42
  result << {
43
+ queue_id: item['id'],
43
44
  title: item.xpath('dc:title').inner_text,
44
45
  artist: item.xpath('dc:creator').inner_text,
45
46
  album: item.xpath('upnp:album').inner_text,
46
- album_art: "http://#{self.ip}:#{PORT}#{item.xpath('upnp:albumArtURI').inner_text}",
47
+ album_art: "http://#{self.ip}:#{Sonos::PORT}#{item.xpath('upnp:albumArtURI').inner_text}",
47
48
  duration: res['duration'],
48
49
  id: res.inner_text
49
50
  }
data/lib/sonos/system.rb CHANGED
@@ -23,13 +23,28 @@ module Sonos
23
23
 
24
24
  # Pause all speakers
25
25
  def pause_all
26
- self.groups.each do |group|
27
- group.pause
26
+ speakers.each do |speaker|
27
+ speaker.pause if speaker.has_music?
28
+ end
29
+ end
30
+
31
+ # Play all speakers
32
+ def play_all
33
+ speakers.each do |speaker|
34
+ speaker.play if speaker.has_music?
28
35
  end
29
36
  end
30
37
 
31
38
  private
32
39
 
40
+ def send_to_all_speakers(action)
41
+ if self.groups.length > 0
42
+ self.groups.each { |group| group.send action }
43
+ else
44
+ self.speakers.each { |speaker| speaker.send action }
45
+ end
46
+ end
47
+
33
48
  def construct_groups
34
49
  # Loop through all of the unique groups
35
50
  @topology.collect(&:group).uniq.each do |group_uid|
data/lib/sonos/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Sonos
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sonos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
5
- prerelease:
4
+ version: 0.3.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Sam Soffes
@@ -10,12 +9,11 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-02-02 00:00:00.000000000 Z
12
+ date: 2013-06-28 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: savon
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
18
  - - ~>
21
19
  - !ruby/object:Gem::Version
@@ -23,7 +21,6 @@ dependencies:
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
25
  - - ~>
29
26
  - !ruby/object:Gem::Version
@@ -31,33 +28,29 @@ dependencies:
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: nokogiri
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
- - - ! '>='
32
+ - - '>='
37
33
  - !ruby/object:Gem::Version
38
34
  version: '0'
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
- - - ! '>='
39
+ - - '>='
45
40
  - !ruby/object:Gem::Version
46
41
  version: '0'
47
42
  - !ruby/object:Gem::Dependency
48
43
  name: thor
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
- - - ! '>='
46
+ - - '>='
53
47
  - !ruby/object:Gem::Version
54
48
  version: '0'
55
49
  type: :runtime
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
- - - ! '>='
53
+ - - '>='
61
54
  - !ruby/object:Gem::Version
62
55
  version: '0'
63
56
  description: Control Sonos speakers with Ruby
@@ -70,6 +63,7 @@ extensions: []
70
63
  extra_rdoc_files: []
71
64
  files:
72
65
  - .gitignore
66
+ - .ruby-version
73
67
  - .travis.yml
74
68
  - Changelog.markdown
75
69
  - Gemfile
@@ -102,30 +96,26 @@ files:
102
96
  homepage: https://github.com/soffes/sonos
103
97
  licenses:
104
98
  - MIT
99
+ metadata: {}
105
100
  post_install_message:
106
101
  rdoc_options: []
107
102
  require_paths:
108
103
  - lib
109
104
  required_ruby_version: !ruby/object:Gem::Requirement
110
- none: false
111
105
  requirements:
112
- - - ! '>='
106
+ - - '>='
113
107
  - !ruby/object:Gem::Version
114
108
  version: 1.9.2
115
109
  required_rubygems_version: !ruby/object:Gem::Requirement
116
- none: false
117
110
  requirements:
118
- - - ! '>='
111
+ - - '>='
119
112
  - !ruby/object:Gem::Version
120
113
  version: '0'
121
- segments:
122
- - 0
123
- hash: -1378351241916050478
124
114
  requirements: []
125
115
  rubyforge_project:
126
- rubygems_version: 1.8.23
116
+ rubygems_version: 2.0.2
127
117
  signing_key:
128
- specification_version: 3
118
+ specification_version: 4
129
119
  summary: Control Sonos speakers with Ruby
130
120
  test_files:
131
121
  - test/cassettes/topology.yml