rtmidi 0.2.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/adamjmurray/ruby-rtmidi.png)](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
|
};
|