1 /**
2 * File name: SampleBrowser.cpp
3 * Project: Geonkick (A percussion synthesizer)
4 *
5 * Copyright (C) 2020 Iurie Nistor <http://iuriepage.wordpress.com>
6 *
7 * This file is part of Geonkick.
8 *
9 * GeonKick is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include "SampleBrowser.h"
25 #include "file_dialog.h"
26 #include "ViewState.h"
27 #include "BufferView.h"
28 #include "geonkick_button.h"
29 #include "geonkick_slider.h"
30
31 #include "RkContainer.h"
32
33 RK_DECLARE_IMAGE_RC(play_preview_sample);
34 RK_DECLARE_IMAGE_RC(play_preview_sample_hover);
35 RK_DECLARE_IMAGE_RC(play_preview_sample_pressed);
36 RK_DECLARE_IMAGE_RC(load_preview_sample);
37 RK_DECLARE_IMAGE_RC(load_preview_sample_hover);
38 RK_DECLARE_IMAGE_RC(load_preview_sample_pressed);
39 RK_DECLARE_IMAGE_RC(osc1_preview_sample);
40 RK_DECLARE_IMAGE_RC(osc1_preview_sample_hover);
41 RK_DECLARE_IMAGE_RC(osc1_preview_sample_pressed);
42 RK_DECLARE_IMAGE_RC(osc2_preview_sample);
43 RK_DECLARE_IMAGE_RC(osc2_preview_sample_hover);
44 RK_DECLARE_IMAGE_RC(osc2_preview_sample_pressed);
45
SampleBrowser(GeonkickWidget * parent,GeonkickApi * api)46 SampleBrowser::SampleBrowser(GeonkickWidget *parent, GeonkickApi* api)
47 : GeonkickWidget(parent)
48 , geonkickApi{api}
49 , fileBrowser{new FileDialog(this, FileDialog::Type::Browse, std::string())}
50 , samplePreviewWidget{new BufferView(this)}
51 , playButton{nullptr}
52 , loadButton{nullptr}
53 , osc1Button{nullptr}
54 , osc2Button{nullptr}
55 , previewLimiter{nullptr}
56
57 {
58 setFixedSize(parent->size());
59 fileBrowser->setFilters({".wav", ".WAV", ".flac", ".FLAC", ".ogg", ".OGG"});
60 fileBrowser->setHomeDirectory(geonkickApi->getSettings("GEONKICK_CONFIG/HOME_PATH"));
61 fileBrowser->setCurrentDirectoy(viewState()->samplesBrowserPath());
62 setPreviewSample(viewState()->samplesBrowserPreviewFile());
63 RK_ACT_BIND(fileBrowser,
64 directoryChanged,
65 RK_ACT_ARGS(const std::string &path),
66 viewState(),
67 setSamplesBrowserPath(path));
68 RK_ACT_BIND(fileBrowser,
69 currentFileChanged,
70 RK_ACT_ARGS(const std::string &file),
71 this,
72 setPreviewSample(file));
73 RK_ACT_BIND(fileBrowser,
74 currentFileChanged,
75 RK_ACT_ARGS(const std::string &file),
76 viewState(),
77 setSamplesBrowserPreviewFile(file));
78 RK_ACT_BINDL(fileBrowser,
79 selectedFile,
80 RK_ACT_ARGS(const std::string &file),
__anon283eba310102(const std::string &file) 81 [&](const std::string &file) {
82 viewState()->setSamplesBrowserPreviewFile(file);
83 loadSample();
84 });
85
86 samplePreviewWidget->setSize(250, 260);
87 samplePreviewWidget->show();
88 RK_ACT_BIND(samplePreviewWidget, graphPressed, RK_ACT_ARGS(), geonkickApi, playSamplePreview());
89
90 previewLimiter = new GeonkickSlider(this, GeonkickSlider::Orientation::Vertical);
91 previewLimiter->onSetValue(Geonkick::toDecibel(geonkickApi->samplePreviewLimiter()) + 80);
92 RK_ACT_BIND(previewLimiter,
93 valueUpdated, RK_ACT_ARGS(int val),
94 geonkickApi,
95 setSamplePreviewLimiter(Geonkick::fromDecibel(val - 80)));
96
97 previewLimiter->setSize(16, samplePreviewWidget->height());
98
99 auto mainLayout = new RkContainer(this);
100 mainLayout->setSize(parent->size());
101 mainLayout->addWidget(fileBrowser);
102
103 auto previewWidgetContainer = new RkContainer(this, Rk::Orientation::Horizontal);
104 previewWidgetContainer->setSize({samplePreviewWidget->width() + 10 + previewLimiter->width(),
105 samplePreviewWidget->height()});
106 previewWidgetContainer->addWidget(samplePreviewWidget);
107 previewWidgetContainer->addSpace(8);
108 previewWidgetContainer->addWidget(previewLimiter);
109
110 auto previewContainer = new RkContainer(this, Rk::Orientation::Vertical);
111 previewContainer->setSize({previewWidgetContainer->width() + 10, mainLayout->height()});
112 previewContainer->addSpace(35);
113 previewContainer->addContainer(previewWidgetContainer);
114
115 auto previewMenuContainer = new RkContainer(this);
116 previewMenuContainer->setSize({previewContainer->width(), 25});
117 createPreviewMenu(previewMenuContainer);
118 previewContainer->addSpace(5);
119 previewContainer->addContainer(previewMenuContainer);
120 mainLayout->addSpace(5);
121 mainLayout->addContainer(previewContainer);
122 setOscillator(viewState()->samplesBrowserOscillator());
123 show();
124 }
125
createPreviewMenu(RkContainer * container)126 void SampleBrowser::createPreviewMenu(RkContainer* container)
127 {
128 playButton = new GeonkickButton(this);
129 playButton->setType(RkButton::ButtonType::ButtonPush);
130 playButton->setSize(33, 18);
131 playButton->setImage(RkImage(playButton->size(), RK_IMAGE_RC(play_preview_sample)),
132 RkButton::State::Unpressed);
133 playButton->setImage(RkImage(playButton->size(), RK_IMAGE_RC(play_preview_sample_hover)),
134 RkButton::State::UnpressedHover);
135 playButton->setImage(RkImage(playButton->size(), RK_IMAGE_RC(play_preview_sample_pressed)),
136 RkButton::State::Pressed);
137 RK_ACT_BIND(playButton, pressed, RK_ACT_ARGS(), geonkickApi, playSamplePreview());
138 container->addSpace(5);
139 container->addWidget(playButton);
140 container->addSpace(3);
141
142 loadButton = new GeonkickButton(this);
143 loadButton->setType(RkButton::ButtonType::ButtonPush);
144 loadButton->setSize(33, 18);
145 loadButton->setImage(RkImage(loadButton->size(), RK_IMAGE_RC(load_preview_sample)),
146 RkButton::State::Unpressed);
147 loadButton->setImage(RkImage(loadButton->size(), RK_IMAGE_RC(load_preview_sample_hover)),
148 RkButton::State::UnpressedHover);
149 loadButton->setImage(RkImage(loadButton->size(), RK_IMAGE_RC(load_preview_sample_pressed)),
150 RkButton::State::Pressed);
151 RK_ACT_BIND(loadButton, pressed, RK_ACT_ARGS(), this, loadSample());
152 container->addWidget(loadButton);
153 container->addSpace(15);
154
155 osc1Button = new GeonkickButton(this);
156 osc1Button->setSize(33, 18);
157 osc1Button->setImage(RkImage(osc1Button->size(), RK_IMAGE_RC(osc1_preview_sample)),
158 RkButton::State::Unpressed);
159 osc1Button->setImage(RkImage(osc1Button->size(), RK_IMAGE_RC(osc1_preview_sample_hover)),
160 RkButton::State::UnpressedHover);
161 osc1Button->setImage(RkImage(osc1Button->size(), RK_IMAGE_RC(osc1_preview_sample_pressed)),
162 RkButton::State::Pressed);
163 RK_ACT_BIND(osc1Button, pressed,
164 RK_ACT_ARGS(), this,
165 setOscillator(GeonkickApi::OscillatorType::Oscillator1));
166 container->addWidget(osc1Button);
167 container->addSpace(3);
168
169 osc2Button = new GeonkickButton(this);
170 osc2Button->setSize(33, 18);
171 osc2Button->setImage(RkImage(osc2Button->size(), RK_IMAGE_RC(osc2_preview_sample)),
172 RkButton::State::Unpressed);
173 osc2Button->setImage(RkImage(osc2Button->size(), RK_IMAGE_RC(osc2_preview_sample_hover)),
174 RkButton::State::UnpressedHover);
175 osc2Button->setImage(RkImage(osc2Button->size(), RK_IMAGE_RC(osc2_preview_sample_pressed)),
176 RkButton::State::Pressed);
177 RK_ACT_BIND(osc2Button, pressed,
178 RK_ACT_ARGS(), this,
179 setOscillator(GeonkickApi::OscillatorType::Oscillator2));
180 container->addWidget(osc2Button);
181 }
182
setOscillator(GeonkickApi::OscillatorType osc)183 void SampleBrowser::setOscillator(GeonkickApi::OscillatorType osc)
184 {
185 osc1Button->setPressed(osc == GeonkickApi::OscillatorType::Oscillator1);
186 osc2Button->setPressed(osc == GeonkickApi::OscillatorType::Oscillator2);
187 }
188
loadSample()189 void SampleBrowser::loadSample()
190 {
191 if (osc1Button->isPressed()) {
192 geonkickApi->setOscillatorSample(samplePreviewWidget->getData(),
193 static_cast<int>(GeonkickApi::OscillatorType::Oscillator1));
194 geonkickApi->setOscillatorFunction(static_cast<int>(GeonkickApi::OscillatorType::Oscillator1),
195 GeonkickApi::FunctionType::Sample);
196 } else if (osc2Button->isPressed()) {
197 geonkickApi->setOscillatorSample(samplePreviewWidget->getData(),
198 static_cast<int>(GeonkickApi::OscillatorType::Oscillator2));
199 geonkickApi->setOscillatorFunction(static_cast<int>(GeonkickApi::OscillatorType::Oscillator2),
200 GeonkickApi::FunctionType::Sample);
201 }
202 }
203
setPreviewSample(const std::string & file)204 void SampleBrowser::setPreviewSample(const std::string &file)
205 {
206 try {
207 if (std::filesystem::exists(file) && !std::filesystem::is_directory(file)) {
208 std::vector<float> data = geonkickApi->setPreviewSample(file);
209 if (!data.empty()) {
210 samplePreviewWidget->setData(data);
211 geonkickApi->playSamplePreview();
212 }
213 }
214 } catch (...) {
215 }
216 }
217