Class: Webmidi::Network::RTP::ControlPacket
- Inherits:
-
Object
- Object
- Webmidi::Network::RTP::ControlPacket
- Defined in:
- lib/webmidi/network/rtp.rb
Constant Summary collapse
- SIGNATURE =
0xFFFF- PROTOCOL_VERSION =
2- COMMANDS =
{ invitation: "IN", accepted: "OK", rejected: "NO", synchronization: "CK", receiver_feedback: "RS", end_session: "BY" }.freeze
- COMMAND_BY_CODE =
COMMANDS.invert.freeze
Instance Attribute Summary collapse
-
#command ⇒ Object
readonly
Returns the value of attribute command.
-
#count ⇒ Object
readonly
Returns the value of attribute count.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#sequence_number ⇒ Object
readonly
Returns the value of attribute sequence_number.
-
#ssrc ⇒ Object
readonly
Returns the value of attribute ssrc.
-
#timestamps ⇒ Object
readonly
Returns the value of attribute timestamps.
-
#token ⇒ Object
readonly
Returns the value of attribute token.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
- .accepted(token:, ssrc:, name:, version: PROTOCOL_VERSION) ⇒ Object
- .end_session(ssrc:) ⇒ Object
- .invitation(token:, ssrc:, name:, version: PROTOCOL_VERSION) ⇒ Object
- .parse(bytes) ⇒ Object
- .parse_payload(command, payload) ⇒ Object
- .receiver_feedback(ssrc:, sequence_number:) ⇒ Object
- .rejected(token:, ssrc:, name:, version: PROTOCOL_VERSION) ⇒ Object
- .synchronization(ssrc:, count:, timestamps:) ⇒ Object
- .timestamp ⇒ Object
- .validate_range!(value, name, min, max) ⇒ Object
Instance Method Summary collapse
-
#initialize(command:, version: PROTOCOL_VERSION, token: 0, ssrc: 0, name: "", count: 0, timestamps: [], sequence_number: 0) ⇒ ControlPacket
constructor
A new instance of ControlPacket.
- #to_bytes ⇒ Object
Constructor Details
#initialize(command:, version: PROTOCOL_VERSION, token: 0, ssrc: 0, name: "", count: 0, timestamps: [], sequence_number: 0) ⇒ ControlPacket
Returns a new instance of ControlPacket.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/webmidi/network/rtp.rb', line 28 def initialize(command:, version: PROTOCOL_VERSION, token: 0, ssrc: 0, name: "", count: 0, timestamps: [], sequence_number: 0) raise InvalidMessageError, "Unknown AppleMIDI command: #{command.inspect}" unless COMMANDS.key?(command) self.class.validate_range!(version, "Protocol version", 0, 0xFFFF_FFFF) self.class.validate_range!(token, "Initiator token", 0, 0xFFFF_FFFF) self.class.validate_range!(ssrc, "SSRC", 0, 0xFFFF_FFFF) self.class.validate_range!(count, "Synchronization count", 0, 3) self.class.validate_range!(sequence_number, "Sequence number", 0, 0xFFFF) @command = command @version = version @token = token @ssrc = ssrc @name = name.to_s @count = count @timestamps = .dup.freeze @sequence_number = sequence_number end |
Instance Attribute Details
#command ⇒ Object (readonly)
Returns the value of attribute command.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def command @command end |
#count ⇒ Object (readonly)
Returns the value of attribute count.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def count @count end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def name @name end |
#sequence_number ⇒ Object (readonly)
Returns the value of attribute sequence_number.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def sequence_number @sequence_number end |
#ssrc ⇒ Object (readonly)
Returns the value of attribute ssrc.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def ssrc @ssrc end |
#timestamps ⇒ Object (readonly)
Returns the value of attribute timestamps.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def @timestamps end |
#token ⇒ Object (readonly)
Returns the value of attribute token.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def token @token end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
26 27 28 |
# File 'lib/webmidi/network/rtp.rb', line 26 def version @version end |
Class Method Details
.accepted(token:, ssrc:, name:, version: PROTOCOL_VERSION) ⇒ Object
51 52 53 |
# File 'lib/webmidi/network/rtp.rb', line 51 def self.accepted(token:, ssrc:, name:, version: PROTOCOL_VERSION) new(command: :accepted, version: version, token: token, ssrc: ssrc, name: name) end |
.end_session(ssrc:) ⇒ Object
67 68 69 |
# File 'lib/webmidi/network/rtp.rb', line 67 def self.end_session(ssrc:) new(command: :end_session, ssrc: ssrc) end |
.invitation(token:, ssrc:, name:, version: PROTOCOL_VERSION) ⇒ Object
47 48 49 |
# File 'lib/webmidi/network/rtp.rb', line 47 def self.invitation(token:, ssrc:, name:, version: PROTOCOL_VERSION) new(command: :invitation, version: version, token: token, ssrc: ssrc, name: name) end |
.parse(bytes) ⇒ Object
76 77 78 79 80 81 82 83 84 |
# File 'lib/webmidi/network/rtp.rb', line 76 def self.parse(bytes) return nil if bytes.bytesize < 4 signature = bytes[0, 2].unpack1("n") command = COMMAND_BY_CODE[bytes[2, 2]] return nil unless signature == SIGNATURE && command parse_payload(command, bytes[4..] || "") end |
.parse_payload(command, payload) ⇒ Object
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/webmidi/network/rtp.rb', line 86 def self.parse_payload(command, payload) case command when :invitation, :accepted, :rejected return nil if payload.bytesize < 12 version, token, ssrc = payload[0, 12].unpack("NNN") name = (payload[12..] || "").split("\0", 2).first new(command: command, version: version, token: token, ssrc: ssrc, name: name) when :synchronization return nil if payload.bytesize < 28 ssrc = payload[0, 4].unpack1("N") count = payload.getbyte(4) = payload[8, 24].unpack("Q>Q>Q>") new(command: command, ssrc: ssrc, count: count, timestamps: ) when :receiver_feedback return nil if payload.bytesize < 6 ssrc, sequence_number = payload[0, 6].unpack("Nn") new(command: command, ssrc: ssrc, sequence_number: sequence_number) when :end_session return nil if payload.bytesize < 4 new(command: command, ssrc: payload[0, 4].unpack1("N")) end end |
.receiver_feedback(ssrc:, sequence_number:) ⇒ Object
63 64 65 |
# File 'lib/webmidi/network/rtp.rb', line 63 def self.receiver_feedback(ssrc:, sequence_number:) new(command: :receiver_feedback, ssrc: ssrc, sequence_number: sequence_number) end |
.rejected(token:, ssrc:, name:, version: PROTOCOL_VERSION) ⇒ Object
55 56 57 |
# File 'lib/webmidi/network/rtp.rb', line 55 def self.rejected(token:, ssrc:, name:, version: PROTOCOL_VERSION) new(command: :rejected, version: version, token: token, ssrc: ssrc, name: name) end |
.synchronization(ssrc:, count:, timestamps:) ⇒ Object
59 60 61 |
# File 'lib/webmidi/network/rtp.rb', line 59 def self.synchronization(ssrc:, count:, timestamps:) new(command: :synchronization, ssrc: ssrc, count: count, timestamps: ) end |
.timestamp ⇒ Object
113 114 115 |
# File 'lib/webmidi/network/rtp.rb', line 113 def self. (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1_000_000).to_i end |
.validate_range!(value, name, min, max) ⇒ Object
117 118 119 120 121 |
# File 'lib/webmidi/network/rtp.rb', line 117 def self.validate_range!(value, name, min, max) return if value.is_a?(Integer) && value.between?(min, max) raise InvalidMessageError, "#{name} must be between #{min} and #{max}, got #{value.inspect}" end |