midinous 1.0.0.beta
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.
- checksums.yaml +7 -0
- data/COPYING.L +674 -0
- data/README.md +31 -0
- data/lib/doc/Hotkeys.txt +30 -0
- data/lib/doc/Notes and Scales.txt +64 -0
- data/lib/midinous/canvas.rb +388 -0
- data/lib/midinous/constants.rb +108 -0
- data/lib/midinous/init.rb +166 -0
- data/lib/midinous/key_bindings.rb +81 -0
- data/lib/midinous/logic.rb +165 -0
- data/lib/midinous/points.rb +1060 -0
- data/lib/midinous/proc_midi.rb +100 -0
- data/lib/midinous/style/midinous.glade +928 -0
- data/lib/midinous/style/midinous_themes.style +4022 -0
- data/lib/midinous/style/ui.rb +686 -0
- data/lib/midinous.rb +21 -0
- data/lib/saves/sample.nous +9 -0
- metadata +102 -0
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Midinous: Grid-based Generative Music Software
|
2
|
+
|
3
|
+
Midinous combines generative features with a grid-based GUI to offer a supplemental unique compositional experience
|
4
|
+
|
5
|
+
## Requirements
|
6
|
+
|
7
|
+
* [GTK3](http://www.gtk.org/) 3.3.6 or later
|
8
|
+
* Midinous is designed to run on 64-bit architectures
|
9
|
+
* You must have 64-bit Ruby version 2.5.5 installed with the devkit and MSYS2
|
10
|
+
|
11
|
+
## Install
|
12
|
+
|
13
|
+
gem install midinous
|
14
|
+
|
15
|
+
## Tutorials, examples:
|
16
|
+
|
17
|
+
* doc/Hotkeys.txt: Useful hotkeys used within the program
|
18
|
+
* saves/sample.nous: Example Midinous project having every basic feature. Experiment from this starting point!
|
19
|
+
|
20
|
+
## License
|
21
|
+
|
22
|
+
Copyright (C) 2019 James "Nornec" Ratliff
|
23
|
+
|
24
|
+
Midinous is free software: you can redistribute it and/or modify
|
25
|
+
it under the terms of the GNU General Public License as published by
|
26
|
+
the Free Software Foundation, either version 3 of the License, or
|
27
|
+
(at your option) any later version.
|
28
|
+
|
29
|
+
## Project Websites
|
30
|
+
|
31
|
+
* https://github.com/Nornec/Midinous
|
data/lib/doc/Hotkeys.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
[ -- decrement grid size/change time signature divisor -1
|
2
|
+
] -- increment grid size/ change time signature divisor +1
|
3
|
+
{ -- decrement time signature denominator (slows down play) - min 2
|
4
|
+
} -- increment time signature denominator (speeds up play) - max 16
|
5
|
+
delete -- deletes selected point(s)
|
6
|
+
home -- deletes paths entering selected point(s)
|
7
|
+
end -- deletes paths leaving selected point(s)
|
8
|
+
Page Up -- change path direction
|
9
|
+
Page Down -- change path direction
|
10
|
+
A -- Make starting point (need at least 1 to begin play)
|
11
|
+
T -- Built path - build a path between one or more points
|
12
|
+
Q -- Select Tool - Box select or single select points
|
13
|
+
W -- Point Place Tool - Places a point
|
14
|
+
E -- Move Tool - moves selected points based on a stencil
|
15
|
+
R -- Path Tool - Select source point, select target points, push build path or hit 'T'
|
16
|
+
< and > -- Cycle Play Mode - between robin, portal (random, split, if more than one path is leaving a point)
|
17
|
+
, and . -- Cycle starting path if more than one path is leaving a point
|
18
|
+
+ and - -- add or subtract 1 from the currently selected points' note
|
19
|
+
Num 6 -- play
|
20
|
+
Num 5 -- stop
|
21
|
+
space -- toggle play/stop
|
22
|
+
Ctrl+A -- select all
|
23
|
+
Ctrl+C -- copy selected points
|
24
|
+
Ctrl+X -- cut selected points
|
25
|
+
Ctrl+V -- paste copied/cut points
|
26
|
+
Ctrl+O -- Open
|
27
|
+
Ctrl+S -- Save
|
28
|
+
Shift+Ctrl+S -- Save As
|
29
|
+
Ctrl+N -- New
|
30
|
+
Ctrl+Q -- Quit
|
@@ -0,0 +1,64 @@
|
|
1
|
+
Note Octave
|
2
|
+
-2 -1 0 1 2 3 4 5 6 7 8
|
3
|
+
C 0 12 24 36 48 60 72 84 96 108 120
|
4
|
+
C# 1 13 25 37 49 61 73 85 97 109 121
|
5
|
+
D 2 14 26 38 50 62 74 86 98 110 122
|
6
|
+
D# 3 15 27 39 51 63 75 87 99 111 123
|
7
|
+
E 4 16 28 40 52 64 76 88 100 112 124
|
8
|
+
F 5 17 29 41 53 65 77 89 101 113 125
|
9
|
+
F# 6 18 30 42 54 66 78 90 102 114 126
|
10
|
+
G 7 19 31 43 55 67 79 91 103 115 127
|
11
|
+
G# 8 20 32 44 56 68 80 92 104 116 -
|
12
|
+
A 9 21 33 45 57 69 81 93 105 117 -
|
13
|
+
A# 10 22 34 46 58 70 82 94 106 118 -
|
14
|
+
B 11 23 35 47 59 71 83 95 107 119 -
|
15
|
+
|
16
|
+
Note Octave
|
17
|
+
-2 -1 0 1 2 3 4 5 6 7 8
|
18
|
+
C 00 0C 18 24 30 3C 48 54 60 6C 78
|
19
|
+
C# 01 0D 19 25 31 3D 49 55 61 6D 79
|
20
|
+
D 02 0E 1A 26 32 3E 4A 56 62 6E 7A
|
21
|
+
D# 03 0F 1B 27 33 3F 4B 57 63 6F 7B
|
22
|
+
E 04 10 1C 28 34 40 4C 58 64 70 7C
|
23
|
+
F 05 11 1D 29 35 41 4D 59 65 71 7D
|
24
|
+
F# 06 12 1E 2A 36 42 4E 5A 66 72 7E
|
25
|
+
G 07 13 1F 2B 37 43 4F 5B 67 73 7F
|
26
|
+
G# 08 14 20 2C 38 44 50 5C 68 74 -
|
27
|
+
A 09 15 21 2D 39 45 51 5D 69 75 -
|
28
|
+
A# 0A 16 22 2E 3A 46 52 5E 6A 76 -
|
29
|
+
B 0B 17 23 2F 3B 47 53 5F 6B 77 -
|
30
|
+
|
31
|
+
W = whole tone, H = Half tone
|
32
|
+
Scales and their relative intervals
|
33
|
+
Aeolian R-W-H-W-W-H-W-W
|
34
|
+
Altered R-H-W-H-W-W-W-W
|
35
|
+
Augmented R-3H-H-3H-H-3H-H
|
36
|
+
Blues R-3H-W-H-H-3H-W
|
37
|
+
Chromatic R-H-H-H-H-H-H-H-H-H-H-H-H
|
38
|
+
Dorian R-W-H-W-W-W-H-W
|
39
|
+
Flamenco R-H-3H-H-W-H-3H-H
|
40
|
+
Half Diminished R-W-H-W-H-W-W-W
|
41
|
+
Harmonic major R-W-W-H-W-H-3H-H
|
42
|
+
Harmonic minor R-W-H-W-W-H-3H-H
|
43
|
+
Hirajoshi R-2W-W-H-2W-H
|
44
|
+
Hungarian R-W-H-3H-H-H-3H-H
|
45
|
+
Insen R-H-2W-W-2W-W
|
46
|
+
Ionian R-W-W-H-W-W-W-H
|
47
|
+
Iwato R-H-2W-H-2W-W
|
48
|
+
Locrian R-H-W-W-H-W-W-W
|
49
|
+
Locrian Major R-W-W-H-H-W-W-W
|
50
|
+
Lydian R-W-W-W-H-W-W-H
|
51
|
+
Lydian Augmented R-W-W-W-W-H-W-H
|
52
|
+
Pentatonic Major R-W-W-3H-W-3H
|
53
|
+
Pentatonic Minor R-3H-W-W-3H-W
|
54
|
+
Melodic minor R-W-H-W-W-W-W-H
|
55
|
+
Mixolydian R-W-W-H-W-W-H-W
|
56
|
+
Octatonic Whole R-W-H-W-H-W-H-W-H
|
57
|
+
Octatonic Half R-H-W-H-W-H-W-H-W
|
58
|
+
Persian R-H-3H-H-H-W-3H-H
|
59
|
+
Phrygian R-H-W-W-W-H-W-W
|
60
|
+
Prometheus R-W-W-W-3H-H-W
|
61
|
+
Tritone R-H-3H-W-H-3H-W
|
62
|
+
Two-semitone Tritone R-H-H-4H-H-H
|
63
|
+
Ukrainian Dorian R-W-H-3H-H-W-H-W
|
64
|
+
Whole Tone R-W-W-W-W-W-W
|
@@ -0,0 +1,388 @@
|
|
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
|
+
require "midinous/points"
|
19
|
+
|
20
|
+
class Canvas_Control
|
21
|
+
include Logic_Controls
|
22
|
+
attr_accessor :nouspoints, :travelers, :beats, :beat_note, :scale, :root_note,
|
23
|
+
:tempo, :repeaters, :queued_note_plays, :queued_note_stops
|
24
|
+
attr_reader :grid_spacing, :midi_sync, :ms_per_tick, :dragging, :start_time,
|
25
|
+
:mouse_last_pos, :scale_posns
|
26
|
+
def initialize
|
27
|
+
@mouse_last_pos = nil
|
28
|
+
@sel_box = nil
|
29
|
+
@selecting = false
|
30
|
+
@sel_white = [0.8,0.8,0.8,0.1] #selection box colors
|
31
|
+
@sel_blue = [0,0.5,1,0.5] #selection box colors
|
32
|
+
@point_origin = nil
|
33
|
+
@path_origin = nil
|
34
|
+
@point_move = nil
|
35
|
+
@dragging = false
|
36
|
+
@diff = [0,0]
|
37
|
+
@nouspoints = []
|
38
|
+
@travelers = []
|
39
|
+
@starters = []
|
40
|
+
@repeaters = []
|
41
|
+
@scale = "Chromatic"
|
42
|
+
@root_note = 60
|
43
|
+
@scale_notes = []
|
44
|
+
@scale_posns = []
|
45
|
+
set_scale(@scale,@root_note)
|
46
|
+
@tempo = 120.000
|
47
|
+
@midi_sync = 0.000
|
48
|
+
@path_sourced = false
|
49
|
+
@attempt_path = false
|
50
|
+
@ms_per_tick = 125.000 #default tempo of 120bpm
|
51
|
+
@beats = 4 #number of beats in a whole note -- should be reasonably between 1 and 16
|
52
|
+
@beat_note = 4 #as a fraction of a whole note -- should be between 2 and 16 via powers of 2
|
53
|
+
@grid_spacing = 35
|
54
|
+
@queued_note_plays = []
|
55
|
+
@queued_note_stops = []
|
56
|
+
end
|
57
|
+
|
58
|
+
def set_tempo(tempo)
|
59
|
+
@tempo = tempo
|
60
|
+
@ms_per_tick = (1000 * (15 / @tempo)) / (@beat_note / 4)
|
61
|
+
end
|
62
|
+
def set_scale(scale_text,root)
|
63
|
+
@scale = scale_text
|
64
|
+
@root_note = root
|
65
|
+
scale = SCALES[scale_text]
|
66
|
+
slen = scale.length
|
67
|
+
@scale_notes = []
|
68
|
+
@scale_notes << root
|
69
|
+
|
70
|
+
c = 0
|
71
|
+
note = root
|
72
|
+
while note < 127
|
73
|
+
note += scale[c]
|
74
|
+
@scale_notes << note unless note > 127
|
75
|
+
c = (c + 1) % slen
|
76
|
+
end
|
77
|
+
|
78
|
+
c = 0
|
79
|
+
note = root
|
80
|
+
while note > 0
|
81
|
+
note -= scale.reverse[c]
|
82
|
+
@scale_notes << note unless note < 0
|
83
|
+
c = (c + 1) % slen
|
84
|
+
end
|
85
|
+
@scale_notes.sort!
|
86
|
+
|
87
|
+
(0..127).each do |num|
|
88
|
+
@scale_posns[num] = false
|
89
|
+
@scale_posns[num] = true if @scale_notes.find {|f| f == num} != nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def canvas_generic(string) #Used as a pseudo-handler between classes
|
94
|
+
case string
|
95
|
+
when "path"
|
96
|
+
if !@nouspoints.empty? && @nouspoints.find_all(&:pathable).any?
|
97
|
+
@nouspoints = Pl.add_path(@nouspoints)
|
98
|
+
@nouspoints, @path_sourced = Pl.cancel_path(@nouspoints)
|
99
|
+
UI::canvas.queue_draw
|
100
|
+
end
|
101
|
+
when "prop"
|
102
|
+
@nouspoints = Pl.modify_properties(@nouspoints)
|
103
|
+
Pl.populate_prop(@nouspoints)
|
104
|
+
UI::canvas.queue_draw
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def canvas_play
|
109
|
+
|
110
|
+
if @nouspoints.find(&:traveler_start)
|
111
|
+
@playing = true
|
112
|
+
@nouspoints.find_all {|n| n.path_to.length > 1}.each {|p| p.path_to.each {|e| p.path_to_memory << e}}
|
113
|
+
UI::play.sensitive = false
|
114
|
+
UI::stop.sensitive = true
|
115
|
+
end
|
116
|
+
|
117
|
+
@nouspoints.find_all(&:traveler_start).each do |n|
|
118
|
+
@starters << Starter.new(nil,n,nil)
|
119
|
+
UI::canvas.queue_draw
|
120
|
+
@queued_note_plays.each {|o| o.play}
|
121
|
+
signal_chain(n,n.note)
|
122
|
+
end
|
123
|
+
@stored_time = Time.now.to_f*1000
|
124
|
+
canvas_timeout(@ms_per_tick) #Start sequence
|
125
|
+
end
|
126
|
+
|
127
|
+
def canvas_timeout(ms)
|
128
|
+
GLib::Timeout.add(ms) do
|
129
|
+
UI::canvas.signal_emit('travel-event') unless !@playing
|
130
|
+
false
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def canvas_travel
|
135
|
+
@queued_note_plays = []
|
136
|
+
canvas_stop if !@playing ||
|
137
|
+
(@travelers.length == 0 &&
|
138
|
+
@starters.length == 0 &&
|
139
|
+
@repeaters.length == 0)
|
140
|
+
|
141
|
+
@starters.each {|s| s.travel}
|
142
|
+
@travelers.each {|t| t.travel}
|
143
|
+
@travelers.find_all(&:reached).each do |t|
|
144
|
+
signal_chain(t.dest,t.played_note) #Pass the last played note here. Gather the played note from the first traveler creation
|
145
|
+
t.reached = false
|
146
|
+
end
|
147
|
+
@repeaters.each {|r| r.repeat}
|
148
|
+
|
149
|
+
@queued_note_stops.each {|n| n.stop}
|
150
|
+
@queued_note_plays.each {|n| n.play}
|
151
|
+
@starters.reject!(&:remove)
|
152
|
+
@travelers.reject!(&:remove)
|
153
|
+
@repeaters.reject!(&:remove)
|
154
|
+
@queued_note_stops = []
|
155
|
+
|
156
|
+
canvas_timeout(sync_diff(@stored_time))
|
157
|
+
@stored_time += @ms_per_tick
|
158
|
+
UI::canvas.queue_draw
|
159
|
+
end
|
160
|
+
|
161
|
+
def canvas_stop
|
162
|
+
@playing = false
|
163
|
+
@starters = []
|
164
|
+
@repeaters = []
|
165
|
+
@queued_note_plays = []
|
166
|
+
@queued_note_stops = []
|
167
|
+
@nouspoints.find_all {|n| n.path_to.length > 1}.each {|p| p.reset_path_to}
|
168
|
+
UI::canvas.queue_draw
|
169
|
+
@nouspoints.each do |n|
|
170
|
+
n.playing = false
|
171
|
+
n.repeating = false
|
172
|
+
Pm.note_rlse(n.channel,n.note) unless n.note.to_s.include?("+") || n.note.to_s.include?("-")
|
173
|
+
end
|
174
|
+
@travelers.each do |t|
|
175
|
+
Pm.note_rlse(t.dest.channel,t.played_note) unless t.played_note == nil
|
176
|
+
end
|
177
|
+
@travelers = []
|
178
|
+
UI::stop.sensitive = false
|
179
|
+
UI::play.sensitive = true
|
180
|
+
end
|
181
|
+
|
182
|
+
def signal_chain(point,pn) #pn = played note
|
183
|
+
case point.play_modes[0]
|
184
|
+
when "robin"
|
185
|
+
p = point.path_to.first
|
186
|
+
if p
|
187
|
+
@travelers << Traveler.new(point,p,pn)
|
188
|
+
point.path_to.rotate!
|
189
|
+
end
|
190
|
+
when "split"
|
191
|
+
point.path_to.each {|p| @travelers << Traveler.new(point,p,pn)}
|
192
|
+
when "portal"
|
193
|
+
point.path_to.each do |p|
|
194
|
+
@starters << Starter.new(point,p,pn)
|
195
|
+
UI::canvas.queue_draw
|
196
|
+
#@queued_note_plays.each {|o| o.play}
|
197
|
+
signal_chain(p,pn)
|
198
|
+
end
|
199
|
+
when "random"
|
200
|
+
p = point.path_to.sample
|
201
|
+
if p
|
202
|
+
@travelers << Traveler.new(point,p,pn)
|
203
|
+
point.path_to.rotate!(rand(point.path_to.length))
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def canvas_grid_change(dir)
|
209
|
+
prev_beat_note = @beat_note
|
210
|
+
case dir
|
211
|
+
when "+"
|
212
|
+
@beats += 1
|
213
|
+
@beats = 16 if @beats > 16
|
214
|
+
when "-"
|
215
|
+
@beats -= 1
|
216
|
+
@beats = 1 if @beats < 1
|
217
|
+
when "++"
|
218
|
+
@beat_note *= 2
|
219
|
+
@beat_note = 16 if @beat_note > 16
|
220
|
+
when "--"
|
221
|
+
@beat_note /= 2
|
222
|
+
@beat_note = 2 if @beat_note < 2
|
223
|
+
end
|
224
|
+
if @beat_note != prev_beat_note
|
225
|
+
case dir
|
226
|
+
when "++"
|
227
|
+
@ms_per_tick /= 2
|
228
|
+
when "--"
|
229
|
+
@ms_per_tick *= 2
|
230
|
+
end
|
231
|
+
end
|
232
|
+
UI::t_sig.text = "#{@beats}/#{@beat_note}"
|
233
|
+
UI::canvas.queue_draw
|
234
|
+
end
|
235
|
+
|
236
|
+
def canvas_press(event)
|
237
|
+
UI::logic_controls.focus = true
|
238
|
+
case Active_Tool.tool_id
|
239
|
+
when 1
|
240
|
+
@sel_box = [event.x,event.y,event.x,event.y]
|
241
|
+
@selecting = true
|
242
|
+
when 2
|
243
|
+
@point_origin = [event.x,event.y]
|
244
|
+
when 3
|
245
|
+
@point_move = [event.x,event.y,event.x,event.y]
|
246
|
+
when 4
|
247
|
+
@path_origin = [event.x,event.y]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
def canvas_drag(obj,event)
|
251
|
+
@dragging = false
|
252
|
+
@mouse_last_pos = [event.x,event.y]
|
253
|
+
case
|
254
|
+
when (@selecting && @sel_box)
|
255
|
+
@dragging = true
|
256
|
+
@sel_box[2] = event.x
|
257
|
+
@sel_box[3] = event.y
|
258
|
+
obj.queue_draw
|
259
|
+
when (@point_origin)
|
260
|
+
@dragging = true
|
261
|
+
@point_origin[0] = event.x
|
262
|
+
@point_origin[1] = event.y
|
263
|
+
when (@point_move)
|
264
|
+
@dragging = true
|
265
|
+
# difference in movement of the point, cumulative until mouse released
|
266
|
+
@diff = round_to_grid([(event.x - @point_move[0]) , (event.y - @point_move[1])])
|
267
|
+
@point_move[2] = event.x
|
268
|
+
@point_move[3] = event.y
|
269
|
+
obj.queue_draw
|
270
|
+
end
|
271
|
+
end
|
272
|
+
def canvas_release(obj,event)
|
273
|
+
@dragging = false
|
274
|
+
case Active_Tool.tool_id
|
275
|
+
when 1
|
276
|
+
unless !@sel_box
|
277
|
+
@sel_box = pos_box(@sel_box)
|
278
|
+
@nouspoints = Pl.select_points(@sel_box,@nouspoints)
|
279
|
+
@sel_box = nil
|
280
|
+
@selecting = false
|
281
|
+
end
|
282
|
+
when 2 #Add a point where/when the tool is released
|
283
|
+
unless !@point_origin
|
284
|
+
@nouspoints = Pl.add_point(round_to_grid(@point_origin),@nouspoints)
|
285
|
+
@point_origin = nil
|
286
|
+
end
|
287
|
+
when 3 #move point(s) designated by the move stencil
|
288
|
+
@nouspoints = Pl.move_points(@diff,@nouspoints)
|
289
|
+
@point_move = nil
|
290
|
+
@diff = [0,0]
|
291
|
+
when 4 #select singular point
|
292
|
+
@nouspoints, @path_sourced = Pl.select_path_point(@path_origin,@nouspoints,@path_sourced)
|
293
|
+
end
|
294
|
+
obj.queue_draw
|
295
|
+
end
|
296
|
+
|
297
|
+
def canvas_del
|
298
|
+
@nouspoints = Pl.delete_points(@nouspoints)
|
299
|
+
UI::canvas.queue_draw
|
300
|
+
end
|
301
|
+
|
302
|
+
def canvas_bg_draw(cr)
|
303
|
+
# fill background with black
|
304
|
+
cr.set_source_rgb(BLACK)
|
305
|
+
cr.paint
|
306
|
+
cr.set_source_rgb(BLUGR)
|
307
|
+
x = @grid_spacing
|
308
|
+
while x < CANVAS_SIZE
|
309
|
+
y = @grid_spacing
|
310
|
+
while y < CANVAS_SIZE
|
311
|
+
cr.circle(x,y,1)
|
312
|
+
cr.fill
|
313
|
+
y += @grid_spacing
|
314
|
+
end
|
315
|
+
x += @grid_spacing
|
316
|
+
end
|
317
|
+
#Handle measure drawing via notches on paths instead of this, maybe
|
318
|
+
cr.set_source_rgba(DGREY)
|
319
|
+
x = @grid_spacing
|
320
|
+
y = CANVAS_SIZE - @grid_spacing
|
321
|
+
while x < CANVAS_SIZE
|
322
|
+
cr.move_to(x,@grid_spacing)
|
323
|
+
cr.line_to(x,CANVAS_SIZE-@grid_spacing)
|
324
|
+
cr.set_line_width(1)
|
325
|
+
cr.stroke
|
326
|
+
x += @grid_spacing*@beats
|
327
|
+
end
|
328
|
+
y = @grid_spacing
|
329
|
+
x = CANVAS_SIZE - @grid_spacing
|
330
|
+
while y < CANVAS_SIZE
|
331
|
+
cr.move_to(@grid_spacing,y)
|
332
|
+
cr.line_to(CANVAS_SIZE-@grid_spacing,y)
|
333
|
+
cr.set_line_width(1)
|
334
|
+
cr.stroke
|
335
|
+
y += @grid_spacing*@beats
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def canvas_draw(cr)
|
340
|
+
canvas_bg_draw(cr)
|
341
|
+
case #These draw events are for in-progress/temporary activities
|
342
|
+
when(@sel_box)
|
343
|
+
width = @sel_box[2] - @sel_box[0]
|
344
|
+
height = @sel_box[3] - @sel_box[1]
|
345
|
+
|
346
|
+
cr.set_source_rgba(@sel_blue)
|
347
|
+
cr.rectangle(@sel_box[0],@sel_box[1],width,height)
|
348
|
+
cr.set_line_width(2)
|
349
|
+
cr.stroke
|
350
|
+
when(@point_move)
|
351
|
+
start_coord = [@point_move[0],@point_move[1]]
|
352
|
+
end_coord = [@point_move[2],@point_move[3]]
|
353
|
+
start_coord = round_to_grid(start_coord)
|
354
|
+
end_coord = round_to_grid(end_coord)
|
355
|
+
|
356
|
+
cr.move_to(start_coord[0],start_coord[1])
|
357
|
+
cr.set_source_rgba(RED)
|
358
|
+
cr.line_to(end_coord[0],end_coord[1])
|
359
|
+
cr.set_line_width(2)
|
360
|
+
cr.stroke
|
361
|
+
cr.rounded_rectangle(end_coord[0]-10,end_coord[1]-10,20,20,2,2)
|
362
|
+
cr.set_line_width(2)
|
363
|
+
cr.stroke
|
364
|
+
end
|
365
|
+
|
366
|
+
#Set the scene if the current tool does not permit a style
|
367
|
+
case Active_Tool.tool_id
|
368
|
+
when 1
|
369
|
+
@nouspoints, @path_sourced = Pl.cancel_path(@nouspoints)
|
370
|
+
when 2
|
371
|
+
@nouspoints, @path_sourced = Pl.cancel_path(@nouspoints)
|
372
|
+
when 3
|
373
|
+
@nouspoints, @path_sourced = Pl.cancel_path(@nouspoints)
|
374
|
+
when 4
|
375
|
+
@nouspoints = Pl.cancel_selected(@nouspoints)
|
376
|
+
end
|
377
|
+
|
378
|
+
#Draw all the points and paths last
|
379
|
+
#Paths are behind points, so draw them first
|
380
|
+
@nouspoints.each { |n| n.path_draw(cr) }
|
381
|
+
@nouspoints.each { |n| n.caret_draw(cr)}
|
382
|
+
@nouspoints.each { |n| n.draw(cr) }
|
383
|
+
|
384
|
+
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
CC = Canvas_Control.new
|
@@ -0,0 +1,108 @@
|
|
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
|
+
CANVAS_SIZE = 4400
|
19
|
+
PI = 3.14159265358979
|
20
|
+
RED = [0.8,0.0,0.0]
|
21
|
+
GREEN = [0.0,0.6,0.0]
|
22
|
+
LGRN = [0.4,0.6,0.4]
|
23
|
+
BLUE = [0.0,0.0,0.6]
|
24
|
+
GREY = [0.6,0.6,0.6]
|
25
|
+
WHITE = [1.0,1.0,1.0]
|
26
|
+
ORNGE = [1.0,0.5,0.5]
|
27
|
+
CYAN = [0.0,0.5,1.0]
|
28
|
+
VLET = [0.6,0.2,0.8]
|
29
|
+
BLACK = [0.1,0.1,0.1]
|
30
|
+
BLUGR = [0.2,0.4,0.7]
|
31
|
+
DGREY = [0.5,0.5,0.5,0.3]
|
32
|
+
|
33
|
+
SCALES = {
|
34
|
+
"Aeolian" => [2,1,2,2,1,2,2],
|
35
|
+
"Altered" => [1,2,1,2,2,2,2],
|
36
|
+
"Augmented" => [3,1,3,1,3,1],
|
37
|
+
"Blues" => [3,2,1,1,3,2],
|
38
|
+
"Chromatic" => [1,1,1,1,1,1,1,1,1,1,1,1],
|
39
|
+
"Dorian" => [2,1,2,2,2,1,2],
|
40
|
+
"Flamenco" => [1,3,1,2,1,3,1],
|
41
|
+
"Half Diminished" => [2,1,2,1,2,2,2],
|
42
|
+
"Harmonic Major" => [2,2,1,2,1,3,1],
|
43
|
+
"Harmonic Minor" => [2,1,2,2,1,3,1],
|
44
|
+
"Hirajoshi" => [4,2,1,4,1],
|
45
|
+
"Hungarian" => [2,1,3,1,1,3,1],
|
46
|
+
"Insen" => [1,4,2,4,2],
|
47
|
+
"Ionian" => [2,2,1,2,2,2,1],
|
48
|
+
"Iwato" => [1,4,1,4,2],
|
49
|
+
"Locrian" => [1,2,2,1,2,2,2],
|
50
|
+
"Locrian Major" => [2,2,1,1,2,2,2],
|
51
|
+
"Lydian" => [2,2,2,1,2,2,1],
|
52
|
+
"Lydian Augmented" => [2,2,2,2,1,2,1],
|
53
|
+
"Pentatonic Major" => [2,2,3,2,3],
|
54
|
+
"Pentatonic Minor" => [3,2,2,3,2],
|
55
|
+
"Melodic Minor" => [2,1,2,2,2,2,1],
|
56
|
+
"Mixolydian" => [2,2,1,2,2,1,2],
|
57
|
+
"Octatonic Whole" => [2,1,2,1,2,1,2,1],
|
58
|
+
"Octatonic Half" => [1,2,1,2,1,2,1,2],
|
59
|
+
"Persian" => [1,3,1,1,2,3,1],
|
60
|
+
"Phrygian" => [1,2,2,2,1,2,2],
|
61
|
+
"Prometheus" => [2,2,2,3,1,2],
|
62
|
+
"Tritone" => [1,3,2,1,3,2],
|
63
|
+
"Two Semitone Tritone" => [1,1,4,1,1],
|
64
|
+
"Ukrainian Dorian" => [2,1,3,1,2,1,2],
|
65
|
+
"Whole Tone" => [2,2,2,2,2,2]
|
66
|
+
}
|
67
|
+
|
68
|
+
=begin
|
69
|
+
|
70
|
+
Pentatonic
|
71
|
+
"Hirajoshi"
|
72
|
+
"Insen"
|
73
|
+
"Iwato"
|
74
|
+
"Pentatonic Major"
|
75
|
+
"Pentatonic Minor"
|
76
|
+
"Two Semitone Tritone"
|
77
|
+
Traditional
|
78
|
+
"Aeolian"
|
79
|
+
"Dorian"
|
80
|
+
"Harmonic Major"
|
81
|
+
"Harmonic Minor"
|
82
|
+
"Ionian"
|
83
|
+
"Locrian"
|
84
|
+
"Lydian"
|
85
|
+
"Mixolydian"
|
86
|
+
"Phrygian"
|
87
|
+
Modified Traditional
|
88
|
+
"Altered"
|
89
|
+
"Half Diminished"
|
90
|
+
"Locrian Major"
|
91
|
+
"Lydian Augmented"
|
92
|
+
"Melodic Minor"
|
93
|
+
"Ukrainian Dorian"
|
94
|
+
Exotic
|
95
|
+
"Augmented"
|
96
|
+
"Blues"
|
97
|
+
"Flamenco"
|
98
|
+
"Hungarian"
|
99
|
+
"Persian"
|
100
|
+
"Prometheus"
|
101
|
+
Mathematical
|
102
|
+
"Chromatic"
|
103
|
+
"Octatonic Whole"
|
104
|
+
"Octatonic Half"
|
105
|
+
"Tritone"
|
106
|
+
"Whole Tone"
|
107
|
+
|
108
|
+
=end
|