sonos 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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