qcmd 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,84 +0,0 @@
1
- module OSC
2
- class StoppingServer < Server
3
- def initialize *args
4
- @state = :initialized
5
- @port = args.first
6
- super(*args)
7
- end
8
-
9
- def run
10
- @state = :starting
11
- super
12
- end
13
-
14
- def stop
15
- @state = :stopping
16
- stop_detector
17
- stop_dispatcher
18
- end
19
-
20
- def state
21
- @state
22
- end
23
-
24
- private
25
-
26
- def stop_detector
27
- # send listening port a "CLOSE" signal on the open UDP port
28
- _closer = UDPSocket.new
29
- _closer.connect('', @port)
30
- _closer.puts "CLOSE-#{@port}"
31
- _closer.close unless _closer.closed? || !_closer.respond_to?(:close)
32
- end
33
-
34
- def stop_dispatcher
35
- @queue << :stop
36
- end
37
-
38
- def dispatcher
39
- loop do
40
- mesg = @queue.pop
41
- dispatch_message( mesg )
42
- end
43
- rescue StopException
44
- @state = :stopped
45
- end
46
-
47
- def dispatch_message message
48
- if message.is_a?(Symbol) && message.to_s == 'stop'
49
- raise StopException.new
50
- end
51
-
52
- super(message)
53
- end
54
-
55
- def detector
56
- @state = :listening
57
-
58
- loop do
59
- osc_data, network = @socket.recvfrom( 16384 )
60
-
61
- # quit if socket receives the close signal
62
- if osc_data == "CLOSE-#{@port}"
63
- @socket.close if !@socket.closed? && @socket.respond_to?(:close)
64
- break
65
- end
66
-
67
- unpack_socket_receipt osc_data, network
68
- end
69
- end
70
-
71
- def unpack_socket_receipt osc_data, network
72
- ip_info = Array.new
73
- ip_info << network[1]
74
- ip_info.concat(network[2].split('.'))
75
- OSC::OSCPacket.messages_from_network( osc_data, ip_info ).each do |message|
76
- @queue.push(message)
77
- end
78
- rescue EOFError
79
- # pass
80
- end
81
- end
82
-
83
- class StopException < Exception; end
84
- end
@@ -1,175 +0,0 @@
1
- require 'osc-ruby'
2
-
3
- require 'json'
4
-
5
- module Qcmd
6
- class TimeoutError < Exception; end
7
-
8
- class Server
9
- attr_accessor :receive_channel, :receive_thread, :receive_port, :send_channel, :machine
10
-
11
- def initialize *args
12
- options = args.extract_options!
13
-
14
- self.receive_port = options[:receive]
15
- connect_to_client
16
-
17
- @handler = Qcmd::Handler.new
18
- @sent_messages = []
19
- @sent_messages_expecting_reply = []
20
- @received_messages = []
21
- end
22
-
23
- def connect_to_client
24
- self.machine = Qcmd.context.machine
25
- self.send_channel = OSC::Client.new machine.address, machine.port
26
-
27
- Qcmd.debug '(setting up listening connection)'
28
- listen
29
- end
30
-
31
- def generic_responding_proc
32
- proc do |osc_message|
33
- @received_messages << osc_message
34
-
35
- begin
36
- Qcmd.debug "(received message: #{ osc_message.address })"
37
- reply_received QLab::Reply.new(osc_message)
38
- rescue => ex
39
- Qcmd.debug "(ERROR #{ ex.message })"
40
- end
41
- end
42
- end
43
-
44
- # initialize
45
- def listen
46
- if receive_channel
47
- stop
48
- end
49
-
50
- self.receive_channel = OSC::StoppingServer.new(self.receive_port)
51
-
52
- Qcmd.debug "(opening receiving channel: #{ self.receive_channel.inspect })"
53
-
54
- receive_channel.add_method %r{/reply/?(.*)}, &generic_responding_proc
55
- end
56
-
57
- def replies_expected?
58
- @sent_messages_expecting_reply.size > 0
59
- end
60
-
61
- def reply_received reply
62
- Qcmd.debug "(receiving #{ reply })"
63
-
64
- # update world state
65
- begin
66
- @handler.handle reply
67
- rescue => ex
68
- print "(ERROR: #{ ex.message })"
69
- end
70
-
71
- # FIFO
72
- @sent_messages_expecting_reply.shift
73
-
74
- Qcmd.debug "(#{ @sent_messages_expecting_reply.size } messages awaiting reply)"
75
- end
76
-
77
- def wait_for_replies
78
- begin
79
- yield
80
-
81
- naps = 0
82
- while replies_expected? do
83
- if naps > 20
84
- # FAILED TO GET RESPONSE
85
- raise TimeoutError.new
86
- end
87
-
88
- naps += 1
89
- sleep 0.1
90
- end
91
- rescue TimeoutError => ex
92
- Qcmd.log "[error: reply timeout]"
93
- # clear expecting reply item, assume it will never arrive
94
- @sent_messages_expecting_reply.shift
95
- end
96
- end
97
-
98
- def send_command command, *args
99
- options = args.extract_options!
100
-
101
- Qcmd.debug "(building command from command, args, options: #{ command.inspect }, #{ args.inspect }, #{ options.inspect })"
102
-
103
- # make sure command is valid OSC Address
104
- if %r[^/] =~ command
105
- address = command
106
- else
107
- address = "/#{ command }"
108
- end
109
-
110
- osc_message = OSC::Message.new address, *args
111
-
112
- send_message osc_message
113
- end
114
-
115
- def send_message osc_message
116
- Qcmd.debug "(sending osc message #{ osc_message.address } #{osc_message.has_arguments? ? 'with' : 'without'} args)"
117
-
118
- @sent_messages << osc_message
119
- if Qcmd::Commands.expects_reply?(osc_message)
120
- Qcmd.debug "(this command expects a reply)"
121
- @sent_messages_expecting_reply << osc_message
122
- end
123
-
124
- wait_for_replies do
125
- send_channel.send osc_message
126
- end
127
- end
128
-
129
- def stop
130
- receive_channel.stop if receive_channel && receive_channel.state == :listening
131
- end
132
-
133
- def run
134
- Qcmd.debug '(starting server)'
135
- self.receive_thread = Thread.new do
136
- Qcmd.debug '(server is up)'
137
- receive_channel.run
138
- end
139
- end
140
- alias :start :run
141
-
142
- def send_workspace_command _command, *args
143
- command = "workspace/#{ Qcmd.context.workspace.id }/#{ _command }"
144
- send_command(command, *args)
145
- end
146
-
147
- def send_cue_command number, action, *args
148
- command = "cue/#{ number }/#{ action }"
149
- send_workspace_command(command, *args)
150
- end
151
-
152
- ## QLab commands
153
-
154
- def load_workspaces
155
- send_command 'workspaces'
156
- end
157
-
158
- def load_cues
159
- send_workspace_command 'cueLists'
160
- end
161
-
162
- def connect_to_workspace workspace
163
- if workspace.passcode?
164
- send_command "workspace/#{workspace.id}/connect", "%04i" % workspace.passcode
165
- else
166
- send_command "workspace/#{workspace.id}/connect"
167
- end
168
-
169
- # if it worked, load cues automatically
170
- if Qcmd.context.workspace
171
- load_cues
172
- end
173
- end
174
- end
175
- end
@@ -1,78 +0,0 @@
1
- require File.join( File.dirname(__FILE__) , '..', 'spec_helper' )
2
- require 'qcmd'
3
- require 'socket'
4
-
5
- class PortFactory
6
- @@counter = 12345
7
-
8
- def self.new_port
9
- @@counter += 1
10
- @@counter
11
- end
12
- end
13
-
14
- describe OSC::StoppingServer do
15
- before :each do
16
- @port = PortFactory.new_port
17
- end
18
-
19
- it "should bind to a socket when initialized" do
20
- UDPSocket.any_instance.should_receive(:bind).with('', @port)
21
- server = OSC::StoppingServer.new @port
22
- end
23
-
24
- it 'should start a listening thread when started' do
25
- server = OSC::StoppingServer.new @port
26
-
27
- test_thread = Thread.new do
28
- Thread.should_receive :fork
29
- server.run
30
- end
31
-
32
- server.stop
33
- end
34
-
35
- it 'should kill the listening thread and close socket when stopped' do
36
- server = OSC::StoppingServer.new @port
37
-
38
- test_thread = Thread.new do
39
- server.run
40
- end
41
-
42
- sleep 0.1
43
- server.stop
44
- sleep 0.1
45
-
46
- # server has stopped blocking
47
- test_thread.alive?.should == false
48
-
49
- # server claims it is closed
50
- server.state.should == :stopped
51
- end
52
-
53
- it 'should create messages for legitimate OSC commands' do
54
- server = OSC::StoppingServer.new @port
55
-
56
- received = nil
57
-
58
- server.add_method '/test' do |message|
59
- received = message
60
- end
61
-
62
- test_thread = Thread.new do
63
- server.run
64
- end
65
-
66
- received.should == nil
67
-
68
- client = OSC::Client.new 'localhost', @port
69
- client.send OSC::Message.new('/test', 'ansible')
70
-
71
- sleep 0.1
72
- server.stop
73
-
74
- received.is_a?(OSC::Message).should == true
75
- received.to_a.first.should == 'ansible'
76
- end
77
- end
78
-