midi-communications 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,79 @@
1
+ module MIDICommunications
2
+ class Input
3
+ module StreamReader
4
+ # Returns any data in the input buffer that have been received since the last call to a
5
+ # StreamReader method. If a StreamReader method has not yet been called, all data received
6
+ # since the program was initialized will be returned
7
+ #
8
+ # The data is returned as array of MIDI event hashes as such:
9
+ # [
10
+ # { data: [144, 60, 100], timestamp: 1024 },
11
+ # { data: [128, 60, 100], timestamp: 1100 },
12
+ # { data: [144, 40, 120], timestamp: 1200 }
13
+ # ]
14
+ #
15
+ # In this case, the data is an array of Numeric bytes
16
+ # The timestamp is the number of millis since this input was enabled
17
+ # Arguments are passed to the underlying device object
18
+ #
19
+ # @param [*Object] args
20
+ # @return [Array<Hash>]
21
+ def gets(*args)
22
+ @device.gets(*args)
23
+ rescue SystemExit, Interrupt
24
+ exit
25
+ end
26
+
27
+ # Returns any data in the input buffer that have been received since the last call to a
28
+ # StreamReader method. If a StreamReader method has not yet been called, all data received
29
+ # since the program was initialized will be returned
30
+ #
31
+ # Similar to Input#gets except that the returned message data as string of hex digits eg:
32
+ # [
33
+ # { data: "904060", timestamp: 904 },
34
+ # { data: "804060", timestamp: 1150 },
35
+ # { data: "90447F", timestamp: 1300 }
36
+ # ]
37
+ #
38
+ # @param [*Object] args
39
+ # @return [Array<Hash>]
40
+ def gets_s(*args)
41
+ @device.gets_s(*args)
42
+ rescue SystemExit, Interrupt
43
+ exit
44
+ end
45
+ alias gets_bytestr gets_s
46
+ alias gets_hex gets_s
47
+
48
+ # Returns any data in the input buffer that have been received since the last call to a
49
+ # StreamReader method. If a StreamReader method has not yet been called, all data received
50
+ # since the program was initialized will be returned
51
+ #
52
+ # Similar to Input#gets except that the returned message data as an array of data bytes such as
53
+ # [144, 60, 100, 128, 60, 100, 144, 40, 120]
54
+ #
55
+ # @param [*Object] args
56
+ # @return [Array<Integer>]
57
+ def gets_data(*args)
58
+ arr = gets(*args)
59
+ arr.map { |msg| msg[:data] }.inject(:+)
60
+ end
61
+
62
+ # Returns any data in the input buffer that have been received since the last call to a
63
+ # StreamReader method. If a StreamReader method has not yet been called, all data received
64
+ # since the program was initialized will be returned
65
+ #
66
+ # Similar to Input#gets except that the returned message data as a string of data such as
67
+ # "90406080406090447F"
68
+ #
69
+ # @param [*Object] args
70
+ # @return [String]
71
+ def gets_data_s(*args)
72
+ arr = gets_bytestr(*args)
73
+ arr.map { |msg| msg[:data] }.join
74
+ end
75
+ alias gets_data_bytestr gets_data_s
76
+ alias gets_data_hex gets_data_s
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,16 @@
1
+ require 'midi-communications/input/stream_reader'
2
+
3
+ module MIDICommunications
4
+ # A MIDI input device
5
+ class Input
6
+ extend Device::ClassMethods
7
+ include Device::InstanceMethods
8
+ include StreamReader
9
+
10
+ # All MIDI input devices -- used to populate the class
11
+ # @return [Array<Input>]
12
+ def self.all
13
+ Loader.devices(direction: :input)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ module MIDICommunications
2
+
3
+ # Populate UniMIDI devices using the underlying device objects from the platform-specific gems
4
+ class Loader
5
+ class << self
6
+ # Use the given platform-specific adapter to load devices
7
+ # @param [MIDICommunications::Adapter::Loader] loader
8
+ def use(loader)
9
+ @loader = loader
10
+ end
11
+
12
+ # Get all MIDI devices
13
+ # @param [Hash] options
14
+ # @option options [Symbol] :direction Return only a particular direction of device eg :input, :output
15
+ # @return [Array<Input>, Array<Output>]
16
+ def devices(options = {})
17
+ if @devices.nil?
18
+ inputs = @loader.inputs.map { |device| ::MIDICommunications::Input.new(device) }
19
+ outputs = @loader.outputs.map { |device| ::MIDICommunications::Output.new(device) }
20
+ @devices = {
21
+ input: inputs,
22
+ output: outputs
23
+ }
24
+ end
25
+ options[:direction].nil? ? @devices.values.flatten : @devices[options[:direction]]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,60 @@
1
+ module MIDICommunications
2
+
3
+ # A MIDI output device
4
+ class Output
5
+ extend Device::ClassMethods
6
+ include Device::InstanceMethods
7
+
8
+ # All MIDI output devices -- used to populate the class
9
+ # @return [Array<Output>]
10
+ def self.all
11
+ Loader.devices(direction: :output)
12
+ end
13
+
14
+ # Sends a message to the output.
15
+ #
16
+ # The message format can be:
17
+ #
18
+ # 1. Numeric bytes eg output.puts(0x90, 0x40, 0x40)
19
+ # 2. An array of numeric bytes [0x90, 0x40, 0x40]
20
+ # 3. A string of bytes eg "904040"
21
+ # 4. An array of strings ["904040", "804040"]
22
+ #
23
+ # @param [*Array<Integer>, *Array<String>, *Integer, *String] messages
24
+ # @return [Array<Integer>, Array<String>]
25
+ def puts(*messages)
26
+ message = messages.first
27
+ case message
28
+ when Array then messages.each { |array| puts(*array.flatten) }
29
+ when Integer then puts_bytes(*messages)
30
+ when String then puts_s(*messages)
31
+ else
32
+ if message.respond_to?(:to_bytes)
33
+ puts_bytes(*message.to_bytes.flatten)
34
+ elsif message.respond_to?(:to_a)
35
+ puts_bytes(*message.to_a.flatten)
36
+ end
37
+ end
38
+ end
39
+
40
+ # Sends a message to the output in a form of a string eg "904040". This method does not do
41
+ # type checking
42
+ # @param [*String] messages
43
+ # @return [Array<String>, Array<Array<String>>]
44
+ def puts_s(*messages)
45
+ @device.puts_s(*messages)
46
+ messages.count < 2 ? messages[0] : messages
47
+ end
48
+ alias puts_bytestr puts_s
49
+ alias puts_hex puts_s
50
+
51
+ # Sends a message to the output in a form of bytes eg output.puts_bytes(0x90, 0x40, 0x40).
52
+ # This method does not do type checking.
53
+ # @param [*Array<Integer>] messages
54
+ # @return [Array<Integer>, Array<Array<Integer>>]
55
+ def puts_bytes(*messages)
56
+ @device.puts_bytes(*messages)
57
+ messages.count < 2 ? messages[0] : messages
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,33 @@
1
+ module MIDICommunications
2
+
3
+ # Deal with different dependencies between different user environments
4
+ module Platform
5
+ extend self
6
+
7
+ # Loads the proper MIDI library and adapter for the user's environment
8
+ def bootstrap
9
+ require("midi-communications/adapter/#{platform_lib}")
10
+ Loader.use(platform_module::Loader)
11
+ end
12
+
13
+ private
14
+
15
+ def platform_lib
16
+ case RUBY_PLATFORM
17
+ when /darwin/ then 'macos'
18
+ when /java/ then 'jruby'
19
+ when /linux/ then 'linux'
20
+ when /mingw/ then 'windows'
21
+ end
22
+ end
23
+
24
+ def platform_module
25
+ case RUBY_PLATFORM
26
+ when /darwin/ then Adapter::MacOS
27
+ when /java/ then Adapter::JRuby
28
+ when /linux/ then Adapter::Linux
29
+ when /mingw/ then Adapter::Windows
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module MIDICommunications
2
+
3
+ # Utility for converting between different data formats
4
+ module TypeConversion
5
+ extend self
6
+
7
+ # Convert an array of numeric bytes to string of hex bytes
8
+ # @param [Array<Integer>] bytes An array of numeric bytes eg [0x90, 0x40, 0x40]
9
+ # @return [String] A string of hex bytes eg "904040"
10
+ def numeric_byte_array_to_hex_string(bytes)
11
+ bytes.map { |b| b.to_s(16) }.join
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ #
2
+ # MIDI Communications
3
+ # Platform independent realtime MIDI IO for Ruby
4
+ #
5
+ # (c)2021 Javier Sánchez Yeste for the modifications, licensed under LGPL 3.0 License
6
+ # (c)2011-2017 Ari Russo
7
+ #
8
+
9
+ # modules
10
+ require 'midi-communications/device'
11
+ require 'midi-communications/platform'
12
+ require 'midi-communications/type_conversion'
13
+
14
+ # classes
15
+ require 'midi-communications/input'
16
+ require 'midi-communications/loader'
17
+ require 'midi-communications/output'
18
+
19
+ module MIDICommunications
20
+ VERSION = '0.5.1'.freeze
21
+ Platform.bootstrap
22
+ end
@@ -0,0 +1,31 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'midi-communications'
3
+ s.version = '0.5.1'
4
+ s.date = '2021-11-19'
5
+ s.summary = 'Platform independent realtime MIDI input and output for Ruby'
6
+ s.description = 'Access MIDI devices for MacOS, Linux (wip), Windows (wip) and JRuby (wip).'
7
+ s.authors = ['Javier Sánchez Yeste']
8
+ s.email = ['javier.sy@gmail.com']
9
+ s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
10
+ s.homepage = 'https://rubygems.org/gems/midi-communications'
11
+ s.license = 'LGPL-3.0'
12
+
13
+ s.required_ruby_version = '~> 2.7'
14
+
15
+ # TODO
16
+ #s.metadata = {
17
+ # "source_code_uri" => "https://",
18
+ # "homepage_uri" => "",
19
+ # "documentation_uri" => "",
20
+ # "changelog_uri" => ""
21
+ #}
22
+
23
+ s.add_runtime_dependency 'midi-communications-macos', '~> 0.5', '>= 0.5.0'
24
+ # s.add_runtime_dependency 'alsa-rawmidi', '~> 0.3', '>= 0.3.1'
25
+ # s.add_runtime_dependency 'midi-jruby', '~> 0.1', '>= 0.1.4'
26
+ # s.add_runtime_dependency 'midi-winmm', '~> 0.1', '>= 0.1.10'
27
+
28
+ s.add_development_dependency 'minitest', '~> 5.14', '>= 5.14.4'
29
+ s.add_development_dependency 'rake', '~> 13.0', '>= 13.0.6'
30
+ s.add_development_dependency 'shoulda-context', '~> 2.0', '>= 2.0.0'
31
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: midi-communications
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.1
5
+ platform: ruby
6
+ authors:
7
+ - Javier Sánchez Yeste
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-11-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: midi-communications-macos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.5'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.5.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.5'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.5.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: minitest
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '5.14'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 5.14.4
43
+ type: :development
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '5.14'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 5.14.4
53
+ - !ruby/object:Gem::Dependency
54
+ name: rake
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '13.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 13.0.6
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '13.0'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 13.0.6
73
+ - !ruby/object:Gem::Dependency
74
+ name: shoulda-context
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '2.0'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.0
83
+ type: :development
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 2.0.0
93
+ description: Access MIDI devices for MacOS, Linux (wip), Windows (wip) and JRuby (wip).
94
+ email:
95
+ - javier.sy@gmail.com
96
+ executables: []
97
+ extensions: []
98
+ extra_rdoc_files: []
99
+ files:
100
+ - ".gitignore"
101
+ - Gemfile
102
+ - LICENSE
103
+ - LICENSE.unimidi
104
+ - README.md
105
+ - Rakefile
106
+ - examples/input.rb
107
+ - examples/output.rb
108
+ - examples/select_a_device.rb
109
+ - examples/sysex_output.rb
110
+ - lib/midi-communications.rb
111
+ - lib/midi-communications/adapter/jruby.rb
112
+ - lib/midi-communications/adapter/linux.rb
113
+ - lib/midi-communications/adapter/macos.rb
114
+ - lib/midi-communications/adapter/windows.rb
115
+ - lib/midi-communications/device.rb
116
+ - lib/midi-communications/input.rb
117
+ - lib/midi-communications/input/stream_reader.rb
118
+ - lib/midi-communications/loader.rb
119
+ - lib/midi-communications/output.rb
120
+ - lib/midi-communications/platform.rb
121
+ - lib/midi-communications/type_conversion.rb
122
+ - midi-communications.gemspec
123
+ homepage: https://rubygems.org/gems/midi-communications
124
+ licenses:
125
+ - LGPL-3.0
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
134
+ - !ruby/object:Gem::Version
135
+ version: '2.7'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubygems_version: 3.1.6
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Platform independent realtime MIDI input and output for Ruby
146
+ test_files: []