Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
System now owns groups that correctly represent the topology
- Loading branch information
Showing
12 changed files
with
189 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,21 @@ | ||
require 'sonos/version' | ||
require 'sonos/system' | ||
require 'sonos/discovery' | ||
require 'sonos/device' | ||
require 'sonos/group' | ||
|
||
module Sonos | ||
PORT = 1400 | ||
NAMESPACE = 'http://www.sonos.com/Services/1.1' | ||
|
||
def self.Speaker(ip) | ||
Speaker.new(ip) | ||
end | ||
|
||
def self.discover | ||
Sonos::Discovery.new.discover | ||
# Create a new speaker with it's IP address | ||
# @param [String] the speaker's IP address | ||
def self.speaker(ip) | ||
Device::Speaker.new(ip) | ||
end | ||
|
||
module Device | ||
# Get the Sonos system | ||
def self.system | ||
@system ||= Sonos::System.new | ||
end | ||
end | ||
|
||
require 'sonos/version' | ||
require 'sonos/discovery' | ||
|
||
require 'sonos/device/base' | ||
require 'sonos/device/speaker' | ||
require 'sonos/device/bridge' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module Sonos | ||
module Device | ||
end | ||
end | ||
|
||
require 'sonos/device/base' | ||
require 'sonos/device/speaker' | ||
require 'sonos/device/bridge' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,5 +17,9 @@ class Speaker < Base | |
def self.model_numbers | ||
MODEL_NUMBERS | ||
end | ||
|
||
def speaker? | ||
true | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,48 @@ | ||
module Sonos | ||
# Represents a Sonos group. A group can contain one or more speakers. All speakers in a group | ||
# play the same music in sync. | ||
class Group | ||
attr_reader :devices | ||
# The master speaker in the group | ||
attr_reader :master_speaker | ||
|
||
# All other speakers in the group | ||
attr_reader :slave_speakers | ||
|
||
def initialize(master_speaker, slave_speakers) | ||
@master_speaker = master_speaker | ||
@slave_speakers = (slave_speakers or []) | ||
end | ||
|
||
# All of the speakers in the group | ||
def speakers | ||
[self.master_speaker] + self.slave_speakers | ||
end | ||
|
||
# Remove all speakers from the group | ||
def disband | ||
self.slave_speakers.each do |speaker| | ||
speaker.ungroup | ||
end | ||
end | ||
|
||
# Full group name | ||
def name | ||
self.speakers.collect(&:name).uniq.join(', ') | ||
end | ||
|
||
# Forward AVTransport methods to the master speaker | ||
%w{now_playing pause stop next previous queue clear_queue}.each do |method| | ||
define_method(method) do | ||
self.master_speaker.send(method.to_sym) | ||
end | ||
end | ||
|
||
def play(uri = nil) | ||
self.master_speaker.play(uri) | ||
end | ||
|
||
def save_queue(name) | ||
self.master_speaker.save_queue(name) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,60 @@ | ||
module Sonos | ||
# The Sonos system. The root object to manage the collection of groups and devices. This is | ||
# intended to be a singleton accessed from `Sonos.system`. | ||
class System | ||
attr_reader :topology | ||
attr_reader :groups | ||
attr_reader :devices | ||
|
||
# Initialize the system | ||
# @param [Array] the system topology. If this is nil, it will autodiscover. | ||
def initialize(topology = Sonos::Discovery.new.topology) | ||
@topology = topology | ||
construct_groups | ||
end | ||
|
||
# Returns all speakers | ||
def speakers | ||
@devices.select(&:speaker?) | ||
end | ||
|
||
# Pause all speakers | ||
def pause_all | ||
# It looks like Sonos is just telling all of the groups to pause instead of | ||
# having a message to actually pause all | ||
self.groups.each do |group| | ||
group.pause | ||
end | ||
end | ||
|
||
def self.discover | ||
Sonos::Discovery.new.discover | ||
private | ||
|
||
def construct_groups | ||
# Reset | ||
@groups = [] | ||
@devices = @topology.collect(&:device) | ||
|
||
# Loop through all of the unique groups | ||
@topology.collect(&:group).uniq.each do |group_uid| | ||
# Select all of the nodes with this group uid | ||
nodes = @topology.select do |node| | ||
node.group == group_uid | ||
end | ||
|
||
next if nodes.empty? | ||
|
||
# Find master node | ||
master_uuid = group_uid.split(':').first | ||
master = nodes.select do |node| | ||
node.uuid == master_uuid | ||
end | ||
|
||
next unless master.count == 1 | ||
master = master.first | ||
|
||
nodes.delete(master) | ||
|
||
# Add the group | ||
@groups << Group.new(master.device, nodes.collect(&:device)) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.