Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/Ruby_Scripts/110.builtin_commands.rb

Parent Directory Parent Directory | Revision Log Revision Log


Revision 184 - (show annotations) (download)
Sun Mar 8 09:16:51 2020 UTC (4 years, 1 month ago) by toshinagata1964
File size: 8581 byte(s)
Scale selected time dialog is slightly improved
1 # Copyright (c) 2010-2017 Toshi Nagata. All rights reserved.
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation version 2 of the License.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
11
12 class Sequence
13
14 # The commands in this file are hardcoded so that the names should not be modified
15
16 def change_control_number
17 hash = Dialog.run("Change Control Number") {
18 @bind_global_settings = "change_control_number_dialog"
19 layout(1,
20 layout(2,
21 item(:text, :title=>"Old control number"),
22 item(:textfield, :width=>40, :range=>[0, 127], :tag=>"old"),
23 item(:text, :title=>"New control number"),
24 item(:textfield, :width=>40, :range=>[0, 127], :tag=>"new")),
25 item(:checkbox, :title=>"Change only editable tracks", :tag=>"editable_only"),
26 item(:checkbox, :title=>"Change only selected events", :tag=>"selection_only"))
27 }
28 if hash[:status] == 0
29 p hash
30 old = Integer(hash["old"])
31 new = Integer(hash["new"])
32 editable_only = (hash["editable_only"] != 0)
33 selection_only = (hash["selection_only"] != 0)
34 each_track { |tr|
35 next if editable_only && !tr.editable?
36 sel = (selection_only ? tr.selection : tr.all_events)
37 sel = sel.select { |pt| pt.kind == :control && pt.code == old }
38 sel.modify_code([new]) # modify_code(new) offsets the control numbers, which is not what we want
39 }
40 end
41 end
42
43 def shift_selected_events
44 hash = Dialog.run("Shift Selected Events") {
45 @bind_global_settings = "shift_selected_events_dialog"
46 layout(1,
47 item(:text, :title=>"Shift amount"),
48 layout(6,
49 item(:text, :title=>"bar"),
50 item(:textfield, :width=>50, :tag=>"bar"),
51 item(:text, :title=>"beat"),
52 item(:textfield, :width=>50, :tag=>"beat"),
53 item(:text, :title=>"tick"),
54 item(:textfield, :width=>50, :tag=>"tick")),
55 item(:checkbox, :title=>"Shift backward", :tag=>"backward"))
56 }
57 p hash
58 if hash[:status] == 0
59 bar = hash["bar"].to_f
60 beat = hash["beat"].to_f
61 tick = hash["tick"].to_f
62 sign = (hash["backward"] == 0 ? 1 : -1)
63 if (bar == 0 && beat == 0)
64 delta = sign * tick
65 else
66 range = tick_for_selection(true)
67 return if range[0] < 0
68 origin = tick_to_measure(range[0])
69 delta = measure_to_tick(origin[0] + sign * bar, origin[1] + sign * beat, origin[2] + sign * tick) - range[0]
70 end
71 p self
72 each_track { |tr|
73 puts tr
74 next if !tr.editable?
75 tr.selection.modify_tick(delta)
76 # The following code does _not_ work:
77 # tr.each_selected { |pt| pt.tick = pt.tick + delta }
78 # This is because changing tick may change the event position, so that 'pt'
79 # may not point the correct event
80 }
81 end
82 end
83
84 def scale_selected_time_dialog
85 s_tick, e_tick = self.editing_range
86 return [] if s_tick < 0
87 duration = e_tick - s_tick
88 s_str = tick_to_measure(s_tick).join(".")
89 e_str = tick_to_measure(e_tick).join(".")
90 new_e_tick = e_tick
91 new_duration = duration
92 seq = self
93 hash = Dialog.run("Scale Selected Time") {
94 @bind_global_settings = "scale_selected_time_dialog"
95 str_to_tick = proc { |str|
96 a = str.scan(/\d+/)
97 while a.length < 3; a.unshift("1"); end
98 seq.measure_to_tick(a[0].to_i, a[1].to_i, a[2].to_i)
99 }
100 layout(1,
101 layout(2,
102 item(:text, :title=>"Start:"),
103 item(:textfield, :width=>100, :tag=>"start", :value=>s_str,
104 :action=>proc { |it|
105 new_e_tick = s_tick + value("new_duration").to_i
106 s_tick = str_to_tick.call(it[:value])
107 if s_tick > e_tick
108 s_tick = e_tick
109 set_value("start", seq.tick_to_measure(s_tick).join("."))
110 end
111 duration = e_tick - s_tick
112 set_value("duration", sprintf("%d", duration))
113 new_duration = new_e_tick - s_tick
114 set_value("new_duration", sprintf("%d", new_duration))
115 }),
116 item(:text, :title=>"End:"),
117 item(:textfield, :width=>100, :tag=>"end", :value=>e_str,
118 :action=>proc { |it|
119 e_tick = str_to_tick.call(it[:value])
120 if s_tick > e_tick
121 e_tick = s_tick
122 set_value("end", seq.tick_to_measure(e_tick).join("."))
123 end
124 e_tick = s_tick + 1 if s_tick >= e_tick
125 duration = e_tick - s_tick
126 set_value("duration", sprintf("%d", duration))
127 }),
128 item(:text, :title=>"Duration:"),
129 item(:textfield, :width=>100, :tag=>"duration", :value=>sprintf("%d", duration),
130 :action=>proc { |it|
131 duration = it[:value].to_i
132 if duration < 0
133 duration = 0
134 set_value("duration", "0")
135 end
136 e_tick = s_tick + duration
137 set_value("end", seq.tick_to_measure(e_tick).join("."))
138 })
139 ),
140 layout(2,
141 item(:radio, :title=>"Specify end tick", :tag=>"new_end_radio", :value=>1),
142 item(:textfield, :width=>100, :tag=>"new_end", :value=>e_str,
143 :action=>proc { |it|
144 val_tick = str_to_tick.call(it[:value])
145 if val_tick != new_e_tick
146 set_value("new_duration", sprintf("%d", val_tick - s_tick))
147 set_value("new_duration_radio", 0)
148 set_value("new_end_radio", 1)
149 new_e_tick = val_tick
150 new_duration = new_e_tick - s_tick
151 end
152 }),
153 item(:radio, :title=>"Specify duration", :tag=>"new_duration_radio", :value=>0),
154 item(:textfield, :width=>100, :tag=>"new_duration", :value=>duration.to_s,
155 :action=>proc { |it|
156 d = Integer(it[:value])
157 if d != new_duration
158 val_str = seq.tick_to_measure(s_tick + d).join(".")
159 set_value("new_end", val_str)
160 set_value("new_duration_radio", 1)
161 set_value("new_end_radio", 0)
162 new_duration = d
163 new_e_tick = s_tick + d
164 end
165 }),
166 item(:checkbox, :title=>"Insert TEMPO event to keep absolute timings", :tag=>"insert_tempo"),
167 -1)
168 )
169 }
170 if hash[:status] == 0
171 return [s_tick, e_tick, new_duration, hash["insert_tempo"]]
172 else
173 return []
174 end
175 end
176
177 #
178 # Not used at present
179 #
180 def edit_sysex_dialog(track_no, event_no)
181 seq = self
182 tracks = (0...seq.ntracks).map { |i| seq.track(i).name }
183 sysexs = seq.track(track_no).eventset { |pt| pt.kind == :sysex }
184 sysex_names = sysexs.map { |pt|
185 "#{pt.position + 1} - #{seq.tick_to_measure(pt.tick).join(':')}"
186 }
187 sysex_idx = sysexs.find_index { |pt| pt.position == event_no } || -1
188 if (sysex_idx >= 0)
189 data = seq.track(track_no).event(event_no).data
190 sysex_data = ""
191 data.each_with_index { |d, i|
192 next if i == 0 || i == data.length - 1 # Remove f0 and f7
193 sysex_data += sprintf("%02X", d) + (i % 8 == 0 ? "\n" : " ")
194 }
195 sysex_data.strip!
196 sysex_desc = sysex_data.dup
197 end
198 def check_data(data, old_data, pos)
199 data = data.upcase
200 # Find 'bad character'; if present, remove all bad charaters, and
201 # set the selection at the position of the first bad character.
202 idx = (data =~ /[^ \n0-9A-F]/)
203 if idx
204 data.gsub!(/[^ \n0-9A-F]/, "")
205 pos = idx
206 end
207 # Insert blanks after every two characters of alphanumeric
208 i = 0
209 x = 0
210 d = data.dup
211 data.each_byte { |n|
212 if (n >= 48 && n < 58) || (n >= 65 && n < 71)
213 if i == 2
214 d[x, 0] = " "
215 if pos >= x
216 pos += 1
217 end
218 i = 0
219 x += 1
220 end
221 i += 1
222 else
223 i = 0
224 end
225 x += 1
226 }
227 return d, pos
228 end
229 def data_to_desc(data)
230 return data
231 end
232 hash = Dialog.run("Edit Sysex: " + seq.name, "OK", "Cancel", :resizable=>true) {
233 old_data = sysex_data
234 layout(1,
235 layout(2,
236 item(:text, :title=>"Track"),
237 item(:popup, :subitems=>tracks, :value=>track_no),
238 item(:text, :title=>"Sysex"),
239 item(:popup, :subitems=>sysex_names, :value=>sysex_idx),
240 :flex=>[0,0,1,1,0,0]),
241 layout(1,
242 layout(1, item(:text, :title=>"F0 ->")),
243 item(:textview, :value=>sysex_data, :width=>200, :height=>100, :flex=>[0,0,0,0,1,1],
244 :tag=>"sysex_data",
245 :action=>lambda { |it|
246 data = it[:value]
247 sel = it[:selected_range]
248 data2, pos = seq.check_data(data, old_data, sel[0])
249 it[:value] = data2
250 if pos
251 it[:selected_range] = [pos, pos]
252 else
253 it[:selected_range] = sel
254 end
255 old_data = data2
256 desc = seq.data_to_desc(data2)
257 set_value("sysex_desc", desc)
258 }),
259 item(:text, :title=>"-> F7", :align=>:right), :padding=>0),
260 item(:line),
261 item(:textview, :value=>sysex_desc, :width=>200, :height=>80, :flex=>[0,1,0,0,1,0],
262 :tag=>"sysex_desc"),
263 :flex=>[0,0,0,0,1,1])
264 }
265 end
266
267 register_menu("Shift Selected Events...", :shift_selected_events, 1)
268 register_menu("Change Control Number...", :change_control_number, 1)
269
270 end

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26