Class: Qcmd::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/qcmd/server.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Server

Returns a new instance of Server.



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/qcmd/server.rb', line 16

def initialize *args
  options = args.extract_options!

  self.receive_port = options[:receive]
  connect_to_client

  @handler = Qcmd::Handler.new
  @sent_messages = []
  @sent_messages_expecting_reply = []
  @received_messages = []
end

Instance Attribute Details

#machineObject

Returns the value of attribute machine.



14
15
16
# File 'lib/qcmd/server.rb', line 14

def machine
  @machine
end

#receive_channelObject

Returns the value of attribute receive_channel.



14
15
16
# File 'lib/qcmd/server.rb', line 14

def receive_channel
  @receive_channel
end

#receive_portObject

Returns the value of attribute receive_port.



14
15
16
# File 'lib/qcmd/server.rb', line 14

def receive_port
  @receive_port
end

#receive_threadObject

Returns the value of attribute receive_thread.



14
15
16
# File 'lib/qcmd/server.rb', line 14

def receive_thread
  @receive_thread
end

#send_channelObject

Returns the value of attribute send_channel.



14
15
16
# File 'lib/qcmd/server.rb', line 14

def send_channel
  @send_channel
end

Instance Method Details

#connect_to_clientObject



28
29
30
31
32
33
34
# File 'lib/qcmd/server.rb', line 28

def connect_to_client
  self.machine = Qcmd.context.machine
  self.send_channel = OSC::Client.new machine.address, machine.port

  Qcmd.debug '(setting up listening connection)'
  listen
end

#connect_to_workspace(workspace) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/qcmd/server.rb', line 168

def connect_to_workspace workspace
  if workspace.passcode?
    send_command "workspace/#{workspace.id}/connect", "%04i" % workspace.passcode
  else
    send_command "workspace/#{workspace.id}/connect"
  end

  # if it worked, load cues automatically
  if Qcmd.context.workspace
    load_cues
  end
end

#generic_responding_procObject



36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/qcmd/server.rb', line 36

def generic_responding_proc
  proc do |osc_message|
    @received_messages << osc_message

    begin
      Qcmd.debug "(received message: #{ osc_message.address })"
      reply_received QLab::Reply.new(osc_message)
    rescue => ex
      Qcmd.debug "(ERROR #{ ex.message })"
    end
  end
end

#listenObject

initialize



50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/qcmd/server.rb', line 50

def listen
  if receive_channel
    Qcmd.debug "(stopping existing server)"
    stop
  end

  self.receive_channel = OSC::EMServer.new(self.receive_port)

  Qcmd.debug "(opening receiving channel: #{ self.receive_channel.inspect })"

  receive_channel.add_method %r{/reply/?(.*)}, &generic_responding_proc
end

#load_cuesObject



164
165
166
# File 'lib/qcmd/server.rb', line 164

def load_cues
  send_workspace_command 'cueLists'
end

#load_workspacesObject

QLab commands



160
161
162
# File 'lib/qcmd/server.rb', line 160

def load_workspaces
  send_command 'workspaces'
end

#replies_expected?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/qcmd/server.rb', line 63

def replies_expected?
  @sent_messages_expecting_reply.size > 0
end

#reply_received(reply) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/qcmd/server.rb', line 67

def reply_received reply
  Qcmd.debug "(receiving #{ reply })"

  # update world state
  begin
    @handler.handle reply
  rescue => ex
    print "(ERROR: #{ ex.message })"
  end

  # FIFO
  @sent_messages_expecting_reply.shift

  Qcmd.debug "(#{ @sent_messages_expecting_reply.size } messages awaiting reply)"
end

#runObject Also known as: start



139
140
141
142
143
144
145
# File 'lib/qcmd/server.rb', line 139

def run
  Qcmd.debug '(starting server)'
  self.receive_thread = Thread.new do
    Qcmd.debug '(server is up)'
    receive_channel.run
  end
end

#send_command(command, *args) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/qcmd/server.rb', line 104

def send_command command, *args
  options = args.extract_options!

  Qcmd.debug "(building command from command, args, options: #{ command.inspect }, #{ args.inspect }, #{ options.inspect })"

  # make sure command is valid OSC Address
  if %r[^/] =~ command
    address = command
  else
    address = "/#{ command }"
  end

  osc_message = OSC::Message.new address, *args

  send_message osc_message
end

#send_cue_command(number, action, *args) ⇒ Object



153
154
155
156
# File 'lib/qcmd/server.rb', line 153

def send_cue_command number, action, *args
  command = "cue/#{ number }/#{ action }"
  send_workspace_command(command, *args)
end

#send_message(osc_message) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/qcmd/server.rb', line 121

def send_message osc_message
  Qcmd.debug "(sending osc message #{ osc_message.address } #{osc_message.has_arguments? ? 'with' : 'without'} args)"

  @sent_messages << osc_message
  if Qcmd::Commands.expects_reply?(osc_message)
    Qcmd.debug "(this command expects a reply)"
    @sent_messages_expecting_reply << osc_message
  end

  wait_for_replies do
    send_channel.send osc_message
  end
end

#send_workspace_command(_command, *args) ⇒ Object



148
149
150
151
# File 'lib/qcmd/server.rb', line 148

def send_workspace_command _command, *args
  command = "workspace/#{ Qcmd.context.workspace.id }/#{ _command }"
  send_command(command, *args)
end

#stopObject



135
136
137
# File 'lib/qcmd/server.rb', line 135

def stop
  Thread.kill(receive_thread) if receive_thread.alive?
end

#wait_for_repliesObject



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/qcmd/server.rb', line 83

def wait_for_replies
  begin
    yield

    naps = 0
    while replies_expected? do
      if naps > 20
        # FAILED TO GET RESPONSE
        raise TimeoutError.new
      end

      naps += 1
      sleep 0.1
    end
  rescue TimeoutError => ex
    Qcmd.log "[error: reply timeout]"
    # clear expecting reply item, assume it will never arrive
    @sent_messages_expecting_reply.shift
  end
end