midinous 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,686 @@
1
+ # Copyright (C) 2019 James "Nornec" Ratliff
2
+ #
3
+ # This file is part of Midinous
4
+ #
5
+ # Midinous is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # Midinous is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with Midinous. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ class GtkRadioButtonEx < Gtk::RadioButton
19
+ type_register
20
+ def initialize
21
+ super()
22
+ end
23
+ define_signal('keybinding-event',nil,nil,nil)
24
+ end
25
+ class GtkButtonEx < Gtk::Button
26
+ type_register
27
+ def initialize
28
+ super()
29
+ end
30
+ define_signal('keybinding-event',nil,nil,nil)
31
+ end
32
+ class GtkCanvas < Gtk::DrawingArea
33
+ type_register
34
+ def initialize
35
+ super()
36
+ end
37
+ define_signal('delete-selected-event',nil,nil,nil)
38
+ define_signal('beat-up',nil,nil,nil)
39
+ define_signal('beat-dn',nil,nil,nil)
40
+ define_signal('beat-note-up',nil,nil,nil)
41
+ define_signal('beat-note-dn',nil,nil,nil)
42
+ define_signal('travel-event',nil,nil,nil)
43
+ define_signal('cycle-play-mode-bck',nil,nil,nil)
44
+ define_signal('cycle-play-mode-fwd',nil,nil,nil)
45
+ define_signal('set-start',nil,nil,nil)
46
+ define_signal('del-path-to',nil,nil,nil)
47
+ define_signal('del-path-from',nil,nil,nil)
48
+ define_signal('set-path-mode-h',nil,nil,nil)
49
+ define_signal('set-path-mode-v',nil,nil,nil)
50
+ define_signal('note-inc-up',nil,nil,nil)
51
+ define_signal('note-inc-dn',nil,nil,nil)
52
+ define_signal('path-rotate-bck',nil,nil,nil)
53
+ define_signal('path-rotate-fwd',nil,nil,nil)
54
+ end
55
+ class GtkPropEntry < Gtk::Entry
56
+ type_register
57
+ def initialize
58
+ super()
59
+ end
60
+ define_signal('keybinding-event',nil,nil,nil)
61
+ end
62
+
63
+ class UI_Elements
64
+ include Logic_Controls
65
+ # Construct a Gtk::Builder instance and load our UI description
66
+ attr_reader :menu_commands,:canvas_commands,:in_device_items,:out_device_items
67
+ def initialize
68
+ @current_file = nil
69
+ @operation_file = nil
70
+ @current_window = nil
71
+ @scale_iters = []
72
+ @in_device_items = []
73
+ @out_device_items = []
74
+ end
75
+ def build_ui
76
+ builder_file = "#{File.dirname(__FILE__)}/midinous.glade"
77
+
78
+ # Connect signal handlers to the constructed widgets
79
+ @builder = Gtk::Builder.new(:file => builder_file)
80
+
81
+ #Windows
82
+ def midinous
83
+ @builder.get_object("midinous")
84
+ end
85
+ def file_chooser
86
+ @builder.get_object("file_chooser")
87
+ end
88
+ def confirmer
89
+ @builder.get_object("confirmer")
90
+ end
91
+
92
+ #Menus
93
+ def input_menu
94
+ @builder.get_object("input_menu")
95
+ end
96
+ def output_menu
97
+ @builder.get_object("output_menu")
98
+ end
99
+
100
+ #Menu Items
101
+ def file_new
102
+ @builder.get_object("file_new")
103
+ end
104
+ def file_open
105
+ @builder.get_object("file_open")
106
+ end
107
+ def file_save
108
+ @builder.get_object("file_save")
109
+ end
110
+ def file_save_as
111
+ @builder.get_object("file_save_as")
112
+ end
113
+ def file_quit
114
+ @builder.get_object("file_quit")
115
+ end
116
+ def help_about
117
+ @builder.get_object("help_about")
118
+ end
119
+
120
+ #Drawing Areas
121
+ def canvas
122
+ @builder.get_object("canvas")
123
+ end
124
+ def canvas_viewport
125
+ @builder.get_object("canvas_viewport")
126
+ end
127
+ def canvas_scroll_window
128
+ @builder.get_object("canvas_scroll_window")
129
+ end
130
+
131
+ #Adjustments
132
+ def canvas_h_adj
133
+ @builder.get_object("canvas_scroll_h")
134
+ end
135
+ def canvas_v_adj
136
+ @builder.get_object("canvas_scroll_v")
137
+ end
138
+ def tempo_adj
139
+ @builder.get_object("tempo_adj")
140
+ end
141
+ def root_adj
142
+ @builder.get_object("root_adj")
143
+ end
144
+
145
+ #Buttons
146
+ def main_tool_1
147
+ @builder.get_object("main_tool_1")
148
+ end
149
+ def main_tool_2
150
+ @builder.get_object("main_tool_2")
151
+ end
152
+ def main_tool_3
153
+ @builder.get_object("main_tool_3")
154
+ end
155
+ def main_tool_4
156
+ @builder.get_object("main_tool_4")
157
+ end
158
+ def path_builder
159
+ @builder.get_object("path_builder")
160
+ end
161
+ def prop_mod_button
162
+ @builder.get_object("prop_mod_button")
163
+ end
164
+ def play
165
+ @builder.get_object("play")
166
+ end
167
+ def stop
168
+ @builder.get_object("stop")
169
+ end
170
+ def tempo
171
+ @builder.get_object("tempo")
172
+ end
173
+ def root_select
174
+ @builder.get_object("root_select")
175
+ end
176
+ def file_operation
177
+ @builder.get_object("file_operation")
178
+ end
179
+ def file_cancel
180
+ @builder.get_object("file_cancel")
181
+ end
182
+ def confirmer_confirm
183
+ @builder.get_object("confirmer_confirm")
184
+ end
185
+ def confirmer_cancel
186
+ @builder.get_object("confirmer_cancel")
187
+ end
188
+
189
+ #Button Areas
190
+ def logic_controls
191
+ @builder.get_object("logic_controls")
192
+ end
193
+
194
+ #Text Areas
195
+ def tool_descrip
196
+ @builder.get_object("tool_descrip")
197
+ end
198
+ def status_area
199
+ @builder.get_object("status_area")
200
+ end
201
+ def prop_mod
202
+ @builder.get_object("prop_mod")
203
+ end
204
+ def t_sig
205
+ @builder.get_object("t_sig")
206
+ end
207
+ def file_name
208
+ @builder.get_object("file_name")
209
+ end
210
+
211
+ #Labels
212
+ def perf_label
213
+ @builder.get_object("perf_label")
214
+ end
215
+ def tool_label
216
+ @builder.get_object("tool_label")
217
+ end
218
+ def tempo_label
219
+ @builder.get_object("tempo_label")
220
+ end
221
+ def property_label
222
+ @builder.get_object("property_label")
223
+ end
224
+ def modify_label
225
+ @builder.get_object("modify_label")
226
+ end
227
+ def t_sig_label
228
+ @builder.get_object("t_sig_label")
229
+ end
230
+ def confirmer_label
231
+ @builder.get_object("confirmer_label")
232
+ end
233
+ def scale_label
234
+ @builder.get_object("scale_label")
235
+ end
236
+
237
+ #Point Property Tree
238
+ def prop_list_model
239
+ @builder.get_object("prop_list_model")
240
+ end
241
+ def prop_list_view
242
+ @builder.get_object("prop_list_view")
243
+ end
244
+ def prop_list
245
+ @builder.get_object("prop_list")
246
+ end
247
+ def prop_list_col1_h
248
+ @builder.get_object("prop_list_col1_h")
249
+ end
250
+ def prop_list_col2_h
251
+ @builder.get_object("prop_list_col2_h")
252
+ end
253
+ def prop_list_col1
254
+ @builder.get_object("prop_list_col1")
255
+ end
256
+ def prop_list_col2
257
+ @builder.get_object("prop_list_col2")
258
+ end
259
+ def prop_list_selection
260
+ @builder.get_object("prop_list_selection")
261
+ end
262
+
263
+ #Scale Selection Combo Box
264
+ def scale_combo
265
+ @builder.get_object("scale_combo")
266
+ end
267
+ def scale_tree_model
268
+ @builder.get_object("scale_tree_model")
269
+ end
270
+ def scale_display
271
+ @builder.get_object("scale_display")
272
+ end
273
+
274
+ Pm.in_list.each {|i| @in_device_items << Gtk::ImageMenuItem.new(label: i.name)}
275
+ @in_device_items.each {|i| input_menu.append(i)}
276
+ input_menu.show_all
277
+
278
+ Pm.out_list.each {|o| @out_device_items << Gtk::ImageMenuItem.new(label: o.name)}
279
+ @out_device_items.each {|o| output_menu.append(o)}
280
+ output_menu.show_all
281
+
282
+ def set_device(id,type)
283
+ case type
284
+ when 'i'
285
+ Pm.sel_in(id)
286
+ when 'o'
287
+ Pm.sel_out(id)
288
+ end
289
+ regen_status
290
+ end
291
+
292
+ def regen_status
293
+ status_area.text = "Using: Output[#{Pm.out_list[Pm.out_id].name}] Input[#{Pm.in_list[Pm.in_id].name}]"
294
+ end
295
+
296
+ #Set up accelerators (keyboard shortcuts)
297
+ @menu_commands = Gtk::AccelGroup.new
298
+ @canvas_commands = Gtk::AccelGroup.new
299
+ midinous.add_accel_group(@menu_commands)
300
+ midinous.add_accel_group(@canvas_commands)
301
+
302
+ scale_cat_1 = scale_tree_model.append(nil)
303
+ scale_cat_1_sub_01 = scale_tree_model.append(scale_cat_1)
304
+ scale_cat_1_sub_02 = scale_tree_model.append(scale_cat_1)
305
+ scale_cat_1_sub_03 = scale_tree_model.append(scale_cat_1)
306
+ scale_cat_1_sub_04 = scale_tree_model.append(scale_cat_1)
307
+ scale_cat_1_sub_05 = scale_tree_model.append(scale_cat_1)
308
+ scale_cat_1_sub_06 = scale_tree_model.append(scale_cat_1)
309
+ scale_cat_2 = scale_tree_model.append(nil)
310
+ scale_cat_2_sub_01 = scale_tree_model.append(scale_cat_2)
311
+ scale_cat_2_sub_02 = scale_tree_model.append(scale_cat_2)
312
+ scale_cat_2_sub_03 = scale_tree_model.append(scale_cat_2)
313
+ scale_cat_2_sub_04 = scale_tree_model.append(scale_cat_2)
314
+ scale_cat_2_sub_05 = scale_tree_model.append(scale_cat_2)
315
+ scale_cat_2_sub_06 = scale_tree_model.append(scale_cat_2)
316
+ scale_cat_2_sub_07 = scale_tree_model.append(scale_cat_2)
317
+ scale_cat_2_sub_08 = scale_tree_model.append(scale_cat_2)
318
+ scale_cat_2_sub_09 = scale_tree_model.append(scale_cat_2)
319
+ scale_cat_3 = scale_tree_model.append(nil)
320
+ scale_cat_3_sub_01 = scale_tree_model.append(scale_cat_3)
321
+ scale_cat_3_sub_02 = scale_tree_model.append(scale_cat_3)
322
+ scale_cat_3_sub_03 = scale_tree_model.append(scale_cat_3)
323
+ scale_cat_3_sub_04 = scale_tree_model.append(scale_cat_3)
324
+ scale_cat_3_sub_05 = scale_tree_model.append(scale_cat_3)
325
+ scale_cat_3_sub_06 = scale_tree_model.append(scale_cat_3)
326
+ scale_cat_4 = scale_tree_model.append(nil)
327
+ scale_cat_4_sub_01 = scale_tree_model.append(scale_cat_4)
328
+ scale_cat_4_sub_02 = scale_tree_model.append(scale_cat_4)
329
+ scale_cat_4_sub_03 = scale_tree_model.append(scale_cat_4)
330
+ scale_cat_4_sub_04 = scale_tree_model.append(scale_cat_4)
331
+ scale_cat_4_sub_05 = scale_tree_model.append(scale_cat_4)
332
+ scale_cat_4_sub_06 = scale_tree_model.append(scale_cat_4)
333
+ scale_cat_5 = scale_tree_model.append(nil)
334
+ scale_cat_5_sub_01 = scale_tree_model.append(scale_cat_5)
335
+ scale_cat_5_sub_02 = scale_tree_model.append(scale_cat_5)
336
+ scale_cat_5_sub_03 = scale_tree_model.append(scale_cat_5)
337
+ scale_cat_5_sub_04 = scale_tree_model.append(scale_cat_5)
338
+ scale_cat_5_sub_05 = scale_tree_model.append(scale_cat_5)
339
+
340
+ scale_cat_1 [0] = "Pentatonic"
341
+ scale_cat_1_sub_01[0] = "Hirajoshi"
342
+ scale_cat_1_sub_02[0] = "Insen"
343
+ scale_cat_1_sub_03[0] = "Iwato"
344
+ scale_cat_1_sub_04[0] = "Pentatonic Major"
345
+ scale_cat_1_sub_05[0] = "Pentatonic Minor"
346
+ scale_cat_1_sub_06[0] = "Two Semitone Tritone"
347
+ scale_cat_2 [0] = "Traditional"
348
+ scale_cat_2_sub_01[0] = "Aeolian"
349
+ scale_cat_2_sub_02[0] = "Dorian"
350
+ scale_cat_2_sub_03[0] = "Harmonic Major"
351
+ scale_cat_2_sub_04[0] = "Harmonic Minor"
352
+ scale_cat_2_sub_05[0] = "Ionian"
353
+ scale_cat_2_sub_06[0] = "Locrian"
354
+ scale_cat_2_sub_07[0] = "Lydian"
355
+ scale_cat_2_sub_08[0] = "Mixolydian"
356
+ scale_cat_2_sub_09[0] = "Phrygian"
357
+ scale_cat_3 [0] = "Modified Traditional"
358
+ scale_cat_3_sub_01[0] = "Altered"
359
+ scale_cat_3_sub_02[0] = "Half Diminished"
360
+ scale_cat_3_sub_03[0] = "Locrian Major"
361
+ scale_cat_3_sub_04[0] = "Lydian Augmented"
362
+ scale_cat_3_sub_05[0] = "Melodic Minor"
363
+ scale_cat_3_sub_06[0] = "Ukrainian Dorian"
364
+ scale_cat_4 [0] = "Exotic"
365
+ scale_cat_4_sub_01[0] = "Augmented"
366
+ scale_cat_4_sub_02[0] = "Blues"
367
+ scale_cat_4_sub_03[0] = "Flamenco"
368
+ scale_cat_4_sub_04[0] = "Hungarian"
369
+ scale_cat_4_sub_05[0] = "Persian"
370
+ scale_cat_4_sub_06[0] = "Prometheus"
371
+ scale_cat_5 [0] = "Mathematical"
372
+ scale_cat_5_sub_01[0] = "Chromatic"
373
+ scale_cat_5_sub_02[0] = "Octatonic Whole"
374
+ scale_cat_5_sub_03[0] = "Octatonic Half"
375
+ scale_cat_5_sub_04[0] = "Tritone"
376
+ scale_cat_5_sub_05[0] = "Whole Tone"
377
+
378
+ @scale_iters << scale_cat_1_sub_01
379
+ @scale_iters << scale_cat_1_sub_02
380
+ @scale_iters << scale_cat_1_sub_03
381
+ @scale_iters << scale_cat_1_sub_04
382
+ @scale_iters << scale_cat_1_sub_05
383
+ @scale_iters << scale_cat_1_sub_06
384
+ @scale_iters << scale_cat_2_sub_01
385
+ @scale_iters << scale_cat_2_sub_02
386
+ @scale_iters << scale_cat_2_sub_03
387
+ @scale_iters << scale_cat_2_sub_04
388
+ @scale_iters << scale_cat_2_sub_05
389
+ @scale_iters << scale_cat_2_sub_06
390
+ @scale_iters << scale_cat_2_sub_07
391
+ @scale_iters << scale_cat_2_sub_08
392
+ @scale_iters << scale_cat_2_sub_09
393
+ @scale_iters << scale_cat_3_sub_01
394
+ @scale_iters << scale_cat_3_sub_02
395
+ @scale_iters << scale_cat_3_sub_03
396
+ @scale_iters << scale_cat_3_sub_04
397
+ @scale_iters << scale_cat_3_sub_05
398
+ @scale_iters << scale_cat_3_sub_06
399
+ @scale_iters << scale_cat_4_sub_01
400
+ @scale_iters << scale_cat_4_sub_02
401
+ @scale_iters << scale_cat_4_sub_03
402
+ @scale_iters << scale_cat_4_sub_04
403
+ @scale_iters << scale_cat_4_sub_05
404
+ @scale_iters << scale_cat_4_sub_06
405
+ @scale_iters << scale_cat_5_sub_01
406
+ @scale_iters << scale_cat_5_sub_02
407
+ @scale_iters << scale_cat_5_sub_03
408
+ @scale_iters << scale_cat_5_sub_04
409
+ @scale_iters << scale_cat_5_sub_05
410
+
411
+ scale_combo.active = 4
412
+ scale_combo.active_iter = scale_cat_5_sub_01
413
+
414
+ #Initialize the elements of the screen
415
+ midinous.add_events("key-press-mask")
416
+ canvas.add_events("button-press-mask")
417
+ canvas.add_events("button-release-mask")
418
+ canvas.add_events("pointer-motion-mask")
419
+ prop_mod.add_events("key-press-mask")
420
+
421
+ path_builder.sensitive = false
422
+ prop_mod_button.sensitive = false
423
+ stop.sensitive = false
424
+
425
+ tool_descrip.text = "Select"
426
+ t_sig.text = "4/4"
427
+
428
+ perf_label.markup = "<b>#{perf_label.text}</b>"
429
+ tempo_label.markup = "<b>#{tempo_label.text}</b>"
430
+ tool_label.markup = "<b>#{tool_label.text}</b>"
431
+ property_label.markup = "<b>#{property_label.text}</b>"
432
+ modify_label.markup = "<b>#{modify_label.text}</b>"
433
+ t_sig_label.markup = "<b>#{t_sig_label.text}</b>"
434
+ scale_label.markup = "<b>#{scale_label.text}</b>"
435
+
436
+ regen_status
437
+
438
+ #canvas.add_events(Gdk::EventMask::BUTTON_PRESS_MASK.nick) #This points to a nickname, basically a string like "button-press-mask" in this case
439
+
440
+ #Accel groups, parameter 2 is the modifier
441
+ # 0 - no modifier
442
+ # 1 - shift
443
+ # 2 - no modifier?
444
+ # 3 - shift again?
445
+ # 4 - Cntl
446
+ # 5 - Cntl+Shift
447
+
448
+ file_chooser.filter = Gtk::FileFilter.new
449
+ file_chooser.filter.add_pattern("*.nous")
450
+ file_chooser.filter.name = "nous file filter"
451
+ end
452
+ def confirm(type)
453
+ case type
454
+ when "new"
455
+ @current_window = "new_confirm"
456
+ confirmer_confirm.label = "Create New"
457
+ confirmer_label.markup = "<b> There are unsaved changes.</b> \n Do you wish to proceed? "
458
+ confirmer_cancel.visible = true
459
+ when "quit"
460
+ @current_window = "quit_confirm"
461
+ confirmer_confirm.label = "Quit"
462
+ confirmer_cancel.visible = true
463
+ confirmer_label.markup = "<b> There are unsaved changes.</b> \n Do you wish to proceed? "
464
+ when "path_warning"
465
+ @current_window = "path_warning"
466
+ confirmer_confirm.label = "OK"
467
+ confirmer_cancel.visible = false
468
+ confirmer_label.markup = "<b> WARNING:</b> Live composition detected. \n This may have affected round-robin point starting paths. "
469
+ end
470
+ confirmer.visible = true
471
+ end
472
+ def file_input_check(type)
473
+ case type
474
+ when "chooser"
475
+ unless UI::file_chooser.uri == nil
476
+ UI::file_name.text = UI::file_chooser.uri.split("/").last
477
+ else
478
+ UI::file_name.text = ""
479
+ end
480
+ when "name"
481
+ unless UI::file_name.text != "" ||
482
+ UI::file_chooser.uri != nil ||
483
+ UI::file_name.text.count(".") > 1
484
+ then
485
+ UI::file_operation.sensitive = false
486
+ else UI::file_operation.sensitive = true
487
+ end
488
+ end
489
+ end
490
+ def file_oper(type)
491
+ case type
492
+ when "open"
493
+ @current_window = "file_open"
494
+ file_chooser.title = "Open"
495
+ file_operation.label = "Open"
496
+ file_chooser.visible = true
497
+ file_name.editable = false
498
+ when "save"
499
+ @current_window = "file_save"
500
+ if @current_file == nil #If the working file does not exist yet
501
+ file_chooser.title = "Save As"
502
+ file_operation.label = "Save As"
503
+ file_name.editable = true
504
+ file_chooser.visible = true
505
+ else
506
+ save_operation #Resave the file if @current_file already exists
507
+ end
508
+ when "saveas"
509
+ @current_window = "file_save"
510
+ #If the working file does not exist yet, suggest a name
511
+ file_name.text = @current_file.split("\\").last unless @current_file == nil
512
+ file_chooser.title = "Save As"
513
+ file_operation.label = "Save As"
514
+ file_name.editable = true
515
+ file_chooser.visible = true
516
+ end
517
+ end
518
+ def confirm_act(choice)
519
+ if choice == "yes"
520
+ case @current_window
521
+ when "new_confirm"
522
+ CC.nouspoints = []
523
+ file_name.text = ""
524
+ CC.tempo = 120
525
+ CC.scale = "Chromatic"
526
+ CC.root_note = 60
527
+ CC.beats = 4
528
+ CC.beat_note = 4
529
+
530
+ CC.set_tempo(CC.tempo)
531
+ CC.set_scale(CC.scale,CC.root_note)
532
+ CC.canvas_grid_change(nil)
533
+ tempo_adj.value = CC.tempo
534
+ @scale_iters.each {|s| scale_combo.active_iter = s if s[0] == CC.scale}
535
+ root_adj.value = CC.root_note
536
+ @current_file = nil
537
+ midinous.title = "Midinous"
538
+ when "quit_confirm"
539
+ Gtk.main_quit
540
+ end
541
+ end
542
+ confirmer.visible = false
543
+ canvas.queue_draw
544
+ end
545
+ def file_oper_act(choice)
546
+ if choice == "yes"
547
+ case @current_window
548
+ when "file_open"
549
+ #Remove current points and load points from file
550
+ load_operation
551
+ when "file_save"
552
+ #Save nouspoints to a new, or existing file, window only if new
553
+ save_operation
554
+ end
555
+ end
556
+ file_chooser.visible = false
557
+ canvas.queue_draw
558
+ end
559
+
560
+ def save_operation
561
+
562
+ unless file_name.text[-5..-1] == ".nous"
563
+ @current_file = "#{file_chooser.current_folder_uri}/#{file_name.text}.nous"
564
+
565
+ else @current_file = "#{file_chooser.current_folder_uri}/#{file_name.text}"
566
+ end
567
+
568
+ operator = @current_file.sub("file:///","")
569
+ operator = operator.gsub("/","\\")
570
+
571
+ IO.binwrite(operator, "")
572
+ save = File.open(operator, "a")
573
+ issued_id = 0
574
+ CC.nouspoints.each do |n|
575
+ n.save_id = issued_id
576
+ issued_id += 1
577
+ end
578
+ CC.nouspoints.each do |n|
579
+ n.write_props(save)
580
+ save.write("\n")
581
+ end
582
+ save.write("#{CC.tempo}<~>")
583
+ save.write("#{CC.scale}<~>")
584
+ save.write("#{CC.root_note}<~>")
585
+ save.write("#{CC.beats}<~>")
586
+ save.write("#{CC.beat_note}")
587
+ midinous.title = "Midinous - #{operator}"
588
+ save.close
589
+ end
590
+ def load_operation
591
+ CC.canvas_stop
592
+ CC.nouspoints = []
593
+ @current_file = file_chooser.uri
594
+ operator = @current_file.sub("file:///","")
595
+ operator = operator.gsub("/","\\")
596
+
597
+ load = IO.binread(operator)
598
+ load = load.gsub("\r","")
599
+ load = load.split("\n")
600
+ load[0..-2].each do |point_line|
601
+ point_line = point_line.split("<~>")
602
+ CC.nouspoints << NousPoint.new(eval(point_line[1]),point_line[0].to_i)
603
+ end
604
+ CC.nouspoints.each do |n|
605
+ load.each do |point_line|
606
+ point_line = point_line.split("<~>")
607
+ if point_line[0].to_i == n.save_id
608
+ if point_line[2].match(/^([+]|-)[0-9]{1,2}$/)
609
+ n.note = point_line[2]
610
+ n.use_rel = true
611
+ elsif (point_line[2].to_i >= 0 &&
612
+ point_line[2].to_i <= 127 &&
613
+ !(point_line[2].include?("+") || point_line[2].include?("-")))
614
+ then
615
+ n.note = point_line[2].to_i
616
+ end
617
+ n.velocity = point_line[3].to_i
618
+ n.channel = point_line[4].to_i
619
+ n.duration = point_line[5].to_i
620
+ n.set_default_color(hex_to_color(point_line[6]))
621
+ n.repeat = point_line[7].to_i
622
+ n.play_modes = eval(point_line[8])
623
+ n.traveler_start = eval(point_line[9])
624
+ n.use_rel = eval(point_line[10])
625
+ n.path_mode = point_line[11]
626
+ n.path_to_rels = eval(point_line[12])
627
+ n.path_from_rels = eval(point_line[13])
628
+ n.path_to_rels.each {|ptr| n.path_to << CC.nouspoints.find {|f| ptr == f.save_id}}
629
+ n.path_from_rels.each {|pfr| n.path_from << CC.nouspoints.find {|f| pfr == f.save_id}}
630
+ end
631
+ end
632
+ end
633
+ load_last = load.last.split("<~>")
634
+ CC.tempo = load_last[0].to_f
635
+ CC.scale = load_last[1]
636
+ CC.root_note = load_last[2].to_i
637
+ CC.beats = load_last[3].to_i
638
+ CC.beat_note = load_last[4].to_i
639
+
640
+ CC.set_tempo(CC.tempo)
641
+ CC.set_scale(CC.scale,CC.root_note)
642
+ CC.canvas_grid_change(nil)
643
+ tempo_adj.value = CC.tempo
644
+ @scale_iters.each {|s| scale_combo.active_iter = s if s[0] == CC.scale}
645
+ root_adj.value = CC.root_note
646
+
647
+ midinous.title = "Midinous - #{operator}"
648
+ end
649
+ end
650
+
651
+ class Tool
652
+ attr_reader :tool_id
653
+ def initialize
654
+ @tool_id = 1
655
+ end
656
+ def set_tool(id)
657
+ @tool_id = id
658
+ unless @tool_id == 4
659
+ UI::path_builder.sensitive = false
660
+ end
661
+ case
662
+ when @tool_id == 1
663
+ UI::main_tool_1.active = true
664
+ UI::tool_descrip.text = "Select"
665
+ UI::canvas.queue_draw
666
+ when @tool_id == 2
667
+ UI::main_tool_2.active = true
668
+ UI::tool_descrip.text = "Place"
669
+ UI::canvas.queue_draw
670
+ when @tool_id == 3
671
+ UI::main_tool_3.active = true
672
+ UI::tool_descrip.text = "Move"
673
+ UI::canvas.queue_draw
674
+ when @tool_id == 4
675
+ UI::main_tool_4.active = true
676
+ UI::path_builder.sensitive = true
677
+ UI::tool_descrip.text = "Path"
678
+ UI::canvas.queue_draw
679
+ end
680
+ end
681
+
682
+ end
683
+
684
+ UI = UI_Elements.new() #Create a new UI_Elements object
685
+ UI::build_ui
686
+ Active_Tool = Tool.new
data/lib/midinous.rb ADDED
@@ -0,0 +1,21 @@
1
+ # Copyright (C) 2019 James "Nornec" Ratliff
2
+ #
3
+ # Midinous 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, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # Midinous is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with Midinous. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ require "unimidi"
17
+ require "midi-eye"
18
+ require "gtk3"
19
+ require "midinous/init"
20
+
21
+ Gtk.main