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