patchmaster 0.0.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.
- data/bin/patchmaster +20 -0
- data/lib/patchmaster.rb +15 -0
- data/lib/patchmaster/app/info_window.rb +32 -0
- data/lib/patchmaster/app/info_window_contents.txt +15 -0
- data/lib/patchmaster/app/list_window.rb +26 -0
- data/lib/patchmaster/app/main.rb +161 -0
- data/lib/patchmaster/app/patch_window.rb +61 -0
- data/lib/patchmaster/app/pm_window.rb +41 -0
- data/lib/patchmaster/app/prompt_window.rb +61 -0
- data/lib/patchmaster/connection.rb +90 -0
- data/lib/patchmaster/consts.rb +439 -0
- data/lib/patchmaster/dsl.rb +227 -0
- data/lib/patchmaster/filter.rb +23 -0
- data/lib/patchmaster/io.rb +87 -0
- data/lib/patchmaster/list.rb +121 -0
- data/lib/patchmaster/list_container.rb +36 -0
- data/lib/patchmaster/patch.rb +48 -0
- data/lib/patchmaster/patchmaster.rb +168 -0
- data/lib/patchmaster/predicates.rb +125 -0
- data/lib/patchmaster/song.rb +24 -0
- data/lib/patchmaster/song_list.rb +39 -0
- data/lib/patchmaster/sorted_song_list.rb +15 -0
- data/test/test_helper.rb +58 -0
- metadata +88 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
require 'patchmaster/consts'
|
|
2
|
+
|
|
3
|
+
class Integer
|
|
4
|
+
|
|
5
|
+
def high_nibble
|
|
6
|
+
self & 0xf0
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def channel
|
|
10
|
+
self & 0x0f
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def channel?
|
|
14
|
+
self >= PM::NOTE_ON && self < PM::SYSEX
|
|
15
|
+
end
|
|
16
|
+
alias_method :chan?, :channel?
|
|
17
|
+
|
|
18
|
+
def note_on?
|
|
19
|
+
(self & 0xf0) == PM::NOTE_ON
|
|
20
|
+
end
|
|
21
|
+
alias_method :on?, :note_on?
|
|
22
|
+
|
|
23
|
+
def note_off?
|
|
24
|
+
(self & 0xf0) == PM::NOTE_OFF
|
|
25
|
+
end
|
|
26
|
+
alias_method :off?, :note_off?
|
|
27
|
+
|
|
28
|
+
def poly_pressure?
|
|
29
|
+
(self & 0xf0) == PM::POLY_PRESSURE
|
|
30
|
+
end
|
|
31
|
+
alias_method :poly_press?, :poly_pressure?
|
|
32
|
+
|
|
33
|
+
# Returns true if self is a status byte for a message that targets a note
|
|
34
|
+
# (note on, note off, or poly pressure).
|
|
35
|
+
def note?
|
|
36
|
+
self >= PM::NOTE_OFF && self < PM::CONTROLLER
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def controller?
|
|
40
|
+
(self & 0xf0) == PM::CONTROLLER
|
|
41
|
+
end
|
|
42
|
+
alias_method :ctrl?, :controller?
|
|
43
|
+
|
|
44
|
+
def program_change?
|
|
45
|
+
(self & 0xf0) == PM::PROGRAM_CHANGE
|
|
46
|
+
end
|
|
47
|
+
alias_method :pc?, :program_change?
|
|
48
|
+
|
|
49
|
+
def pitch_bend?
|
|
50
|
+
(self & 0xf0) == PM::PITCH_BEND
|
|
51
|
+
end
|
|
52
|
+
alias_method :pb?, :pitch_bend?
|
|
53
|
+
|
|
54
|
+
def system?
|
|
55
|
+
self >= PM::SYSEX && self <= PM::EOX
|
|
56
|
+
end
|
|
57
|
+
alias_method :sys?, :system?
|
|
58
|
+
|
|
59
|
+
def realtime?
|
|
60
|
+
self >= 0xf8 && self <= 0xff
|
|
61
|
+
end
|
|
62
|
+
alias_method :rt?, :realtime?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
class Array
|
|
66
|
+
|
|
67
|
+
def high_nibble
|
|
68
|
+
self[0].high_nibble
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def channel
|
|
72
|
+
self[0].channel
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def channel?
|
|
76
|
+
self[0].channel?
|
|
77
|
+
end
|
|
78
|
+
alias_method :chan?, :channel?
|
|
79
|
+
|
|
80
|
+
def note_on?
|
|
81
|
+
self[0].note_on?
|
|
82
|
+
end
|
|
83
|
+
alias_method :on?, :note_on?
|
|
84
|
+
|
|
85
|
+
def note_off?
|
|
86
|
+
self[0].note_off?
|
|
87
|
+
end
|
|
88
|
+
alias_method :off?, :note_off?
|
|
89
|
+
|
|
90
|
+
def poly_pressure?
|
|
91
|
+
self[0].poly_pressure?
|
|
92
|
+
end
|
|
93
|
+
alias_method :poly_press?, :poly_pressure?
|
|
94
|
+
|
|
95
|
+
# Returns true if self is a message that targets a note (note on, note
|
|
96
|
+
# off, or poly pressure).
|
|
97
|
+
def note?
|
|
98
|
+
self[0].note?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def controller?
|
|
102
|
+
self[0].controller?
|
|
103
|
+
end
|
|
104
|
+
alias_method :ctrl?, :controller?
|
|
105
|
+
|
|
106
|
+
def program_change?
|
|
107
|
+
self[0].program_change?
|
|
108
|
+
end
|
|
109
|
+
alias_method :pc?, :program_change?
|
|
110
|
+
|
|
111
|
+
def pitch_bend?
|
|
112
|
+
self[0].pitch_bend?
|
|
113
|
+
end
|
|
114
|
+
alias_method :pb?, :pitch_bend?
|
|
115
|
+
|
|
116
|
+
def system?
|
|
117
|
+
self[0].system?
|
|
118
|
+
end
|
|
119
|
+
alias_method :sys?, :system?
|
|
120
|
+
|
|
121
|
+
def realtime?
|
|
122
|
+
self[0].realtime?
|
|
123
|
+
end
|
|
124
|
+
alias_method :rt?, :realtime?
|
|
125
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'patchmaster/list'
|
|
2
|
+
require 'patchmaster/list_container'
|
|
3
|
+
|
|
4
|
+
module PM
|
|
5
|
+
|
|
6
|
+
# A Song is a named list of Patches with a cursor.
|
|
7
|
+
class Song
|
|
8
|
+
|
|
9
|
+
attr_accessor :name, :patches
|
|
10
|
+
|
|
11
|
+
include ListContainer
|
|
12
|
+
|
|
13
|
+
def initialize(name)
|
|
14
|
+
@name = name
|
|
15
|
+
@patches = List.new
|
|
16
|
+
PatchMaster.instance.all_songs << self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def <<(patch)
|
|
20
|
+
@patches << patch
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'patchmaster/list'
|
|
2
|
+
require 'patchmaster/list_container'
|
|
3
|
+
|
|
4
|
+
module PM
|
|
5
|
+
|
|
6
|
+
# A SongList is a list of Songs with a cursor.
|
|
7
|
+
class SongList
|
|
8
|
+
|
|
9
|
+
attr_accessor :name, :songs
|
|
10
|
+
|
|
11
|
+
include ListContainer
|
|
12
|
+
|
|
13
|
+
def initialize(name)
|
|
14
|
+
@name = name
|
|
15
|
+
@songs = List.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def <<(song)
|
|
19
|
+
@songs << song
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Returns the first Song that matches +name+. +name+ may be either a
|
|
23
|
+
# Regexp or a String. The match will be made case-insensitive. Does not
|
|
24
|
+
# move or set the cursor.
|
|
25
|
+
def find(name_regex)
|
|
26
|
+
name_regex = Regexp.new(name_regex.to_s, true) # make case-insensitive
|
|
27
|
+
@songs.detect { |s| s.name =~ name_regex }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
%w(first prev curr next last).each do |dir|
|
|
31
|
+
instance_eval("def #{dir}_patch; @songs.curr.#{dir}_patch; end")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Called when moving out of this song list to another
|
|
35
|
+
def stop_current_song
|
|
36
|
+
@songs.stop_current
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'patchmaster'
|
|
3
|
+
|
|
4
|
+
# For all tests, make sure mock I/O MIDI ports are used.
|
|
5
|
+
PM::PatchMaster.instance.no_midi!
|
|
6
|
+
|
|
7
|
+
module PM
|
|
8
|
+
|
|
9
|
+
# To help with testing, we replace MockInputPort#gets_data and
|
|
10
|
+
# MockOutputPort#puts with versions that send what we want and save what is
|
|
11
|
+
# received.
|
|
12
|
+
class MockInputPort
|
|
13
|
+
|
|
14
|
+
attr_accessor :data_to_send
|
|
15
|
+
|
|
16
|
+
def gets_data
|
|
17
|
+
retval = @data_to_send || []
|
|
18
|
+
@data_to_send = []
|
|
19
|
+
retval
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class MockOutputPort
|
|
24
|
+
|
|
25
|
+
attr_accessor :buffer
|
|
26
|
+
|
|
27
|
+
def initialize
|
|
28
|
+
@buffer = []
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def puts(bytes)
|
|
32
|
+
@buffer += bytes
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# A TestConnection records all bytes received and passes them straight
|
|
38
|
+
# through.
|
|
39
|
+
class TestConnection < PM::Connection
|
|
40
|
+
|
|
41
|
+
attr_accessor :bytes_received
|
|
42
|
+
|
|
43
|
+
def midi_in(bytes)
|
|
44
|
+
@bytes_received ||= []
|
|
45
|
+
@bytes_received += bytes
|
|
46
|
+
midi_out(@output, bytes)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class PMTest < Test::Unit::TestCase
|
|
52
|
+
|
|
53
|
+
# Data comes out of UniMIDI::Input#gets_ata as an array of arrays of MIDI
|
|
54
|
+
# bytes.
|
|
55
|
+
def midi_data(*bytes)
|
|
56
|
+
[bytes]
|
|
57
|
+
end
|
|
58
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: patchmaster
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.0
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Jim Menard
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2012-04-09 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: unimidi
|
|
16
|
+
requirement: &2151875240 !ruby/object:Gem::Requirement
|
|
17
|
+
none: false
|
|
18
|
+
requirements:
|
|
19
|
+
- - ! '>='
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '0'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: *2151875240
|
|
25
|
+
description: ! 'PatchMaster is realtime MIDI performance software that alloweds a
|
|
26
|
+
musician
|
|
27
|
+
|
|
28
|
+
to totally reconfigure a MIDI setup instantaneously and modify the MIDI data
|
|
29
|
+
|
|
30
|
+
while it''s being sent.
|
|
31
|
+
|
|
32
|
+
'
|
|
33
|
+
email: jim@jimmenard.com
|
|
34
|
+
executables:
|
|
35
|
+
- patchmaster
|
|
36
|
+
extensions: []
|
|
37
|
+
extra_rdoc_files: []
|
|
38
|
+
files:
|
|
39
|
+
- bin/patchmaster
|
|
40
|
+
- lib/patchmaster/app/info_window.rb
|
|
41
|
+
- lib/patchmaster/app/info_window_contents.txt
|
|
42
|
+
- lib/patchmaster/app/list_window.rb
|
|
43
|
+
- lib/patchmaster/app/main.rb
|
|
44
|
+
- lib/patchmaster/app/patch_window.rb
|
|
45
|
+
- lib/patchmaster/app/pm_window.rb
|
|
46
|
+
- lib/patchmaster/app/prompt_window.rb
|
|
47
|
+
- lib/patchmaster/connection.rb
|
|
48
|
+
- lib/patchmaster/consts.rb
|
|
49
|
+
- lib/patchmaster/dsl.rb
|
|
50
|
+
- lib/patchmaster/filter.rb
|
|
51
|
+
- lib/patchmaster/io.rb
|
|
52
|
+
- lib/patchmaster/list.rb
|
|
53
|
+
- lib/patchmaster/list_container.rb
|
|
54
|
+
- lib/patchmaster/patch.rb
|
|
55
|
+
- lib/patchmaster/patchmaster.rb
|
|
56
|
+
- lib/patchmaster/predicates.rb
|
|
57
|
+
- lib/patchmaster/song.rb
|
|
58
|
+
- lib/patchmaster/song_list.rb
|
|
59
|
+
- lib/patchmaster/sorted_song_list.rb
|
|
60
|
+
- lib/patchmaster.rb
|
|
61
|
+
- test/test_helper.rb
|
|
62
|
+
homepage: https://github.com/jimm/patchmaster
|
|
63
|
+
licenses:
|
|
64
|
+
- Ruby
|
|
65
|
+
post_install_message:
|
|
66
|
+
rdoc_options: []
|
|
67
|
+
require_paths:
|
|
68
|
+
- lib
|
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
|
+
none: false
|
|
71
|
+
requirements:
|
|
72
|
+
- - ! '>='
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
|
+
none: false
|
|
77
|
+
requirements:
|
|
78
|
+
- - ! '>='
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0'
|
|
81
|
+
requirements: []
|
|
82
|
+
rubyforge_project:
|
|
83
|
+
rubygems_version: 1.8.11
|
|
84
|
+
signing_key:
|
|
85
|
+
specification_version: 3
|
|
86
|
+
summary: Realtime MIDI setup configuration and MIDI filtering
|
|
87
|
+
test_files:
|
|
88
|
+
- test/test_helper.rb
|