midi-communications-windows 0.0.3
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 +8 -0
- data/.version +6 -0
- data/.yardoc/checksums +8 -0
- data/.yardoc/complete +0 -0
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/.yardopts +8 -0
- data/Gemfile +3 -0
- data/LICENSE +165 -0
- data/README.md +176 -0
- data/Rakefile +13 -0
- data/doc/MIDICommunicationsWindows/API/MIDIHdr.html +144 -0
- data/doc/MIDICommunicationsWindows/API/MIDIInCaps.html +142 -0
- data/doc/MIDICommunicationsWindows/API/MIDIOutCaps.html +140 -0
- data/doc/MIDICommunicationsWindows/API/MSG.html +143 -0
- data/doc/MIDICommunicationsWindows/API.html +981 -0
- data/doc/MIDICommunicationsWindows/Device/ClassMethods.html +365 -0
- data/doc/MIDICommunicationsWindows/Device/InstanceMethods.html +1096 -0
- data/doc/MIDICommunicationsWindows/Device.html +988 -0
- data/doc/MIDICommunicationsWindows/Error.html +438 -0
- data/doc/MIDICommunicationsWindows/Input.html +1554 -0
- data/doc/MIDICommunicationsWindows/Message.html +700 -0
- data/doc/MIDICommunicationsWindows/Output.html +1697 -0
- data/doc/MIDICommunicationsWindows/TypeConversion.html +369 -0
- data/doc/MIDICommunicationsWindows.html +210 -0
- data/doc/_index.html +262 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +206 -0
- data/doc/css/style.css +1089 -0
- data/doc/file.README.html +240 -0
- data/doc/file.testing-on-windows.html +253 -0
- data/doc/file_list.html +64 -0
- data/doc/frames.html +22 -0
- data/doc/index.html +240 -0
- data/doc/js/app.js +801 -0
- data/doc/js/full_list.js +334 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +382 -0
- data/doc/top-level-namespace.html +112 -0
- data/docs/testing-on-windows.md +222 -0
- data/examples/input.rb +27 -0
- data/examples/list_ports.rb +17 -0
- data/examples/output.rb +22 -0
- data/examples/sysex_output.rb +15 -0
- data/lib/midi-communications-windows/api.rb +340 -0
- data/lib/midi-communications-windows/device.rb +310 -0
- data/lib/midi-communications-windows/input.rb +486 -0
- data/lib/midi-communications-windows/message.rb +133 -0
- data/lib/midi-communications-windows/output.rb +206 -0
- data/lib/midi-communications-windows/type_conversion.rb +20 -0
- data/lib/midi-communications-windows/version.rb +4 -0
- data/lib/midi-communications-windows.rb +76 -0
- data/midi-communications-windows.gemspec +32 -0
- metadata +220 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
module MIDICommunicationsWindows
|
|
2
|
+
# A MIDI output port: somewhere to send messages.
|
|
3
|
+
#
|
|
4
|
+
# @example Send a note through the first output
|
|
5
|
+
# output = MIDICommunicationsWindows::Output.first
|
|
6
|
+
# output.open
|
|
7
|
+
# output.puts(0x90, 60, 100) # Note On, middle C
|
|
8
|
+
# sleep 0.5
|
|
9
|
+
# output.puts(0x80, 60, 0) # Note Off
|
|
10
|
+
#
|
|
11
|
+
# @example Send the same thing as a hex string
|
|
12
|
+
# output.puts_s('903C64')
|
|
13
|
+
#
|
|
14
|
+
# @see Input for receiving
|
|
15
|
+
#
|
|
16
|
+
# @api public
|
|
17
|
+
class Output
|
|
18
|
+
extend Device::ClassMethods
|
|
19
|
+
include Device::InstanceMethods
|
|
20
|
+
|
|
21
|
+
# @return [Symbol] `:output`
|
|
22
|
+
def self.direction
|
|
23
|
+
:output
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Sends a MIDI message, in whichever form it is given.
|
|
27
|
+
#
|
|
28
|
+
# @param args [Array<Integer>, Array<String>, Integer, String] one message,
|
|
29
|
+
# as loose bytes, an array of bytes, or a hex string
|
|
30
|
+
# @return [Boolean] true
|
|
31
|
+
# @raise [Error] if WinMM refuses the message
|
|
32
|
+
#
|
|
33
|
+
# @example Every one of these sends the same Note On
|
|
34
|
+
# output.puts(0x90, 60, 100)
|
|
35
|
+
# output.puts([0x90, 60, 100])
|
|
36
|
+
# output.puts('903C64')
|
|
37
|
+
def puts(*args)
|
|
38
|
+
case args.first
|
|
39
|
+
when Array then args.each { |argument| puts(*argument) }
|
|
40
|
+
when Integer then puts_bytes(*args)
|
|
41
|
+
when String then puts_s(*args)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
true
|
|
45
|
+
end
|
|
46
|
+
alias write puts
|
|
47
|
+
|
|
48
|
+
# Sends a MIDI message given as a hex string.
|
|
49
|
+
#
|
|
50
|
+
# @param data [String] hex, two characters per byte, e.g. `'903C64'`
|
|
51
|
+
# @return [Boolean] true
|
|
52
|
+
# @raise [Error] if WinMM refuses the message
|
|
53
|
+
def puts_s(data)
|
|
54
|
+
puts_bytes(*data.scan(/../).map(&:hex))
|
|
55
|
+
end
|
|
56
|
+
alias puts_bytestr puts_s
|
|
57
|
+
alias puts_hex puts_s
|
|
58
|
+
|
|
59
|
+
# Sends a MIDI message given as numeric bytes.
|
|
60
|
+
#
|
|
61
|
+
# System Exclusive takes a different route through WinMM than everything
|
|
62
|
+
# else, and this is where the two part company.
|
|
63
|
+
#
|
|
64
|
+
# @param data [Array<Integer>] the message, status byte first
|
|
65
|
+
# @return [Boolean] true
|
|
66
|
+
# @raise [Error] if WinMM refuses the message
|
|
67
|
+
def puts_bytes(*data)
|
|
68
|
+
Message.sysex?(data) ? send_sysex(data) : send_short(data)
|
|
69
|
+
|
|
70
|
+
true
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
# Opens the port.
|
|
76
|
+
#
|
|
77
|
+
# `CALLBACK_NULL` asks WinMM for no notifications at all. The only event an
|
|
78
|
+
# output can raise is `MM_MOM_DONE`, saying a System Exclusive buffer has
|
|
79
|
+
# finished, and {#send_sysex} learns that from the buffer's own flags
|
|
80
|
+
# instead. Asking for no callback keeps the driver from ever calling into
|
|
81
|
+
# Ruby, which is one whole class of threading problem that then cannot
|
|
82
|
+
# occur on the sending side.
|
|
83
|
+
#
|
|
84
|
+
# @return [void]
|
|
85
|
+
# @raise [Error]
|
|
86
|
+
# @api private
|
|
87
|
+
def connect
|
|
88
|
+
handle_pointer = FFI::MemoryPointer.new(:uintptr_t)
|
|
89
|
+
|
|
90
|
+
API.check!(API.midiOutOpen(handle_pointer, @id, 0, 0, API::CALLBACK_NULL),
|
|
91
|
+
:midiOutOpen, :output)
|
|
92
|
+
|
|
93
|
+
@handle = handle_pointer.read(:uintptr_t)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Closes the port.
|
|
97
|
+
#
|
|
98
|
+
# `midiOutReset` first, and not only for tidiness: it turns off every note
|
|
99
|
+
# the port has left sounding and releases any buffer still queued. Closing
|
|
100
|
+
# without it can leave a synthesiser holding notes with nothing left to
|
|
101
|
+
# send it a Note Off.
|
|
102
|
+
#
|
|
103
|
+
# @return [void]
|
|
104
|
+
# @raise [Error]
|
|
105
|
+
# @api private
|
|
106
|
+
def disconnect
|
|
107
|
+
API.check!(API.midiOutReset(@handle), :midiOutReset, :output)
|
|
108
|
+
API.check!(API.midiOutClose(@handle), :midiOutClose, :output)
|
|
109
|
+
|
|
110
|
+
@handle = nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Sends a message of three bytes or fewer.
|
|
114
|
+
#
|
|
115
|
+
# @param data [Array<Integer>]
|
|
116
|
+
# @return [void]
|
|
117
|
+
# @raise [Error]
|
|
118
|
+
# @api private
|
|
119
|
+
def send_short(data)
|
|
120
|
+
API.check!(API.midiOutShortMsg(@handle, Message.pack(data)), :midiOutShortMsg, :output)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Sends a System Exclusive message.
|
|
124
|
+
#
|
|
125
|
+
# WinMM wants such a message in a buffer it has been told about, and the
|
|
126
|
+
# sequence is fixed: prepare the header, send it, wait for the driver to
|
|
127
|
+
# finish with it, then unprepare. Unpreparing early fails with
|
|
128
|
+
# `MIDIERR_STILLPLAYING`, and freeing the buffer early is worse than that.
|
|
129
|
+
#
|
|
130
|
+
# The wait can be a real one. MIDI runs at 31250 baud, so on a physical
|
|
131
|
+
# interface a byte takes about 320 microseconds and a 200-byte dump should
|
|
132
|
+
# occupy something like 64 milliseconds during which this method does not
|
|
133
|
+
# return — a caller sending System Exclusive from a sequencer thread should
|
|
134
|
+
# know that is possible. Said as arithmetic rather than as measurement: the
|
|
135
|
+
# only device this has been run against is a software synthesiser, which
|
|
136
|
+
# marks the buffer done at once because there is no wire, and returned in
|
|
137
|
+
# well under a millisecond.
|
|
138
|
+
#
|
|
139
|
+
# @param data [Array<Integer>] the whole message, 0xF0 through 0xF7
|
|
140
|
+
# @return [void]
|
|
141
|
+
# @raise [Error]
|
|
142
|
+
# @api private
|
|
143
|
+
def send_sysex(data)
|
|
144
|
+
buffer = FFI::MemoryPointer.new(:uint8, data.size)
|
|
145
|
+
buffer.write_array_of_uint8(data)
|
|
146
|
+
|
|
147
|
+
header = API::MIDIHdr.new
|
|
148
|
+
header[:lpData] = buffer
|
|
149
|
+
header[:dwBufferLength] = data.size
|
|
150
|
+
header[:dwBytesRecorded] = data.size
|
|
151
|
+
|
|
152
|
+
API.check!(API.midiOutPrepareHeader(@handle, header, API::MIDIHdr.size),
|
|
153
|
+
:midiOutPrepareHeader, :output)
|
|
154
|
+
|
|
155
|
+
begin
|
|
156
|
+
API.check!(API.midiOutLongMsg(@handle, header, API::MIDIHdr.size), :midiOutLongMsg, :output)
|
|
157
|
+
wait_until_sent(header)
|
|
158
|
+
rescue Error
|
|
159
|
+
# The driver still owns the buffer. Unpreparing it now would fail with
|
|
160
|
+
# MIDIERR_STILLPLAYING and the memory would be freed underneath a device
|
|
161
|
+
# that is still reading it; midiOutReset takes it back first.
|
|
162
|
+
API.midiOutReset(@handle)
|
|
163
|
+
raise
|
|
164
|
+
ensure
|
|
165
|
+
API.midiOutUnprepareHeader(@handle, header, API::MIDIHdr.size)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Blocks until the driver marks the buffer done, or gives up.
|
|
170
|
+
#
|
|
171
|
+
# There is no blocking WinMM call to wait on, so this polls the flag the
|
|
172
|
+
# driver sets. The interval is short enough not to add meaningfully to a
|
|
173
|
+
# transfer measured in tens of milliseconds, and long enough not to spin.
|
|
174
|
+
#
|
|
175
|
+
# The wait is bounded because the flag is set by a device that can go away:
|
|
176
|
+
# unplug an interface in the middle of a dump and it is never set at all.
|
|
177
|
+
# Without a limit this would spin for the life of the process, on whichever
|
|
178
|
+
# thread happened to be sending — in MusaDSL, the sequencer's.
|
|
179
|
+
#
|
|
180
|
+
# @param header [API::MIDIHdr]
|
|
181
|
+
# @return [void]
|
|
182
|
+
# @raise [Error] if the device has not finished within {SYSEX_TIMEOUT}
|
|
183
|
+
# @api private
|
|
184
|
+
def wait_until_sent(header)
|
|
185
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + SYSEX_TIMEOUT
|
|
186
|
+
|
|
187
|
+
until (header[:dwFlags] & API::MHDR_DONE) != 0
|
|
188
|
+
if Process.clock_gettime(Process::CLOCK_MONOTONIC) > deadline
|
|
189
|
+
raise Error.new(:midiOutLongMsg, nil,
|
|
190
|
+
"the device did not finish sending a #{header[:dwBufferLength]}-byte " \
|
|
191
|
+
"System Exclusive message within #{SYSEX_TIMEOUT} s")
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
sleep SYSEX_POLL_INTERVAL
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# How often to look at a System Exclusive buffer's done flag, in seconds.
|
|
199
|
+
SYSEX_POLL_INTERVAL = 0.001
|
|
200
|
+
|
|
201
|
+
# How long to wait for a System Exclusive message to go out, in seconds.
|
|
202
|
+
# MIDI runs at 31250 baud, so this is room for roughly 3 kB — far more than
|
|
203
|
+
# any message, and short enough that a vanished device is noticed.
|
|
204
|
+
SYSEX_TIMEOUT = 1.0
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module MIDICommunicationsWindows
|
|
2
|
+
# Utility methods for converting between MIDI data formats.
|
|
3
|
+
#
|
|
4
|
+
# @api public
|
|
5
|
+
module TypeConversion
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
# Converts an array of numeric bytes to a hex string.
|
|
9
|
+
#
|
|
10
|
+
# @param bytes [Array<Integer>] numeric bytes, e.g. `[0x90, 0x40, 0x40]`
|
|
11
|
+
# @return [String] uppercase hex, two characters per byte, e.g. `'904040'`
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# TypeConversion.numeric_bytes_to_hex_string([0x90, 0x40, 0x40])
|
|
15
|
+
# # => "904040"
|
|
16
|
+
def numeric_bytes_to_hex_string(bytes)
|
|
17
|
+
bytes.map { |byte| format('%02X', byte) }.join
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#
|
|
2
|
+
# midi-communications-windows
|
|
3
|
+
# Realtime MIDI IO with Ruby for Windows
|
|
4
|
+
#
|
|
5
|
+
# (c)2026 Javier Sánchez Yeste, licensed under LGPL 3.0 License
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
# Libs
|
|
9
|
+
require 'ffi'
|
|
10
|
+
|
|
11
|
+
# Modules with no platform binding of their own, so that they load anywhere
|
|
12
|
+
require 'midi-communications-windows/message'
|
|
13
|
+
require 'midi-communications-windows/type_conversion'
|
|
14
|
+
|
|
15
|
+
# Modules and classes that bind winmm.dll
|
|
16
|
+
require 'midi-communications-windows/api'
|
|
17
|
+
require 'midi-communications-windows/device'
|
|
18
|
+
require 'midi-communications-windows/input'
|
|
19
|
+
require 'midi-communications-windows/output'
|
|
20
|
+
|
|
21
|
+
require_relative 'midi-communications-windows/version'
|
|
22
|
+
|
|
23
|
+
# Windows-specific MIDI I/O through the Windows Multimedia (WinMM) API.
|
|
24
|
+
#
|
|
25
|
+
# This library gives low-level access to MIDI ports on Windows by binding
|
|
26
|
+
# `winmm.dll` with FFI. It is normally used through the higher-level
|
|
27
|
+
# {https://github.com/javier-sy/midi-communications midi-communications} gem,
|
|
28
|
+
# which selects it automatically on Windows.
|
|
29
|
+
#
|
|
30
|
+
# The classes are {Input}, for receiving, and {Output}, for sending. {Device}
|
|
31
|
+
# enumerates both.
|
|
32
|
+
#
|
|
33
|
+
# ## Why WinMM, and not one of the newer APIs
|
|
34
|
+
#
|
|
35
|
+
# Windows has three MIDI APIs a program could use. WinMM is the oldest, and as
|
|
36
|
+
# of February 2026 it is also the most sensible choice for Ruby.
|
|
37
|
+
#
|
|
38
|
+
# Windows MIDI Services, generally available in Windows 11 since then, replaced
|
|
39
|
+
# the MIDI stack underneath. The existing MIDI 1.0 APIs were reconnected to the
|
|
40
|
+
# new service rather than retired, so a WinMM client reaches what the new stack
|
|
41
|
+
# offers with nothing installed — including the loopback endpoints the system
|
|
42
|
+
# now creates itself, which used to need a third-party driver.
|
|
43
|
+
#
|
|
44
|
+
# Whether a port can be opened by more than one program at a time follows the
|
|
45
|
+
# endpoint, not the API. Measured: two clients shared a loopback input and both
|
|
46
|
+
# received every message, while a second open of a classic `wdmaud` device was
|
|
47
|
+
# refused as already in use. On Windows 10 there is no Windows MIDI Services.
|
|
48
|
+
#
|
|
49
|
+
# The new App SDK offers MIDI 2.0 and UMP, which this library does not need —
|
|
50
|
+
# `midi-communications` and MusaDSL are MIDI 1.0 throughout — and it is
|
|
51
|
+
# published only as WinRT. Microsoft's own guidance is that other languages
|
|
52
|
+
# need a WinRT projection from their toolchain, and Ruby has none.
|
|
53
|
+
#
|
|
54
|
+
# ## Why no compiled artifact
|
|
55
|
+
#
|
|
56
|
+
# `winmm.dll` is present on every Windows installation, so this gem binds a
|
|
57
|
+
# library that is already there and ships no binary of its own. The only
|
|
58
|
+
# compiled dependency is `ffi` itself, which is published for every Windows
|
|
59
|
+
# platform including ARM64. Distributing platform-specific binaries through
|
|
60
|
+
# RubyGems is where installations break; there is nothing here to break.
|
|
61
|
+
#
|
|
62
|
+
# @example List the output ports
|
|
63
|
+
# MIDICommunicationsWindows::Output.all.each do |output|
|
|
64
|
+
# puts "#{output.id}: #{output.name}"
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# @example Send a note
|
|
68
|
+
# output = MIDICommunicationsWindows::Output.first
|
|
69
|
+
# output.open
|
|
70
|
+
# output.puts(0x90, 60, 100)
|
|
71
|
+
#
|
|
72
|
+
# @see https://learn.microsoft.com/en-us/windows/win32/multimedia/midi-reference Microsoft's MIDI reference
|
|
73
|
+
#
|
|
74
|
+
# @api public
|
|
75
|
+
module MIDICommunicationsWindows
|
|
76
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require_relative 'lib/midi-communications-windows/version'
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = 'midi-communications-windows'
|
|
5
|
+
s.version = MIDICommunicationsWindows::VERSION
|
|
6
|
+
s.date = '2026-09-06'
|
|
7
|
+
s.summary = 'Realtime MIDI IO with Ruby for Windows'
|
|
8
|
+
s.description = 'Access the Windows Multimedia (WinMM) MIDI API with Ruby.'
|
|
9
|
+
s.authors = ['Javier Sánchez Yeste']
|
|
10
|
+
s.email = ['javier.sy@gmail.com']
|
|
11
|
+
s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
12
|
+
s.homepage = 'https://github.com/javier-sy/midi-communications-windows'
|
|
13
|
+
s.license = 'LGPL-3.0-or-later'
|
|
14
|
+
|
|
15
|
+
s.required_ruby_version = '>= 2.7'
|
|
16
|
+
|
|
17
|
+
s.metadata = {
|
|
18
|
+
'homepage_uri' => s.homepage,
|
|
19
|
+
'source_code_uri' => s.homepage,
|
|
20
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/midi-communications-windows'
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
s.add_runtime_dependency 'ffi', '~> 1.15', '>= 1.15.4'
|
|
24
|
+
|
|
25
|
+
s.add_development_dependency 'minitest', '~>5', '>= 5.14.4'
|
|
26
|
+
s.add_development_dependency 'rake', '~>13', '>= 13.0.6'
|
|
27
|
+
s.add_development_dependency 'shoulda-context', '~>2', '>= 2.0.0'
|
|
28
|
+
|
|
29
|
+
s.add_development_dependency 'yard', '~> 0.9'
|
|
30
|
+
s.add_development_dependency 'redcarpet', '~> 3.6'
|
|
31
|
+
s.add_development_dependency 'webrick', '~> 1.8'
|
|
32
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: midi-communications-windows
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.3
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Javier Sánchez Yeste
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-09-06 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: ffi
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.15'
|
|
19
|
+
- - ">="
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: 1.15.4
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - "~>"
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: '1.15'
|
|
29
|
+
- - ">="
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: 1.15.4
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: minitest
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - "~>"
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '5'
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: 5.14.4
|
|
42
|
+
type: :development
|
|
43
|
+
prerelease: false
|
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - "~>"
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '5'
|
|
49
|
+
- - ">="
|
|
50
|
+
- !ruby/object:Gem::Version
|
|
51
|
+
version: 5.14.4
|
|
52
|
+
- !ruby/object:Gem::Dependency
|
|
53
|
+
name: rake
|
|
54
|
+
requirement: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - "~>"
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '13'
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: 13.0.6
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '13'
|
|
69
|
+
- - ">="
|
|
70
|
+
- !ruby/object:Gem::Version
|
|
71
|
+
version: 13.0.6
|
|
72
|
+
- !ruby/object:Gem::Dependency
|
|
73
|
+
name: shoulda-context
|
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - "~>"
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: '2'
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 2.0.0
|
|
82
|
+
type: :development
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '2'
|
|
89
|
+
- - ">="
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: 2.0.0
|
|
92
|
+
- !ruby/object:Gem::Dependency
|
|
93
|
+
name: yard
|
|
94
|
+
requirement: !ruby/object:Gem::Requirement
|
|
95
|
+
requirements:
|
|
96
|
+
- - "~>"
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: '0.9'
|
|
99
|
+
type: :development
|
|
100
|
+
prerelease: false
|
|
101
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
102
|
+
requirements:
|
|
103
|
+
- - "~>"
|
|
104
|
+
- !ruby/object:Gem::Version
|
|
105
|
+
version: '0.9'
|
|
106
|
+
- !ruby/object:Gem::Dependency
|
|
107
|
+
name: redcarpet
|
|
108
|
+
requirement: !ruby/object:Gem::Requirement
|
|
109
|
+
requirements:
|
|
110
|
+
- - "~>"
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: '3.6'
|
|
113
|
+
type: :development
|
|
114
|
+
prerelease: false
|
|
115
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
116
|
+
requirements:
|
|
117
|
+
- - "~>"
|
|
118
|
+
- !ruby/object:Gem::Version
|
|
119
|
+
version: '3.6'
|
|
120
|
+
- !ruby/object:Gem::Dependency
|
|
121
|
+
name: webrick
|
|
122
|
+
requirement: !ruby/object:Gem::Requirement
|
|
123
|
+
requirements:
|
|
124
|
+
- - "~>"
|
|
125
|
+
- !ruby/object:Gem::Version
|
|
126
|
+
version: '1.8'
|
|
127
|
+
type: :development
|
|
128
|
+
prerelease: false
|
|
129
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
130
|
+
requirements:
|
|
131
|
+
- - "~>"
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: '1.8'
|
|
134
|
+
description: Access the Windows Multimedia (WinMM) MIDI API with Ruby.
|
|
135
|
+
email:
|
|
136
|
+
- javier.sy@gmail.com
|
|
137
|
+
executables: []
|
|
138
|
+
extensions: []
|
|
139
|
+
extra_rdoc_files: []
|
|
140
|
+
files:
|
|
141
|
+
- ".gitignore"
|
|
142
|
+
- ".version"
|
|
143
|
+
- ".yardoc/checksums"
|
|
144
|
+
- ".yardoc/complete"
|
|
145
|
+
- ".yardoc/object_types"
|
|
146
|
+
- ".yardoc/objects/root.dat"
|
|
147
|
+
- ".yardoc/proxy_types"
|
|
148
|
+
- ".yardopts"
|
|
149
|
+
- Gemfile
|
|
150
|
+
- LICENSE
|
|
151
|
+
- README.md
|
|
152
|
+
- Rakefile
|
|
153
|
+
- doc/MIDICommunicationsWindows.html
|
|
154
|
+
- doc/MIDICommunicationsWindows/API.html
|
|
155
|
+
- doc/MIDICommunicationsWindows/API/MIDIHdr.html
|
|
156
|
+
- doc/MIDICommunicationsWindows/API/MIDIInCaps.html
|
|
157
|
+
- doc/MIDICommunicationsWindows/API/MIDIOutCaps.html
|
|
158
|
+
- doc/MIDICommunicationsWindows/API/MSG.html
|
|
159
|
+
- doc/MIDICommunicationsWindows/Device.html
|
|
160
|
+
- doc/MIDICommunicationsWindows/Device/ClassMethods.html
|
|
161
|
+
- doc/MIDICommunicationsWindows/Device/InstanceMethods.html
|
|
162
|
+
- doc/MIDICommunicationsWindows/Error.html
|
|
163
|
+
- doc/MIDICommunicationsWindows/Input.html
|
|
164
|
+
- doc/MIDICommunicationsWindows/Message.html
|
|
165
|
+
- doc/MIDICommunicationsWindows/Output.html
|
|
166
|
+
- doc/MIDICommunicationsWindows/TypeConversion.html
|
|
167
|
+
- doc/_index.html
|
|
168
|
+
- doc/class_list.html
|
|
169
|
+
- doc/css/common.css
|
|
170
|
+
- doc/css/full_list.css
|
|
171
|
+
- doc/css/style.css
|
|
172
|
+
- doc/file.README.html
|
|
173
|
+
- doc/file.testing-on-windows.html
|
|
174
|
+
- doc/file_list.html
|
|
175
|
+
- doc/frames.html
|
|
176
|
+
- doc/index.html
|
|
177
|
+
- doc/js/app.js
|
|
178
|
+
- doc/js/full_list.js
|
|
179
|
+
- doc/js/jquery.js
|
|
180
|
+
- doc/method_list.html
|
|
181
|
+
- doc/top-level-namespace.html
|
|
182
|
+
- docs/testing-on-windows.md
|
|
183
|
+
- examples/input.rb
|
|
184
|
+
- examples/list_ports.rb
|
|
185
|
+
- examples/output.rb
|
|
186
|
+
- examples/sysex_output.rb
|
|
187
|
+
- lib/midi-communications-windows.rb
|
|
188
|
+
- lib/midi-communications-windows/api.rb
|
|
189
|
+
- lib/midi-communications-windows/device.rb
|
|
190
|
+
- lib/midi-communications-windows/input.rb
|
|
191
|
+
- lib/midi-communications-windows/message.rb
|
|
192
|
+
- lib/midi-communications-windows/output.rb
|
|
193
|
+
- lib/midi-communications-windows/type_conversion.rb
|
|
194
|
+
- lib/midi-communications-windows/version.rb
|
|
195
|
+
- midi-communications-windows.gemspec
|
|
196
|
+
homepage: https://github.com/javier-sy/midi-communications-windows
|
|
197
|
+
licenses:
|
|
198
|
+
- LGPL-3.0-or-later
|
|
199
|
+
metadata:
|
|
200
|
+
homepage_uri: https://github.com/javier-sy/midi-communications-windows
|
|
201
|
+
source_code_uri: https://github.com/javier-sy/midi-communications-windows
|
|
202
|
+
documentation_uri: https://www.rubydoc.info/gems/midi-communications-windows
|
|
203
|
+
rdoc_options: []
|
|
204
|
+
require_paths:
|
|
205
|
+
- lib
|
|
206
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
207
|
+
requirements:
|
|
208
|
+
- - ">="
|
|
209
|
+
- !ruby/object:Gem::Version
|
|
210
|
+
version: '2.7'
|
|
211
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
|
+
requirements:
|
|
213
|
+
- - ">="
|
|
214
|
+
- !ruby/object:Gem::Version
|
|
215
|
+
version: '0'
|
|
216
|
+
requirements: []
|
|
217
|
+
rubygems_version: 3.6.9
|
|
218
|
+
specification_version: 4
|
|
219
|
+
summary: Realtime MIDI IO with Ruby for Windows
|
|
220
|
+
test_files: []
|