Class: GlimmerMetronome::View::AppView

Inherits:
Object
  • Object
show all
Includes:
Glimmer::UI::CustomShell
Defined in:
app/glimmer_metronome/view/app_view.rb

Constant Summary collapse

FILE_SOUND_METRONOME_UP =
File.join(APP_ROOT, 'sounds', 'metronome-up.wav')
FILE_SOUND_METRONOME_DOWN =
File.join(APP_ROOT, 'sounds', 'metronome-down.wav')
COLOR_BEAT_UP =
:yellow
COLOR_BEAT_DOWN =
:white

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#mutedObject Also known as: muted?

Returns the value of attribute muted.



36
37
38
# File 'app/glimmer_metronome/view/app_view.rb', line 36

def muted
  @muted
end

#stoppedObject Also known as: stopped?

Returns the value of attribute stopped.



36
37
38
# File 'app/glimmer_metronome/view/app_view.rb', line 36

def stopped
  @stopped
end

Instance Method Details

#beat(beat_index) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'app/glimmer_metronome/view/app_view.rb', line 167

def beat(beat_index)
  canvas {
    layout_data {
      width_hint 50
      height_hint 50
    }
    
    background :red
    
    rectangle(0, 0, :default, :default, 36, 36) {
      background <= [@rhythm, "beats[#{beat_index}].up", on_read: ->(up) { up ? COLOR_BEAT_UP : COLOR_BEAT_DOWN}]
    }
    polygon(18, 16, 34, 25, 18, 34) {
      background <= [@rhythm, "beats[#{beat_index}].on", on_read: ->(on) { on ? :black : (@rhythm.beats[beat_index].up? ? COLOR_BEAT_UP : COLOR_BEAT_DOWN)}]
      background <= [@rhythm, "beats[#{beat_index}].up", on_read: ->(up) { @rhythm.beats[beat_index].on? ? :black : (up ? COLOR_BEAT_UP : COLOR_BEAT_DOWN)}]
    }
    
    on_mouse_up do
      if @rhythm.beats[beat_index].up?
        @rhythm.beats[beat_index].down!
      else
        @rhythm.beats[beat_index].up!
      end
    end
  }
end

#build_audio_input(sound_file) ⇒ Object



276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'app/glimmer_metronome/view/app_view.rb', line 276

def build_audio_input(sound_file)
  # if running from packaged JAR, we get a uri:classloader sound_file
  if sound_file.start_with?('uri:classloader')
    jar_file_path = sound_file
    file_path = jar_file_path.sub(/^uri\:classloader\:/, '').sub(/^\/+/, '')
    require 'jruby'
    jcl = JRuby.runtime.jruby_class_loader
    resource = jcl.get_resource_as_stream(file_path)
    file_input_stream = resource.to_io.to_input_stream
    java.io.BufferedInputStream.new(file_input_stream)
  else
    java.io.File.new(sound_file)
  end
end

#build_beatsObject



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'app/glimmer_metronome/view/app_view.rb', line 225

def build_beats
  stop_metronome!
  beat_container_layout_change = @rhythm.beat_count != @beats.count && (@rhythm.beat_count < 9 || @beats.count < 9)
  if @rhythm.beat_count > @beats.count
    index_start = @beats.count
    @beat_container.content {
      @beats += (@rhythm.beat_count - @beats.count).times.map do |n|
        beat(index_start + n)
      end
    }
  elsif @rhythm.beat_count < @beats.count
    first_index_to_dispose = -(@beats.count - @rhythm.beat_count)
    @beats[first_index_to_dispose..-1].each(&:dispose)
    @beats = @beats[0...first_index_to_dispose]
  end
  update_beat_container_layout if beat_container_layout_change
  start_metronome!
end

#display_about_dialogObject



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'app/glimmer_metronome/view/app_view.rb', line 291

def display_about_dialog
  dialog(body_root) {
    grid_layout(2, false) {
      margin_width 15
      margin_height 15
    }
    
    background :white
    image ICON
    text 'About'
    
    label {
      layout_data :center, :center, false, false
      background :white
      image ICON, height: 260
    }
    label {
      layout_data :fill, :fill, true, true
      background :white
      text "Glimmer Metronome #{VERSION}\n\n#{LICENSE}\n\nGlimmer Metronome icon made by Freepik from www.flaticon.com"
    }
  }.open
end

#play_sound(sound_file) ⇒ Object

Play sound with the Java Sound library



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'app/glimmer_metronome/view/app_view.rb', line 258

def play_sound(sound_file)
  return if @muted
  begin
    audio_input = build_audio_input(sound_file)
    audio_stream = AudioSystem.get_audio_input_stream(audio_input)
    clip = AudioSystem.clip
    clip.open(audio_stream)
    clip.start
  rescue => e
    puts e.full_message
  ensure
    Thread.new do
      sleep(0.01) while clip.running?
      clip.close
    end
  end
end

#start_metronome!Object



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'app/glimmer_metronome/view/app_view.rb', line 194

def start_metronome!
  self.stopped = false
  @thread ||= Thread.new do
    @rhythm.beat_count.times.cycle { |n|
      begin
        @rhythm.on_beat!(n)
      rescue => e
        puts e.full_message
      end
      sound_file = @rhythm.beats[n].up? ? FILE_SOUND_METRONOME_UP : FILE_SOUND_METRONOME_DOWN
      play_sound(sound_file)
      sleep(60.0/@rhythm.tempo.to_f)
    }
  end
end

#stop_metronome!Object



210
211
212
213
214
215
# File 'app/glimmer_metronome/view/app_view.rb', line 210

def stop_metronome!
  self.stopped = true
  @thread&.kill # not dangerous in this case and is useful to stop sleep
  @thread = nil
  @rhythm.off!
end

#toggle_metronome!Object



217
218
219
220
221
222
223
# File 'app/glimmer_metronome/view/app_view.rb', line 217

def toggle_metronome!
  if stopped?
    start_metronome!
  else
    stop_metronome!
  end
end

#update_beat_container_layoutObject



244
245
246
247
248
249
250
251
252
253
254
255
# File 'app/glimmer_metronome/view/app_view.rb', line 244

def update_beat_container_layout
  @beat_container.content {
    if @rhythm.beat_count < 8
      grid_layout(@rhythm.beat_count, true)
    else
      grid_layout(8, true)
    end
  }
  body_root.layout(true, true)
  body_root.pack(true)
  body_root.center_within_display
end