midiator 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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