rtmidi 0.2.2 → 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 +4 -4
- data/README.md +38 -11
- data/Rakefile +24 -7
- data/examples/list_ports.rb +2 -2
- data/examples/receive_any_message.rb +35 -0
- data/examples/receive_channel_message.rb +35 -0
- data/examples/send_any_message.rb +31 -0
- data/examples/send_channel_message.rb +34 -0
- data/ext/Rakefile +7 -93
- data/ext/ruby-rtmidi.cpp +24 -0
- data/ext/ruby-rtmidi.h +5 -0
- data/ext/ruby-rtmidi.o +0 -0
- data/ext/ruby-rtmidi.so +0 -0
- data/lib/rtmidi.rb +5 -0
- data/lib/rtmidi/build/compiler.rb +132 -0
- data/lib/rtmidi/build/system.rb +58 -0
- data/lib/rtmidi/in.rb +70 -19
- data/lib/rtmidi/interface.rb +11 -6
- data/lib/rtmidi/out.rb +35 -11
- data/spec/rtmidi/build/compiler_spec.rb +438 -0
- data/spec/rtmidi/build/system_spec.rb +130 -0
- data/spec/rtmidi/in_spec.rb +131 -0
- data/spec/rtmidi/out_spec.rb +87 -0
- data/spec/spec_helper.rb +12 -0
- metadata +27 -4
- data/examples/monitor_input.rb +0 -31
- data/examples/play_notes.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c430949e32e04bb62083aae6879c0b20dad223e
|
4
|
+
data.tar.gz: 81ab70ee2a3fe78349ed6de2542fea7e42ca3bfc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55647eec74cde698b047ad3abea4b3b2c88d8b3f42ca318e05106bd4ceaab9191da0194873b8c16675bc78e6bc0a4f77dd6a19207204261d39f1259e1bb9b690
|
7
|
+
data.tar.gz: 7953645285988a046841e8bf4a75e403d1919b3c95640bbdfaa59db64b7934fc21cacba08bff03e24380569a54e367c5daab7ce346df0d870462c406574f6c4f
|
data/README.md
CHANGED
@@ -1,24 +1,25 @@
|
|
1
1
|
Ruby-RtMidi
|
2
2
|
===========
|
3
3
|
|
4
|
+
[](http://travis-ci.org/adamjmurray/ruby-rtmidi)
|
5
|
+
|
4
6
|
[Ruby](http://www.ruby-lang.org/) wrapper for [RtMidi](http://www.music.mcgill.ca/~gary/rtmidi/index.html),
|
5
7
|
a cross-platform C++ library for realtime MIDI input and output.
|
6
8
|
|
7
9
|
Features:
|
8
10
|
|
9
11
|
* List MIDI I/O ports
|
10
|
-
* Send
|
11
|
-
*
|
12
|
+
* Send MIDI messages to output ports
|
13
|
+
* Receive messages on input ports
|
12
14
|
|
13
|
-
In other words,
|
14
|
-
|
15
|
-
but there is no support for [SySex](https://en.wikipedia.org/wiki/SysEx#System_Exclusive_messages) messages yet.
|
15
|
+
In other words, everything you'd want from a low-level MIDI library.
|
16
|
+
It's still your responsibility to interpret the MIDI message byte streams!
|
16
17
|
|
17
18
|
Supported Platforms:
|
18
19
|
|
19
20
|
* OS X
|
20
21
|
* Windows
|
21
|
-
* Linux
|
22
|
+
* Linux
|
22
23
|
|
23
24
|
|
24
25
|
Requirements
|
@@ -54,8 +55,14 @@ Windows Setup
|
|
54
55
|
* MinGW Developer ToolKit
|
55
56
|
* Use the the MinGW Shell (MSYS) to install
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
Note: when installing under MinGW, this library may not work outside of MinGW. If that is a problem for you, use Visual Studio to install.
|
59
|
+
|
60
|
+
Linux Setup
|
61
|
+
-----------
|
62
|
+
|
63
|
+
Install [JACK](http://jackaudio.org/) or [ALSA](http://www.alsa-project.org).
|
64
|
+
|
65
|
+
This should work on Ubuntu:
|
59
66
|
|
60
67
|
sudo apt-get install g++
|
61
68
|
sudo apt-get install jackd
|
@@ -75,19 +82,39 @@ Usage
|
|
75
82
|
|
76
83
|
See the following examples:
|
77
84
|
|
78
|
-
* [
|
79
|
-
* [MIDI output](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/
|
80
|
-
* [MIDI input](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/
|
85
|
+
* [list MIDI devices](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/list_ports.rb)
|
86
|
+
* [MIDI channel output](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/send_channel_message.rb)
|
87
|
+
* [MIDI channel input](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/receive_channel_input.rb)
|
88
|
+
* [arbitrary MIDI output](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/send_any_message.rb)
|
89
|
+
* [arbitrary MIDI input](http://rdoc.info/github/adamjmurray/ruby-rtmidi/file/examples/receive_any_input.rb)
|
90
|
+
|
91
|
+
Use the arbitrary MIDI IO to handle channel messages, SysEx, timing, and/or active sensing messages.
|
92
|
+
If you only need channel messages (notes, modulation/CC, pitch bend, aftertouch), it's recommended you
|
93
|
+
follow the channel IO examples.
|
81
94
|
|
82
95
|
|
83
96
|
Documentation
|
84
97
|
=============
|
98
|
+
|
85
99
|
[http://rdoc.info/github/adamjmurray/ruby-rtmidi/frames](http://rdoc.info/github/adamjmurray/ruby-rtmidi/frames)
|
86
100
|
|
87
101
|
|
102
|
+
Contributing
|
103
|
+
============
|
104
|
+
|
105
|
+
Pull requests are welcome. The following must work:
|
106
|
+
|
107
|
+
* `rake test` shows all unit tests are passing
|
108
|
+
* Build and test the gem manually:
|
109
|
+
* `gem build rtmidi.gemspec`
|
110
|
+
* `gem install rtmidi-#{version}.gem`
|
111
|
+
* the examples can be run successfully against this version of the gem (`ruby examples/**`)
|
112
|
+
|
113
|
+
|
88
114
|
Changelog
|
89
115
|
=========
|
90
116
|
|
117
|
+
* 0.3 - Support for arbitrary MIDI messages including SysEx
|
91
118
|
* 0.2.2 - Compilable with Visual Studio on Windows
|
92
119
|
* 0.2.1 - Linux support (thanks to [@quark-zju](https://github.com/quark-zju))
|
93
120
|
* 0.2 - First stable release
|
data/Rakefile
CHANGED
@@ -1,10 +1,27 @@
|
|
1
|
-
|
1
|
+
require 'rake/clean'
|
2
|
+
|
3
|
+
CLEAN.include %w[ **/*.o **/*.lib **/*.obj **/*.log ]
|
4
|
+
CLOBBER.include %w[ **/*.so **/*.dll ]
|
5
|
+
|
2
6
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
7
|
+
require 'rspec/core/rake_task'
|
8
|
+
|
9
|
+
desc "Run tests"
|
10
|
+
RSpec::Core::RakeTask.new('test') do |spec|
|
11
|
+
spec.rspec_opts = ["--color", "--format", "nested"]
|
12
|
+
if ARGV[1]
|
13
|
+
# only run specs with filenames starting with the command line argument
|
14
|
+
spec.pattern = "spec/**/#{ARGV[1]}*"
|
8
15
|
end
|
9
|
-
puts
|
10
16
|
end
|
17
|
+
|
18
|
+
task :spec => :test # alias test task as spec task
|
19
|
+
|
20
|
+
|
21
|
+
load File.expand_path('ext/Rakefile', File.dirname(__FILE__))
|
22
|
+
|
23
|
+
|
24
|
+
desc 'Build the gem'
|
25
|
+
task :gem do
|
26
|
+
system 'gem build rtmidi.gemspec'
|
27
|
+
end
|
data/examples/list_ports.rb
CHANGED
@@ -4,12 +4,12 @@ puts
|
|
4
4
|
|
5
5
|
midiin = RtMidi::In.new
|
6
6
|
puts "Available MIDI input ports"
|
7
|
-
midiin.port_names.each_with_index{|name,index| puts "
|
7
|
+
midiin.port_names.each_with_index{|name,index| puts " #{index+1}: #{name}" }
|
8
8
|
|
9
9
|
puts
|
10
10
|
|
11
11
|
midiout = RtMidi::Out.new
|
12
12
|
puts "Available MIDI output ports"
|
13
|
-
midiout.port_names.each_with_index{|name,index| puts "
|
13
|
+
midiout.port_names.each_with_index{|name,index| puts " #{index+1}: #{name}" }
|
14
14
|
|
15
15
|
puts
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "rtmidi"
|
2
|
+
|
3
|
+
midiin = RtMidi::In.new
|
4
|
+
|
5
|
+
|
6
|
+
##############################################################################
|
7
|
+
# Boilerplate code for selecting a MIDI port
|
8
|
+
|
9
|
+
puts "Available MIDI input ports"
|
10
|
+
midiin.port_names.each_with_index{|name,index| printf "%3i: %s\n", index, name }
|
11
|
+
|
12
|
+
def select_port(midiio)
|
13
|
+
print "Select a port number: "
|
14
|
+
if (port = gets) =~ /^\d+$/
|
15
|
+
return port.to_i if (0...midiio.port_count).include? port.to_i
|
16
|
+
end
|
17
|
+
puts "Invalid port number"
|
18
|
+
end
|
19
|
+
|
20
|
+
port_index = select_port(midiin) until port_index
|
21
|
+
|
22
|
+
##############################################################################
|
23
|
+
# Use this approach when you need to receive any message including:
|
24
|
+
# System Exclusive (SysEx), timing, active sensing
|
25
|
+
|
26
|
+
midiin.receive_message do |*bytes|
|
27
|
+
puts bytes.inspect
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "Receiving MIDI messages including SysEx..."
|
31
|
+
puts "Ctrl+C to exit"
|
32
|
+
|
33
|
+
midiin.open_port(port_index)
|
34
|
+
|
35
|
+
sleep # prevent Ruby from exiting immediately
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "rtmidi"
|
2
|
+
|
3
|
+
midiin = RtMidi::In.new
|
4
|
+
|
5
|
+
|
6
|
+
##############################################################################
|
7
|
+
# Boilerplate code for selecting a MIDI port
|
8
|
+
|
9
|
+
puts "Available MIDI input ports"
|
10
|
+
midiin.port_names.each_with_index{|name,index| printf "%3i: %s\n", index, name }
|
11
|
+
|
12
|
+
def select_port(midiio)
|
13
|
+
print "Select a port number: "
|
14
|
+
if (port = gets) =~ /^\d+$/
|
15
|
+
return port.to_i if (0...midiio.port_count).include? port.to_i
|
16
|
+
end
|
17
|
+
puts "Invalid port number"
|
18
|
+
end
|
19
|
+
|
20
|
+
port_index = select_port(midiin) until port_index
|
21
|
+
|
22
|
+
##############################################################################
|
23
|
+
# Use this approach when you only need to receive channel message like:
|
24
|
+
# MIDI notes, modulation/CC, pitch bend, aftertouch
|
25
|
+
|
26
|
+
midiin.receive_channel_message do |byte1, byte2, byte3|
|
27
|
+
puts "#{byte1} #{byte2} #{byte3}"
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "Receiving MIDI channel messages..."
|
31
|
+
puts "Ctrl+C to exit"
|
32
|
+
|
33
|
+
midiin.open_port(port_index)
|
34
|
+
|
35
|
+
sleep # prevent Ruby from exiting immediately
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "rtmidi"
|
2
|
+
|
3
|
+
midiout = RtMidi::Out.new
|
4
|
+
|
5
|
+
|
6
|
+
##############################################################################
|
7
|
+
# Boilerplate code for selecting a MIDI port
|
8
|
+
|
9
|
+
puts "Available MIDI output ports"
|
10
|
+
midiout.port_names.each_with_index{|name,index| printf "%3i: %s\n", index, name }
|
11
|
+
|
12
|
+
def select_port(midiio)
|
13
|
+
print "Select a port number: "
|
14
|
+
if (port = gets) =~ /^\d+$/
|
15
|
+
return port.to_i if (0...midiio.port_count).include? port.to_i
|
16
|
+
end
|
17
|
+
puts "Invalid port number"
|
18
|
+
end
|
19
|
+
|
20
|
+
port_index = select_port(midiout) until port_index
|
21
|
+
|
22
|
+
##############################################################################
|
23
|
+
# Use this approach when you need to send any message including:
|
24
|
+
# System Exclusive (SysEx), timing, active sensing
|
25
|
+
|
26
|
+
midiout.open_port(port_index)
|
27
|
+
|
28
|
+
# Now send some SysEx messages
|
29
|
+
midiout.send_message(240, 67, 16, 0, 16, 34, 247)
|
30
|
+
# or if you prefer a single array argument:
|
31
|
+
midiout.send_message( [240, 67, 16, 0, 16, 35, 247] )
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "rtmidi"
|
2
|
+
|
3
|
+
midiout = RtMidi::Out.new
|
4
|
+
|
5
|
+
|
6
|
+
##############################################################################
|
7
|
+
# Boilerplate code for selecting a MIDI port
|
8
|
+
|
9
|
+
puts "Available MIDI output ports"
|
10
|
+
midiout.port_names.each_with_index{|name,index| printf "%3i: %s\n", index, name }
|
11
|
+
|
12
|
+
def select_port(midiio)
|
13
|
+
print "Select a port number: "
|
14
|
+
if (port = gets) =~ /^\d+$/
|
15
|
+
return port.to_i if (0...midiio.port_count).include? port.to_i
|
16
|
+
end
|
17
|
+
puts "Invalid port number"
|
18
|
+
end
|
19
|
+
|
20
|
+
port_index = select_port(midiout) until port_index
|
21
|
+
|
22
|
+
##############################################################################
|
23
|
+
# Use this approach when you only need to send channel message like:
|
24
|
+
# MIDI notes, modulation/CC, pitch bend, aftertouch
|
25
|
+
|
26
|
+
midiout.open_port(port_index)
|
27
|
+
|
28
|
+
for pitch in [60, 62, 64, 65, 67]
|
29
|
+
midiout.send_channel_message(0x90, pitch, 127) # note on
|
30
|
+
sleep 0.5
|
31
|
+
midiout.send_channel_message(0x90, pitch, 0) # note off
|
32
|
+
end
|
33
|
+
|
34
|
+
sleep 0.5 # give the final note off time to release
|
data/ext/Rakefile
CHANGED
@@ -1,97 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
EXT_DIR = File.expand_path(File.dirname __FILE__)
|
4
|
-
RTMIDI_DIR = "#{EXT_DIR}/rtmidi-2.0.1"
|
5
|
-
|
6
|
-
HOST_OS = RbConfig::CONFIG['host_os'].downcase
|
7
|
-
OS_X = (HOST_OS =~ /darwin/)
|
8
|
-
WINDOWS = ((HOST_OS =~ /win/ and HOST_OS !~ /darwin/) or HOST_OS =~ /mingw/)
|
9
|
-
LINUX = (HOST_OS =~ /linux/)
|
10
|
-
|
11
|
-
CLEAN.include('**/*.o', '*.log')
|
12
|
-
CLOBBER.include('*.so')
|
13
|
-
|
14
|
-
def cd(dir)
|
15
|
-
puts "cd #{dir}"
|
16
|
-
Dir.chdir(dir)
|
17
|
-
end
|
18
|
-
|
19
|
-
def run(cmd)
|
20
|
-
puts cmd
|
21
|
-
unless system(cmd)
|
22
|
-
puts "Error: command exited with return value #{$?.exitstatus}"
|
23
|
-
exit $?.exitstatus
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
|
28
|
-
require "mkmf"
|
29
|
-
COMPILER = if WINDOWS and find_executable "cl.exe"
|
30
|
-
:cl
|
31
|
-
else
|
32
|
-
if find_executable "gcc" and find_executable "g++"
|
33
|
-
:gcc
|
34
|
-
else
|
35
|
-
abort "Cannot find gcc/g++ #{'or cl.exe ' if WINDOWS}compiler"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
PREDEFINE, SYSTEM_LIBS = *case
|
40
|
-
when OS_X then ["__MACOSX_CORE__", "-framework CoreMIDI -framework CoreAudio -framework CoreFoundation"]
|
41
|
-
when WINDOWS then ["__WINDOWS_MM__", "-lwinmm"]
|
42
|
-
when LINUX then
|
43
|
-
defines, libs = '', ''
|
44
|
-
{:alsa => '__LINUX_ALSA__', :jack => '__UNIX_JACK__'}.select do |pkg, _|
|
45
|
-
system "pkg-config --exists #{pkg}"
|
46
|
-
end.each do |pkg, macro|
|
47
|
-
defines << "#{macro} "
|
48
|
-
libs << `pkg-config --libs #{pkg}`.chomp
|
49
|
-
end
|
50
|
-
if defines.empty?
|
51
|
-
raise 'Neither JACK or ALSA detected using pkg-config. Please install one of them first.'
|
52
|
-
end
|
53
|
-
[defines, libs]
|
54
|
-
else
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
def compile_rtmidi
|
59
|
-
cd RTMIDI_DIR
|
60
|
-
if COMPILER == :gcc
|
61
|
-
run "g++ -O3 -Wall -Iinclude -fPIC -D#{PREDEFINE} -o RtMidi.o -c RtMidi.cpp"
|
62
|
-
else
|
63
|
-
run "cl /O2 /Iinclude /D#{PREDEFINE} /EHsc /FoRtMidi.obj /c RtMidi.cpp"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def compile_ruby_rtmidi_wrapper
|
68
|
-
cd EXT_DIR
|
69
|
-
if COMPILER == :gcc
|
70
|
-
run "g++ -g -Wall -I#{RTMIDI_DIR} -fPIC -o ruby-rtmidi.o -c ruby-rtmidi.cpp"
|
71
|
-
else
|
72
|
-
run "cl /I#{RTMIDI_DIR} /D__RUBY_RTMIDI_DLL__ /EHsc /Foruby-rtmidi.obj /c ruby-rtmidi.cpp"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def create_shared_library
|
77
|
-
cd EXT_DIR
|
78
|
-
if COMPILER == :gcc
|
79
|
-
run "g++ -g -Wall -I#{RTMIDI_DIR} -I#{RTMIDI_DIR}/include -D#{PREDEFINE} -fPIC -shared -o ruby-rtmidi.so " +
|
80
|
-
"ruby-rtmidi.o #{RTMIDI_DIR}/RtMidi.o #{SYSTEM_LIBS}"
|
81
|
-
else
|
82
|
-
run "cl /I#{RTMIDI_DIR} /I#{RTMIDI_DIR}/include /D#{PREDEFINE} /LD ruby-rtmidi.obj #{RTMIDI_DIR}/RtMidi.obj winmm.lib"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
|
87
|
-
desc 'run the make task'
|
1
|
+
desc 'Run the make task'
|
88
2
|
task :default => :make
|
89
3
|
|
90
|
-
desc '
|
4
|
+
desc 'Compile the RtMidi C++ library with Ruby FFI wrapper'
|
91
5
|
task :make do
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
6
|
+
require_relative '../lib/rtmidi/build/compiler'
|
7
|
+
ext_dir = File.expand_path(File.dirname __FILE__)
|
8
|
+
rtmidi_dir = "#{ext_dir}/rtmidi-2.0.1"
|
9
|
+
compiler = RtMidi::Build::Compiler.new(ext_dir, rtmidi_dir, verbose: true)
|
10
|
+
compiler.compile
|
97
11
|
end
|
data/ext/ruby-rtmidi.cpp
CHANGED
@@ -67,6 +67,21 @@ void midiin_set_callback(rtmidi_ptr p, rtmidi_callback callback) {
|
|
67
67
|
midiin->setCallback(midiin_callback_proxy, (void *)callback);
|
68
68
|
}
|
69
69
|
|
70
|
+
void midiin_varargs_callback_proxy( double deltatime, std::vector< unsigned char > *message, void *userData )
|
71
|
+
{
|
72
|
+
unsigned int byte_count = message->size();
|
73
|
+
// for ( unsigned int i=0; i<byte_count; i++ )
|
74
|
+
// std::cout << "Byte " << i << " = " << (int)message->at(i) << ", ";
|
75
|
+
// if ( byte_count > 0 )
|
76
|
+
// std::cout << "stamp = " << deltatime << std::endl; # TODO: do we care about the deltatime?
|
77
|
+
((rtmidi_varargs_callback)userData)(&(*message)[0], byte_count);
|
78
|
+
}
|
79
|
+
|
80
|
+
void midiin_set_varargs_callback(rtmidi_ptr p, rtmidi_varargs_callback callback) {
|
81
|
+
RtMidiIn *midiin = static_cast<RtMidiIn *>(p);
|
82
|
+
midiin->setCallback(midiin_varargs_callback_proxy, (void *)callback);
|
83
|
+
}
|
84
|
+
|
70
85
|
void midiin_cancel_callback(rtmidi_ptr p) {
|
71
86
|
RtMidiIn *midiin = static_cast<RtMidiIn *>(p);
|
72
87
|
midiin->cancelCallback();
|
@@ -117,3 +132,12 @@ void midiout_send_message(rtmidi_ptr p, int byte1, int byte2, int byte3) {
|
|
117
132
|
message[2] = byte3;
|
118
133
|
midiout->sendMessage(&message);
|
119
134
|
}
|
135
|
+
|
136
|
+
void midiout_send_bytes(rtmidi_ptr p, int* bytes, int byte_count) {
|
137
|
+
RtMidiOut *midiout = static_cast<RtMidiOut *>(p);
|
138
|
+
std::vector<unsigned char> message;
|
139
|
+
for(int i=0; i<byte_count; i++) {
|
140
|
+
message.push_back(bytes[i]);
|
141
|
+
}
|
142
|
+
midiout->sendMessage(&message);
|
143
|
+
}
|
data/ext/ruby-rtmidi.h
CHANGED
@@ -8,6 +8,7 @@ extern "C"
|
|
8
8
|
{
|
9
9
|
typedef void* rtmidi_ptr;
|
10
10
|
typedef void (*rtmidi_callback)(int byte1, int byte2, int byte3);
|
11
|
+
typedef void (*rtmidi_varargs_callback)(unsigned char* bytes, int byte_count);
|
11
12
|
|
12
13
|
//================================================
|
13
14
|
// INPUT
|
@@ -28,6 +29,8 @@ extern "C"
|
|
28
29
|
|
29
30
|
DLL_EXPORT void midiin_set_callback(rtmidi_ptr p, rtmidi_callback callback);
|
30
31
|
|
32
|
+
DLL_EXPORT void midiin_set_varargs_callback(rtmidi_ptr p, rtmidi_varargs_callback callback);
|
33
|
+
|
31
34
|
DLL_EXPORT void midiin_cancel_callback(rtmidi_ptr p);
|
32
35
|
|
33
36
|
|
@@ -47,4 +50,6 @@ extern "C"
|
|
47
50
|
DLL_EXPORT void midiout_close_port(rtmidi_ptr p);
|
48
51
|
|
49
52
|
DLL_EXPORT void midiout_send_message(rtmidi_ptr p, int byte1, int byte2, int byte3);
|
53
|
+
|
54
|
+
DLL_EXPORT void midiout_send_bytes(rtmidi_ptr p, int* bytes, int byte_count);
|
50
55
|
};
|