bernstein 0.0.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 +7 -0
- data/.gitignore +5 -0
- data/Gemfile +9 -0
- data/LICENSE +21 -0
- data/README.md +57 -0
- data/Rakefile +23 -0
- data/bernstein.gemspec +22 -0
- data/bernstein.sample.yml +14 -0
- data/bin/bernstein +26 -0
- data/lib/bernstein/client.rb +34 -0
- data/lib/bernstein/message.rb +78 -0
- data/lib/bernstein/osc_connection.rb +20 -0
- data/lib/bernstein/redis_queue.rb +86 -0
- data/lib/bernstein/server.rb +41 -0
- data/lib/bernstein/states.rb +5 -0
- data/lib/bernstein/version.rb +3 -0
- data/lib/bernstein.rb +20 -0
- data/spec/bernstein/client_spec.rb +35 -0
- data/spec/bernstein/message_spec.rb +221 -0
- data/spec/bernstein/osc_connection_spec.rb +31 -0
- data/spec/bernstein/redis_queue_spec.rb +125 -0
- data/spec/bernstein/server_spec.rb +91 -0
- data/spec/helper.rb +15 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 28bd90208deb3660afce5ecadda52636d9c31e8c
|
4
|
+
data.tar.gz: e84c2e6717ed39563921b813f676e678b91e79f5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1c5605a448740f7e0940175e9c72ada85f6f6ea36e6d1c24fb53982cca179e8de9891cea93ed71da27294e12058eb022f3d8fdccc9dc2f66b25ae0c5236d97f9
|
7
|
+
data.tar.gz: 1e52a953484c378fc81638411255d5a6b1a4896995658639af604d9450ea770ee7a104c1581302126befaf76be1676d2c9880cd74e9697a8163f59213bf5a510
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Anthony Plekhov
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# Bernstein
|
2
|
+
|
3
|
+
Bernstein is a simple Ruby message queue for [OSC](http://en.wikipedia.org/wiki/Open_Sound_Control) messages
|
4
|
+
that gives Ruby the ability to asynchronously send messages to OSC-enabled software and hardware.
|
5
|
+
It is built on top of the [ruby-osc](https://github.com/maca/ruby-osc) libray and currently uses Redis to
|
6
|
+
queue the messages. Bernstein provides support for float,integer and string datatypes. In addition, it offers an
|
7
|
+
awk-mode that a client can use to be notified that an OSC message was delivered and awknowledged.
|
8
|
+
|
9
|
+
## Why is it useful?
|
10
|
+
|
11
|
+
While typical OSC communication is 1:1 between a client and an OSC consumer, Bernstein allows for many clients
|
12
|
+
to control an OSC device or process. For example, there could be a web interface adapting requests from
|
13
|
+
many users and sending them as OSC messages to a sound generator in an installation or performance.
|
14
|
+
See [here](https://github.com/aplekhov/bernstein-web).
|
15
|
+
Due to the queuing there is an inherent latency, however that might be neglible in certain situations.
|
16
|
+
|
17
|
+
|
18
|
+
## Basic Usage
|
19
|
+
|
20
|
+
gem install bernstein
|
21
|
+
|
22
|
+
Make sure that Redis is running. Start the background poller daemon:
|
23
|
+
|
24
|
+
bernstein start -- -c bernstein.yml
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'bernstein'
|
28
|
+
|
29
|
+
# see sample yml file for options
|
30
|
+
Bernstein.configure_from_yaml!('bernstein.yml')
|
31
|
+
|
32
|
+
# send a message string, all parameters will be converted to floats
|
33
|
+
msg_id = Bernstein::Client.send_message_by_string "/synths/4/filter_cutoff 0.5"
|
34
|
+
|
35
|
+
# send a message with specific types
|
36
|
+
msg_id = Bernstein::Client.send_message '/synth/params', 'sinewave', 440, 556.3, 334.0
|
37
|
+
|
38
|
+
# get status ('queued','sending','sent')
|
39
|
+
Bernstein::Client.message_status(msg_id)
|
40
|
+
```
|
41
|
+
|
42
|
+
Stop the background poller like this:
|
43
|
+
|
44
|
+
bernstein stop
|
45
|
+
|
46
|
+
## Default Configuration
|
47
|
+
See bernstein.sample.yml.
|
48
|
+
Note: if no redis options are passed, then the redis connection defaults will be used.
|
49
|
+
|
50
|
+
## Awk mode
|
51
|
+
By default, bernstein has awk mode enabled which means that it will send an internal message id along with every
|
52
|
+
message and expect the OSC receiver to respond back with an OSC 'awk' that contains the same message id. For many software
|
53
|
+
OSC implementations this is pretty easy to setup, however it is not likely to work with hardware. Make sure to disable it
|
54
|
+
using the `require_awks` config key.
|
55
|
+
|
56
|
+
## License
|
57
|
+
The MIT License. Copyright (c) 2014 Anthony Plekhov. See LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'rdoc/task'
|
3
|
+
|
4
|
+
desc "Run specs"
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
desc "Generate code coverage"
|
8
|
+
RSpec::Core::RakeTask.new(:coverage) do |t|
|
9
|
+
t.rcov = true
|
10
|
+
t.rcov_opts = ['--exclude', 'spec']
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Generate documentation for plugin.'
|
14
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
15
|
+
rdoc.rdoc_dir = 'rdoc'
|
16
|
+
rdoc.title = 'Timeliness'
|
17
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
18
|
+
rdoc.rdoc_files.include('README')
|
19
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Default: run specs.'
|
23
|
+
task :default => :spec
|
data/bernstein.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/bernstein/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Anthony Plekhov"]
|
6
|
+
gem.email = ["anthony.plekhov@gmail.com"]
|
7
|
+
gem.description = gem.summary = "Ruby OSC message queue"
|
8
|
+
gem.license = "MIT"
|
9
|
+
gem.executables = ['bernstein']
|
10
|
+
gem.files = `git ls-files`.split("\n")
|
11
|
+
gem.test_files = `git ls-files -- spec/*`.split("\n")
|
12
|
+
gem.name = "bernstein"
|
13
|
+
gem.require_paths = ["lib"]
|
14
|
+
gem.version = Bernstein::VERSION
|
15
|
+
gem.add_dependency 'redis', '>= 3.1.0'
|
16
|
+
gem.add_dependency 'redis-namespace', '>= 1.5.1'
|
17
|
+
gem.add_dependency 'eventmachine', '>= 1.0.3'
|
18
|
+
gem.add_dependency 'json', '>= 1.8.1'
|
19
|
+
gem.add_dependency 'daemons', '>= 1.1.9'
|
20
|
+
gem.add_dependency 'ruby-osc', '>= 0.31.0'
|
21
|
+
gem.add_development_dependency 'rspec', '>= 3.1.0'
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# osc config for where osc messages need to be delivered
|
2
|
+
:osc_client:
|
3
|
+
:port: 9090
|
4
|
+
:host: '127.0.0.1'
|
5
|
+
# osc config that bernstein listens on for awk OSC messages
|
6
|
+
:osc_server:
|
7
|
+
:port: 9000
|
8
|
+
:host: '127.0.0.1'
|
9
|
+
:require_awks: true
|
10
|
+
# redis config, accepts all Redis gem options
|
11
|
+
:redis_queue:
|
12
|
+
:key_expiry: 300
|
13
|
+
:host: '127.0.0.1'
|
14
|
+
:port: 6379
|
data/bin/bernstein
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bernstein'
|
4
|
+
require 'daemons'
|
5
|
+
|
6
|
+
#options = {
|
7
|
+
# :backtrace => true,
|
8
|
+
# :ontop => true,
|
9
|
+
# :log_output => true,
|
10
|
+
#}
|
11
|
+
|
12
|
+
working_directory = Dir.pwd
|
13
|
+
config_opt_index = ARGV.find_index('-c')
|
14
|
+
if ARGV[0] == "start" && config_opt_index.nil?
|
15
|
+
puts "Usage: bundle exec bernstein [start|stop|restart] -- -c <bernstein yaml file>"
|
16
|
+
exit
|
17
|
+
else
|
18
|
+
init_proc = Proc.new do
|
19
|
+
Bernstein.configure_from_yaml!(File.join( working_directory, ARGV[config_opt_index + 1]))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Daemons.run_proc('bernstein') do
|
24
|
+
init_proc.call
|
25
|
+
Bernstein::Server.start
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Bernstein
|
2
|
+
class Client
|
3
|
+
##
|
4
|
+
# Example: Bernstein::Client.send_message("/synths/4/filter_cutoff .5")
|
5
|
+
# note: only accepts float arguments
|
6
|
+
#
|
7
|
+
def self.send_message_by_string(message_string)
|
8
|
+
msg = Message.build_from_string(message_string)
|
9
|
+
save_and_return_id(msg)
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Example: Bernstein::Client.send_message("/synths/frequencies", 440, 556.3 334.0")
|
14
|
+
# note: only accepts float arguments
|
15
|
+
#
|
16
|
+
def self.send_message(address = '/', *args)
|
17
|
+
msg = Message.build(address, *args)
|
18
|
+
save_and_return_id(msg)
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Example: Bernstein::Client.message_status("34246456458856")
|
23
|
+
#
|
24
|
+
def self.message_status(message_id)
|
25
|
+
Message.get_status(message_id)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def self.save_and_return_id(msg)
|
30
|
+
msg.save!
|
31
|
+
msg.id
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'ruby-osc'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Bernstein
|
5
|
+
class Message
|
6
|
+
attr_reader :id, :osc_message
|
7
|
+
@@persister = RedisQueue
|
8
|
+
@@osc_connection = OSCConnection
|
9
|
+
|
10
|
+
def initialize(osc_message, id = nil)
|
11
|
+
@osc_message = osc_message
|
12
|
+
@id = id || new_id
|
13
|
+
@is_saved = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.build(address = '', *args)
|
17
|
+
Message.new(OSC::Message.new(address, *args))
|
18
|
+
end
|
19
|
+
|
20
|
+
# only supports float arguments
|
21
|
+
def self.build_from_string(message_string)
|
22
|
+
address, args = parse_message_string(message_string)
|
23
|
+
Message.new(OSC::Message.new(address, *args))
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.deserialize(serialized_msg)
|
27
|
+
data = JSON.parse(serialized_msg)
|
28
|
+
Message.new OSC::Message.new(data['address'], *data['args']), data['id']
|
29
|
+
end
|
30
|
+
|
31
|
+
def serialize
|
32
|
+
{'id' => @id, 'address' => @osc_message.address, 'args' => @osc_message.args}.to_json
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.get_status(id)
|
36
|
+
@@persister.status(id)
|
37
|
+
end
|
38
|
+
|
39
|
+
def status
|
40
|
+
@@persister.status(@id)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.get_queued_messages
|
44
|
+
@@persister.queued_messages
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.set_as_sent!(id)
|
48
|
+
@@persister.mark_as_sent(id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def save!
|
52
|
+
unless @is_saved
|
53
|
+
@@persister.add(self)
|
54
|
+
@is_saved = true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def send!(expect_awk = true)
|
59
|
+
@@osc_connection.send_message self, expect_awk
|
60
|
+
@@persister.dequeue @id, !expect_awk
|
61
|
+
end
|
62
|
+
|
63
|
+
def ==(other)
|
64
|
+
(self.class == other.class) && (self.osc_message == other.osc_message) &&
|
65
|
+
(self.id == other.id)
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
def new_id
|
70
|
+
Time.now.to_f.to_s.delete('.')
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.parse_message_string message_string
|
74
|
+
message_array = message_string.split
|
75
|
+
[message_array.shift, message_array.map{|arg| arg.to_f}]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ruby-osc'
|
2
|
+
|
3
|
+
module Bernstein
|
4
|
+
class OSCConnection
|
5
|
+
include OSC
|
6
|
+
|
7
|
+
@options = {port: 8000, host: '127.0.0.1'}
|
8
|
+
|
9
|
+
def self.configure!(options = {})
|
10
|
+
@options.merge!(options || {})
|
11
|
+
@connection = OSC::Client.new @options[:port], @options[:host]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.send_message(message, with_message_id = true)
|
15
|
+
osc_message = message.osc_message
|
16
|
+
osc_message = OSC::Bundle.new(nil, osc_message, OSC::Message.new('/message_id', message.id)) if with_message_id
|
17
|
+
@connection.send osc_message
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'redis'
|
2
|
+
require 'redis-namespace'
|
3
|
+
|
4
|
+
module Bernstein
|
5
|
+
class RedisQueue
|
6
|
+
include States
|
7
|
+
|
8
|
+
QUEUE_SET = "queued_messages"
|
9
|
+
@options = {key_expiry: 300, redis: {}}
|
10
|
+
|
11
|
+
def self.configure!(options = {})
|
12
|
+
@options.merge!(options || {})
|
13
|
+
@redis = Redis::Namespace.new(:bernstein, :redis => Redis.new(@options[:redis]))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.add(message)
|
17
|
+
@redis.multi do
|
18
|
+
@redis.sadd QUEUE_SET, message.id
|
19
|
+
@redis.setex message.id, @options[:key_expiry], message.serialize
|
20
|
+
@redis.setex status_key(message.id), @options[:key_expiry], STATES[:queued]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.status(id)
|
25
|
+
@redis.get(status_key(id)) || STATES[:not_yet_queued]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.queued_messages
|
29
|
+
queued_message_ids = @redis.smembers QUEUE_SET
|
30
|
+
messages = []
|
31
|
+
unless queued_message_ids.empty?
|
32
|
+
messages = @redis.mget(queued_message_ids).compact
|
33
|
+
unless messages.empty?
|
34
|
+
messages.map!{|m| Message.deserialize(m)}
|
35
|
+
end
|
36
|
+
if messages.size < queued_message_ids.size
|
37
|
+
clean_up_queue(queued_message_ids - messages.map{|m| m.id})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
messages
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.clear
|
44
|
+
@redis.del QUEUE_SET
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.dequeue(id, mark_as_sent = false)
|
48
|
+
remove_and_change_status(id, (mark_as_sent ? STATES[:sent] : STATES[:sending]))
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.mark_as_sent(id)
|
52
|
+
set_status(id, STATES[:sent])
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def self.status_key(id)
|
57
|
+
"#{id}_status"
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.remove_and_change_status(id, status)
|
61
|
+
remove(id){ set_status(id, status) }
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.set_status(id, status)
|
65
|
+
@redis.setex status_key(id), @options[:key_expiry], status
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.remove(id)
|
69
|
+
if block_given?
|
70
|
+
@redis.multi do
|
71
|
+
@redis.srem QUEUE_SET, id
|
72
|
+
yield
|
73
|
+
end
|
74
|
+
else
|
75
|
+
@redis.srem QUEUE_SET, id
|
76
|
+
end
|
77
|
+
@redis.del id
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.clean_up_queue(ids_to_remove)
|
81
|
+
@redis.pipelined do
|
82
|
+
ids_to_remove.each{|id| @redis.srem QUEUE_SET, id}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'ruby-osc'
|
3
|
+
|
4
|
+
module Bernstein
|
5
|
+
class Server
|
6
|
+
@options = {port: 9000, host: '127.0.0.1', require_awks: true, poll_interval: 5, awk_address: '/awk_id'}
|
7
|
+
def self.configure!(options = {})
|
8
|
+
@options.merge!(options || {})
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.start
|
12
|
+
OSC.run do
|
13
|
+
@server = OSC::Server.new(@options[:port],@options[:host])
|
14
|
+
if @options[:require_awks]
|
15
|
+
@server.add_pattern @options[:awk_address] do |*args|
|
16
|
+
handle_awknowledgement(args[1])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
@timer = EventMachine::PeriodicTimer.new(@options[:poll_interval]) do
|
21
|
+
process_queued_messages
|
22
|
+
end
|
23
|
+
yield if block_given?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.stop
|
28
|
+
@server.stop unless @server.nil?
|
29
|
+
@timer.cancel unless @timer.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def self.process_queued_messages
|
34
|
+
Message.get_queued_messages.each{|m| m.send!(@options[:require_awks])}
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.handle_awknowledgement(id)
|
38
|
+
Message.set_as_sent!(id)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/bernstein.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bernstein/states'
|
2
|
+
require 'bernstein/redis_queue'
|
3
|
+
require 'bernstein/osc_connection'
|
4
|
+
require 'bernstein/message'
|
5
|
+
require 'bernstein/client'
|
6
|
+
require 'bernstein/server'
|
7
|
+
require 'bernstein/version'
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
module Bernstein
|
11
|
+
def self.configure_from_yaml!(file_path)
|
12
|
+
configure!(YAML.load_file(file_path))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configure!(options = {})
|
16
|
+
RedisQueue.configure!(options[:redis_queue])
|
17
|
+
OSCConnection.configure!(options[:osc_client])
|
18
|
+
Server.configure!(options[:osc_server])
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Bernstein::Client do
|
4
|
+
subject { Bernstein::Client }
|
5
|
+
|
6
|
+
describe "sending a message" do
|
7
|
+
it "should build the message object and return its id" do
|
8
|
+
id = subject.send_message_by_string("/synths/4/chord/notes 25 30 10")
|
9
|
+
expect(id).to_not be_nil
|
10
|
+
queued_messages = Bernstein::Message.get_queued_messages
|
11
|
+
message = queued_messages.find{|m| m.id == id}
|
12
|
+
expect(message).to_not be_nil
|
13
|
+
expect(message.osc_message.address).to eq("/synths/4/chord/notes")
|
14
|
+
expect(message.osc_message.args).to eq([25.0, 30.0, 10.0])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should accept arguments to build the message" do
|
18
|
+
id = subject.send_message("/synths/4/parameters", 20, 34.2, 'squarewave')
|
19
|
+
expect(id).to_not be_nil
|
20
|
+
queued_messages = Bernstein::Message.get_queued_messages
|
21
|
+
message = queued_messages.find{|m| m.id == id}
|
22
|
+
expect(message).to_not be_nil
|
23
|
+
expect(message.osc_message.address).to eq("/synths/4/parameters")
|
24
|
+
expect(message.osc_message.args).to eq([20, 34.2, 'squarewave'])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "querying a message's status by id" do
|
29
|
+
it "should return the current status or not yet queued" do
|
30
|
+
id = subject.send_message("/synths/4/chord/notes 25 30 10")
|
31
|
+
expect_state(subject.message_status(id), :queued)
|
32
|
+
expect_state(subject.message_status('123'), :not_yet_queued)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'ruby-osc'
|
3
|
+
|
4
|
+
class DummyPersister
|
5
|
+
attr_accessor :queue, :sent_messages, :message_states
|
6
|
+
def initialize
|
7
|
+
@queue, @sent_messages, @message_states = [],[], {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(message)
|
11
|
+
@queue << message
|
12
|
+
@message_states[message] = :queued
|
13
|
+
end
|
14
|
+
|
15
|
+
def queued_messages
|
16
|
+
@queue
|
17
|
+
end
|
18
|
+
|
19
|
+
def dequeue(id, mark_as_sent = false)
|
20
|
+
message = @queue.find{|m| m.id == id}
|
21
|
+
if !message.nil?
|
22
|
+
@message_states[message] = (mark_as_sent ? :sent : :sending)
|
23
|
+
@sent_messages << message
|
24
|
+
@queue.delete(message)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def mark_as_sent(id)
|
29
|
+
message = @message_states.keys.find{|m| m.id == id}
|
30
|
+
@message_states[message] = :sent unless message.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def status(id)
|
34
|
+
message = @message_states.keys.find{|m| m.id == id}
|
35
|
+
Bernstein::States::STATES[@message_states[message]]
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear
|
39
|
+
@queue.clear
|
40
|
+
@sent_messages.clear
|
41
|
+
@message_states.clear
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class DummyOSCConnection
|
46
|
+
attr_accessor :fail_send, :sent_messages, :sent_ids
|
47
|
+
def initialize
|
48
|
+
@fail_send, @sent_messages, @sent_ids = false, [], []
|
49
|
+
end
|
50
|
+
|
51
|
+
def send_message message, with_message_id = true
|
52
|
+
if @fail_send
|
53
|
+
throw "something went wrong"
|
54
|
+
else
|
55
|
+
@sent_messages << message
|
56
|
+
@sent_ids << message.id if with_message_id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe Bernstein::Message do
|
62
|
+
subject { Bernstein::Message }
|
63
|
+
|
64
|
+
before(:all) do
|
65
|
+
@mock_queue = DummyPersister.new
|
66
|
+
@mock_osc_connection = DummyOSCConnection.new
|
67
|
+
@real_persister = Bernstein::Message.class_variable_get('@@persister')
|
68
|
+
@real_osc_connection = Bernstein::Message.class_variable_get('@@osc_connection')
|
69
|
+
Bernstein::Message.class_variable_set('@@persister', @mock_queue)
|
70
|
+
Bernstein::Message.class_variable_set('@@osc_connection', @mock_osc_connection)
|
71
|
+
end
|
72
|
+
|
73
|
+
after(:all) do
|
74
|
+
Bernstein::Message.class_variable_set('@@persister', @real_persister)
|
75
|
+
Bernstein::Message.class_variable_set('@@osc_connection', @real_osc_connection)
|
76
|
+
end
|
77
|
+
|
78
|
+
before(:each) do
|
79
|
+
@mock_queue.clear
|
80
|
+
@message = Bernstein::Message.build_from_string("/test 1 2 3")
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "building a new message" do
|
84
|
+
it "should be able to be built from a message string and turn all parameters into floats" do
|
85
|
+
address = "/test/this/out"
|
86
|
+
args = ['1', '2', '3.5']
|
87
|
+
message = subject.build_from_string("#{address} #{args.join(' ')}")
|
88
|
+
expect(message.osc_message.address).to eq(address)
|
89
|
+
expect(message.osc_message.args).to eq(args.map{|a| a.to_f})
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be able to built from address and args, preserving types" do
|
93
|
+
address = "/test/this/out"
|
94
|
+
args = [5, 'pizza', 9.9, 2.0]
|
95
|
+
message = subject.build(address,*args)
|
96
|
+
expect(message.osc_message.address).to eq(address)
|
97
|
+
expect(message.osc_message.args).to eq(args)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should be able to be built from an already built osc message" do
|
101
|
+
msg = OSC::Message.new('/hi/msg','2',4)
|
102
|
+
message1 = subject.new(msg)
|
103
|
+
expect(message1.osc_message).to eq(msg)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should return a unique id" do
|
107
|
+
messages = []
|
108
|
+
5.times {|i| messages << subject.build_from_string("/test #{i}")}
|
109
|
+
messages.each do |message|
|
110
|
+
expect(message.id).to_not be_nil
|
111
|
+
(messages - [message]).each{|other_message| expect(other_message.id).to_not eq(message.id)}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be able to be built with a set id" do
|
116
|
+
address = "/test/this/out"
|
117
|
+
args = ['1', '2', '3']
|
118
|
+
id = "456"
|
119
|
+
osc_msg = OSC::Message.new(address, *args)
|
120
|
+
message = subject.new osc_msg, id
|
121
|
+
expect(message.id).to eq(id)
|
122
|
+
expect(message.osc_message.address).to eq(address)
|
123
|
+
expect(message.osc_message.args).to eq(args)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should be equal to another message with the same id, args and address" do
|
127
|
+
message1 = subject.build_from_string("/test 1 2 3")
|
128
|
+
message2 = subject.new(OSC::Message.new("/test", 1,2,3), message1.id)
|
129
|
+
message3 = subject.new(message2.osc_message, '999')
|
130
|
+
expect(message1).to eq(message2)
|
131
|
+
expect(message1).to_not eq(message3)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "serialization" do
|
136
|
+
it "should serialize and deserialize the osc message and id" do
|
137
|
+
@message = subject.build_from_string("/test 1 2 3.2345")
|
138
|
+
serialized_msg = @message.serialize
|
139
|
+
expect(@message).to eq(subject.deserialize(serialized_msg))
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should handle float, integer and string arguments" do
|
143
|
+
@message = subject.build("/test", 3.4567, 10, 'a_string')
|
144
|
+
serialized_msg = @message.serialize
|
145
|
+
expect(@message).to eq(subject.deserialize(serialized_msg))
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "saving a message" do
|
150
|
+
it "should add message onto the queue upon save" do
|
151
|
+
@message.save!
|
152
|
+
expect(@mock_queue.queue).to include(@message)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should not be able to add the same message onto the queue again" do
|
156
|
+
@message.save!
|
157
|
+
expect{@message.save!}.to_not change(@mock_queue.queue, :size)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "sending a message" do
|
162
|
+
before(:each) do
|
163
|
+
@message.save!
|
164
|
+
end
|
165
|
+
|
166
|
+
after(:each) do
|
167
|
+
@mock_osc_connection.fail_send = false
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should send the message and message id on the OSC connection and remove from queue" do
|
171
|
+
@message.send!
|
172
|
+
expect(@mock_osc_connection.sent_messages).to include(@message)
|
173
|
+
expect(@mock_osc_connection.sent_ids).to include(@message.id)
|
174
|
+
expect(@mock_queue.sent_messages).to include(@message)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should not mark the message as sent on the queue if there is an error" do
|
178
|
+
@mock_osc_connection.fail_send = true
|
179
|
+
@message.send rescue
|
180
|
+
expect(@mock_queue.sent_messages).to_not include(@message)
|
181
|
+
expect(@mock_osc_connection.sent_messages).to_not include(@message)
|
182
|
+
expect(@mock_osc_connection.sent_ids).to_not include(@message.id)
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should send the message and mark as sent and not ask to send message id along" do
|
186
|
+
@message.send!(false)
|
187
|
+
expect_state(@message.status, :sent)
|
188
|
+
expect(@mock_osc_connection.sent_messages).to include(@message)
|
189
|
+
expect(@mock_osc_connection.sent_ids).to_not include(@message.id)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "querying status" do
|
194
|
+
before(:each) do
|
195
|
+
@message.save!
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should return the current status for a message object" do
|
199
|
+
expect_state(@message.status, :queued)
|
200
|
+
@message.send!
|
201
|
+
expect_state(@message.status, :sending)
|
202
|
+
@mock_queue.mark_as_sent(@message.id)
|
203
|
+
expect_state(@message.status, :sent)
|
204
|
+
end
|
205
|
+
|
206
|
+
it "should return the current status by message id" do
|
207
|
+
expect_state(subject.get_status(@message.id), :queued)
|
208
|
+
@message.send!(false)
|
209
|
+
expect_state(subject.get_status(@message.id), :sent)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "getting queued messages" do
|
214
|
+
it "should return all queued messages" do
|
215
|
+
@message.save!
|
216
|
+
@message2 = subject.build_from_string("/test/2 4 5 6")
|
217
|
+
@message2.save!
|
218
|
+
expect(subject.get_queued_messages).to eq([@message, @message2])
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
def current_client
|
4
|
+
Bernstein::OSCConnection.instance_variable_get('@connection')
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Bernstein::OSCConnection do
|
8
|
+
describe "configuring" do
|
9
|
+
it "should instantiate a new osc client based on the port and host that was given" do
|
10
|
+
expect(OSC::Client).to receive(:new).with(9000, '10.10.10.1')
|
11
|
+
Bernstein::OSCConnection.configure!({port: 9000, host: '10.10.10.1'})
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "sending a message" do
|
16
|
+
it "should create a new osc message from the passed in message and call send on the client" do
|
17
|
+
Bernstein::OSCConnection.configure!({port: 9000, host: '10.10.10.1'})
|
18
|
+
expect(OSC::Message).to receive(:new).with('/test', 1.0,2.0,3.0).and_return("mock")
|
19
|
+
message1 = Bernstein::Message.build_from_string("/test 1 2 3")
|
20
|
+
expect(current_client).to receive(:send).with("mock")
|
21
|
+
Bernstein::OSCConnection.send_message(message1, false)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should send a bundle when asked to send message id" do
|
25
|
+
Bernstein::OSCConnection.configure!({port: 9000, host: '10.10.10.1'})
|
26
|
+
message1 = Bernstein::Message.build_from_string("/test 1 2 3")
|
27
|
+
expect(current_client).to receive(:send).with(kind_of(OSC::Bundle))
|
28
|
+
Bernstein::OSCConnection.send_message(message1, true)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
def redis_connection
|
4
|
+
Bernstein::RedisQueue.instance_variable_get('@redis')
|
5
|
+
end
|
6
|
+
|
7
|
+
def redis_queue
|
8
|
+
redis_connection.smembers(Bernstein::RedisQueue::QUEUE_SET)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Bernstein::RedisQueue do
|
12
|
+
subject { Bernstein::RedisQueue }
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
@message = Bernstein::Message.build_from_string("/test/3 1 2.55 4")
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "initialization and configuration" do
|
19
|
+
after(:all){Bernstein::RedisQueue.configure!({redis:{}})}
|
20
|
+
|
21
|
+
it "should pass redis options to initialize a new redis connection" do
|
22
|
+
redis_opts = {host: "10.0.1.1", port: 6380, db: 15}
|
23
|
+
expect(Redis).to receive(:new).with(redis_opts).and_call_original
|
24
|
+
Bernstein::RedisQueue.configure!({key_expiry: 600, redis: redis_opts})
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should be namespaced" do
|
28
|
+
expect(redis_connection.class).to eq(Redis::Namespace)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "adding a new message" do
|
33
|
+
it "should serialize the message and add it to the proper sets" do
|
34
|
+
subject.add(@message)
|
35
|
+
data = redis_connection.get(@message.id)
|
36
|
+
expect(Bernstein::Message.deserialize(data)).to eq(@message)
|
37
|
+
expect(redis_queue).to include(@message.id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "expired messages" do
|
42
|
+
before(:all) do
|
43
|
+
@key_expiry = 1
|
44
|
+
Bernstein::RedisQueue.configure! key_expiry: @key_expiry
|
45
|
+
end
|
46
|
+
|
47
|
+
after(:all) do
|
48
|
+
Bernstein::RedisQueue.configure! key_expiry: 300
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should expire messages based on set expiry times" do
|
52
|
+
subject.add(@message)
|
53
|
+
expect_state(subject.status(@message.id), :queued)
|
54
|
+
expect(redis_connection.get(@message.id)).to_not be_nil
|
55
|
+
sleep @key_expiry + 1
|
56
|
+
expect(redis_connection.get(@message.id)).to be_nil
|
57
|
+
expect_state(subject.status(@message.id), :not_yet_queued)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should expire messages that have had their status changed" do
|
61
|
+
subject.add(@message)
|
62
|
+
subject.mark_as_sent(@message.id)
|
63
|
+
expect_state(subject.status(@message.id), :sent)
|
64
|
+
sleep @key_expiry + 1
|
65
|
+
expect_state(subject.status(@message.id), :not_yet_queued)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should clean up request_queue of unhandled expired messages" do
|
69
|
+
subject.add(@message)
|
70
|
+
expect(subject.queued_messages).to include(@message)
|
71
|
+
sleep @key_expiry + 1
|
72
|
+
@another_message = Bernstein::Message.build_from_string("/test/current 5 6 7")
|
73
|
+
subject.add(@another_message)
|
74
|
+
queued_messages = subject.queued_messages
|
75
|
+
queue_set = redis_queue
|
76
|
+
expect(queued_messages).to_not include(@message)
|
77
|
+
expect(queued_messages).to include(@another_message)
|
78
|
+
expect(queue_set).to_not include(@message.id)
|
79
|
+
expect(queue_set).to include(@another_message.id)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "marking and requesting status" do
|
84
|
+
it "should return not yet sent queued for unknown messages" do
|
85
|
+
expect_state(subject.status('123456'), :not_yet_queued)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should set new messages' status to queued" do
|
89
|
+
subject.add(@message)
|
90
|
+
expect_state(subject.status(@message.id), :queued)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should mark a message as sent" do
|
94
|
+
subject.add(@message)
|
95
|
+
subject.mark_as_sent(@message.id)
|
96
|
+
expect_state(subject.status(@message.id), :sent)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should dequeue messages and set them to sending state by default" do
|
100
|
+
subject.add(@message)
|
101
|
+
subject.dequeue(@message.id)
|
102
|
+
expect_state(subject.status(@message.id), :sending)
|
103
|
+
expect(redis_queue).to_not include(@message.id)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should dequeue messages and set their state straight to sent" do
|
107
|
+
subject.add(@message)
|
108
|
+
subject.dequeue(@message.id, true)
|
109
|
+
expect_state(subject.status(@message.id), :sent)
|
110
|
+
expect(redis_queue).to_not include(@message.id)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "getting queued messages" do
|
115
|
+
it "should pull queued messages and deserialize them" do
|
116
|
+
subject.clear
|
117
|
+
message = Bernstein::Message.build_from_string("/test/1 1")
|
118
|
+
message2 = Bernstein::Message.build_from_string("/test/2 1 2")
|
119
|
+
message3 = Bernstein::Message.build_from_string("/test/3 1 2 3")
|
120
|
+
messages = [message, message2, message3]
|
121
|
+
messages.each{|m| subject.add(m)}
|
122
|
+
expect(subject.queued_messages.sort{|a,b| a.id <=> b.id}).to eq(messages.sort{|a,b| a.id <=> b.id})
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'ruby-osc'
|
3
|
+
require 'eventmachine'
|
4
|
+
|
5
|
+
describe Bernstein::Server do
|
6
|
+
describe "initialization and configuration" do
|
7
|
+
it "should pass options to initialize a new OSC server" do
|
8
|
+
opts = {port: 9004, host: '127.0.0.1'}
|
9
|
+
expect(OSC::Server).to receive(:new).with(opts[:port], opts[:host]).and_call_original
|
10
|
+
Bernstein::Server.configure!(opts)
|
11
|
+
Bernstein::Server.start do
|
12
|
+
Bernstein::Server.stop
|
13
|
+
EventMachine.stop_event_loop
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "processing queued messages" do
|
19
|
+
before(:each) do
|
20
|
+
connection = Bernstein::Message.class_variable_get('@@osc_connection')
|
21
|
+
allow(connection).to receive(:send_message)
|
22
|
+
Bernstein::RedisQueue.clear
|
23
|
+
@message = Bernstein::Client.send_message_by_string("/test/1 1")
|
24
|
+
@message2 = Bernstein::Client.send_message_by_string("/test/2 1 2")
|
25
|
+
@message3 = Bernstein::Client.send_message_by_string("/test/3 1 2 3")
|
26
|
+
[@message, @message2, @message3].each do |message_id|
|
27
|
+
expect_state(Bernstein::Client.message_status(message_id), :queued)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
it "should call send on all queued messages" do
|
33
|
+
Bernstein::Server.configure!({poll_interval:1, require_awks:true})
|
34
|
+
Bernstein::Server.start do
|
35
|
+
EventMachine.add_timer 4 do
|
36
|
+
Bernstein::Server.stop
|
37
|
+
EventMachine.stop_event_loop
|
38
|
+
end
|
39
|
+
end
|
40
|
+
[@message, @message2, @message3].each do |message_id|
|
41
|
+
expect_state(Bernstein::Client.message_status(message_id), :sending)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "awks" do
|
47
|
+
before(:each) do
|
48
|
+
connection = Bernstein::Message.class_variable_get('@@osc_connection')
|
49
|
+
allow(connection).to receive(:send_message)
|
50
|
+
Bernstein::RedisQueue.clear
|
51
|
+
@message_id = Bernstein::Client.send_message_by_string("/test/1 1")
|
52
|
+
expect_state(Bernstein::Client.message_status(@message_id), :queued)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should listen for awks and set messages with corresponding ids to sent if configured" do
|
56
|
+
Bernstein::Server.configure!({port: 9090, host: '127.0.0.1', poll_interval: 1, require_awks: true})
|
57
|
+
Bernstein::Server.start do
|
58
|
+
client = OSC::Client.new 9090
|
59
|
+
EventMachine.add_timer 2 do
|
60
|
+
expect_state(Bernstein::Client.message_status(@message_id), :sending)
|
61
|
+
end
|
62
|
+
EventMachine.add_timer 3 do
|
63
|
+
client.send OSC::Message.new('/awk_id', @message_id)
|
64
|
+
end
|
65
|
+
EventMachine.add_timer 4 do
|
66
|
+
Bernstein::Server.stop
|
67
|
+
EventMachine.stop_event_loop
|
68
|
+
end
|
69
|
+
end
|
70
|
+
expect_state(Bernstein::Client.message_status(@message_id), :sent)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should not listen for awks and set messages directly to sent if configured" do
|
74
|
+
Bernstein::Server.configure!({port: 9090, host: '127.0.0.1', require_awks: false, poll_interval: 1})
|
75
|
+
Bernstein::Server.start do
|
76
|
+
client = OSC::Client.new 9090
|
77
|
+
EventMachine.add_timer 2 do
|
78
|
+
expect_state(Bernstein::Client.message_status(@message_id), :sent)
|
79
|
+
end
|
80
|
+
EventMachine.add_timer 3 do
|
81
|
+
client.send OSC::Message.new('/awk_id', @message_id)
|
82
|
+
end
|
83
|
+
EventMachine.add_timer 4 do
|
84
|
+
Bernstein::Server.stop
|
85
|
+
EventMachine.stop_event_loop
|
86
|
+
end
|
87
|
+
end
|
88
|
+
expect_state(Bernstein::Client.message_status(@message_id), :sent)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
$:.unshift( File.join( File.dirname( __FILE__), '..', 'lib' ) )
|
3
|
+
require 'bernstein'
|
4
|
+
|
5
|
+
RSpec.configure do |c|
|
6
|
+
c.mock_with :rspec
|
7
|
+
end
|
8
|
+
|
9
|
+
Bernstein.configure!
|
10
|
+
|
11
|
+
include Bernstein::States
|
12
|
+
|
13
|
+
def expect_state(something, state)
|
14
|
+
expect(something).to eq(STATES[state])
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bernstein
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anthony Plekhov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redis
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis-namespace
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.5.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.5.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: eventmachine
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.8.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.8.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: daemons
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.1.9
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.1.9
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ruby-osc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.31.0
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.31.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.1.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.1.0
|
111
|
+
description: Ruby OSC message queue
|
112
|
+
email:
|
113
|
+
- anthony.plekhov@gmail.com
|
114
|
+
executables:
|
115
|
+
- bernstein
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- .gitignore
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bernstein.gemspec
|
125
|
+
- bernstein.sample.yml
|
126
|
+
- bin/bernstein
|
127
|
+
- lib/bernstein.rb
|
128
|
+
- lib/bernstein/client.rb
|
129
|
+
- lib/bernstein/message.rb
|
130
|
+
- lib/bernstein/osc_connection.rb
|
131
|
+
- lib/bernstein/redis_queue.rb
|
132
|
+
- lib/bernstein/server.rb
|
133
|
+
- lib/bernstein/states.rb
|
134
|
+
- lib/bernstein/version.rb
|
135
|
+
- spec/bernstein/client_spec.rb
|
136
|
+
- spec/bernstein/message_spec.rb
|
137
|
+
- spec/bernstein/osc_connection_spec.rb
|
138
|
+
- spec/bernstein/redis_queue_spec.rb
|
139
|
+
- spec/bernstein/server_spec.rb
|
140
|
+
- spec/helper.rb
|
141
|
+
homepage:
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
148
|
+
- lib
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubyforge_project:
|
161
|
+
rubygems_version: 2.4.2
|
162
|
+
signing_key:
|
163
|
+
specification_version: 4
|
164
|
+
summary: Ruby OSC message queue
|
165
|
+
test_files:
|
166
|
+
- spec/bernstein/client_spec.rb
|
167
|
+
- spec/bernstein/message_spec.rb
|
168
|
+
- spec/bernstein/osc_connection_spec.rb
|
169
|
+
- spec/bernstein/redis_queue_spec.rb
|
170
|
+
- spec/bernstein/server_spec.rb
|
171
|
+
- spec/helper.rb
|