midiator 0.1.0

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.
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A module that you can include to get access to constants representing known
4
+ # drum note numbers.
5
+ #
6
+ # == Authors
7
+ #
8
+ # * Ben Bleything <ben@bleything.net>
9
+ #
10
+ # == Copyright
11
+ #
12
+ # Copyright (c) 2008 Ben Bleything
13
+ #
14
+ # This code released under the terms of the MIT license.
15
+ #
16
+
17
+ module MIDIator::Drums # this file does not rdoc well, so uhh.... :nodoc:
18
+
19
+ ##########################################################################
20
+ ### G E N E R A L M I D I D R U M N O T E S
21
+ ##########################################################################
22
+ BassDrum1 = 36 ;;; LongGuiro = 74 ;;; OpenHiHat = 46
23
+ BassDrum2 = 35 ;;; LongWhistle = 72 ;;; OpenHighConga = 63
24
+ Cabasa = 69 ;;; LowAgogo = 68 ;;; OpenTriangle = 81
25
+ ChineseCymbal = 52 ;;; LowBongo = 61 ;;; PedalHiHat = 44
26
+ Claves = 75 ;;; LowConga = 64 ;;; RideBell = 53
27
+ ClosedHiHat = 42 ;;; LowTimbale = 66 ;;; RideCymbal1 = 51
28
+ Cowbell = 56 ;;; LowTom1 = 43 ;;; RideCymbal2 = 59
29
+ CrashCymbal1 = 49 ;;; LowTom2 = 41 ;;; ShortGuiro = 73
30
+ CrashCymbal2 = 57 ;;; LowWoodBlock = 77 ;;; ShortWhistle = 71
31
+ HandClap = 39 ;;; Maracas = 70 ;;; SideStick = 37
32
+ HighAgogo = 67 ;;; MidTom1 = 47 ;;; SnareDrum1 = 38
33
+ HighBongo = 60 ;;; MidTom2 = 45 ;;; SnareDrum2 = 40
34
+ HighTimbale = 65 ;;; MuteCuica = 78 ;;; SplashCymbal = 55
35
+ HighTom1 = 50 ;;; MuteHighConga = 62 ;;; Tambourine = 54
36
+ HighTom2 = 48 ;;; MuteTriangle = 80 ;;; VibraSlap = 58
37
+ HighWoodBlock = 76 ;;; OpenCuica = 79
38
+
39
+ end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A collection of exceptions used by MIDIator.
4
+ #
5
+ # == Authors
6
+ #
7
+ # * Ben Bleything <ben@bleything.net>
8
+ #
9
+ # == Copyright
10
+ #
11
+ # Copyright (c) 2008 Ben Bleything
12
+ #
13
+ # This code released under the terms of the MIT license.
14
+ #
15
+
16
+ ### Raised when the selected driver is unable to find any available MIDI
17
+ ### destinations.
18
+ class MIDIator::NoMIDIDestinations < RuntimeError ; end
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # The main entry point into MIDIator. Create a MIDIator::Interface object and
4
+ # off you go.
5
+ #
6
+ # == Authors
7
+ #
8
+ # * Ben Bleything <ben@bleything.net>
9
+ #
10
+ # == Copyright
11
+ #
12
+ # Copyright (c) 2008 Ben Bleything
13
+ #
14
+ # This code released under the terms of the MIT license.
15
+ #
16
+
17
+ require 'midiator'
18
+
19
+ class MIDIator::Interface
20
+ attr_reader :driver
21
+
22
+ ### Automatically select a driver to use
23
+ def autodetect_driver
24
+ self.use( :winmm ) if RUBY_PLATFORM.include? 'win32'
25
+ self.use( :core_midi ) if RUBY_PLATFORM.include? 'darwin'
26
+ self.use( :alsa ) if RUBY_PLATFORM.include? 'linux'
27
+ end
28
+
29
+
30
+ ### Attempts to load the MIDI system driver called +driver_name+.
31
+ def use( driver_name )
32
+ driver_path = "midiator/drivers/#{driver_name.to_s}"
33
+
34
+ begin
35
+ require driver_path
36
+ rescue LoadError => e
37
+ raise LoadError,
38
+ "Could not load driver '#{driver_name}'."
39
+ end
40
+
41
+ # Fix two side-effects of the camelization process... first, change
42
+ # instances of Midi to MIDI. This fixes the acronym form but doesn't
43
+ # change, for instance, 'timidity'.
44
+ #
45
+ # Second, the require path is midiator/drivers/foo, but the module
46
+ # name is Driver singular, so fix that.
47
+ driver_class = driver_path.camelize.
48
+ gsub( /Midi/, 'MIDI' ).
49
+ sub( /::Drivers::/, '::Driver::')
50
+
51
+ # special case for the ALSA driver
52
+ driver_class.sub!( /Alsa/, 'ALSA' )
53
+
54
+ # special case for the WinMM driver
55
+ driver_class.sub!( /Winmm/, 'WinMM' )
56
+
57
+ # this little trick stolen from ActiveSupport. It looks for a top-
58
+ # level module with the given name.
59
+ @driver = Object.module_eval( "::#{driver_class}" ).new
60
+ end
61
+
62
+
63
+ ### A little shortcut method for playing the given +note+ for the specified
64
+ ### +duration+.
65
+ def play( note, duration = 0.1, channel = 0, velocity = 100 )
66
+ @driver.note_on( note, channel, velocity )
67
+ sleep duration
68
+ @driver.note_off( note, channel, velocity )
69
+ end
70
+
71
+
72
+ ### Does nothing for +duration+ seconds.
73
+ def rest( duration = 0.1 )
74
+ sleep duration
75
+ end
76
+
77
+ #######
78
+ private
79
+ #######
80
+
81
+ ### Checks to see if the currently-loaded driver knows how to do +method+ and
82
+ ### passes the message on if so. Raises an exception (as normal) if not.
83
+ def method_missing( method, *args )
84
+ raise NoMethodError, "Neither MIDIator::Interface nor #{@driver.class} " +
85
+ "has a '#{method}' method." unless @driver.respond_to? method
86
+
87
+ return @driver.send( method, *args )
88
+ end
89
+
90
+ end
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A module that you can include to get access to constants representing the
4
+ # available MIDI note space.
5
+ #
6
+ # == Authors
7
+ #
8
+ # * Ben Bleything <ben@bleything.net>
9
+ #
10
+ # == Copyright
11
+ #
12
+ # Copyright (c) 2008 Ben Bleything
13
+ #
14
+ # This code released under the terms of the MIT license.
15
+ #
16
+
17
+ module MIDIator::Notes # this file does not rdoc well, so uhh.... :nodoc:
18
+
19
+ ##########################################################################
20
+ ### O C T A V E - 1 ;;; O C T A V E 0 ;;; O C T A V E 1
21
+ ##########################################################################
22
+ Cn1 = 0 ; Bsn1 = 0 ;;; C0 = 12 ; Bs0 = 12 ;;; C1 = 24 ; Bs1 = 24
23
+ Csn1 = 1 ; Dbn1 = 1 ;;; Cs0 = 13 ; Db0 = 13 ;;; Cs1 = 25 ; Db1 = 25
24
+ Dn1 = 2 ; ;;; D0 = 14 ; ;;; D1 = 26 ;
25
+ Dsn1 = 3 ; Ebn1 = 3 ;;; Ds0 = 15 ; Eb0 = 15 ;;; Ds1 = 27 ; Eb1 = 27
26
+ En1 = 4 ; Fbn1 = 4 ;;; E0 = 16 ; Fb0 = 16 ;;; E1 = 28 ; Fb1 = 28
27
+ Fn1 = 5 ; ;;; F0 = 17 ; ;;; F1 = 29 ;
28
+ Fsn1 = 6 ; Gbn1 = 6 ;;; Fs0 = 18 ; Gb0 = 18 ;;; Fs1 = 30 ; Gb1 = 30
29
+ Gn1 = 7 ; ;;; G0 = 19 ; ;;; G1 = 31 ;
30
+ Gsn1 = 8 ; Abn1 = 8 ;;; Gs0 = 20 ; Ab0 = 20 ;;; Gs1 = 32 ; Ab1 = 32
31
+ An1 = 9 ; ;;; A0 = 21 ; ;;; A1 = 33 ;
32
+ Asn1 = 10 ; Bbn1 = 10 ;;; As0 = 22 ; Bb0 = 22 ;;; As1 = 34 ; Bb1 = 34
33
+ Bn1 = 11 ; Cb0 = 11 ;;; B0 = 23 ; Cb1 = 23 ;;; B1 = 35 ; Cb2 = 35
34
+
35
+ ##########################################################################
36
+ ### O C T A V E 2 ;;; O C T A V E 3 ;;; O C T A V E 4
37
+ ##########################################################################
38
+ C2 = 36 ; Bs2 = 36 ;;; C3 = 48 ; Bs3 = 48 ;;; C4 = 60 ; Bs4 = 60
39
+ Cs2 = 37 ; Db2 = 37 ;;; Cs3 = 49 ; Db3 = 49 ;;; Cs4 = 61 ; Db4 = 61
40
+ D2 = 38 ; ;;; D3 = 50 ; ;;; D4 = 62 ;
41
+ Ds2 = 39 ; Eb2 = 39 ;;; Ds3 = 51 ; Eb3 = 51 ;;; Ds4 = 63 ; Eb4 = 63
42
+ E2 = 40 ; Fb2 = 40 ;;; E3 = 52 ; Fb3 = 52 ;;; E4 = 64 ; Fb4 = 64
43
+ F2 = 41 ; ;;; F3 = 53 ; ;;; F4 = 65 ;
44
+ Fs2 = 42 ; Gb2 = 42 ;;; Fs3 = 54 ; Gb3 = 54 ;;; Fs4 = 66 ; Gb4 = 66
45
+ G2 = 43 ; ;;; G3 = 55 ; ;;; G4 = 67 ;
46
+ Gs2 = 44 ; Ab2 = 44 ;;; Gs3 = 56 ; Ab3 = 56 ;;; Gs4 = 68 ; Ab4 = 68
47
+ A2 = 45 ; ;;; A3 = 57 ; ;;; A4 = 69 ;
48
+ As2 = 46 ; Bb2 = 46 ;;; As3 = 58 ; Bb3 = 58 ;;; As4 = 70 ; Bb4 = 70
49
+ B2 = 47 ; Cb3 = 47 ;;; B3 = 59 ; Cb4 = 59 ;;; B4 = 71 ; Cb5 = 71
50
+
51
+ ##########################################################################
52
+ ### O C T A V E 5 ;;; O C T A V E 6 ;;; O C T A V E 7
53
+ ##########################################################################
54
+ C5 = 72 ; Bs5 = 72 ;;; C6 = 84 ; Bs6 = 84 ;;; C7 = 96 ; Bs7 = 96
55
+ Cs5 = 73 ; Db5 = 73 ;;; Cs6 = 85 ; Db6 = 85 ;;; Cs7 = 97 ; Db7 = 97
56
+ D5 = 74 ; ;;; D6 = 86 ; ;;; D7 = 98 ;
57
+ Ds5 = 75 ; Eb5 = 75 ;;; Ds6 = 87 ; Eb6 = 87 ;;; Ds7 = 99 ; Eb7 = 99
58
+ E5 = 76 ; Fb5 = 76 ;;; E6 = 88 ; Fb6 = 88 ;;; E7 = 100 ; Fb7 = 100
59
+ F5 = 77 ; ;;; F6 = 89 ; ;;; F7 = 101 ;
60
+ Fs5 = 78 ; Gb5 = 78 ;;; Fs6 = 90 ; Gb6 = 90 ;;; Fs7 = 102 ; Gb7 = 102
61
+ G5 = 79 ; ;;; G6 = 91 ; ;;; G7 = 103 ;
62
+ Gs5 = 80 ; Ab5 = 80 ;;; Gs6 = 92 ; Ab6 = 92 ;;; Gs7 = 104 ; Ab7 = 104
63
+ A5 = 81 ; ;;; A6 = 93 ; ;;; A7 = 105 ;
64
+ As5 = 82 ; Bb5 = 82 ;;; As6 = 94 ; Bb6 = 94 ;;; As7 = 106 ; Bb7 = 106
65
+ B5 = 83 ; Cb6 = 83 ;;; B6 = 95 ; Cb7 = 95 ;;; B7 = 107 ; Cb8 = 107
66
+
67
+ ##########################################################################
68
+ ### O C T A V E 8 ;;; O C T A V E 9
69
+ ##########################################################################
70
+ C8 = 108 ; Bs8 = 108 ;;; C9 = 120 ; Bs9 = 120
71
+ Cs8 = 109 ; Db8 = 109 ;;; Cs9 = 121 ; Db9 = 121
72
+ D8 = 110 ; ;;; D9 = 122 ;
73
+ Ds8 = 111 ; Eb8 = 111 ;;; Ds9 = 123 ; Eb9 = 123
74
+ E8 = 112 ; Fb8 = 112 ;;; E9 = 124 ; Fb9 = 124
75
+ F8 = 113 ; ;;; F9 = 125 ;
76
+ Fs8 = 114 ; Gb8 = 114 ;;; Fs9 = 126 ; Gb9 = 126
77
+ G8 = 115 ; ;;; G9 = 127 ;
78
+ Gs8 = 116 ; Ab8 = 116
79
+ A8 = 117 ;
80
+ As8 = 118 ; Bb8 = 118
81
+ B8 = 119 ; Cb9 = 119
82
+
83
+ # these notes are not valid MIDI notes but they're here to complete the
84
+ # octave. Use at your own risk?
85
+ Gs9 = 128 ; Ab9 = 128
86
+ A9 = 129 ;
87
+ As9 = 130 ; Bb9 = 130
88
+ B9 = 131 ; Cb10 = 131
89
+
90
+ # Shortcuts!
91
+ MiddleC = 84
92
+
93
+ end
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A timer that allows you to schedule notes to be played in the future.
4
+ #
5
+ # == Authors
6
+ #
7
+ # * Topher Cyll
8
+ # * Ben Bleything <ben@bleything.net>
9
+ #
10
+ # == Copyright
11
+ #
12
+ # Copyright (c) 2008 Ben Bleything
13
+ #
14
+ # This code released under the terms of the MIT license.
15
+ #
16
+
17
+ class MIDIator::Timer
18
+ attr_reader :resolution, :queue, :thread
19
+
20
+ ### Create a new Timer object that ticks every +resolution+ seconds.
21
+ def initialize( resolution )
22
+ @resolution = resolution
23
+ @queue = []
24
+
25
+ @thread = Thread.new do
26
+ loop do
27
+ dispatch
28
+ sleep @resolution
29
+ end
30
+ end
31
+ end
32
+
33
+
34
+ ### Empty the queue
35
+ def flush
36
+ @queue.clear
37
+ end
38
+
39
+
40
+ ### Add a new job to be performed at +time+.
41
+ def at( time, &block )
42
+ time = time.to_f if time.kind_of? Time
43
+ @queue.push [ time, block ]
44
+ end
45
+
46
+ #######
47
+ private
48
+ #######
49
+
50
+ ### Check to see if there is work to perform in this timeslice and
51
+ ### do it if so.
52
+ def dispatch
53
+ now = Time.now.to_f
54
+
55
+ # move "ready" work out of the queue
56
+ ready, @queue = @queue.partition {|time, proc| time <= now }
57
+
58
+ # call all of the "ready" jobs, passing in the time
59
+ ready.each {|time, proc| proc.call( time ) }
60
+ end
61
+
62
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Some extensions to the built-in Ruby String class.
4
+ #
5
+ # == Authors
6
+ #
7
+ # * Ben Bleything <ben@bleything.net>
8
+ # * Various others as noted in the code
9
+ #
10
+ # == Copyright
11
+ #
12
+ # Copyright (c) 2008 Ben Bleything, except where noted.
13
+ #
14
+ # This code released under the terms of the MIT license.
15
+ #
16
+
17
+ class String
18
+ ### NOTE: Stolen from ActiveSupport. They hold the copyright. Our
19
+ ### modifications are making it a method on String and removing the
20
+ ### lowerCamelCase option since we don't use it.
21
+ ###
22
+ ### +camelize+ converts strings to CamelCase.
23
+ ###
24
+ ### +camelize+ will also convert '/' to '::' which is useful for converting
25
+ ### paths to namespaces.
26
+ ###
27
+ ### Examples
28
+ ### "active_record".camelize #=> "ActiveRecord"
29
+ ### "active_record/errors".camelize #=> "ActiveRecord::Errors"
30
+ def camelize
31
+ return self.gsub( /\/(.?)/ ) {
32
+ "::" + $1.upcase
33
+ }.
34
+ gsub( /(^|_)(.)/ ) {
35
+ $2.upcase
36
+ }
37
+ end
38
+
39
+ ### NOTE: Stolen from ActiveSupport. They hold the copyright. The only
40
+ ### modifications were to make it a String instance method instead of a
41
+ ### function.
42
+ ###
43
+ ### The reverse of +camelize+. Makes an underscored form from the expression
44
+ ### in the string.
45
+ ###
46
+ ### Changes '::' to '/' to convert namespaces to paths.
47
+ ###
48
+ ### Examples
49
+ ### "ActiveRecord".underscore #=> "active_record"
50
+ ### "ActiveRecord::Errors".underscore #=> active_record/errors
51
+ def underscore
52
+ return self.gsub( /::/, '/' ).
53
+ gsub( /([A-Z]+)([A-Z][a-z])/, '\1_\2' ).
54
+ gsub( /([a-z\d])([A-Z])/ , '\1_\2' ).
55
+ tr( "-", "_" ).
56
+ downcase
57
+ end
58
+
59
+ end
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Rake tasks related to packaging.
4
+ #
5
+ # == Authors
6
+ #
7
+ # * Ben Bleything <ben@bleything.net>
8
+ #
9
+ # == Copyright
10
+ #
11
+ # Copyright (c) 2008 Ben Bleything
12
+ #
13
+ # This code released under the terms of the MIT license.
14
+ #
15
+
16
+ require 'midiator'
17
+
18
+ require 'rake/packagetask'
19
+ require 'rake/gempackagetask'
20
+
21
+ ### Task: gem
22
+ gemspec = Gem::Specification.new do |gem|
23
+ gem.name = "midiator"
24
+ gem.version = MIDIator::VERSION
25
+
26
+ gem.summary = "MIDIator - A a nice Ruby interface to your system's MIDI services."
27
+ gem.description = "MIDIator provides an OS-agnostic way to send live MIDI messages to " +
28
+ "your machine's MIDI playback system."
29
+
30
+ gem.authors = "Ben Bleything"
31
+ gem.email = "ben@bleything.net"
32
+ gem.homepage = "http://projects.bleything.net/projects/show/midiator"
33
+
34
+ gem.rubyforge_project = 'midiator'
35
+
36
+ gem.has_rdoc = true
37
+
38
+ gem.files = RELEASE_FILES.
39
+ collect {|f| f.relative_path_from(BASE_DIR).to_s }
40
+ gem.test_files = SPEC_FILES.
41
+ collect {|f| f.relative_path_from(BASE_DIR).to_s }
42
+ end
43
+
44
+ Rake::GemPackageTask.new( gemspec ) do |task|
45
+ task.gem_spec = gemspec
46
+ task.need_tar = false
47
+ task.need_tar_gz = true
48
+ task.need_tar_bz2 = true
49
+ task.need_zip = true
50
+ end
data/misc/rake/rdoc.rb ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Rake tasks for generating rdoc
4
+ #
5
+ # == Authors
6
+ #
7
+ # * Ben Bleything <ben@bleything.net>
8
+ #
9
+ # == Copyright
10
+ #
11
+ # Copyright (c) 2008 Ben Bleything
12
+ #
13
+ # This code released under the terms of the MIT license.
14
+ #
15
+
16
+ require 'rake/rdoctask'
17
+
18
+ # uncomment for darkfish!
19
+ # gem 'darkfish-rdoc'
20
+ # require 'darkfish-rdoc'
21
+
22
+ # uncomment for hanna!
23
+ gem 'mislav-hanna'
24
+ require 'hanna'
25
+
26
+ ### Task: rdoc
27
+ Rake::RDocTask.new do |rdoc|
28
+ rdoc.rdoc_dir = 'docs/rdoc'
29
+ rdoc.title = "MIDIator - a nice Ruby interface to your system's MIDI services."
30
+
31
+ rdoc.options += [
32
+ '-w', '4',
33
+ '-SHNa',
34
+ '-i', BASE_DIR.to_s,
35
+ # '-f', 'darkfish', # uncomment for darkfish!
36
+ '-T', 'hanna', # uncomment for hanna!
37
+ '-m', 'README',
38
+ '-W', 'http://projects.bleything.net/repositories/changes/midiator/',
39
+ ]
40
+
41
+ rdoc.rdoc_files.include 'README'
42
+ rdoc.rdoc_files.include 'LICENSE'
43
+ rdoc.rdoc_files.include 'LICENSE.prp'
44
+ rdoc.rdoc_files.include LIB_FILES.collect {|f| f.relative_path_from(BASE_DIR).to_s }
45
+ end