1 /* -----------------------------------------------------------------------------
2 *
3 * Giada - Your Hardcore Loopmachine
4 *
5 * -----------------------------------------------------------------------------
6 *
7 * Copyright (C) 2010-2020 Giovanni A. Zuliani | Monocasual
8 *
9 * This file is part of Giada - Your Hardcore Loopmachine.
10 *
11 * Giada - Your Hardcore Loopmachine is free software: you can
12 * redistribute it and/or modify it under the terms of the GNU General
13 * Public License as published by the Free Software Foundation, either
14 * version 3 of the License, or (at your option) any later version.
15 *
16 * Giada - Your Hardcore Loopmachine is distributed in the hope that it
17 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 * See the GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Giada - Your Hardcore Loopmachine. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 * -------------------------------------------------------------------------- */
26
27
28 #include <cstdint>
29 #include <FL/Fl_Menu_Item.H>
30 #include <FL/Fl_Menu_Button.H>
31 #include "core/model/model.h"
32 #include "core/waveFx.h"
33 #include "core/const.h"
34 #include "glue/sampleEditor.h"
35 #include "gui/elems/basics/boxtypes.h"
36 #include "gui/dialogs/sampleEditor.h"
37 #include "waveform.h"
38 #include "waveTools.h"
39
40
41 namespace giada {
42 namespace v
43 {
44 namespace
45 {
46 enum class Menu
47 {
48 CUT = 0,
49 COPY,
50 PASTE,
51 TRIM,
52 SILENCE,
53 REVERSE,
54 NORMALIZE,
55 FADE_IN,
56 FADE_OUT,
57 SMOOTH_EDGES,
58 SET_BEGIN_END,
59 TO_NEW_CHANNEL
60 };
61
62
63 /* -------------------------------------------------------------------------- */
64
65
menuCallback_(Fl_Widget * w,void * v)66 void menuCallback_(Fl_Widget* w, void* v)
67 {
68 const geWaveTools* wt = static_cast<geWaveTools*>(w);
69
70 ID channelId = wt->getChannelData().channelId;
71 ID waveId = wt->getChannelData().waveId;
72 Menu selectedItem = (Menu) (intptr_t) v;
73
74 int a = wt->waveform->getSelectionA();
75 int b = wt->waveform->getSelectionB();
76
77 switch (selectedItem) {
78 case Menu::CUT:
79 c::sampleEditor::cut(channelId, waveId, a, b);
80 break;
81 case Menu::COPY:
82 c::sampleEditor::copy(waveId, a, b);
83 break;
84 case Menu::PASTE:
85 c::sampleEditor::paste(channelId, waveId, a);
86 break;
87 case Menu::TRIM:
88 c::sampleEditor::trim(channelId, waveId, a, b);
89 break;
90 case Menu::SILENCE:
91 c::sampleEditor::silence(channelId, waveId, a, b);
92 break;
93 case Menu::REVERSE:
94 c::sampleEditor::reverse(channelId, waveId, a, b);
95 break;
96 case Menu::NORMALIZE:
97 c::sampleEditor::normalize(channelId, waveId, a, b);
98 break;
99 case Menu::FADE_IN:
100 c::sampleEditor::fade(channelId, waveId, a, b, m::wfx::Fade::IN);
101 break;
102 case Menu::FADE_OUT:
103 c::sampleEditor::fade(channelId, waveId, a, b, m::wfx::Fade::OUT);
104 break;
105 case Menu::SMOOTH_EDGES:
106 c::sampleEditor::smoothEdges(channelId, waveId, a, b);
107 break;
108 case Menu::SET_BEGIN_END:
109 c::sampleEditor::setBeginEnd(channelId, a, b);
110 break;
111 case Menu::TO_NEW_CHANNEL:
112 c::sampleEditor::toNewChannel(channelId, waveId, a, b);
113 break;
114 }
115 }
116 } // {anonymous}
117
118
119 /* -------------------------------------------------------------------------- */
120 /* -------------------------------------------------------------------------- */
121 /* -------------------------------------------------------------------------- */
122
123
geWaveTools(int x,int y,int w,int h)124 geWaveTools::geWaveTools(int x, int y, int w, int h)
125 : Fl_Scroll(x, y, w, h, nullptr)
126 , m_data (nullptr)
127 {
128 type(Fl_Scroll::HORIZONTAL_ALWAYS);
129 hscrollbar.color(G_COLOR_GREY_2);
130 hscrollbar.selection_color(G_COLOR_GREY_4);
131 hscrollbar.labelcolor(G_COLOR_LIGHT_1);
132 hscrollbar.slider(G_CUSTOM_BORDER_BOX);
133
134 waveform = new v::geWaveform(x, y, w, h-24);
135 }
136
137
138
139 /* -------------------------------------------------------------------------- */
140
141
rebuild(const c::sampleEditor::Data & d)142 void geWaveTools::rebuild(const c::sampleEditor::Data& d)
143 {
144 m_data = &d;
145 waveform->rebuild(d);
146 }
147
148
149 /* -------------------------------------------------------------------------- */
150
151
refresh()152 void geWaveTools::refresh()
153 {
154 if (m_data->a_getPreviewStatus() == ChannelStatus::PLAY)
155 waveform->redraw();
156 }
157
158
159 /* -------------------------------------------------------------------------- */
160
161
resize(int x,int y,int w,int h)162 void geWaveTools::resize(int x, int y, int w, int h)
163 {
164 Fl_Widget::resize(x, y, w, h);
165
166 if (this->w() == w || (this->w() != w && this->h() != h)) { // vertical or both resize
167 waveform->resize(x, y, waveform->w(), h-24);
168 waveform->rebuild(*m_data);
169 }
170
171 if (this->w() > waveform->w())
172 waveform->stretchToWindow();
173
174 int offset = waveform->x() + waveform->w() - this->w() - this->x();
175 if (offset < 0)
176 waveform->position(waveform->x()-offset, this->y());
177 }
178
179
180 /* -------------------------------------------------------------------------- */
181
182
handle(int e)183 int geWaveTools::handle(int e)
184 {
185 switch (e) {
186 case FL_MOUSEWHEEL: {
187 waveform->setZoom(Fl::event_dy() == 1 ? geWaveform::Zoom::OUT : geWaveform::Zoom::IN);
188 redraw();
189 return 1;
190 }
191 case FL_PUSH: {
192 if (Fl::event_button3()) { // right button
193 openMenu();
194 return 1;
195 }
196 Fl::focus(waveform);
197 }
198 default:
199 return Fl_Group::handle(e);
200 }
201 }
202
203
204 /* -------------------------------------------------------------------------- */
205
206
openMenu()207 void geWaveTools::openMenu()
208 {
209 Fl_Menu_Item menu[] = {
210 {"Cut", 0, menuCallback_, (void*) Menu::CUT},
211 {"Copy", 0, menuCallback_, (void*) Menu::COPY},
212 {"Paste", 0, menuCallback_, (void*) Menu::PASTE},
213 {"Trim", 0, menuCallback_, (void*) Menu::TRIM},
214 {"Silence", 0, menuCallback_, (void*) Menu::SILENCE},
215 {"Reverse", 0, menuCallback_, (void*) Menu::REVERSE},
216 {"Normalize", 0, menuCallback_, (void*) Menu::NORMALIZE},
217 {"Fade in", 0, menuCallback_, (void*) Menu::FADE_IN},
218 {"Fade out", 0, menuCallback_, (void*) Menu::FADE_OUT},
219 {"Smooth edges", 0, menuCallback_, (void*) Menu::SMOOTH_EDGES},
220 {"Set begin/end here", 0, menuCallback_, (void*) Menu::SET_BEGIN_END},
221 {"Copy to new channel", 0, menuCallback_, (void*) Menu::TO_NEW_CHANNEL},
222 {0}
223 };
224
225 if (!waveform->isSelected()) {
226 menu[(int)Menu::CUT].deactivate();
227 menu[(int)Menu::COPY].deactivate();
228 menu[(int)Menu::TRIM].deactivate();
229 menu[(int)Menu::SILENCE].deactivate();
230 menu[(int)Menu::REVERSE].deactivate();
231 menu[(int)Menu::NORMALIZE].deactivate();
232 menu[(int)Menu::FADE_IN].deactivate();
233 menu[(int)Menu::FADE_OUT].deactivate();
234 menu[(int)Menu::SMOOTH_EDGES].deactivate();
235 menu[(int)Menu::SET_BEGIN_END].deactivate();
236 menu[(int)Menu::TO_NEW_CHANNEL].deactivate();
237 }
238
239 Fl_Menu_Button b(0, 0, 100, 50);
240 b.box(G_CUSTOM_BORDER_BOX);
241 b.textsize(G_GUI_FONT_SIZE_BASE);
242 b.textcolor(G_COLOR_LIGHT_2);
243 b.color(G_COLOR_GREY_2);
244
245 const Fl_Menu_Item* m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, &b);
246 if (m != nullptr)
247 m->do_callback(this, m->user_data());
248
249 return;
250 }
251
252 }} // giada::v::
253