Class: PM::PatchMaster
- Inherits:
-
SimpleDelegator
- Object
- SimpleDelegator
- PM::PatchMaster
- Includes:
- Singleton
- Defined in:
- lib/patchmaster/patchmaster.rb
Overview
Global behavior: master list of songs, list of song lists, stuff like that.
Typical use:
PatchMaster.instance.load("my_pm_dsl_file")
PatchMaster.instance.start
# ...when you're done
PatchMaster.instance.stop
Constant Summary collapse
- DEBUG_FILE =
'/tmp/pm_debug.txt'
Instance Attribute Summary collapse
-
#all_songs ⇒ Object
readonly
Returns the value of attribute all_songs.
-
#code_bindings ⇒ Object
readonly
Returns the value of attribute code_bindings.
-
#cursor ⇒ Object
readonly
A Cursor to which we delegate incoming position methods (#song_list, #song, #patch, #next_song, #prev_patch, etc.).
-
#gui ⇒ Object
Returns the value of attribute gui.
-
#inputs ⇒ Object
readonly
Returns the value of attribute inputs.
-
#loaded_file ⇒ Object
readonly
Returns the value of attribute loaded_file.
-
#message_bindings ⇒ Object
readonly
Returns the value of attribute message_bindings.
-
#messages ⇒ Object
readonly
Returns the value of attribute messages.
-
#outputs ⇒ Object
readonly
Returns the value of attribute outputs.
-
#song_lists ⇒ Object
readonly
Returns the value of attribute song_lists.
-
#use_midi ⇒ Object
(also: #use_midi?)
Returns the value of attribute use_midi.
Instance Method Summary collapse
- #bind_code(code_key) ⇒ Object
- #bind_message(name, key) ⇒ Object
- #close_debug_file ⇒ Object
-
#debug(str) ⇒ Object
Output
str
to @debug_file or $stderr. -
#init_data ⇒ Object
Initializes the cursor and all data.
-
#initialize ⇒ PatchMaster
constructor
A new instance of PatchMaster.
-
#load(file) ⇒ Object
Loads
file
. - #no_gui! ⇒ Object
-
#panic(individual_notes = false) ⇒ Object
Sends the
CM_ALL_NOTES_OFF
controller message to all output instruments on all 16 MIDI channels. -
#run ⇒ Object
Run PatchMaster without the GUI.
- #running? ⇒ Boolean
- #save(file) ⇒ Object
-
#send_message(name) ⇒ Object
Send the message with the given
name
to all outputs. -
#start(init_cursor = true) ⇒ Object
If
init_cursor
istrue
(the default), initializes current song list, song, and patch. -
#stop ⇒ Object
Stop everything, including input instruments’ MIDIEye listener threads.
Constructor Details
#initialize ⇒ PatchMaster
Returns a new instance of PatchMaster.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/patchmaster/patchmaster.rb', line 34 def initialize @running = false @cursor = Cursor.new(self) super(@cursor) @use_midi = true @gui = nil @message_bindings = {} @code_bindings = {} if $DEBUG @debug_file = File.open(DEBUG_FILE, 'a') end init_data end |
Instance Attribute Details
#all_songs ⇒ Object (readonly)
Returns the value of attribute all_songs.
23 24 25 |
# File 'lib/patchmaster/patchmaster.rb', line 23 def all_songs @all_songs end |
#code_bindings ⇒ Object (readonly)
Returns the value of attribute code_bindings.
24 25 26 |
# File 'lib/patchmaster/patchmaster.rb', line 24 def code_bindings @code_bindings end |
#cursor ⇒ Object (readonly)
A Cursor to which we delegate incoming position methods (#song_list, #song, #patch, #next_song, #prev_patch, etc.)
32 33 34 |
# File 'lib/patchmaster/patchmaster.rb', line 32 def cursor @cursor end |
#gui ⇒ Object
Returns the value of attribute gui.
27 28 29 |
# File 'lib/patchmaster/patchmaster.rb', line 27 def gui @gui end |
#inputs ⇒ Object (readonly)
Returns the value of attribute inputs.
23 24 25 |
# File 'lib/patchmaster/patchmaster.rb', line 23 def inputs @inputs end |
#loaded_file ⇒ Object (readonly)
Returns the value of attribute loaded_file.
28 29 30 |
# File 'lib/patchmaster/patchmaster.rb', line 28 def loaded_file @loaded_file end |
#message_bindings ⇒ Object (readonly)
Returns the value of attribute message_bindings.
24 25 26 |
# File 'lib/patchmaster/patchmaster.rb', line 24 def @message_bindings end |
#messages ⇒ Object (readonly)
Returns the value of attribute messages.
24 25 26 |
# File 'lib/patchmaster/patchmaster.rb', line 24 def @messages end |
#outputs ⇒ Object (readonly)
Returns the value of attribute outputs.
23 24 25 |
# File 'lib/patchmaster/patchmaster.rb', line 23 def outputs @outputs end |
#song_lists ⇒ Object (readonly)
Returns the value of attribute song_lists.
23 24 25 |
# File 'lib/patchmaster/patchmaster.rb', line 23 def song_lists @song_lists end |
#use_midi ⇒ Object Also known as: use_midi?
Returns the value of attribute use_midi.
25 26 27 |
# File 'lib/patchmaster/patchmaster.rb', line 25 def use_midi @use_midi end |
Instance Method Details
#bind_code(code_key) ⇒ Object
86 87 88 |
# File 'lib/patchmaster/patchmaster.rb', line 86 def bind_code(code_key) @code_bindings[code_key.key] = code_key end |
#bind_message(name, key) ⇒ Object
82 83 84 |
# File 'lib/patchmaster/patchmaster.rb', line 82 def (name, key) @message_bindings[key] = name end |
#close_debug_file ⇒ Object
180 181 182 |
# File 'lib/patchmaster/patchmaster.rb', line 180 def close_debug_file @debug_file.close if @debug_file end |
#debug(str) ⇒ Object
Output str
to @debug_file or $stderr.
173 174 175 176 177 178 |
# File 'lib/patchmaster/patchmaster.rb', line 173 def debug(str) return unless $DEBUG f = @debug_file || $stderr f.puts str f.flush end |
#init_data ⇒ Object
Initializes the cursor and all data.
91 92 93 94 95 96 97 98 99 |
# File 'lib/patchmaster/patchmaster.rb', line 91 def init_data @cursor.clear @inputs = [] @outputs = [] @song_lists = [] @all_songs = SortedSongList.new('All Songs') @song_lists << @all_songs @messages = {} end |
#load(file) ⇒ Object
Loads file
. Does its best to restore the current song list, song, and patch after loading.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/patchmaster/patchmaster.rb', line 56 def load(file) restart = running? stop @cursor.mark init_data DSL.new.load(file) @loaded_file = file @cursor.restore if restart start(false) elsif @cursor.patch @cursor.patch.start end rescue => ex raise("error loading #{file}: #{ex}\n" + caller.join("\n")) end |
#no_gui! ⇒ Object
50 51 52 |
# File 'lib/patchmaster/patchmaster.rb', line 50 def no_gui! @no_gui = true end |
#panic(individual_notes = false) ⇒ Object
Sends the CM_ALL_NOTES_OFF
controller message to all output instruments on all 16 MIDI channels. If individual_notes
is true
send individual NOTE_OFF
messages to all notes as well.
158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/patchmaster/patchmaster.rb', line 158 def panic(individual_notes=false) debug("panic(#{individual_notes})") @outputs.each do |out| buf = [] MIDI_CHANNELS.times do |chan| buf += [CONTROLLER + chan, CM_ALL_NOTES_OFF, 0] if individual_notes buf += (0..127).collect { |note| [NOTE_OFF + chan, note, 0] }.flatten end end out.midi_out(buf) end end |
#run ⇒ Object
Run PatchMaster without the GUI. Don’t use this when using PM::Main. If there is a GUI then forward this request to it. Otherwise, call #start, wait for inputs’ MIDIEye listener threads to finish, then call #stop. Note that normally nothing stops those threads, so this is used as a way to make sure the script doesn’t quit until killed by something like SIGINT.
123 124 125 126 127 128 129 130 131 |
# File 'lib/patchmaster/patchmaster.rb', line 123 def run if @gui @gui.run else start(true) @inputs.each { |input| input.listener.join } stop end end |
#running? ⇒ Boolean
133 134 135 |
# File 'lib/patchmaster/patchmaster.rb', line 133 def running? @running end |
#save(file) ⇒ Object
75 76 77 78 79 80 |
# File 'lib/patchmaster/patchmaster.rb', line 75 def save(file) DSL.new.save(file) @loaded_file = file rescue => ex raise("error saving #{file}: #{ex}" + caller.join("\n")) end |
#send_message(name) ⇒ Object
Send the message with the given name
to all outputs. Names are matched case-insensitively.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/patchmaster/patchmaster.rb', line 139 def (name) _correct_case_name, msg = @messages[name.downcase] if !msg ("Message \"#{name}\" not found") return end debug("Sending message \"#{name}\"") @outputs.each { |out| out.midi_out(msg) } # If the user accidentally calls send_message in a filter at the end, # then the filter will return whatever this method returns. Just in # case, return nil instead of whatever the preceding code would return. nil end |
#start(init_cursor = true) ⇒ Object
If init_cursor
is true
(the default), initializes current song list, song, and patch.
103 104 105 106 107 108 |
# File 'lib/patchmaster/patchmaster.rb', line 103 def start(init_cursor = true) @cursor.init if init_cursor @cursor.patch.start if @cursor.patch @running = true @inputs.map(&:start) end |