Class: Pinnacle::Wrapper::Voice::VoiceSocket
- Inherits:
-
Object
- Object
- Pinnacle::Wrapper::Voice::VoiceSocket
- Defined in:
- lib/pinnacle/wrapper/voice/voice_socket.rb
Instance Attribute Summary collapse
-
#call ⇒ Object
Returns the value of attribute call.
-
#call_id ⇒ Object
Returns the value of attribute call_id.
-
#socket ⇒ Object
readonly
Returns the value of attribute socket.
Class Method Summary collapse
Instance Method Summary collapse
- #answer(params = nil, command_id: create_voice_command_id) ⇒ Object
- #cancel_input(command_id: create_voice_command_id) ⇒ Object
- #close(code = nil, reason = nil) ⇒ Object
- #command(frame) ⇒ Object
- #command_and_wait(frame, timeout_ms: 10_000) ⇒ Object
- #connect ⇒ Object
- #end_call(params = nil, command_id: create_voice_command_id) ⇒ Object
- #get_input(params = nil, command_id: create_voice_command_id) ⇒ Object
- #handle_message(data) ⇒ Object
-
#initialize(socket, create_socket: nil, reconnect: nil) ⇒ VoiceSocket
constructor
A new instance of VoiceSocket.
- #on(event, &listener) ⇒ Object
- #open? ⇒ Boolean
- #play_audio(params, command_id: create_voice_command_id) ⇒ Object
- #ready_state ⇒ Object
- #reconnect_now ⇒ Object
- #reduce_noise(params, command_id: create_voice_command_id) ⇒ Object
- #send(frame) ⇒ Object
- #send_dtmf(params, command_id: create_voice_command_id) ⇒ Object
- #send_media(media) ⇒ Object
- #start_recording(command_id: create_voice_command_id) ⇒ Object
- #stop_audio(command_id: create_voice_command_id) ⇒ Object
- #stop_recording(command_id: create_voice_command_id) ⇒ Object
- #transfer(params, command_id: create_voice_command_id) ⇒ Object
- #update_state(params, command_id: create_voice_command_id) ⇒ Object
- #wait_for_ack(command_id, timeout_ms: 10_000) ⇒ Object
- #wait_until_open(timeout_ms: 10_000) ⇒ Object
Constructor Details
#initialize(socket, create_socket: nil, reconnect: nil) ⇒ VoiceSocket
Returns a new instance of VoiceSocket.
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 16 def initialize(socket, create_socket: nil, reconnect: nil) @socket = socket @create_socket = create_socket @reconnect = (reconnect || {}) @listeners = Hash.new { |hash, key| hash[key] = [] } @pending_acks = {} @closed_by_user = false @reconnect_attempts = 0 @reconnect_thread = nil bind_socket end |
Instance Attribute Details
#call ⇒ Object
Returns the value of attribute call.
13 14 15 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 13 def call @call end |
#call_id ⇒ Object
Returns the value of attribute call_id.
13 14 15 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 13 def call_id @call_id end |
#socket ⇒ Object (readonly)
Returns the value of attribute socket.
14 15 16 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 14 def socket @socket end |
Class Method Details
.create_voice_command_id ⇒ Object
347 348 349 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 347 def create_voice_command_id "cmd_#{SecureRandom.uuid}" end |
Instance Method Details
#answer(params = nil, command_id: create_voice_command_id) ⇒ Object
107 108 109 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 107 def answer(params = nil, command_id: create_voice_command_id) command(with_optional_params(command_frame(command_id, Types::CALL_ANSWER), params)) end |
#cancel_input(command_id: create_voice_command_id) ⇒ Object
143 144 145 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 143 def cancel_input(command_id: create_voice_command_id) command(command_frame(command_id, Types::INPUT_CANCEL)) end |
#close(code = nil, reason = nil) ⇒ Object
188 189 190 191 192 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 188 def close(code = nil, reason = nil) @closed_by_user = true @reconnect_thread&.kill close_socket(@socket, code, reason) end |
#command(frame) ⇒ Object
96 97 98 99 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 96 def command(frame) send(frame) frame.fetch(:command_id) end |
#command_and_wait(frame, timeout_ms: 10_000) ⇒ Object
101 102 103 104 105 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 101 def command_and_wait(frame, timeout_ms: 10_000) waiter = wait_for_ack(frame.fetch(:command_id), timeout_ms: timeout_ms) command(frame) waiter.call end |
#connect ⇒ Object
83 84 85 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 83 def connect wait_until_open end |
#end_call(params = nil, command_id: create_voice_command_id) ⇒ Object
111 112 113 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 111 def end_call(params = nil, command_id: create_voice_command_id) command(with_optional_params(command_frame(command_id, Types::CALL_END), params)) end |
#get_input(params = nil, command_id: create_voice_command_id) ⇒ Object
139 140 141 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 139 def get_input(params = nil, command_id: create_voice_command_id) command(with_optional_params(command_frame(command_id, Types::INPUT_GET), params)) end |
#handle_message(data) ⇒ Object
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 205 def (data) frame = parse_voice_frame(data) emit("frame", frame) case frame["event"] when "ack" resolve_pending_ack(frame) emit("ack", frame) when "event" emit("event", frame) when "media" emit("media", frame) when "connected" nil else raise "Voice socket received an unknown frame event." end rescue StandardError => e emit("error", e) end |
#on(event, &listener) ⇒ Object
87 88 89 90 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 87 def on(event, &listener) @listeners[event] << listener -> { @listeners[event].delete(listener) } end |
#open? ⇒ Boolean
38 39 40 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 38 def open? ready_state == 1 end |
#play_audio(params, command_id: create_voice_command_id) ⇒ Object
127 128 129 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 127 def play_audio(params, command_id: create_voice_command_id) command(command_frame(command_id, Types::AUDIO_PLAY, params)) end |
#ready_state ⇒ Object
28 29 30 31 32 33 34 35 36 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 28 def ready_state if @socket.respond_to?(:ready_state) @socket.ready_state elsif @socket.respond_to?(:readyState) @socket.readyState else 0 end end |
#reconnect_now ⇒ Object
194 195 196 197 198 199 200 201 202 203 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 194 def reconnect_now raise "Voice socket was not configured with a reconnect factory." if @create_socket.nil? @closed_by_user = false @socket = @create_socket.call bind_socket @reconnect_attempts = 0 emit("reconnected", @socket) self end |
#reduce_noise(params, command_id: create_voice_command_id) ⇒ Object
135 136 137 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 135 def reduce_noise(params, command_id: create_voice_command_id) command(command_frame(command_id, Types::AUDIO_REDUCE_NOISE, params)) end |
#send(frame) ⇒ Object
92 93 94 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 92 def send(frame) @socket.send(JSON.generate(frame)) end |
#send_dtmf(params, command_id: create_voice_command_id) ⇒ Object
147 148 149 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 147 def send_dtmf(params, command_id: create_voice_command_id) command(command_frame(command_id, Types::DTMF_SEND, params)) end |
#send_media(media) ⇒ Object
155 156 157 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 155 def send_media(media) send({ event: "media", media: media }) end |
#start_recording(command_id: create_voice_command_id) ⇒ Object
119 120 121 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 119 def start_recording(command_id: create_voice_command_id) command(command_frame(command_id, Types::RECORDING_START)) end |
#stop_audio(command_id: create_voice_command_id) ⇒ Object
131 132 133 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 131 def stop_audio(command_id: create_voice_command_id) command(command_frame(command_id, Types::AUDIO_STOP)) end |
#stop_recording(command_id: create_voice_command_id) ⇒ Object
123 124 125 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 123 def stop_recording(command_id: create_voice_command_id) command(command_frame(command_id, Types::RECORDING_STOP)) end |
#transfer(params, command_id: create_voice_command_id) ⇒ Object
115 116 117 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 115 def transfer(params, command_id: create_voice_command_id) command(command_frame(command_id, Types::CALL_TRANSFER, params)) end |
#update_state(params, command_id: create_voice_command_id) ⇒ Object
151 152 153 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 151 def update_state(params, command_id: create_voice_command_id) command(command_frame(command_id, Types::CALL_UPDATE_STATE, params)) end |
#wait_for_ack(command_id, timeout_ms: 10_000) ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 159 def wait_for_ack(command_id, timeout_ms: 10_000) raise "Already waiting for ack #{command_id}." if @pending_acks.key?(command_id) mutex = Mutex.new condition = ConditionVariable.new result = nil error = nil done = false @pending_acks[command_id] = ->(ack, next_error) do mutex.synchronize do result = ack error = next_error done = true condition.signal end end -> do mutex.synchronize do condition.wait(mutex, timeout_ms / 1000.0) unless done end @pending_acks.delete(command_id) raise Timeout::Error, "Timed out waiting for ack #{command_id}." unless done raise error unless error.nil? result end end |
#wait_until_open(timeout_ms: 10_000) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/pinnacle/wrapper/voice/voice_socket.rb', line 42 def wait_until_open(timeout_ms: 10_000) return if open? mutex = Mutex.new condition = ConditionVariable.new error = nil done = false unsubscribers = [] cleanup = -> do unsubscribers.each(&:call) end finish = ->(next_error) do mutex.synchronize do error = next_error done = true condition.signal end end unsubscribers << on("open") do cleanup.call finish.call(nil) end unsubscribers << on("close") do cleanup.call finish.call(RuntimeError.new("Voice socket closed before opening.")) end unsubscribers << on("error") do |event| cleanup.call finish.call(to_error(event)) end mutex.synchronize do condition.wait(mutex, timeout_ms / 1000.0) unless done end cleanup.call unless done raise Timeout::Error, "Timed out waiting for voice socket to open." unless done raise error unless error.nil? end |