squeezer-ruby 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ ._*
2
+ Gemfile.lock
3
+ coverage/*
4
+ doc/*
5
+ test.rb
6
+ .yardoc
7
+ .bundle
8
+ .AppleDouble
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.mkd ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2011 Daniël van Hoesel
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.mkd ADDED
@@ -0,0 +1,67 @@
1
+ Squeezer: Ruby Squeezebox Gem
2
+ ====================
3
+ A Ruby wrapper for the [Squeezebox](http://www.logitech.com/en-us/speakers-audio/wireless-music-systems) [Server](http://www.squeezenetwork.com/download) CLI API.
4
+
5
+ WORK IN PROGRESS
6
+ ----------------
7
+ This project is in it's early stages, it is not finished by any means.
8
+ **Feel free to comment with help or criticism!**
9
+
10
+ It also lacks proper error handling and documentation.
11
+ Most of the critical refactor points have been marked with a 'todo' comment.
12
+
13
+ - active record like search methods and model relations (database chained search engine?)
14
+ - playlist handling
15
+ - add convenience methods
16
+ - add some more sugar
17
+
18
+ Installation
19
+ ------------
20
+ gem install squeezer-ruby
21
+
22
+ Usage Examples
23
+ --------------
24
+ General:
25
+
26
+ require "squeezer"
27
+
28
+ Squeezer.configure do |config|
29
+ config.server = "127.0.0.1"
30
+ config.port = 9090
31
+ end
32
+
33
+ client = Squeezer::Client.new
34
+
35
+ puts client.version
36
+
37
+ client.players.each do |id, player|
38
+ puts "Name: #{player.name}"
39
+ puts "Model: #{player.model}"
40
+ puts "Signal: #{player.signal_strength}" if player.wireless?
41
+ puts "Volume: #{player.volume}"
42
+
43
+ player.on! if player.off?
44
+ player.volume = "+40"
45
+ end
46
+
47
+ puts client.total_artists
48
+
49
+ client.artists.each do |artist|
50
+ puts artist.name
51
+ end
52
+
53
+ client.exit
54
+
55
+ Models:
56
+
57
+ begin
58
+ include Squeezer::Models
59
+
60
+ puts Player.find_by_name("living room").ip
61
+ puts Player.find_by_ip("192.168.1.1").name
62
+ end
63
+
64
+ Copyright
65
+ ---------
66
+ Copyright (c) 2011 Daniël van Hoesel.
67
+ See [LICENSE](https://github.com/s0meone/squeezer/blob/master/LICENSE.mkd) for details.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ namespace :doc do
10
+ require 'yard'
11
+ YARD::Rake::YardocTask.new do |task|
12
+ task.files = ['HISTORY.mkd', 'LICENSE.mkd', 'lib/**/*.rb']
13
+ task.options = [
14
+ '--protected',
15
+ '--output-dir', 'doc/yard',
16
+ '--markup', 'markdown',
17
+ ]
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path('../connection', __FILE__)
2
+
3
+ module Squeezer
4
+ class API
5
+
6
+ # @private
7
+ attr_accessor *Configuration::VALID_OPTIONS_KEYS
8
+
9
+ # Creates a new API
10
+ def initialize(options={})
11
+ options = Squeezer.options.merge(options)
12
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
13
+ send("#{key}=", options[key])
14
+ end
15
+ end
16
+
17
+ include Connection
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ module Squeezer
2
+ class Client
3
+ module Database
4
+
5
+ # doesn't include 'Various Artists'
6
+ def total_artists
7
+ count(:artists)
8
+ end
9
+
10
+ def total_albums
11
+ count(:albums)
12
+ end
13
+
14
+ def total_songs
15
+ count(:songs)
16
+ end
17
+
18
+ def total_genres
19
+ count(:genres)
20
+ end
21
+
22
+ def count(entity)
23
+ raise "unknown entity" unless %w{artists albums songs genres}.include?(entity.to_s)
24
+ cmd("info total #{entity.to_s} ?").to_i
25
+ end
26
+
27
+ # TODO this is ugly, refactor!
28
+ def artists
29
+ Models::Model.entities(Models::Artist, extract_data([:id, :artist, :textkey], cmd("artists 0 #{total_artists + 1} charset:utf8 tags:s")))
30
+ end
31
+
32
+ private
33
+
34
+ # TODO optimize this, attributes have to be in the correct order for the regex to match, which is stupid
35
+ def extract_data(attributes, data)
36
+ result = Array.new
37
+ data.scan Regexp.new(attributes.map{|a| "#{a.to_s}%3A([^\s]+)" }.join(" ")) do |match|
38
+ record = Hash.new
39
+ match.each_with_index do |field, index|
40
+ record[attributes[index]] = URI.unescape(field)
41
+ end
42
+ result << record
43
+ end
44
+ result.size == 1 ? result.first : result
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,22 @@
1
+ module Squeezer
2
+ class Client
3
+ module General
4
+
5
+ def version
6
+ cmd "version ?"
7
+ end
8
+
9
+ # TODO seems like my server doesn't respond to this command
10
+ def can(command)
11
+ cmd("can #{command} ?").to_boolean
12
+ end
13
+
14
+ def shutdown_server(sure=:no)
15
+ return false unless sure == :yes
16
+ cmd("shutdown")
17
+ true
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module Squeezer
2
+ class Client
3
+ module Players
4
+
5
+ # beware of offline players, they still show up on the list
6
+ # test if those players are connected with Player#connected?
7
+ def players
8
+ Models::Player.all
9
+ end
10
+
11
+ def find_player_by_name(name)
12
+ Models::Player.find_by_name(name)
13
+ end
14
+
15
+ def find_player_by_ip(ip)
16
+ Models::Player.find_by_ip(ip)
17
+ end
18
+
19
+ def find_player_by_id(id)
20
+ Models::Player.find_by_id(id)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module Squeezer
2
+ class Client
3
+ module Playlist
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Squeezer
2
+ class Client
3
+ module Utils
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Squeezer
2
+ class Client < API
3
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f}
4
+
5
+ include Squeezer::Client::Database
6
+ include Squeezer::Client::General
7
+ include Squeezer::Client::Players
8
+ include Squeezer::Client::Playlist
9
+
10
+ include Squeezer::Client::Utils
11
+ end
12
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path('../version', __FILE__)
2
+
3
+ module Squeezer
4
+ # Defines constants and methods related to configuration
5
+ module Configuration
6
+ # An array of valid keys in the options hash when configuring an {Squeezer::API}
7
+ VALID_OPTIONS_KEYS = [:server, :port].freeze
8
+
9
+ # By default, don't set an server
10
+ DEFAULT_SERVER = nil.freeze
11
+
12
+ # The port where the CLI interface is running on
13
+ #
14
+ # @note The default is set to 9090
15
+ DEFAULT_PORT = 9090.freeze
16
+
17
+ # @private
18
+ attr_accessor *VALID_OPTIONS_KEYS
19
+
20
+ # When this module is extended, set all configuration options to their default values
21
+ def self.extended(base)
22
+ base.reset
23
+ end
24
+
25
+ # Convenience method to allow configuration options to be set in a block
26
+ def configure
27
+ yield self
28
+ end
29
+
30
+ # Create a hash of options and their values
31
+ def options
32
+ VALID_OPTIONS_KEYS.inject({}) do |option, key|
33
+ option.merge!(key => send(key))
34
+ end
35
+ end
36
+
37
+ # Reset all configuration options to defaults
38
+ def reset
39
+ self.server = DEFAULT_SERVER
40
+ self.port = DEFAULT_PORT
41
+ self
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,48 @@
1
+ require 'net/telnet'
2
+
3
+ module Squeezer
4
+ # @private
5
+ module Connection
6
+
7
+ # don't forget to close the connection! Or else the connection stay's
8
+ # in memory of the eigenclass!
9
+ def exit
10
+ cmd("exit")
11
+ Connection.close_connection
12
+ end
13
+
14
+ private
15
+
16
+ def cmd(command, options={})
17
+ # TODO raise exceptions instead of returning false
18
+ response = connection.cmd(command)
19
+ puts response if options == :debug
20
+ return false if response.nil?
21
+ return true if response.strip.eql?(command)
22
+ result = response.gsub(command.gsub('?', '').strip, '').strip
23
+ result.force_encoding("UTF-8") unless /^1\.8/ === RUBY_VERSION
24
+ result
25
+ end
26
+
27
+ def connection
28
+ Connection.retrieve_connection
29
+ end
30
+
31
+ class << self
32
+ def close_connection
33
+ @connection.sock.close
34
+ @connection = nil
35
+ end
36
+
37
+ def retrieve_connection
38
+ @connection ||= open_connection
39
+ end
40
+
41
+ def open_connection
42
+ # do authentication and stuff
43
+ Net::Telnet.new("Host" => Squeezer.server, "Port" => Squeezer.port, "Telnetmode" => false, "Prompt" => /\n/)
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,6 @@
1
+ class String
2
+ def to_boolean
3
+ return true if self == "true" or self == "1"
4
+ return false if self == "false" or self == "0"
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Squeezer
2
+ module Models
3
+ class Artist < Model
4
+ attr_accessor :id, :artist, :textkey
5
+ alias :name :artist
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,190 @@
1
+ module Squeezer
2
+ module Models
3
+ class Player < Model
4
+
5
+ # most of these attributes are cached for the lifetime of the object, since they never change anyway
6
+
7
+ attr_reader :id
8
+
9
+ def initialize(id, options={})
10
+ super options
11
+ @id = id
12
+ end
13
+
14
+ def name
15
+ @name ||= cmd "player name #{id} ?"
16
+ end
17
+
18
+ def ip
19
+ @ip ||= URI.unescape(cmd("player ip #{id} ?")).split(":").first
20
+ end
21
+
22
+ def model
23
+ @model ||= cmd "player model #{id} ?"
24
+ end
25
+
26
+ # "transporter", "squeezebox2", "squeezebox", "slimp3", "softsqueeze", or "http"
27
+ def is_a?(value)
28
+ value = value.to_s if value.is_a?(Symbol)
29
+ model == value
30
+ end
31
+
32
+ def display_type
33
+ @display_type ||= cmd "player displaytype #{id} ?"
34
+ end
35
+
36
+ def can_power_off
37
+ @canpoweroff ||= cmd("player canpoweroff #{id} ?").to_boolean
38
+ end
39
+
40
+ def signal_strength
41
+ cmd("#{id} signalstrength ?").to_i
42
+ end
43
+
44
+ def wireless?
45
+ @wireless ||= (signal_strength != 0)
46
+ end
47
+
48
+ def connected?
49
+ cmd("#{id} connected ?").to_boolean
50
+ end
51
+
52
+ def volume=(value)
53
+ mixer(:volume, value)
54
+ end
55
+
56
+ def volume
57
+ mixer(:volume)
58
+ end
59
+
60
+ def bass=(value)
61
+ raise "command is not supported on this player's model: #{model}" unless %w{slimp3 squeezebox}.include?(model)
62
+ mixer(:bass, value)
63
+ end
64
+
65
+ def bass
66
+ mixer(:bass)
67
+ end
68
+
69
+ def treble=(value)
70
+ raise "command is not supported on this player's model: #{model}" unless %w{slimp3 squeezebox}.include?(model)
71
+ mixer(:treble, value)
72
+ end
73
+
74
+ def treble
75
+ mixer(:treble)
76
+ end
77
+
78
+ def pitch=(value)
79
+ raise "command is not supported on this player's model: #{model}" unless is_a?("squeezebox")
80
+ mixer(:pitch, value)
81
+ end
82
+
83
+ def pitch
84
+ mixer(:pitch)
85
+ end
86
+
87
+ def mixer(attribute, value="?")
88
+ raise "unknown attribute" unless %w{volume bass treble pitch}.include?(attribute.to_s)
89
+ modifier = "+" if value.is_a?(String) and value.include?("+")
90
+ result = cmd("#{id} mixer #{attribute.to_s} #{modifier}#{value == "?" ? "?" : value.to_i}")
91
+ result.respond_to?(:to_i) ? result.to_i : result
92
+ end
93
+
94
+ def power(state)
95
+ state_map = {:on => "1", :off => "0"}
96
+ raise "unknown power state" unless state_map.keys.include?(state)
97
+ result = cmd "#{id} power #{state_map[state]}"
98
+ result
99
+ end
100
+
101
+ def power?
102
+ on = cmd("#{id} power ?").to_boolean
103
+ return :on if on
104
+ return :off if not on
105
+ end
106
+
107
+ def on?
108
+ :on == power?
109
+ end
110
+
111
+ def off?
112
+ :off == power?
113
+ end
114
+
115
+ def on!
116
+ power(:on)
117
+ end
118
+
119
+ def off!
120
+ power(:off)
121
+ end
122
+
123
+ def <=>(target)
124
+ self.name <=> target.name
125
+ end
126
+
127
+ # TODO method_missing anyone? Those find methods could be nice with a ghost method.
128
+
129
+ # beware of offline players, they still show up on the list
130
+ # test if those players are connected with Player#connected?
131
+ def players
132
+ player_map = Hash.new
133
+ count = cmd("player count ?").to_i
134
+ count.to_i.times do |index|
135
+ id = cmd("player id #{index} ?")
136
+ player_map[id] = Models::Player.new(id)
137
+ end
138
+ player_map
139
+ end
140
+
141
+ def self.all
142
+ self.new(nil).players
143
+ end
144
+
145
+ # handle duplicates in these find methods, specs expect only one result
146
+ def find_by_name(name)
147
+ find(:name => name)
148
+ end
149
+
150
+ def self.find_by_name(name)
151
+ self.new(nil).find_by_name(name)
152
+ end
153
+
154
+ def find_by_ip(ip)
155
+ find(:ip => ip)
156
+ end
157
+
158
+ def self.find_by_ip(ip)
159
+ p = self.new(nil)
160
+ result = p.find_by_ip(ip)
161
+ p = nil
162
+ result
163
+ end
164
+
165
+ def find_by_id(id)
166
+ find(:id => id)
167
+ end
168
+
169
+ def self.find_by_id(id)
170
+ self.new(nil).find_by_id(id)
171
+ end
172
+
173
+ def find(values)
174
+ players.each do |id,player|
175
+ match = true
176
+ values.each do |property,value|
177
+ match = false unless player.send(property.to_sym) == value
178
+ end
179
+ return player if match == true
180
+ end
181
+ return nil
182
+ end
183
+
184
+ def self.find(values)
185
+ self.new(nil).find(values)
186
+ end
187
+
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,25 @@
1
+ module Squeezer
2
+ module Models
3
+
4
+ class Model < API
5
+
6
+ def self.entities(model, data)
7
+ result = Array.new
8
+ return result if data.nil?
9
+ data.each do |record|
10
+ entity = model.send(:new)
11
+ record.each do |attribute, value|
12
+ entity.send("#{attribute}=", value)
13
+ end
14
+ result << entity
15
+ end
16
+ result
17
+ end
18
+
19
+ end
20
+
21
+ Dir[File.expand_path('../models/*.rb', __FILE__)].each{|f| require f}
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,4 @@
1
+ module Squeezer
2
+ # The version of the gem
3
+ VERSION = '0.1.1'.freeze unless defined?(::Squeezer::VERSION)
4
+ end
data/lib/squeezer.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'uri'
2
+
3
+ require File.expand_path('../squeezer/core_extentions', __FILE__)
4
+ require File.expand_path('../squeezer/configuration', __FILE__)
5
+ require File.expand_path('../squeezer/api', __FILE__)
6
+ require File.expand_path('../squeezer/client', __FILE__)
7
+ require File.expand_path('../squeezer/models', __FILE__)
8
+
9
+ module Squeezer
10
+ extend Configuration
11
+
12
+ # Alias for Squeezer::Client.new
13
+ #
14
+ # @return [Squeezer::Client]
15
+ def self.client(options={})
16
+ Squeezer::Client.new(options)
17
+ end
18
+
19
+ # Delegate to Squeezer::Client
20
+ def self.method_missing(method, *args, &block)
21
+ return super unless client.respond_to?(method)
22
+ client.send(method, *args, &block)
23
+ end
24
+
25
+ end
@@ -0,0 +1,41 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_group 'Squeezer', 'lib/squeezer'
4
+ add_group 'Specs', 'spec'
5
+ end
6
+
7
+ #require 'mocha'
8
+ RSpec.configure do |config|
9
+ config.mock_with :mocha
10
+
11
+ config.before(:each) do
12
+ # TODO add authentication stuff to the mock
13
+ @connection = mock("connection")
14
+ sock = mock("sock")
15
+ sock.stubs(:close).returns(true)
16
+ @connection.stubs(:sock).returns(sock)
17
+ @connection.stubs(:cmd).with("exit")
18
+
19
+ # Net::Telnet.stubs(:new).returns(@connection)
20
+
21
+ # maybe find a better way to mock the connection? Because the mock
22
+ # stays in memory of the API's eigenclass if we mocked the telnet
23
+ # connection directly. So we mock the connection getter instead.
24
+ # But since we didn't find a way to mock a module method, we mock the
25
+ # getter per class.
26
+ Squeezer::Models::Player.any_instance.stubs(:connection).returns(@connection)
27
+ Squeezer::Client.any_instance.stubs(:connection).returns(@connection)
28
+ end
29
+
30
+ config.after(:each) do
31
+ # Squeezer.exit
32
+ end
33
+ end
34
+
35
+ require File.expand_path('../../lib/squeezer', __FILE__)
36
+
37
+ require 'rspec'
38
+
39
+ def stub_connection
40
+ @connection.stubs(:cmd)
41
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ describe Squeezer::Client do
4
+ before do
5
+ @client = Squeezer::Client.new
6
+ end
7
+
8
+ describe ".total_*" do
9
+ it "should return the entity's total artists" do
10
+ stub_connection.with("info total artists ?").returns("info total artists 2\n")
11
+ @client.total_artists.should == 2
12
+ end
13
+
14
+ it "should return the entity's total albums" do
15
+ stub_connection.with("info total albums ?").returns("info total albums 4\n")
16
+ @client.total_albums.should == 4
17
+ end
18
+
19
+ it "should return the entity's total genres" do
20
+ stub_connection.with("info total genres ?").returns("info total genres 6\n")
21
+ @client.total_genres.should == 6
22
+ end
23
+
24
+ it "should return the entity's total songs" do
25
+ stub_connection.with("info total songs ?").returns("info total songs 8\n")
26
+ @client.total_songs.should == 8
27
+ end
28
+ end
29
+
30
+ describe ".artists" do
31
+ before do
32
+ stub_connection.with("info total artists ?").returns("info total artists 1\n")
33
+ stub_connection.with("artists 0 2 charset:utf8 tags:s").returns("artists 0 2 charset%3Autf8 tags%3As id%3A4631 artist%3AVarious%20Artists textkey%3A%20 id%3A3998 artist%3A1200%20Micrograms textkey%3A1 count%3A434\n")
34
+ end
35
+
36
+ it "should return a list with Artist models" do
37
+ artists = @client.artists
38
+ artists.first.should be_a Squeezer::Models::Artist
39
+ end
40
+
41
+ it "should return a list with all the artists" do
42
+ artists = @client.artists
43
+ artists.should have(2).things
44
+ artists.first.name.should == "Various Artists"
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ describe Squeezer::Client do
4
+ before do
5
+ @client = Squeezer::Client.new
6
+ end
7
+
8
+ describe ".version" do
9
+ it "should return the server's API version" do
10
+ stub_connection.with("version ?").returns("version x.x.x\n")
11
+ @client.version.should == "x.x.x"
12
+ end
13
+ end
14
+
15
+ describe ".can" do
16
+ it "should test if the server can respond to the given command" do
17
+ stub_connection.with("can version ?").returns("can version 1\n")
18
+ @client.can("version").should be true
19
+ stub_connection.with("can foobar ?").returns("can foobar 0\n")
20
+ @client.can("foobar").should be false
21
+ end
22
+ end
23
+
24
+ describe ".shutdown_server" do
25
+ it "should shutdown the server" do
26
+ stub_connection.with("shutdown")
27
+ @client.shutdown_server(:yes).should be true
28
+ end
29
+
30
+ it "should not shutdown the server" do
31
+ stub_connection.with("shutdown")
32
+ @client.shutdown_server.should be false
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ describe Squeezer::Client do
4
+ before do
5
+ stub_connection.with("player count ?").returns("1\n")
6
+ stub_connection.with("player id 0 ?").returns("player id 0 player_id\n")
7
+ stub_connection.with("player name player_id ?").returns("player name player_id Squeezebox\n")
8
+ stub_connection.with("player ip player_id ?").returns("player ip player_id 127.0.0.1%3A12345\n")
9
+ @client = Squeezer::Client.new
10
+ end
11
+
12
+ describe ".players" do
13
+
14
+ it "should return all connected players" do
15
+ @client.players.should have(1).things
16
+ end
17
+
18
+ it "should return a player's id" do
19
+ @client.players["player_id"].id.should == "player_id"
20
+ end
21
+
22
+ it "should return a player's name" do
23
+ @client.players["player_id"].name.should == "Squeezebox"
24
+ end
25
+
26
+ end
27
+
28
+ describe ".find" do
29
+
30
+ it "should find a player by it's name" do
31
+ @client.find_player_by_name("Squeezebox").name.should == "Squeezebox"
32
+ end
33
+
34
+ it "should find a player by it's id" do
35
+ @client.find_player_by_id("player_id").name.should == "Squeezebox"
36
+ end
37
+
38
+ it "should find a player by it's ip" do
39
+ @client.find_player_by_ip("127.0.0.1").name.should == "Squeezebox"
40
+ end
41
+
42
+ # it "should find a player by a combination of search arguments" do
43
+ # @client.find(:id => "player_id", :ip => "127.0.0.1", :name => "Squeezebox").nil?.should be false
44
+ # end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Squeezer do
4
+ after do
5
+ Squeezer.reset
6
+ end
7
+
8
+ context "when delegating to a client" do
9
+
10
+ it "should return the same results as a client" do
11
+ stub_connection.with("version ?").returns("version x.x.x\n")
12
+ Squeezer.version.should == Squeezer::Client.new.version
13
+ end
14
+
15
+ end
16
+
17
+ describe ".client" do
18
+ it "should be a Squeezer::Client" do
19
+ Squeezer.client.should be_a Squeezer::Client
20
+ end
21
+ end
22
+
23
+ describe ".port" do
24
+ it "should return the default port" do
25
+ Squeezer.port.should == Squeezer::Configuration::DEFAULT_PORT
26
+ end
27
+ end
28
+
29
+ describe ".port=" do
30
+ it "should set the port" do
31
+ Squeezer.port = 1234
32
+ Squeezer.port.should == 1234
33
+ end
34
+ end
35
+
36
+ describe ".server=" do
37
+ it "should set the server" do
38
+ Squeezer.server = 'localhost'
39
+ Squeezer.server.should == 'localhost'
40
+ end
41
+ end
42
+
43
+ describe ".configure" do
44
+
45
+ Squeezer::Configuration::VALID_OPTIONS_KEYS.each do |key|
46
+
47
+ it "should set the #{key}" do
48
+ Squeezer.configure do |config|
49
+ config.send("#{key}=", key)
50
+ Squeezer.send(key).should == key
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ end
data/squeezer.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/squeezer/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.add_development_dependency('bundler', '~> 1.0')
6
+ s.add_development_dependency('rake', '~> 0.8')
7
+ s.add_development_dependency('rspec', '~> 2.3')
8
+ s.add_development_dependency('mocha', '~> 0.9.10')
9
+ s.add_development_dependency('simplecov', '~> 0.3')
10
+ s.add_development_dependency('maruku', '~> 0.6')
11
+ s.add_development_dependency('yard', '~> 0.6')
12
+
13
+ s.authors = ["Daniël van Hoesel"]
14
+ s.description = %q{A Ruby wrapper for the Squeezebox Server CLI API}
15
+ # s.post_install_message
16
+ s.email = ['daniel@danielvanhoesel.nl']
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.files = `git ls-files`.split("\n")
19
+ s.homepage = 'http://squeezer.rubyforge.org/'
20
+ s.name = 'squeezer-ruby'
21
+ s.platform = Gem::Platform::RUBY
22
+ s.require_paths = ['lib']
23
+ s.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if s.respond_to? :required_rubygems_version=
24
+ s.rubyforge_project = s.name
25
+ s.summary = %q{Ruby wrapper for the Squeezebox Server CLI API}
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.version = Squeezer::VERSION.dup
28
+ end
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: squeezer-ruby
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - "Dani\xC3\xABl van Hoesel"
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-08 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ version: "1.0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rake
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 8
45
+ version: "0.8"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 2
58
+ - 3
59
+ version: "2.3"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: mocha
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ~>
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ - 9
73
+ - 10
74
+ version: 0.9.10
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: simplecov
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 0
87
+ - 3
88
+ version: "0.3"
89
+ type: :development
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: maruku
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ~>
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
101
+ - 6
102
+ version: "0.6"
103
+ type: :development
104
+ version_requirements: *id006
105
+ - !ruby/object:Gem::Dependency
106
+ name: yard
107
+ prerelease: false
108
+ requirement: &id007 !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ~>
112
+ - !ruby/object:Gem::Version
113
+ segments:
114
+ - 0
115
+ - 6
116
+ version: "0.6"
117
+ type: :development
118
+ version_requirements: *id007
119
+ description: A Ruby wrapper for the Squeezebox Server CLI API
120
+ email:
121
+ - daniel@danielvanhoesel.nl
122
+ executables: []
123
+
124
+ extensions: []
125
+
126
+ extra_rdoc_files: []
127
+
128
+ files:
129
+ - .gitignore
130
+ - Gemfile
131
+ - LICENSE.mkd
132
+ - README.mkd
133
+ - Rakefile
134
+ - lib/squeezer.rb
135
+ - lib/squeezer/api.rb
136
+ - lib/squeezer/client.rb
137
+ - lib/squeezer/client/database.rb
138
+ - lib/squeezer/client/general.rb
139
+ - lib/squeezer/client/players.rb
140
+ - lib/squeezer/client/playlist.rb
141
+ - lib/squeezer/client/utils.rb
142
+ - lib/squeezer/configuration.rb
143
+ - lib/squeezer/connection.rb
144
+ - lib/squeezer/core_extentions.rb
145
+ - lib/squeezer/models.rb
146
+ - lib/squeezer/models/artist.rb
147
+ - lib/squeezer/models/player.rb
148
+ - lib/squeezer/version.rb
149
+ - spec/spec_helper.rb
150
+ - spec/squeezer/client/database_spec.rb
151
+ - spec/squeezer/client/general_spec.rb
152
+ - spec/squeezer/client/players_spec.rb
153
+ - spec/squeezer_spec.rb
154
+ - squeezer.gemspec
155
+ has_rdoc: true
156
+ homepage: http://squeezer.rubyforge.org/
157
+ licenses: []
158
+
159
+ post_install_message:
160
+ rdoc_options: []
161
+
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ none: false
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ segments:
170
+ - 0
171
+ version: "0"
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ none: false
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ segments:
178
+ - 1
179
+ - 3
180
+ - 6
181
+ version: 1.3.6
182
+ requirements: []
183
+
184
+ rubyforge_project: squeezer-ruby
185
+ rubygems_version: 1.3.7
186
+ signing_key:
187
+ specification_version: 3
188
+ summary: Ruby wrapper for the Squeezebox Server CLI API
189
+ test_files: []
190
+