Serenity Operating System
at hosted 146 lines 5.0 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2019-2020, William McPherson <willmcpherson2@gmail.com> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "MainWidget.h" 29#include "AudioEngine.h" 30#include "KeysWidget.h" 31#include "KnobsWidget.h" 32#include "RollWidget.h" 33#include "SamplerWidget.h" 34#include "WaveWidget.h" 35#include <LibGUI/BoxLayout.h> 36#include <LibGUI/TabWidget.h> 37 38MainWidget::MainWidget(AudioEngine& audio_engine) 39 : m_audio_engine(audio_engine) 40{ 41 set_layout<GUI::VerticalBoxLayout>(); 42 layout()->set_spacing(2); 43 layout()->set_margins({ 2, 2, 2, 2 }); 44 set_fill_with_background_color(true); 45 46 m_wave_widget = add<WaveWidget>(audio_engine); 47 m_wave_widget->set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); 48 m_wave_widget->set_preferred_size(0, 100); 49 50 m_tab_widget = add<GUI::TabWidget>(); 51 m_roll_widget = m_tab_widget->add_tab<RollWidget>("Piano Roll", audio_engine); 52 53 m_roll_widget->set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fill); 54 m_roll_widget->set_preferred_size(0, 300); 55 56 m_tab_widget->add_tab<SamplerWidget>("Sampler", audio_engine); 57 58 m_keys_and_knobs_container = add<GUI::Widget>(); 59 m_keys_and_knobs_container->set_layout<GUI::HorizontalBoxLayout>(); 60 m_keys_and_knobs_container->layout()->set_spacing(2); 61 m_keys_and_knobs_container->set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); 62 m_keys_and_knobs_container->set_preferred_size(0, 100); 63 m_keys_and_knobs_container->set_fill_with_background_color(true); 64 65 m_keys_widget = m_keys_and_knobs_container->add<KeysWidget>(audio_engine); 66 67 m_knobs_widget = m_keys_and_knobs_container->add<KnobsWidget>(audio_engine, *this); 68 m_knobs_widget->set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); 69 m_knobs_widget->set_preferred_size(350, 0); 70} 71 72MainWidget::~MainWidget() 73{ 74} 75 76// FIXME: There are some unnecessary calls to update() throughout this program, 77// which are an easy target for optimization. 78 79void MainWidget::custom_event(Core::CustomEvent&) 80{ 81 m_wave_widget->update(); 82 m_roll_widget->update(); 83} 84 85void MainWidget::keydown_event(GUI::KeyEvent& event) 86{ 87 // This is to stop held-down keys from creating multiple events. 88 if (m_keys_pressed[event.key()]) 89 return; 90 else 91 m_keys_pressed[event.key()] = true; 92 93 note_key_action(event.key(), On); 94 special_key_action(event.key()); 95 m_keys_widget->update(); 96} 97 98void MainWidget::keyup_event(GUI::KeyEvent& event) 99{ 100 m_keys_pressed[event.key()] = false; 101 102 note_key_action(event.key(), Off); 103 m_keys_widget->update(); 104} 105 106void MainWidget::note_key_action(int key_code, Switch switch_note) 107{ 108 int key = m_keys_widget->key_code_to_key(key_code); 109 m_keys_widget->set_key(key, switch_note); 110} 111 112void MainWidget::special_key_action(int key_code) 113{ 114 switch (key_code) { 115 case Key_Z: 116 set_octave_and_ensure_note_change(Down); 117 break; 118 case Key_X: 119 set_octave_and_ensure_note_change(Up); 120 break; 121 case Key_C: 122 m_audio_engine.set_wave(Up); 123 m_knobs_widget->update_knobs(); 124 break; 125 } 126} 127 128void MainWidget::set_octave_and_ensure_note_change(Direction direction) 129{ 130 m_keys_widget->set_key(m_keys_widget->mouse_note(), Off); 131 for (int i = 0; i < key_code_count; ++i) { 132 if (m_keys_pressed[i]) 133 note_key_action(i, Off); 134 } 135 136 m_audio_engine.set_octave(direction); 137 138 m_keys_widget->set_key(m_keys_widget->mouse_note(), On); 139 for (int i = 0; i < key_code_count; ++i) { 140 if (m_keys_pressed[i]) 141 note_key_action(i, On); 142 } 143 144 m_knobs_widget->update_knobs(); 145 m_keys_widget->update(); 146}