--------------------------------------------------------------------------------
+0.14.1 --- 2017 . 07 . 16
+- Update JUCE library to 5.0.2
+- Show play head in Sample Editor
+- Refactor pop up menu in Sample Editor
+- Many small fixes and optimizations in waveform drawing routine
+- Makefile cleanup
+- Fix crash while recording with beats/bars greater than 4/1 (GitHub #134)
+
+
0.14.0 --- 2017 . 05 . 29
- Sample Editor reorganized and refactored
- Removed support for old ini-based patch files
src/glue/transport.cpp \
src/glue/recorder.h \
src/glue/recorder.cpp \
+src/glue/sampleEditor.h \
+src/glue/sampleEditor.cpp \
src/gui/dialogs/window.h \
src/gui/dialogs/window.cpp \
src/gui/dialogs/gd_keyGrabber.h \
# via AM_CONDITIONAL inside configure.ac.
# Note: CPPFLAGS = C preprocessor flags, CXXFLAGS = C++ compiler flags.
-# TODO add -DNDEBUG for production code
giada_CXXFLAGS = -std=c++11 -Wall -Werror
giada_CPPFLAGS =
-DJUCE_STANDALONE_APPLICATION=1 \
-DJUCE_PLUGINHOST_VST=1 \
-DJUCE_PLUGINHOST_VST3=0 \
- -DJUCE_PLUGINHOST_AU=0
+ -DJUCE_PLUGINHOST_AU=0 \
+ -DJUCE_WEB_BROWSER=0
endif
if LINUX
giada_SOURCES += src/deps/rtaudio-mod/RtAudio.h src/deps/rtaudio-mod/RtAudio.cpp
-# -Wno-error=vla: mute rtAudio error on variable length array
-# -Wno-error=misleading-indentation: mute JUCE warnings on GCC6
-giada_CXXFLAGS += -Wno-error=vla -Wno-error=misleading-indentation
+# -Wno-error=misleading-indentation: don't stop on JUCE warnings on GCC6
+# -Wno-error=unused-function: don't stop on JUCE's unused functions
+giada_CXXFLAGS += -Wno-error=misleading-indentation -Wno-error=unused-function
giada_CPPFLAGS += -D__LINUX_ALSA__ -D__LINUX_PULSE__ -D__UNIX_JACK__
giada_LDADD = -lsndfile -lfltk -lXext -lX11 -lXft -lXpm -lm -ljack -lasound \
-lpthread -ldl -lpulse-simple -lpulse -lsamplerate -lrtmidi -ljansson \
src/deps/rtaudio-mod/include/asiodrivers.cpp \
src/deps/rtaudio-mod/include/iasiothiscallresolver.h \
src/deps/rtaudio-mod/include/iasiothiscallresolver.cpp
-# -Wno-error=misleading-indentation: mute JUCE warnings on GCC6
-# -Wno-error=unused-but-set-variable: silence ASIO errors
-giada_CXXFLAGS += \
--Wno-error=misleading-indentation \
--Wno-error=unused-but-set-variable
+giada_CXXFLAGS += -Wno-error
giada_CPPFLAGS += \
-I./src/deps/rtaudio-mod/include \
-D__WINDOWS_ASIO__ \
endif
if OSX
-# for 32 bit compilation:
-# export CXXFLAGS="-m32"
-# export LDFLAGS="-m32"
-# -ObjC++: Juce requires to build some Objective C code
-# -Wno-unknown-pragmas: shut up Juce even more
giada_SOURCES += src/utils/cocoa.mm src/utils/cocoa.h
-giada_CXXFLAGS += -ObjC++ -Wno-unknown-pragmas -Wno-auto-var-id
+# -ObjC++: Juce requires to build some Objective C code
+giada_CXXFLAGS += -ObjC++ -Wno-auto-var-id
giada_LDADD = -lsndfile -lm -lpthread -lfltk -lrtmidi -lrtaudio \
-lsamplerate -ljansson
giada_LDFLAGS = -framework CoreAudio -framework Cocoa -framework Carbon \
-DJUCE_STANDALONE_APPLICATION=1 \
-DJUCE_PLUGINHOST_VST=1 \
-DJUCE_PLUGINHOST_VST3=0 \
- -DJUCE_PLUGINHOST_AU=0
+ -DJUCE_PLUGINHOST_AU=0 \
+ -DJUCE_WEB_BROWSER=0
endif
# make rename ------------------------------------------------------------------
# prereq & init
AC_PREREQ(2.60)
-AC_INIT([giada], [0.13], [giadaloopmachine@gmail.com])
+AC_INIT([giada], [0.14], [giadaloopmachine@gmail.com])
AC_CONFIG_SRCDIR([src/main.cpp])
AM_INIT_AUTOMAKE([subdir-objects])
int mainWindowX = 0;
int mainWindowY = 0;
-int mainWindowW = GUI_WIDTH;
-int mainWindowH = GUI_HEIGHT;
+int mainWindowW = G_GUI_WIDTH;
+int mainWindowH = G_GUI_HEIGHT;
int browserX = 0;
int browserY = 0;
#define G_CONST_H
+/* -- environment ----------------------------------------------------------- */
+#if defined(_WIN32)
+ #define G_OS_WINDOWS
+#elif defined(__APPLE__)
+ #define G_OS_MAC
+#elif defined(__linux__)
+ #define G_OS_LINUX
+#endif
+
+#ifndef BUILD_DATE
+ #define BUILD_DATE __DATE__
+#endif
+
+
+
/* -- version --------------------------------------------------------------- */
#define G_APP_NAME "Giada"
-#define G_VERSION_STR "0.14.0"
+#define G_VERSION_STR "0.14.1"
#define G_VERSION_MAJOR 0
#define G_VERSION_MINOR 14
-#define G_VERSION_PATCH 0
+#define G_VERSION_PATCH 1
#define CONF_FILENAME "giada.conf"
-#ifndef BUILD_DATE
- #define BUILD_DATE __DATE__
-#endif
-
-#ifdef _WIN32
+#ifdef G_OS_WINDOWS
#define G_SLASH '\\'
#define G_SLASH_STR "\\"
#else
/* -- GUI ------------------------------------------------------------------- */
-#ifdef _WIN32
- #define GUI_SLEEP 1000/24
+#ifdef G_OS_WINDOWS
+ #define G_GUI_SLEEP 1000/24
#else
- #define GUI_SLEEP 1000000/24 // == 1.000.000 / 24 == 1/24 sec == 24 Hz
+ #define G_GUI_SLEEP 1000000/24 // == 1.000.000 / 24 == 1/24 sec == 24 Hz
#endif
-#define GUI_WIDTH 816
-#define GUI_HEIGHT 510
-#define GUI_PLUGIN_RATE 0.05 // refresh rate for plugin GUIs
-#define GUI_FONT_SIZE_BASE 12
-
-#define COLOR_BD_0 fl_rgb_color(78, 78, 78) // border off - TODO duplicate!
-#define COLOR_BD_1 fl_rgb_color(188, 188, 188) // border on
-#define COLOR_BG_0 fl_rgb_color(37, 37, 37) // bg off
-#define COLOR_BG_1 fl_rgb_color(78, 78, 78) // bg on (clicked) - TODO duplicate!
-#define COLOR_BG_2 fl_rgb_color(177, 142, 142) // bg active (play, for some widgets)
-#define COLOR_BG_3 fl_rgb_color(28, 32, 80) // bg input rec
-#define COLOR_BG_4 fl_rgb_color(113, 31, 31) // bg action rec
-#define COLOR_ALERT fl_rgb_color(239, 75, 53) // peak meter alert
-#define COLOR_TEXT_0 fl_rgb_color(200, 200, 200)
-#define COLOR_TEXT_1 fl_rgb_color(25, 25, 25) // TODO duplicate!
-#define COLOR_BG_MAIN fl_rgb_color(25, 25, 25) // windows background - TODO duplicate!
-#define COLOR_BG_RICH fl_rgb_color(30, 30, 30) // lighter background
-#define COLOR_BG_LINE fl_rgb_color(54, 54, 54) // lighter, for bg lines
-#define COLOR_BG_DARK fl_rgb_color(0, 0, 0) // inputs background
+#define G_GUI_WIDTH 816
+#define G_GUI_HEIGHT 510
+#define G_GUI_PLUGIN_RATE 0.05 // refresh rate for plugin GUIs
+#define G_GUI_FONT_SIZE_BASE 12
+
+#define G_COLOR_RED fl_rgb_color(28, 32, 80)
+#define G_COLOR_BLUE fl_rgb_color(113, 31, 31)
+#define G_COLOR_RED_ALERT fl_rgb_color(239, 75, 53)
+
+#define G_COLOR_LIGHT_2 fl_rgb_color(200, 200, 200)
+#define G_COLOR_LIGHT_1 fl_rgb_color(170, 170, 170)
+#define G_COLOR_GREY_4 fl_rgb_color(78, 78, 78)
+#define G_COLOR_GREY_3 fl_rgb_color(54, 54, 54)
+#define G_COLOR_GREY_2 fl_rgb_color(37, 37, 37)
+#define G_COLOR_GREY_1 fl_rgb_color(25, 25, 25)
+#define G_COLOR_BLACK fl_rgb_color(0, 0, 0)
#define G_MAX_BARS 32
#define G_MAX_QUANTIZE 8
#define G_MAX_PATCHNAME_LEN 32
-#define G_DB_MIN_SCALE 60.0f
+#define G_MIN_DB_SCALE 60.0f
#define G_MIN_COLUMN_WIDTH 140
#define G_MAX_BOOST_DB 20.0f
#define G_MAX_PITCH 4.0f
/* -- default system -------------------------------------------------------- */
-#if defined(__linux__)
+#if defined(G_OS_LINUX)
#define G_DEFAULT_SOUNDSYS G_SYS_API_NONE
-#elif defined(_WIN32)
+#elif defined(G_OS_WINDOWS)
#define G_DEFAULT_SOUNDSYS G_SYS_API_DS
-#elif defined(__APPLE__)
+#elif defined(G_OS_MAC)
#define G_DEFAULT_SOUNDSYS G_SYS_API_CORE
#endif
void init_startGUI(int argc, char **argv)
{
- G_MainWin = new gdMainWindow(GUI_WIDTH, GUI_HEIGHT, "", argc, argv);
+ G_MainWin = new gdMainWindow(G_GUI_WIDTH, G_GUI_HEIGHT, "", argc, argv);
G_MainWin->resize(conf::mainWindowX, conf::mainWindowY, conf::mainWindowW,
conf::mainWindowH);
void init(int framesInSeq, int audioBufferSize)
{
- /* Allocate virtual input channels. vChanInput relies on clock::totalFrames:
- it has variable size. */
+ /* Allocate virtual input channels. vChanInput has variable size: it depends
+ on how many frames there are in sequencer. */
+
+ allocVirtualInput(framesInSeq);
- if (vChanInput != nullptr)
- free(vChanInput);
- vChanInput = (float*) malloc(framesInSeq * sizeof(float));
if (vChanInToOut != nullptr)
free(vChanInToOut);
vChanInToOut = (float*) malloc(audioBufferSize * 2 * sizeof(float));
/* -------------------------------------------------------------------------- */
+void allocVirtualInput(int frames)
+{
+ if (vChanInput != nullptr)
+ free(vChanInput);
+ vChanInput = (float*) malloc(frames * sizeof(float));
+ if (!vChanInput)
+ gu_log("[Mixer] vChanInput realloc error!\n");
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
int masterPlay(void *_outBuf, void *_inBuf, unsigned bufferSize,
double streamTime, RtAudioStreamStatus status, void *userData)
{
namespace mixer
{
void init(int framesInSeq, int audioBufferSize);
-int close();
+
+/* allocVirtualInput
+Allocates new memory for the virtual input channel. Call this whenever you
+shrink or resize the sequencer. */
+
+void allocVirtualInput(int frames);
+
+int close();
/* masterPlay
* core method (callback) */
pi.manufacturerName = pd->manufacturerName.toStdString();
pi.format = pd->pluginFormatName.toStdString();
pi.isInstrument = pd->isInstrument;
-/*
- if (!p) {
- gu_log("[pluginHost::getAvailablePlugin] unable to create plugin instance!\n");
- return nullptr;
- }
- */
return pi;
}
return 0;
}
- gu_log("[wfx] cutting from %d to %d, new size=%d (video=%d)\n", a, b, newSize, newSize/2);
+ gu_log("[wfx] cutting from %d to %d, new size=%d (video=%d)\n",
+ a, b, newSize, newSize/2);
for (int i=0, k=0; i<w->size; i++) {
if (i < a || i >= b) { // left margin always included, in order to keep
/* -------------------------------------------------------------------------- */
-void glue_setBeginEndChannel(SampleChannel *ch, int b, int e)
-{
- ch->setBegin(b);
- ch->setEnd(e);
- gdSampleEditor *gdEditor = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
- if (gdEditor) {
- Fl::lock();
- gdEditor->rangeTool->refresh();
- Fl::unlock();
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
void glue_setBoost(SampleChannel *ch, float val)
{
ch->setBoost(val);
/* TODO move to glue_sampleEditor */
void glue_setPanning(SampleChannel *ch, float val);
-/* setBeginEndChannel
- * sets start/end points in the sample editor. Recalc=false: don't recalc
- * internal position. check=true: check the points' consistency */
-
-/* TODO move to glue_sampleEditor */
-void glue_setBeginEndChannel(SampleChannel *ch, int b, int e);
-
/* TODO move to glue_sampleEditor */
void glue_setBoost(SampleChannel *ch, float val);
clock::setBeats(beats);
clock::setBars(bars);
clock::updateFrameBars();
+ mixer::allocVirtualInput(clock::getTotalFrames());
/* Update recorded actions, if 'expand' required and an expansion is taking
place. */
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include <cassert>
+#include <FL/Fl.H>
+#include "../gui/dialogs/gd_mainWindow.h"
+#include "../gui/dialogs/sampleEditor.h"
+#include "../gui/dialogs/gd_warnings.h"
+#include "../gui/elems/sampleEditor/waveTools.h"
+#include "../gui/elems/sampleEditor/volumeTool.h"
+#include "../gui/elems/sampleEditor/boostTool.h"
+#include "../gui/elems/sampleEditor/panTool.h"
+#include "../gui/elems/sampleEditor/pitchTool.h"
+#include "../gui/elems/sampleEditor/rangeTool.h"
+#include "../gui/elems/sampleEditor/waveform.h"
+#include "../core/sampleChannel.h"
+#include "../core/waveFx.h"
+#include "../core/const.h"
+#include "../utils/gui.h"
+#include "channel.h"
+#include "sampleEditor.h"
+
+
+extern gdMainWindow *G_MainWin;
+
+
+using namespace giada::m;
+
+
+namespace giada {
+namespace c {
+namespace sampleEditor
+{
+gdSampleEditor* getSampleEditorWindow()
+{
+ gdSampleEditor* se = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
+ assert(se != nullptr);
+ return se;
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+void setBeginEndChannel(SampleChannel* ch, int b, int e)
+{
+ ch->setBegin(b);
+ ch->setEnd(e);
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ Fl::lock();
+ gdEditor->rangeTool->refresh();
+ Fl::unlock();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void cut(SampleChannel* ch, int a, int b)
+{
+ if (!wfx_cut(ch->wave, a, b)) {
+ gdAlert("Unable to cut the sample!");
+ return;
+ }
+ setBeginEndChannel(ch, ch->begin, ch->end);
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ gdEditor->waveTools->waveform->clearSel();
+ gdEditor->waveTools->waveform->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void silence(SampleChannel* ch, int a, int b)
+{
+ wfx_silence(ch->wave, a, b);
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ gdEditor->waveTools->waveform->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void fade(SampleChannel* ch, int a, int b, int type)
+{
+ wfx_fade(ch->wave, a, b, type);
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ gdEditor->waveTools->waveform->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void smoothEdges(SampleChannel* ch, int a, int b)
+{
+ wfx_smooth(ch->wave, a, b);
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ gdEditor->waveTools->waveform->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void setStartEnd(SampleChannel* ch, int a, int b)
+{
+ setBeginEndChannel(ch, a * 2, b * 2); // stereo values
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ gdEditor->waveTools->waveform->recalcPoints();
+ gdEditor->waveTools->waveform->clearSel();
+ gdEditor->waveTools->waveform->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void trim(SampleChannel* ch, int a, int b)
+{
+ if (!wfx_trim(ch->wave, a, b)) {
+ gdAlert("Unable to trim the sample!");
+ return;
+ }
+ setBeginEndChannel(ch, ch->begin, ch->end);
+ gdSampleEditor* gdEditor = getSampleEditorWindow();
+ gdEditor->waveTools->waveform->clearSel();
+ gdEditor->waveTools->waveform->refresh();
+}
+
+}}}; // giada::c::sampleEditor::
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef G_GLUE_SAMPLE_EDITOR_H
+#define G_GLUE_SAMPLE_EDITOR_H
+
+
+class SampleChannel;
+class geWaveform;
+
+
+namespace giada {
+namespace c {
+namespace sampleEditor
+{
+
+
+/* setBeginEndChannel
+Sets start/end points in the sample editor. */
+
+void setBeginEndChannel(SampleChannel* ch, int b, int e);
+
+void cut(SampleChannel* ch, int a, int b);
+void trim(SampleChannel* ch, int a, int b);
+void silence(SampleChannel* ch, int a, int b);
+void fade(SampleChannel* ch, int a, int b, int type);
+void smoothEdges(SampleChannel* ch, int a, int b);
+void setStartEnd(SampleChannel* ch, int a, int b);
+
+}}}; // giada::c::sampleEditor::
+
+#endif
hiddenFiles->callback(cb_toggleHiddenFiles, (void*) this);
where->readonly(true);
- where->cursor_color(COLOR_BG_DARK);
+ where->cursor_color(G_COLOR_BLACK);
where->value(path.c_str());
updir->callback(cb_up, (void*) this);
Fl_Tabs *tabs = new Fl_Tabs(8, 8, w-16, h-44);
tabs->box(G_CUSTOM_BORDER_BOX);
- tabs->labelcolor(COLOR_TEXT_0);
+ tabs->labelcolor(G_COLOR_LIGHT_2);
tabs->begin();
tabAudio = new geTabAudio(tabs->x()+10, tabs->y()+20, tabs->w()-20, tabs->h()-40);
Fl::set_boxtype(FL_UP_BOX, G_CUSTOM_UP_BOX);
Fl::set_boxtype(FL_DOWN_BOX, G_CUSTOM_DOWN_BOX);
- size_range(GUI_WIDTH, GUI_HEIGHT);
+ size_range(G_GUI_WIDTH, G_GUI_HEIGHT);
mainMenu = new geMainMenu(8, -1);
mainIO = new geMainIO(412, 8);
list = new Fl_Scroll(8, 8, 476, 188);
list->type(Fl_Scroll::VERTICAL);
- list->scrollbar.color(COLOR_BG_0);
- list->scrollbar.selection_color(COLOR_BG_1);
- list->scrollbar.labelcolor(COLOR_BD_1);
+ list->scrollbar.color(G_COLOR_GREY_2);
+ list->scrollbar.selection_color(G_COLOR_GREY_4);
+ list->scrollbar.labelcolor(G_COLOR_LIGHT_1);
list->scrollbar.slider(G_CUSTOM_BORDER_BOX);
list->begin();
resize((Fl::w() - pluginW) / 2, (Fl::h() - pluginH) / 2, pluginW, pluginH);
- Fl::add_timeout(GUI_PLUGIN_RATE, cb_refresh, (void*) this);
+ Fl::add_timeout(G_GUI_PLUGIN_RATE, cb_refresh, (void*) this);
copy_label(pPlugin->getName().c_str());
void gdPluginWindowGUI::__cb_refresh()
{
pluginHost::runDispatchLoop();
- Fl::repeat_timeout(GUI_PLUGIN_RATE, cb_refresh, (void*) this);
+ Fl::repeat_timeout(G_GUI_PLUGIN_RATE, cb_refresh, (void*) this);
}
geBox *box = new geBox(10, 10, 280, 40, c);
geButton *b = new geButton(210, 60, 80, 20, "Close");
modal->end();
- box->labelsize(GUI_FONT_SIZE_BASE);
+ box->labelsize(G_GUI_FONT_SIZE_BASE);
b->callback(__cb_window_closer, (void *)modal);
b->shortcut(FL_Enter);
gu_setFavicon(modal);
#include <FL/Fl_Group.H>
#include <FL/fl_draw.H>
#include "../../glue/channel.h"
+#include "../../glue/sampleEditor.h"
#include "../../core/waveFx.h"
#include "../../core/conf.h"
#include "../../core/const.h"
using namespace giada::m;
+using namespace giada::c;
gdSampleEditor::gdSampleEditor(SampleChannel *ch)
grid->add("16");
grid->add("32");
grid->add("64");
- grid->value(grid->find_item(gu_itoa(conf::sampleEditorGridVal).c_str()));
+ if (conf::sampleEditorGridVal == 0)
+ grid->value(0);
+ else
+ grid->value(grid->find_item(gu_itoa(conf::sampleEditorGridVal).c_str()));
grid->callback(cb_changeGrid, (void*)this);
snap->value(conf::sampleEditorGridOn);
waveTools->waveform->stretchToWindow();
waveTools->updateWaveform();
- glue_setBeginEndChannel(ch, 0, ch->wave->size);
+ sampleEditor::setBeginEndChannel(ch, 0, ch->wave->size);
redraw();
}
{
int color;
if (selected) /// && geActionEditor !disabled
- color = COLOR_BD_1;
+ color = G_COLOR_LIGHT_2;
else
- color = COLOR_BG_2;
+ color = G_COLOR_LIGHT_1;
if (ch->mode == SINGLE_PRESS) {
fl_rectf(x(), y(), w(), h(), (Fl_Color) color);
else {
fl_rectf(x(), y(), MIN_WIDTH, h(), (Fl_Color) color);
if (type == G_ACTION_KEYPRESS)
- fl_rectf(x()+3, y()+h()-11, 2, 8, COLOR_BD_0);
+ fl_rectf(x()+3, y()+h()-11, 2, 8, G_COLOR_GREY_4);
else
if (type == G_ACTION_KEYREL)
- fl_rectf(x()+3, y()+3, 2, 8, COLOR_BD_0);
+ fl_rectf(x()+3, y()+3, 2, 8, G_COLOR_GREY_4);
}
}
/* print label */
- fl_color(COLOR_BG_1);
+ fl_color(G_COLOR_GREY_4);
fl_font(FL_HELVETICA, 12);
if (active())
fl_draw("start/stop", x()+4, y(), w(), h(), (Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_CENTER)); /// FIXME h() is too much!
/* clear the screen */
if (clear)
- fl_rectf(x(), y(), w(), h(), COLOR_BG_MAIN);
+ fl_rectf(x(), y(), w(), h(), G_COLOR_GREY_1);
/* draw the container */
- fl_color(COLOR_BD_0);
+ fl_color(G_COLOR_GREY_4);
fl_rect(x(), y(), w(), h());
/* grid drawing, if > 1 */
/* bars and beats drawing */
- fl_color(COLOR_BD_0);
+ fl_color(G_COLOR_GREY_4);
for (int i=0; i<(int) pParent->gridTool->beats.size(); i++) {
int px = pParent->gridTool->beats.at(i)+x()-1;
fl_line(px, y()+1, px, y()+h()-2);
}
- fl_color(COLOR_BG_2);
+ fl_color(G_COLOR_LIGHT_1);
for (int i=0; i<(int) pParent->gridTool->bars.size(); i++) {
int px = pParent->gridTool->bars.at(i)+x()-1;
fl_line(px, y()+1, px, y()+h()-2);
int coverWidth = pParent->totalWidth-pParent->coverX;
if (coverWidth != 0)
- fl_rectf(pParent->coverX+x(), y()+1, coverWidth, h()-2, COLOR_BG_1);
+ fl_rectf(pParent->coverX+x(), y()+1, coverWidth, h()-2, G_COLOR_GREY_4);
}
/* print label */
- fl_color(COLOR_BG_1);
+ fl_color(G_COLOR_GREY_4);
fl_font(FL_HELVETICA, 12);
fl_draw(l, x()+4, y(), 80, h(), (Fl_Align) (FL_ALIGN_LEFT));
int pxNew = 0;
int pyNew = 0;
- fl_color(COLOR_BG_2);
+ fl_color(G_COLOR_LIGHT_1);
for (unsigned i=0; i<points.size(); i++) {
pyNew = points.at(i).y+y();
if (selectedPoint == (int) i) {
- fl_color(COLOR_BD_1);
+ fl_color(G_COLOR_LIGHT_1);
fl_rectf(pxNew, pyNew, 7, 7);
- fl_color(COLOR_BG_2);
+ fl_color(G_COLOR_LIGHT_1);
}
else
fl_rectf(pxNew, pyNew, 7, 7);
/* print label */
- fl_color(COLOR_BG_1);
+ fl_color(G_COLOR_GREY_4);
fl_font(FL_HELVETICA, 12);
fl_draw("mute", x()+4, y(), w(), h(), (Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_CENTER));
/* draw "on" and "off" labels. Must stay in background */
- fl_color(COLOR_BG_1);
+ fl_color(G_COLOR_GREY_4);
fl_font(FL_HELVETICA, 9);
fl_draw("on", x()+4, y(), w(), h(), (Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_TOP));
fl_draw("off", x()+4, y()+h()-14, w(), h(), (Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_TOP));
/* draw on-off points. On = higher rect, off = lower rect. It always
* starts with a note_off */
- fl_color(COLOR_BG_2);
+ fl_color(G_COLOR_LIGHT_1);
int pxOld = x()+1;
int pxNew = 0;
fl_line(pxNew, y()+h()-5, pxNew, y()+4);
if (selectedPoint == (int) i) {
- fl_color(COLOR_BD_1);
+ fl_color(G_COLOR_LIGHT_1);
fl_rectf(pxNew-3, pyDot, 7, 7);
- fl_color(COLOR_BG_2);
+ fl_color(G_COLOR_LIGHT_1);
}
else
fl_rectf(pxNew-3, pyDot, 7, 7);
/* clear background */
- fl_rectf(x(), y(), w(), h(), COLOR_BG_MAIN);
+ fl_rectf(x(), y(), w(), h(), G_COLOR_GREY_1);
/* clip pianoRoll to pianoRollContainer size */
draw_child(*pianoRoll);
fl_pop_clip();
- fl_color(COLOR_BD_0);
+ fl_color(G_COLOR_GREY_4);
fl_line_style(0);
fl_rect(x(), y(), pParent->totalWidth, h());
}
void gePianoItem::draw()
{
int _w = w() > MIN_WIDTH ? w() : MIN_WIDTH;
- fl_rectf(x(), y()+2, _w, h()-3, (Fl_Color) selected ? COLOR_BD_1 : COLOR_BG_2);
+ fl_rectf(x(), y()+2, _w, h()-3, (Fl_Color) selected ? G_COLOR_LIGHT_1 : G_COLOR_LIGHT_1);
}
gePianoItemOrphaned::gePianoItemOrphaned(int x, int y, int xRel, int yRel,
recorder::action *action, gdActionEditor *pParent)
- : geBasePianoItem(x, y, WIDTH, pParent),
- action (action)
+ : geBasePianoItem(x, y, WIDTH, pParent)
{
note = kernelMidi::getB2(action->iValue);
frame = action->frame;
void gePianoItemOrphaned::draw()
{
- fl_rect(x(), y()+2, WIDTH, h()-3, (Fl_Color) selected ? COLOR_BD_1 : COLOR_BG_2);
+ fl_rect(x(), y()+2, WIDTH, h()-3, (Fl_Color) selected ? G_COLOR_LIGHT_1 : G_COLOR_LIGHT_1);
}
{
private:
- struct giada::m::recorder::action *action;
-
int note;
int frame;
int event;
/* warning: only w() and h() come from this widget, x and y coordinates
* are absolute, since we are writing in a memory chunk */
- fl_rectf(0, 0, CELL_W, h(), COLOR_BG_MAIN);
+ fl_rectf(0, 0, CELL_W, h(), G_COLOR_GREY_1);
fl_line_style(FL_DASH, 0, nullptr);
- fl_font(FL_HELVETICA, GUI_FONT_SIZE_BASE);
+ fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
int octave = MAX_OCTAVES;
char note[6];
switch (i % KEYS) {
case (int) Notes::G:
- fl_rectf(0, i*CELL_H, CELL_W, CELL_H, COLOR_BG_RICH);
+ fl_rectf(0, i*CELL_H, CELL_W, CELL_H, G_COLOR_GREY_2);
sprintf(note, "%dG", octave);
break;
case (int) Notes::FS:
sprintf(note, "%dF", octave);
break;
case (int) Notes::E:
- fl_rectf(0, i*CELL_H, CELL_W, CELL_H, COLOR_BG_RICH);
+ fl_rectf(0, i*CELL_H, CELL_W, CELL_H, G_COLOR_GREY_2);
sprintf(note, "%dE", octave);
break;
case (int) Notes::DS:
sprintf(note, "%dD#", octave);
break;
case (int) Notes::D:
- fl_rectf(0, i*CELL_H, CELL_W, CELL_H, COLOR_BG_RICH);
+ fl_rectf(0, i*CELL_H, CELL_W, CELL_H, G_COLOR_GREY_2);
sprintf(note, "%dD", octave);
break;
case (int) Notes::CS:
sprintf(note, "%dC", octave);
break;
case (int) Notes::B:
- fl_rectf(0, i*CELL_H, CELL_W, CELL_H, COLOR_BG_RICH);
+ fl_rectf(0, i*CELL_H, CELL_W, CELL_H, G_COLOR_GREY_2);
sprintf(note, "%dB", octave);
break;
case (int) Notes::AS:
sprintf(note, "%dA#", octave);
break;
case (int) Notes::A:
- fl_rectf(0, i*CELL_H, CELL_W, CELL_H, COLOR_BG_RICH);
+ fl_rectf(0, i*CELL_H, CELL_W, CELL_H, G_COLOR_GREY_2);
sprintf(note, "%dA", octave);
break;
case (int) Notes::GS:
/* Print note name */
- fl_color(COLOR_BG_LINE);
+ fl_color(G_COLOR_GREY_3);
fl_draw(note, 4, ((i-1)*CELL_H)+1, CELL_W, CELL_H,
(Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_CENTER));
{
surface2 = fl_create_offscreen(CELL_W, h());
fl_begin_offscreen(surface2);
- fl_rectf(0, 0, CELL_W, h(), COLOR_BG_MAIN);
- fl_color(COLOR_BG_LINE);
+ fl_rectf(0, 0, CELL_W, h(), G_COLOR_GREY_1);
+ fl_color(G_COLOR_GREY_3);
fl_line_style(FL_DASH, 0, nullptr);
for (int i=1; i<=MAX_KEYS+1; i++) {
switch (i % KEYS) {
case (int) Notes::D:
case (int) Notes::B:
case (int) Notes::A:
- fl_rectf(0, i*CELL_H, CELL_W, CELL_H, COLOR_BG_RICH);
+ fl_rectf(0, i*CELL_H, CELL_W, CELL_H, G_COLOR_GREY_2);
break;
}
if (i < MAX_KEYS+1) {
- fl_color(COLOR_BG_LINE);
+ fl_color(G_COLOR_GREY_3);
fl_line(0, i*CELL_H, CELL_W, i*CELL_H);
}
}
: Fl_Box(x, y, w, h)
{
copy_label(l);
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
box(FL_NO_BOX);
- labelcolor(COLOR_TEXT_0);
+ labelcolor(G_COLOR_LIGHT_2);
if (al != 0)
align(al | FL_ALIGN_INSIDE);
}
{
fl_color(c);
fl_rectf(x, y, w, h);
- fl_color(COLOR_BD_0);
+ fl_color(G_COLOR_GREY_4);
fl_rect(x, y, w, h);
}
void g_customUpBox(int x, int y, int w, int h, Fl_Color c)
{
- fl_color(COLOR_BG_0);
+ fl_color(G_COLOR_GREY_2);
fl_rectf(x, y, w, h);
- fl_color(COLOR_BG_0);
+ fl_color(G_COLOR_GREY_2);
fl_rect(x, y, w, h);
}
{
fl_color(c);
fl_rectf(x, y, w, h);
- fl_color(COLOR_BG_0);
+ fl_color(G_COLOR_GREY_2);
fl_rect(x, y, w, h);
}
: geBaseButton(x, y, w, h, L),
imgOff (imgOff),
imgOn (imgOn),
- bgColor0 (COLOR_BG_0),
- bgColor1 (COLOR_BG_1),
- bdColor (COLOR_BD_0),
- txtColor (COLOR_TEXT_0)
+ bgColor0 (G_COLOR_GREY_2),
+ bgColor1 (G_COLOR_GREY_4),
+ bdColor (G_COLOR_GREY_4),
+ txtColor (G_COLOR_LIGHT_2)
{
}
void geButton::draw()
{
if (!active()) txtColor = bdColor;
- else txtColor = COLOR_TEXT_0;
+ else txtColor = G_COLOR_LIGHT_2;
fl_rect(x(), y(), w(), h(), bdColor); // borders
if (value()) { // -- clicked
fl_color(FL_INACTIVE_COLOR);
fl_color(txtColor);
- fl_font(FL_HELVETICA, GUI_FONT_SIZE_BASE);
+ fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
fl_draw(label(), x()+2, y(), w()-2, h(), FL_ALIGN_CENTER);
}
void geCheck::draw()
{
- int color = !active() ? FL_INACTIVE_COLOR : COLOR_BD_0;
+ int color = !active() ? FL_INACTIVE_COLOR : G_COLOR_GREY_4;
if (value()) {
fl_rect(x(), y(), 12, 12, (Fl_Color) color);
}
fl_rectf(x()+20, y(), w(), h(), FL_BACKGROUND_COLOR); // clearer
- fl_font(FL_HELVETICA, GUI_FONT_SIZE_BASE);
- fl_color(!active() ? FL_INACTIVE_COLOR : COLOR_TEXT_0);
+ fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
+ fl_color(!active() ? FL_INACTIVE_COLOR : G_COLOR_LIGHT_2);
fl_draw(label(), x()+20, y(), w(), h(), (Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_TOP));
}
geChoice::geChoice(int x, int y, int w, int h, const char *l, bool ang)
: Fl_Choice(x, y, w, h, l), angle(ang)
{
- labelsize(GUI_FONT_SIZE_BASE);
- labelcolor(COLOR_TEXT_0);
+ labelsize(G_GUI_FONT_SIZE_BASE);
+ labelcolor(G_COLOR_LIGHT_2);
box(FL_BORDER_BOX);
- textsize(GUI_FONT_SIZE_BASE);
- textcolor(COLOR_TEXT_0);
- color(COLOR_BG_0);
+ textsize(G_GUI_FONT_SIZE_BASE);
+ textcolor(G_COLOR_LIGHT_2);
+ color(G_COLOR_GREY_2);
}
void geChoice::draw()
{
- fl_rectf(x(), y(), w(), h(), COLOR_BG_0); // bg
- fl_rect(x(), y(), w(), h(), (Fl_Color) COLOR_BD_0); // border
+ fl_rectf(x(), y(), w(), h(), G_COLOR_GREY_2); // bg
+ fl_rect(x(), y(), w(), h(), (Fl_Color) G_COLOR_GREY_4); // border
if (angle)
fl_polygon(x()+w()-8, y()+h()-1, x()+w()-1, y()+h()-8, x()+w()-1, y()+h()-1);
/* pick up the text() from the selected item (value()) and print it in
* the box and avoid overflows */
- fl_color(!active() ? COLOR_BD_0 : COLOR_TEXT_0);
+ fl_color(!active() ? G_COLOR_GREY_4 : G_COLOR_LIGHT_2);
if (value() != -1) {
if (fl_width(text(value())) < w()-8) {
fl_draw(text(value()), x(), y(), w(), h(), FL_ALIGN_CENTER);
geDial::geDial(int x, int y, int w, int h, const char *l)
: Fl_Dial(x, y, w, h, l)
{
- labelsize(GUI_FONT_SIZE_BASE);
- labelcolor(COLOR_TEXT_0);
+ labelsize(G_GUI_FONT_SIZE_BASE);
+ labelcolor(G_COLOR_LIGHT_2);
align(FL_ALIGN_LEFT);
type(FL_FILL_DIAL);
angles(0, 360);
- color(COLOR_BG_0); // background
- selection_color(COLOR_BG_1); // selection
+ color(G_COLOR_GREY_2); // background
+ selection_color(G_COLOR_GREY_4); // selection
}
{
double angle = (angle2()-angle1())*(value()-minimum())/(maximum()-minimum()) + angle1();
- fl_color(COLOR_BG_0);
+ fl_color(G_COLOR_GREY_2);
fl_pie(x(), y(), w(), h(), 270-angle1(), angle > angle1() ? 360+270-angle : 270-360-angle);
- fl_color(COLOR_BD_0);
+ fl_color(G_COLOR_GREY_4);
fl_arc(x(), y(), w(), h(), 0, 360);
fl_pie(x(), y(), w(), h(), 270-angle, 270-angle1());
}
{
//Fl::set_boxtype(G_CUSTOM_BORDER_BOX, gDrawBox, 1, 1, 2, 2);
box(G_CUSTOM_BORDER_BOX);
- labelsize(GUI_FONT_SIZE_BASE);
- labelcolor(COLOR_TEXT_0);
- color(COLOR_BG_DARK);
- textcolor(COLOR_TEXT_0);
- cursor_color(COLOR_TEXT_0);
- selection_color(COLOR_BD_0);
- textsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
+ labelcolor(G_COLOR_LIGHT_2);
+ color(G_COLOR_BLACK);
+ textcolor(G_COLOR_LIGHT_2);
+ cursor_color(G_COLOR_LIGHT_2);
+ selection_color(G_COLOR_GREY_4);
+ textsize(G_GUI_FONT_SIZE_BASE);
}
: Fl_Scroll(x, y, w, h, l)
{
type(Fl_Scroll::VERTICAL);
- scrollbar.color(COLOR_BG_0);
- scrollbar.selection_color(COLOR_BG_1);
- scrollbar.labelcolor(COLOR_BD_1);
+ scrollbar.color(G_COLOR_GREY_2);
+ scrollbar.selection_color(G_COLOR_GREY_4);
+ scrollbar.labelcolor(G_COLOR_LIGHT_1);
scrollbar.slider(G_CUSTOM_BORDER_BOX);
}
geProgress::geProgress(int x, int y, int w, int h, const char *l)
: Fl_Progress(x, y, w, h, l)
{
- color(COLOR_BG_0, COLOR_BD_0);
+ color(G_COLOR_GREY_2, G_COLOR_GREY_4);
box(G_CUSTOM_BORDER_BOX);
}
void geRadio::draw()
{
- int color = !active() ? FL_INACTIVE_COLOR : COLOR_BD_0;
+ int color = !active() ? FL_INACTIVE_COLOR : G_COLOR_GREY_4;
if (value()) {
fl_rect(x(), y(), 12, 12, (Fl_Color) color);
}
fl_rectf(x()+20, y(), w(), h(), FL_BACKGROUND_COLOR); // clearer
- fl_font(FL_HELVETICA, GUI_FONT_SIZE_BASE);
- fl_color(COLOR_TEXT_0);
+ fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
+ fl_color(G_COLOR_LIGHT_2);
fl_draw(label(), x()+20, y(), w(), h(), (Fl_Align) (FL_ALIGN_LEFT | FL_ALIGN_TOP));
}
{
type(t);
- scrollbar.color(COLOR_BG_0);
- scrollbar.selection_color(COLOR_BG_1);
- scrollbar.labelcolor(COLOR_BD_1);
+ scrollbar.color(G_COLOR_GREY_2);
+ scrollbar.selection_color(G_COLOR_GREY_4);
+ scrollbar.labelcolor(G_COLOR_LIGHT_1);
scrollbar.slider(G_CUSTOM_BORDER_BOX);
- hscrollbar.color(COLOR_BG_0);
- hscrollbar.selection_color(COLOR_BG_1);
- hscrollbar.labelcolor(COLOR_BD_1);
+ hscrollbar.color(G_COLOR_GREY_2);
+ hscrollbar.selection_color(G_COLOR_GREY_4);
+ hscrollbar.labelcolor(G_COLOR_LIGHT_1);
hscrollbar.slider(G_CUSTOM_BORDER_BOX);
}
{
type(FL_HOR_FILL_SLIDER);
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
align(FL_ALIGN_LEFT);
- labelcolor(COLOR_TEXT_0);
+ labelcolor(G_COLOR_LIGHT_2);
box(G_CUSTOM_BORDER_BOX);
- color(COLOR_BG_0);
- selection_color(COLOR_BD_0);
+ color(G_COLOR_GREY_2);
+ selection_color(G_COLOR_GREY_4);
}
{
geButton::draw();
if (status)
- fl_draw_pixmap(imgOn, x()+1, y()+1, COLOR_BD_0);
+ fl_draw_pixmap(imgOn, x()+1, y()+1, G_COLOR_GREY_4);
}
showHiddenFiles(false)
{
box(G_CUSTOM_BORDER_BOX);
- textsize(GUI_FONT_SIZE_BASE);
- textcolor(COLOR_TEXT_0);
- selection_color(COLOR_BG_1);
- color(COLOR_BG_0);
+ textsize(G_GUI_FONT_SIZE_BASE);
+ textcolor(G_COLOR_LIGHT_2);
+ selection_color(G_COLOR_GREY_4);
+ color(G_COLOR_GREY_2);
type(FL_SELECT_BROWSER);
- this->scrollbar.color(COLOR_BG_0);
- this->scrollbar.selection_color(COLOR_BG_1);
- this->scrollbar.labelcolor(COLOR_BD_1);
+ this->scrollbar.color(G_COLOR_GREY_2);
+ this->scrollbar.selection_color(G_COLOR_GREY_4);
+ this->scrollbar.labelcolor(G_COLOR_LIGHT_1);
this->scrollbar.slider(G_CUSTOM_BORDER_BOX);
- this->hscrollbar.color(COLOR_BG_0);
- this->hscrollbar.selection_color(COLOR_BG_1);
- this->hscrollbar.labelcolor(COLOR_BD_1);
+ this->hscrollbar.color(G_COLOR_GREY_2);
+ this->hscrollbar.selection_color(G_COLOR_GREY_4);
+ this->hscrollbar.labelcolor(G_COLOR_LIGHT_1);
this->hscrollbar.slider(G_CUSTOM_BORDER_BOX);
take_focus(); // let it have focus on startup
new geBox(x(), rsmpQuality->y()+rsmpQuality->h()+8, w(), 92,
"Restart Giada for the changes to take effect.");
end();
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
soundsys->add("(none)");
end();
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
conf::recsStopOnChanHalt == 1 ? recsStopOnChanHalt_1->value(1) : recsStopOnChanHalt_0->value(1);
conf::chansStopOnSeqHalt == 1 ? chansStopOnSeqHalt_1->value(1) : chansStopOnSeqHalt_0->value(1);
new geBox(x(), sync->y()+sync->h()+8, w(), h()-125, "Restart Giada for the changes to take effect.");
end();
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
system->callback(cb_changeSystem, (void*)this);
debugMsg->add("To standard output");
debugMsg->add("To file");
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
switch (conf::logMode) {
case LOG_MODE_MUTE:
#include <FL/Fl.H>
-#include "../../core/const.h"
-#include "../../core/conf.h"
-#include "../../core/pluginHost.h"
-#include "../../utils/string.h"
-#include "../../utils/fs.h"
+#include "../../../core/const.h"
+#include "../../../core/conf.h"
+#include "../../../core/pluginHost.h"
+#include "../../../utils/string.h"
+#include "../../../utils/fs.h"
#include "../basics/box.h"
#include "../basics/radio.h"
#include "../basics/check.h"
end();
- labelsize(GUI_FONT_SIZE_BASE);
+ labelsize(G_GUI_FONT_SIZE_BASE);
info->label("Scan in progress. Please wait...");
info->hide();
int cursorW = w() / G_MAX_BEATS;
int greyX = clock::getBeats() * cursorW;
- fl_rect(x(), y(), w(), h(), COLOR_BD_0); // border
+ fl_rect(x(), y(), w(), h(), G_COLOR_GREY_4); // border
fl_rectf(x()+1, y()+1, w()-2, h()-2, FL_BACKGROUND_COLOR); // bg
fl_rectf(x()+(clock::getCurrentBeat()*cursorW)+3, y()+3, cursorW-5, h()-6,
- COLOR_BG_2); // cursor
+ G_COLOR_LIGHT_1); // cursor
/* beat cells */
- fl_color(COLOR_BD_0);
+ fl_color(G_COLOR_GREY_4);
for (int i=1; i<=clock::getBeats(); i++)
fl_line(x()+cursorW*i, y()+1, x()+cursorW*i, y()+h()-2);
/* bar line */
- fl_color(COLOR_BG_2);
+ fl_color(G_COLOR_LIGHT_1);
int delta = clock::getBeats() / clock::getBars();
for (int i=1; i<clock::getBars(); i++)
fl_line(x()+cursorW*(i*delta), y()+1, x()+cursorW*(i*delta), y()+h()-2);
/* unused grey area */
- fl_rectf(x()+greyX+1, y()+1, w()-greyX-1, h()-2, COLOR_BG_1);
+ fl_rectf(x()+greyX+1, y()+1, w()-greyX-1, h()-2, G_COLOR_GREY_4);
}
/* draw key */
- fl_color(COLOR_TEXT_0);
+ fl_color(G_COLOR_LIGHT_2);
fl_font(FL_HELVETICA, 11);
fl_draw(key.c_str(), x(), y(), 18, h(), FL_ALIGN_CENTER);
}
void geChannelButton::setInputRecordMode()
{
- bgColor0 = COLOR_BG_3;
+ bgColor0 = G_COLOR_RED;
}
void geChannelButton::setActionRecordMode()
{
- bgColor0 = COLOR_BG_4;
- txtColor = COLOR_TEXT_0;
+ bgColor0 = G_COLOR_BLUE;
+ txtColor = G_COLOR_LIGHT_2;
}
void geChannelButton::setDefaultMode(const char *l)
{
- bgColor0 = COLOR_BG_0;
- bdColor = COLOR_BD_0;
- txtColor = COLOR_TEXT_0;
+ bgColor0 = G_COLOR_GREY_2;
+ bdColor = G_COLOR_GREY_4;
+ txtColor = G_COLOR_LIGHT_2;
if (l)
label(l);
}
void geChannelButton::setPlayMode()
{
- bgColor0 = COLOR_BG_2;
- bdColor = COLOR_BD_1;
- txtColor = COLOR_TEXT_1;
+ bgColor0 = G_COLOR_LIGHT_1;
+ bdColor = G_COLOR_LIGHT_1;
+ txtColor = G_COLOR_GREY_1;
}
void geChannelButton::setEndingMode()
{
- bgColor0 = COLOR_BD_0;
+ bgColor0 = G_COLOR_GREY_4;
}
: Fl_Menu_Button(x, y, w, h, L), ch(ch)
{
box(G_CUSTOM_BORDER_BOX);
- textsize(GUI_FONT_SIZE_BASE);
- textcolor(COLOR_TEXT_0);
- color(COLOR_BG_0);
+ textsize(G_GUI_FONT_SIZE_BASE);
+ textcolor(G_COLOR_LIGHT_2);
+ color(G_COLOR_GREY_2);
add("Loop . basic", 0, cb_changeMode, (void *)LOOP_BASIC);
add("Loop . once", 0, cb_changeMode, (void *)LOOP_ONCE);
void geChannelMode::draw() {
- fl_rect(x(), y(), w(), h(), COLOR_BD_0); // border
+ fl_rect(x(), y(), w(), h(), G_COLOR_GREY_4); // border
switch (ch->mode) {
case LOOP_BASIC:
fl_draw_pixmap(loopBasic_xpm, x()+1, y()+1);
void geChannelStatus::draw()
{
- fl_rect(x(), y(), w(), h(), COLOR_BD_0); // reset border
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_0); // reset background
+ fl_rect(x(), y(), w(), h(), G_COLOR_GREY_4); // reset border
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_GREY_2); // reset background
if (ch != nullptr) {
if (ch->status & (STATUS_WAIT | STATUS_ENDING | REC_ENDING | REC_WAITING) ||
ch->recStatus & (REC_WAITING | REC_ENDING))
{
- fl_rect(x(), y(), w(), h(), COLOR_BD_1);
+ fl_rect(x(), y(), w(), h(), G_COLOR_LIGHT_1);
}
else
if (ch->status == STATUS_PLAY)
- fl_rect(x(), y(), w(), h(), COLOR_BD_1);
+ fl_rect(x(), y(), w(), h(), G_COLOR_LIGHT_1);
else
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_0); // status empty
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_GREY_2); // status empty
if (mixer::recording && ch->armed)
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_3); // take in progress
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_RED); // take in progress
else
if (recorder::active && recorder::canRec(ch, clock::isRunning(), mixer::recording))
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_4); // action record
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_BLUE); // action record
/* equation for the progress bar:
* ((chanTracker - chanStart) * w()) / (chanEnd - chanStart). */
pos = 0;
else
pos = (pos * (w()-1)) / (ch->end - ch->begin);
- fl_rectf(x()+1, y()+1, pos, h()-2, COLOR_BG_2);
+ fl_rectf(x()+1, y()+1, pos, h()-2, G_COLOR_LIGHT_1);
}
}
Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
b->box(G_CUSTOM_BORDER_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
+ b->textsize(G_GUI_FONT_SIZE_BASE);
+ b->textcolor(G_COLOR_LIGHT_2);
+ b->color(G_COLOR_GREY_2);
const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
if (!m) return 0;
spacePressed (false),
addColumnBtn (nullptr)
{
- color(COLOR_BG_MAIN);
+ color(G_COLOR_GREY_1);
type(Fl_Scroll::BOTH_ALWAYS);
- scrollbar.color(COLOR_BG_0);
- scrollbar.selection_color(COLOR_BG_1);
- scrollbar.labelcolor(COLOR_BD_1);
+ scrollbar.color(G_COLOR_GREY_2);
+ scrollbar.selection_color(G_COLOR_GREY_4);
+ scrollbar.labelcolor(G_COLOR_LIGHT_1);
scrollbar.slider(G_CUSTOM_BORDER_BOX);
- hscrollbar.color(COLOR_BG_0);
- hscrollbar.selection_color(COLOR_BG_1);
- hscrollbar.labelcolor(COLOR_BD_1);
+ hscrollbar.color(G_COLOR_GREY_2);
+ hscrollbar.selection_color(G_COLOR_GREY_4);
+ hscrollbar.labelcolor(G_COLOR_LIGHT_1);
hscrollbar.slider(G_CUSTOM_BORDER_BOX);
addColumnBtn = new geButton(8, y(), 200, 20, "Add new column");
Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
b->box(G_CUSTOM_BORDER_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
+ b->textsize(G_GUI_FONT_SIZE_BASE);
+ b->textcolor(G_COLOR_LIGHT_2);
+ b->color(G_COLOR_GREY_2);
const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
if (m)
geSampleChannel *gch = static_cast<geSampleChannel*>(w);
Menu selectedItem = (Menu) (intptr_t) v;
- switch (selectedItem)
- {
+ switch (selectedItem) {
case Menu::INPUT_MONITOR: {
glue_toggleInputMonitor(gch->ch);
break;
Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
b->box(G_CUSTOM_BORDER_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
+ b->textsize(G_GUI_FONT_SIZE_BASE);
+ b->textcolor(G_COLOR_LIGHT_2);
+ b->color(G_COLOR_GREY_2);
const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
if (m)
Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
b->box(G_CUSTOM_BORDER_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
+ b->textsize(G_GUI_FONT_SIZE_BASE);
+ b->textcolor(G_COLOR_LIGHT_2);
+ b->color(G_COLOR_GREY_2);
const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
if (!m) return;
Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
b->box(G_CUSTOM_BORDER_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
+ b->textsize(G_GUI_FONT_SIZE_BASE);
+ b->textcolor(G_COLOR_LIGHT_2);
+ b->color(G_COLOR_GREY_2);
const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
if (!m) return;
: Fl_Browser(x, y, w, h)
{
box(G_CUSTOM_BORDER_BOX);
- textsize(GUI_FONT_SIZE_BASE);
- textcolor(COLOR_TEXT_0);
- selection_color(COLOR_BG_1);
- color(COLOR_BG_0);
-
- this->scrollbar.color(COLOR_BG_0);
- this->scrollbar.selection_color(COLOR_BG_1);
- this->scrollbar.labelcolor(COLOR_BD_1);
+ textsize(G_GUI_FONT_SIZE_BASE);
+ textcolor(G_COLOR_LIGHT_2);
+ selection_color(G_COLOR_GREY_4);
+ color(G_COLOR_GREY_2);
+
+ this->scrollbar.color(G_COLOR_GREY_2);
+ this->scrollbar.selection_color(G_COLOR_GREY_4);
+ this->scrollbar.labelcolor(G_COLOR_LIGHT_1);
this->scrollbar.slider(G_CUSTOM_BORDER_BOX);
- this->hscrollbar.color(COLOR_BG_0);
- this->hscrollbar.selection_color(COLOR_BG_1);
- this->hscrollbar.labelcolor(COLOR_BD_1);
+ this->hscrollbar.color(G_COLOR_GREY_2);
+ this->hscrollbar.selection_color(G_COLOR_GREY_4);
+ this->hscrollbar.labelcolor(G_COLOR_LIGHT_1);
this->hscrollbar.slider(G_CUSTOM_BORDER_BOX);
type(FL_HOLD_BROWSER);
#include "../../../core/sampleChannel.h"
#include "../../../core/wave.h"
#include "../../../glue/channel.h"
+#include "../../../glue/sampleEditor.h"
#include "../../../utils/gui.h"
#include "../../../utils/string.h"
#include "../../dialogs/sampleEditor.h"
#include "rangeTool.h"
+using namespace giada::c;
+
+
geRangeTool::geRangeTool(int x, int y, SampleChannel *ch)
: Fl_Group(x, y, 300, 20),
ch (ch)
void geRangeTool::__cb_setChanPos()
{
- glue_setBeginEndChannel(ch, atoi(begin_->value())*2, atoi(end_->value())*2);
+ sampleEditor::setBeginEndChannel(ch, atoi(begin_->value())*2, atoi(end_->value())*2);
static_cast<gdSampleEditor*>(parent()->parent())->waveTools->updateWaveform();
}
void geRangeTool::__cb_resetStartEnd()
{
- glue_setBeginEndChannel(ch, 0, ch->wave->size);
+ sampleEditor::setBeginEndChannel(ch, 0, ch->wave->size);
static_cast<gdSampleEditor*>(parent()->parent())->waveTools->updateWaveform();
}
*
* Giada - Your Hardcore Loopmachine
*
- * gg_waveTools
- *
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
#include "../../../core/const.h"
+#ifdef G_OS_MAC // our Clang still doesn't know about cstdint (c++11 stuff)
+ #include <stdint.h>
+#else
+ #include <cstdint>
+#endif
+#include <FL/Fl_Menu_Item.H>
+#include <FL/Fl_Menu_Button.H>
+#include "../../../core/sampleChannel.h"
+#include "../../../core/waveFx.h"
+#include "../../../glue/sampleEditor.h"
#include "../basics/boxtypes.h"
#include "waveform.h"
#include "waveTools.h"
+using namespace giada;
+
+
+namespace
+{
+enum class Menu
+{
+ CUT = 0,
+ TRIM,
+ SILENCE,
+ FADE_IN,
+ FADE_OUT,
+ SMOOTH_EDGES,
+ SET_START_END
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void menuCallback(Fl_Widget* w, void* v)
+{
+ geWaveTools* wavetools = static_cast<geWaveTools*>(w);
+ Menu selectedItem = (Menu) (intptr_t) v;
+
+ int a = wavetools->waveform->getSelectionA();
+ int b = wavetools->waveform->getSelectionB();
+
+ switch (selectedItem) {
+ case Menu::CUT:
+ c::sampleEditor::cut(wavetools->ch, a, b);
+ break;
+ case Menu::TRIM:
+ c::sampleEditor::trim(wavetools->ch, a, b);
+ break;
+ case Menu::SILENCE:
+ c::sampleEditor::silence(wavetools->ch, a, b);
+ break;
+ case Menu::FADE_IN:
+ c::sampleEditor::fade(wavetools->ch, a, b, 0);
+ break;
+ case Menu::FADE_OUT:
+ c::sampleEditor::fade(wavetools->ch, a, b, 1);
+ break;
+ case Menu::SMOOTH_EDGES:
+ c::sampleEditor::smoothEdges(wavetools->ch, a, b);
+ break;
+ case Menu::SET_START_END:
+ c::sampleEditor::setStartEnd(wavetools->ch, a, b);
+ break;
+ }
+}
+}; // {anonymous}
+
+
+/* -------------------------------------------------------------------------- */
+
+
geWaveTools::geWaveTools(int x, int y, int w, int h, SampleChannel *ch, const char *l)
- : Fl_Scroll(x, y, w, h, l)
+ : Fl_Scroll(x, y, w, h, l),
+ ch (ch)
{
type(Fl_Scroll::HORIZONTAL_ALWAYS);
- hscrollbar.color(COLOR_BG_0);
- hscrollbar.selection_color(COLOR_BG_1);
- hscrollbar.labelcolor(COLOR_BD_1);
+ hscrollbar.color(G_COLOR_GREY_2);
+ hscrollbar.selection_color(G_COLOR_GREY_4);
+ hscrollbar.labelcolor(G_COLOR_LIGHT_1);
hscrollbar.slider(G_CUSTOM_BORDER_BOX);
waveform = new geWaveform(x, y, w, h-24, ch);
-
-
- //resizable(waveform);
}
void geWaveTools::updateWaveform()
{
- waveform->alloc(w());
- waveform->redraw();
+ waveform->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geWaveTools::redrawWaveformAsync()
+{
+ if (ch->status & (STATUS_PLAY | STATUS_ENDING))
+ waveform->redraw();
}
}
-/* ------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
int geWaveTools::handle(int e)
ret = 1;
break;
}
+ case FL_PUSH: {
+ if (Fl::event_button3()) { // right button
+ openMenu();
+ ret = 1;
+ }
+ break;
+ }
}
return ret;
}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geWaveTools::openMenu()
+{
+ if (!waveform->isSelected())
+ return;
+
+ Fl_Menu_Item menu[] = {
+ {"Cut", 0, menuCallback, (void*) Menu::CUT},
+ {"Trim", 0, menuCallback, (void*) Menu::TRIM},
+ {"Silence", 0, menuCallback, (void*) Menu::SILENCE},
+ {"Fade in", 0, menuCallback, (void*) Menu::FADE_IN},
+ {"Fade out", 0, menuCallback, (void*) Menu::FADE_OUT},
+ {"Smooth edges", 0, menuCallback, (void*) Menu::SMOOTH_EDGES},
+ {"Set start/end here", 0, menuCallback, (void*) Menu::SET_START_END},
+ {0}
+ };
+
+ if (ch->status == STATUS_PLAY) {
+ menu[(int)Menu::CUT].deactivate();
+ menu[(int)Menu::TRIM].deactivate();
+ }
+
+
+ Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
+ b->box(G_CUSTOM_BORDER_BOX);
+ b->textsize(G_GUI_FONT_SIZE_BASE);
+ b->textcolor(G_COLOR_LIGHT_2);
+ b->color(G_COLOR_GREY_2);
+
+ const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+ if (m)
+ m->do_callback(this, m->user_data());
+ return;
+}
-/* ---------------------------------------------------------------------
+/* -----------------------------------------------------------------------------
*
* Giada - Your Hardcore Loopmachine
*
- * gg_waveTools
- *
- * ---------------------------------------------------------------------
+ * -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
*
* along with Giada - Your Hardcore Loopmachine. If not, see
* <http://www.gnu.org/licenses/>.
*
- * ------------------------------------------------------------------ */
+ * -------------------------------------------------------------------------- */
#ifndef GE_WAVE_TOOLS_H
class geWaveTools : public Fl_Scroll
{
+private:
+
+ void openMenu();
+
public:
+ SampleChannel *ch;
geWaveform *waveform;
geWaveTools(int X,int Y,int W, int H, SampleChannel *ch, const char *L=0);
void resize(int x, int y, int w, int h);
int handle(int e);
+ /* updateWaveform
+ Updates the waveform by realloc-ing new data (i.e. when the waveform has
+ changed). */
+
void updateWaveform();
+
+ /* redrawWaveformAsync
+ Redraws the waveform, called by the video thread. This is meant to be called
+ repeatedly when you need to update the play head inside the waveform. The
+ method is smart enough to skip painting if the channel is stopped. */
+
+ void redrawWaveformAsync();
};
#endif
*
* Giada - Your Hardcore Loopmachine
*
- * geWaveform
- * An element which represents a waveform.
- *
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
* -------------------------------------------------------------------------- */
+#include <cassert>
#include <cmath>
#include <FL/fl_draw.H>
#include <FL/Fl_Menu_Button.H>
#include "../../../core/waveFx.h"
#include "../../../core/sampleChannel.h"
#include "../../../glue/channel.h"
+#include "../../../glue/sampleEditor.h"
#include "../basics/boxtypes.h"
#include "waveTools.h"
#include "waveform.h"
using namespace giada::m;
+using namespace giada::c;
-geWaveform::geWaveform(int x, int y, int w, int h, SampleChannel *ch, const char *l)
-: Fl_Widget(x, y, w, h, l),
- chan(ch),
- menuOpen(false),
- chanStart(0),
+geWaveform::geWaveform(int x, int y, int w, int h, SampleChannel* ch, const char* l)
+: Fl_Widget (x, y, w, h, l),
+ selection {},
+ chan (ch),
+ chanStart (0),
chanStartLit(false),
- chanEnd(0),
- chanEndLit(false),
- ratio(0.0f),
- selectionA(0),
- selectionB(0),
- selectionA_abs(0),
- selectionB_abs(0)
+ chanEnd (0),
+ chanEndLit (false),
+ pushed (false),
+ dragged (false),
+ resizedA (false),
+ resizedB (false),
+ ratio (0.0f)
{
data.sup = nullptr;
data.inf = nullptr;
grid.snap = conf::sampleEditorGridOn;
grid.level = conf::sampleEditorGridVal;
- stretchToWindow();
+ alloc(w);
}
void geWaveform::freeData()
{
- if (data.sup != nullptr) {
- free(data.sup);
- free(data.inf);
+ if (data.sup) {
+ delete[] data.sup;
+ delete[] data.inf;
data.sup = nullptr;
data.inf = nullptr;
data.size = 0;
freeData();
data.size = datasize;
- data.sup = (int*) malloc(data.size * sizeof(int));
- data.inf = (int*) malloc(data.size * sizeof(int));
+ data.sup = new (std::nothrow) int[data.size];
+ data.inf = new (std::nothrow) int[data.size];
+
+ if (!data.sup || !data.inf)
+ return 0;
int offset = h() / 2;
int zero = y() + offset; // center, zero amplitude (-inf dB)
void geWaveform::recalcPoints()
{
- selectionA = relativePoint(selectionA_abs);
- selectionB = relativePoint(selectionB_abs);
- chanStart = relativePoint(chan->begin / 2);
-
- /* fix the rounding error when chanEnd is set on the very end of the
- * sample */
-
- if (chan->end == chan->wave->size)
- chanEnd = data.size - 2; // 2 px border
- else
- chanEnd = relativePoint(chan->end / 2);
+ selection.aPixel = relativePoint(selection.aFrame);
+ selection.bPixel = relativePoint(selection.bFrame);
+ chanStart = relativePoint(chan->begin / 2);
+ chanEnd = relativePoint(chan->end / 2);
}
/* -------------------------------------------------------------------------- */
-void geWaveform::draw()
+void geWaveform::drawSelection()
{
- /* blank canvas */
-
- fl_rectf(x(), y(), w(), h(), COLOR_BG_0);
-
- /* draw selection (if any) */
+ if (!isSelected())
+ return;
- if (selectionA != selectionB) {
+ int a_x = selection.aPixel + x(); // - start;
+ int b_x = selection.bPixel + x(); // - start;
- int a_x = selectionA + x() - BORDER; // - start;
- int b_x = selectionB + x() - BORDER; // - start;
+ if (a_x < 0)
+ a_x = 0;
+ if (b_x >= w() + BORDER)
+ b_x = w() + BORDER;
- if (a_x < 0)
- a_x = 0;
- if (b_x >= w()-1)
- b_x = w()-1;
+ if (selection.aPixel < selection.bPixel)
+ fl_rectf(a_x, y(), b_x-a_x, h(), G_COLOR_GREY_4);
+ else
+ fl_rectf(b_x, y(), a_x-b_x, h(), G_COLOR_GREY_4);
+}
- if (selectionA < selectionB)
- fl_rectf(a_x+BORDER, y(), b_x-a_x, h(), COLOR_BD_0);
- else
- fl_rectf(b_x+BORDER, y(), a_x-b_x, h(), COLOR_BD_0);
- }
- /* draw waveform from x1 (offset driven by the scrollbar) to x2
- * (width of parent window). We don't draw the entire waveform,
- * only the visibile part. */
+/* -------------------------------------------------------------------------- */
- int offset = h() / 2;
- int zero = y() + offset; // sample zero (-inf dB)
- int wx1 = abs(x() - ((geWaveTools*)parent())->x());
- int wx2 = wx1 + ((geWaveTools*)parent())->w();
- if (x()+w() < ((geWaveTools*)parent())->w())
- wx2 = x() + w() - BORDER;
+void geWaveform::drawWaveform(int from, int to)
+{
+ int zero = y() + (h() / 2); // zero amplitude (-inf dB)
- fl_color(0, 0, 0);
- for (int i=wx1; i<wx2; i++) {
+ fl_color(G_COLOR_BLACK);
+ for (int i=from; i<to; i++) {
fl_line(i+x(), zero, i+x(), data.sup[i]);
fl_line(i+x(), zero, i+x(), data.inf[i]);
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
- /* print grid */
+void geWaveform::drawGrid(int from, int to)
+{
+ fl_color(G_COLOR_GREY_3);
+ fl_line_style(FL_DASH, 1, nullptr);
+ for (int i=from; i<to; i++) {
for (unsigned k=0; k<grid.points.size(); k++) {
- if (grid.points.at(k) == i) {
- //gu_log("draw grid line at %d\n", i);
- fl_color(fl_rgb_color(54, 54, 54));
- fl_line_style(FL_DASH, 0, nullptr);
- fl_line(i+x(), y(), i+x(), y()+h());
- fl_color(0, 0, 0);
- fl_line_style(FL_SOLID, 0, nullptr);
- break;
- }
+ if (grid.points.at(k) != i)
+ continue;
+ fl_line(i+x(), y(), i+x(), y()+h());
+ break;
}
}
+ fl_line_style(FL_SOLID, 0, nullptr);
+}
+
- /* border box */
+/* -------------------------------------------------------------------------- */
- fl_rect(x(), y(), w(), h(), COLOR_BD_0);
+void geWaveform::drawStartEndPoints()
+{
/* print chanStart */
- int lineX = x()+chanStart+1;
+ int lineX = chanStart + x();
- if (chanStartLit) fl_color(COLOR_BD_1);
- else fl_color(COLOR_BD_0);
+ if (chanStartLit) fl_color(G_COLOR_LIGHT_2);
+ else fl_color(G_COLOR_LIGHT_1);
/* vertical line */
/* print chanEnd */
- lineX = x()+chanEnd;
- if (chanEndLit) fl_color(COLOR_BD_1);
- else fl_color(COLOR_BD_0);
+ lineX = chanEnd + x() - 1;
+ if (chanEndLit) fl_color(G_COLOR_LIGHT_2);
+ else fl_color(G_COLOR_LIGHT_1);
+
+ /* vertical line */
fl_line(lineX, y()+1, lineX, y()+h()-2);
/* -------------------------------------------------------------------------- */
+void geWaveform::drawPlayHead()
+{
+ if (chan->status == STATUS_OFF)
+ return;
+ int p = ceilf(chan->tracker / ratio) + x();
+ fl_color(G_COLOR_LIGHT_2);
+ fl_line(p, y() + 1, p, y() + h() - 2);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geWaveform::draw()
+{
+ assert(data.sup != nullptr);
+ assert(data.inf != nullptr);
+
+ fl_rectf(x(), y(), w(), h(), G_COLOR_GREY_2); // blank canvas
+
+ /* Draw things from 'from' (offset driven by the scrollbar) to 'to' (width of
+ parent window). We don't draw the entire waveform, only the visibile part. */
+
+ int from = abs(x() - parent()->x());
+ int to = from + parent()->w();
+ if (x() + w() < parent()->w())
+ to = x() + w() - BORDER;
+
+ drawSelection();
+ drawWaveform(from, to);
+ drawGrid(from, to);
+ drawPlayHead();
+
+ fl_rect(x(), y(), w(), h(), G_COLOR_GREY_4); // border box
+
+ drawStartEndPoints();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
int geWaveform::handle(int e)
{
int ret = 0;
pushed = true;
if (!mouseOnEnd() && !mouseOnStart()) {
-
- /* right button? show the menu. Don't set selectionA,B,etc */
-
- if (Fl::event_button3()) {
- openEditMenu();
+ if (Fl::event_button3()) { // let the parent (waveTools) handle this
+ ret = 0;
+ break;
}
+ if (mouseOnSelectionA())
+ resizedA = true;
else
- if (mouseOnSelectionA() || mouseOnSelectionB()) {
- resized = true;
- }
+ if(mouseOnSelectionB())
+ resizedB = true;
else {
dragged = true;
- selectionA = Fl::event_x() - x();
-
- if (selectionA >= data.size) selectionA = data.size;
-
- selectionB = selectionA;
- selectionA_abs = absolutePoint(selectionA);
- selectionB_abs = selectionA_abs;
+ selection.aPixel = Fl::event_x() - x();
+ selection.bPixel = selection.aPixel;
}
}
-
ret = 1;
break;
}
case FL_RELEASE: {
- int realChanStart = chan->begin;
- int realChanEnd = chan->end;
+ /* If selection has been done (dragged or resized), make sure that point A
+ is always lower than B. */
- if (chanStartLit)
- realChanStart = absolutePoint(chanStart)*2;
- else
- if (chanEndLit)
- realChanEnd = absolutePoint(chanEnd)*2;
+ if (dragged || resizedA || resizedB)
+ fixSelection();
+
+ /* Handle begin/end markers interaction. */
- glue_setBeginEndChannel(chan, realChanStart, realChanEnd);
+ if (chanStartLit || chanEndLit) {
+ int realChanStart = chan->begin;
+ int realChanEnd = chan->end;
+ if (chanStartLit)
+ realChanStart = absolutePoint(chanStart) * 2;
+ else
+ if (chanEndLit)
+ realChanEnd = absolutePoint(chanEnd) * 2;
+ sampleEditor::setBeginEndChannel(chan, realChanStart, realChanEnd);
+ }
- pushed = false;
- dragged = false;
+ pushed = false;
+ dragged = false;
+ resizedA = false;
+ resizedB = false;
redraw();
ret = 1;
redraw();
}
- if (mouseOnSelectionA())
+ if (mouseOnSelectionA() && isSelected())
fl_cursor(FL_CURSOR_WE, FL_WHITE, FL_BLACK);
else
- if (mouseOnSelectionB())
+ if (mouseOnSelectionB() && isSelected())
fl_cursor(FL_CURSOR_WE, FL_WHITE, FL_BLACK);
else
fl_cursor(FL_CURSOR_DEFAULT, FL_WHITE, FL_BLACK);
chanStart = 0;
else
if (chanStart >= chanEnd)
- chanStart = chanEnd-2;
+ chanStart = chanEnd - 2;
redraw();
}
if (grid.snap)
chanEnd = applySnap(chanEnd);
- if (chanEnd >= data.size - 2)
- chanEnd = data.size - 2;
+ if (chanEnd > data.size)
+ chanEnd = data.size;
else
if (chanEnd <= chanStart)
chanEnd = chanStart + 2;
redraw();
}
- /* here the mouse is on the waveform, i.e. a selection */
+ /* Here the mouse is on the waveform, i.e. a new selection has started. */
else
if (dragged) {
-
- selectionB = Fl::event_x() - x();
-
- if (selectionB >= data.size)
- selectionB = data.size;
-
- if (selectionB <= 0)
- selectionB = 0;
-
+ selection.bPixel = Fl::event_x() - x();
if (grid.snap)
- selectionB = applySnap(selectionB);
-
- selectionB_abs = absolutePoint(selectionB);
+ selection.bPixel = applySnap(selection.bPixel);
redraw();
}
/* here the mouse is on a selection boundary i.e. resize */
else
- if (resized) {
+ if (resizedA || resizedB) {
int pos = Fl::event_x() - x();
- if (mouseOnSelectionA()) {
- selectionA = grid.snap ? applySnap(pos) : pos;
- selectionA_abs = absolutePoint(selectionA);
- }
- else
- if (mouseOnSelectionB()) {
- selectionB = grid.snap ? applySnap(pos) : pos;
- selectionB_abs = absolutePoint(selectionB);
- }
+ if (grid.snap)
+ pos = applySnap(pos);
+ resizedA ? selection.aPixel = pos : selection.bPixel = pos;
redraw();
}
+
mouseX = Fl::event_x();
ret = 1;
break;
/* -------------------------------------------------------------------------- */
-/* pixel snap disances (10px) must be equal to those defined in
- * geWaveform::mouseOnSelectionA() and gWaverfrom::mouseOnSelectionB() */
-/* TODO - use constant for 10px */
int geWaveform::applySnap(int pos)
{
+ /* Pixel snap disances (SNAPPING) must be equal to those defined in
+ mouseOnSelectionA() and mouseOnSelectionB(). */
+
for (unsigned i=0; i<grid.points.size(); i++) {
if (pos >= grid.points.at(i) - SNAPPING &&
pos <= grid.points.at(i) + SNAPPING)
bool geWaveform::mouseOnStart()
{
- return mouseX-10 > chanStart + x() - BORDER &&
- mouseX-10 <= chanStart + x() - BORDER + FLAG_WIDTH &&
+ return mouseX - (FLAG_WIDTH / 2) > chanStart + x() - BORDER &&
+ mouseX - (FLAG_WIDTH / 2) <= chanStart + x() - BORDER + FLAG_WIDTH &&
mouseY > h() + y() - FLAG_HEIGHT;
}
bool geWaveform::mouseOnEnd()
{
- return mouseX-10 >= chanEnd + x() - BORDER - FLAG_WIDTH &&
- mouseX-10 <= chanEnd + x() - BORDER &&
+ return mouseX - (FLAG_WIDTH / 2) >= chanEnd + x() - BORDER - FLAG_WIDTH &&
+ mouseX - (FLAG_WIDTH / 2) <= chanEnd + x() - BORDER &&
mouseY <= y() + FLAG_HEIGHT + 1;
}
bool geWaveform::mouseOnSelectionA()
{
- if (selectionA == selectionB)
- return false;
- return mouseX >= selectionA-10+x() && mouseX <= selectionA+10+x();
+ return mouseX >= selection.aPixel - (FLAG_WIDTH / 2) + x() &&
+ mouseX <= selection.aPixel + (FLAG_WIDTH / 2) + x();
}
bool geWaveform::mouseOnSelectionB()
{
- if (selectionA == selectionB)
- return false;
- return mouseX >= selectionB-10+x() && mouseX <= selectionB+10+x();
+ return mouseX >= selection.bPixel - (FLAG_WIDTH / 2) + x() &&
+ mouseX <= selection.bPixel + (FLAG_WIDTH / 2) + x();
}
/* -------------------------------------------------------------------------- */
-void geWaveform::openEditMenu()
+void geWaveform::fixSelection()
{
- if (selectionA == selectionB)
- return;
-
- menuOpen = true;
-
- Fl_Menu_Item menu[] = {
- {"Cut"},
- {"Trim"},
- {"Silence"},
- {"Fade in"},
- {"Fade out"},
- {"Smooth edges"},
- {"Set start/end here"},
- {0}
- };
-
- if (chan->status == STATUS_PLAY) {
- menu[0].deactivate();
- menu[1].deactivate();
- }
-
- Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_CUSTOM_BORDER_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
+ if (selection.aPixel > selection.bPixel) // inverted selection
+ std::swap(selection.aPixel, selection.bPixel);
+ selection.aFrame = absolutePoint(selection.aPixel);
+ selection.bFrame = absolutePoint(selection.bPixel);
+}
- const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
- if (!m) {
- menuOpen = false;
- return;
- }
- /* straightSel() to ensure that point A is always lower than B */
+/* -------------------------------------------------------------------------- */
- straightSel();
- if (strcmp(m->label(), "Silence") == 0) {
- wfx_silence(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB));
+void geWaveform::clearSel()
+{
+ selection.aPixel = 0;
+ selection.bPixel = 0;
+ selection.aFrame = 0;
+ selection.bFrame = 0;
+}
- selectionA = 0;
- selectionB = 0;
- stretchToWindow();
- redraw();
- menuOpen = false;
- return;
- }
-
- if (strcmp(m->label(), "Set start/end here") == 0) {
+/* -------------------------------------------------------------------------- */
- glue_setBeginEndChannel(chan, absolutePoint(selectionA) * 2,
- absolutePoint(selectionB) * 2); // stereo values
- selectionA = 0;
- selectionB = 0;
- selectionA_abs = 0;
- selectionB_abs = 0;
+void geWaveform::setZoom(int type)
+{
+ int newSize = type == ZOOM_IN ? data.size * 2 : data.size / 2;
- recalcPoints();
- redraw();
- menuOpen = false;
+ if (!alloc(newSize))
return;
- }
-
- if (strcmp(m->label(), "Cut") == 0) {
- wfx_cut(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB));
-
- /* for convenience reset start/end points */
-
- glue_setBeginEndChannel(chan, 0, chan->wave->size);
- selectionA = 0;
- selectionB = 0;
- selectionA_abs = 0;
- selectionB_abs = 0;
+ size(newSize, h());
- setZoom(0);
+ /* zoom to pointer */
- menuOpen = false;
- return;
- }
-
- if (strcmp(m->label(), "Trim") == 0) {
- wfx_trim(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB));
-
- glue_setBeginEndChannel(chan, 0, chan->wave->size);
+ int shift;
+ if (x() > 0)
+ shift = Fl::event_x() - x();
+ else
+ if (type == ZOOM_IN)
+ shift = Fl::event_x() + abs(x());
+ else
+ shift = (Fl::event_x() + abs(x())) / -2;
- selectionA = 0;
- selectionB = 0;
- selectionA_abs = 0;
- selectionB_abs = 0;
+ if (x() - shift > BORDER)
+ shift = 0;
- stretchToWindow();
- menuOpen = false;
- redraw();
- return;
- }
+ position(x() - shift, y());
- if (!strcmp(m->label(), "Fade in") || !strcmp(m->label(), "Fade out")) {
- int type = !strcmp(m->label(), "Fade in") ? 0 : 1;
- wfx_fade(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB), type);
+ /* avoid overflow when zooming out with scrollbar like that:
+ * |----------[scrollbar]|
+ *
+ * offset vs smaller:
+ * |[wave------------| offset > 0 smaller = false
+ * |[wave----] | offset < 0, smaller = true
+ * |-------------] | offset < 0, smaller = false */
- selectionA = 0;
- selectionB = 0;
+ int parentW = parent()->w();
+ int thisW = x() + w() - BORDER; // visible width, not full width
+ if (thisW < parentW)
+ position(x() + parentW - thisW, y());
+ if (smaller())
stretchToWindow();
- redraw();
- menuOpen = false;
- return;
- }
-
- if (!strcmp(m->label(), "Smooth edges")) {
-
- wfx_smooth(chan->wave, absolutePoint(selectionA), absolutePoint(selectionB));
- selectionA = 0;
- selectionB = 0;
-
- stretchToWindow();
- redraw();
- menuOpen = false;
- return;
- }
+ redraw();
}
/* -------------------------------------------------------------------------- */
-void geWaveform::straightSel()
+void geWaveform::stretchToWindow()
{
- if (selectionA > selectionB) {
- unsigned tmp = selectionB;
- selectionB = selectionA;
- selectionA = tmp;
- }
+ int s = parent()->w();
+ alloc(s);
+ position(BORDER, y());
+ size(s, h());
}
/* -------------------------------------------------------------------------- */
-void geWaveform::setZoom(int type)
+void geWaveform::refresh()
{
- int newSize;
- if (type == -1) newSize = data.size*2; // zoom in
- else newSize = data.size/2; // zoom out
-
- if (alloc(newSize)) {
- size(data.size, h());
-
- /* zoom to pointer */
-
- int shift;
- if (x() > 0)
- shift = Fl::event_x() - x();
- else
- if (type == -1)
- shift = Fl::event_x() + abs(x());
- else
- shift = (Fl::event_x() + abs(x())) / -2;
-
- if (x() - shift > BORDER)
- shift = 0;
-
- position(x() - shift, y());
-
+ alloc(data.size);
+ redraw();
+}
- /* avoid overflow when zooming out with scrollbar like that:
- * |----------[scrollbar]|
- *
- * offset vs smaller:
- * |[wave------------| offset > 0 smaller = false
- * |[wave----] | offset < 0, smaller = true
- * |-------------] | offset < 0, smaller = false */
- int parentW = ((geWaveTools*)parent())->w();
- int thisW = x() + w() - BORDER; // visible width, not full width
+/* -------------------------------------------------------------------------- */
- if (thisW < parentW)
- position(x() + parentW - thisW, y());
- if (smaller())
- stretchToWindow();
- redraw();
- }
+bool geWaveform::smaller()
+{
+ return w() < parent()->w();
}
/* -------------------------------------------------------------------------- */
-void geWaveform::stretchToWindow()
+void geWaveform::setGridLevel(int l)
{
- int s = ((geWaveTools*)parent())->w();
- alloc(s);
- position(BORDER, y());
- size(s, h());
+ grid.points.clear();
+ grid.level = l;
+ alloc(data.size);
+ redraw();
}
/* -------------------------------------------------------------------------- */
-bool geWaveform::smaller()
+bool geWaveform::isSelected()
{
- return w() < ((geWaveTools*)parent())->w();
+ return selection.aPixel != selection.bPixel;
}
/* -------------------------------------------------------------------------- */
-float geWaveform::displayRatio()
+int geWaveform::getSelectionA()
{
- return 1.0f / (data.size / (float) w());
-};
-
-/* -------------------------------------------------------------------------- */
+ return selection.aFrame;
+}
-void geWaveform::setGridLevel(int l)
+int geWaveform::getSelectionB()
{
- grid.points.clear();
- grid.level = l;
- alloc(data.size);
- redraw();
+ return selection.bFrame;
}
+
*
* Giada - Your Hardcore Loopmachine
*
- * ge_waveform
- * an element which represents a waveform.
- *
* -----------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
static const int FLAG_WIDTH = 20;
static const int FLAG_HEIGHT = 20;
- static const int BORDER = 8; // window border <-> widget border
+ static const int BORDER = 8; // window border <-> widget border
static const int SNAPPING = 10;
+ /* selection
+ Portion of the selected wave, in pixel and in frames. */
+
+ struct
+ {
+ int aPixel;
+ int bPixel;
+ int aFrame;
+ int bFrame;
+ } selection;
+
/* data
- * real graphic stuff from the underlying waveform */
+ Real graphic stuff from the underlying waveform. */
- struct data
+ struct
{
- int *sup;
- int *inf;
- int size;
+ int* sup; // upper part of the waveform
+ int* inf; // lower "" "" "" ""
+ int size; // width of the waveform to draw (in pixel)
} data;
- /* grid */
-
- struct grid
+ struct
{
bool snap;
int level;
std::vector<int> points;
} grid;
- /* chan
- * chan in use. */
-
- SampleChannel *chan;
-
- /* menuOpen
- * is the menu open? */
-
- bool menuOpen;
+ SampleChannel* chan;
/* mouseOnStart/end
- * is mouse on start or end flag? */
+ Is mouse on start or end flag? */
bool mouseOnStart();
bool mouseOnEnd();
/* mouseOnSelectionA/B
- * as above, for the selection */
+ As above, for the selection. */
bool mouseOnSelectionA();
bool mouseOnSelectionB();
/* absolutePoint
- * from a relative 'p' point (zoom affected) returns the same point
- * zoom 1:1 based */
+ From a relative 'p' point (zoom affected) returns the same point zoom 1:1
+ based. */
int absolutePoint(int p);
/* relativePoint
- * from an absolute 'p' point (1:1 zoom), returns the same point zoom
- * affected */
+ From an absolute 'p' point (1:1 zoom) returns the same point zoom affected. */
int relativePoint(int p);
- /* straightSel
- * helper function which flattens the selection if it was made from
- * right to left (inverse selection) */
+ /* fixSelection
+ Helper function which flattens the selection if it was made from right to left
+ (inverse selection). It also computes the absolute points. Call this one
+ whenever the selection gesture is done. */
- void straightSel();
+ void fixSelection();
/* freeData
- * destroy any graphical buffer */
+ Destroys any graphical buffer. */
void freeData();
/* smaller
- * is the waveform smaller than the parent window? */
+ Is the waveform smaller than the parent window? */
bool smaller();
/* applySnap
- * snap a point at 'pos' pixel */
+ Snap a point at 'pos' pixel. */
int applySnap(int pos);
+ /* draw*
+ Drawing functions. */
+
+ void drawSelection();
+ void drawWaveform(int from, int to);
+ void drawGrid(int from, int to);
+ void drawStartEndPoints();
+ void drawPlayHead();
+
public:
- geWaveform(int x, int y, int w, int h, SampleChannel *ch, const char *l=0);
+ static const int ZOOM_IN = -1;
+ static const int ZOOM_OUT = 0;
+
+ geWaveform(int x, int y, int w, int h, SampleChannel* ch, const char* l=0);
~geWaveform();
- void draw();
- int handle(int e);
+
+ void draw() override;
+ int handle(int e) override;
/* alloc
* allocate memory for the picture */
void recalcPoints();
- /* openEditMenu
- * show edit menu on right-click */
-
- void openEditMenu();
-
- /* displayRatio
- * how much of the waveform is being displayed on screen */
-
- float displayRatio();
-
/* zoom
* type == 1 : zoom out, type == -1: zoom in */
void stretchToWindow();
+ /* refresh
+ Redraws the waveform. */
+
+ void refresh();
+
/* setGridLevel
* set a new frequency level for the grid. 0 means disabled. */
void setSnap(bool v) { grid.snap = v; }
bool getSnap() { return grid.snap; }
- inline int getSize() { return data.size; }
+ int getSize() { return data.size; }
+
+ /* isSelected
+ Tells whether a portion of the waveform has been selected. */
+
+ bool isSelected();
+
+ int getSelectionA();
+ int getSelectionB();
+
+ /* clearSel
+ Removes any active selection. */
+
+ void clearSel();
int chanStart;
bool chanStartLit;
bool chanEndLit;
bool pushed;
bool dragged;
- bool resized;
-
+ bool resizedA;
+ bool resizedB;
float ratio;
-
- /* TODO - useless! use Fl::mouse_x() and Fl::mouse_y() instead */
- int mouseX; // mouse pos for drag.n.drop
- int mouseY;
-
- /* selectionA/B = portion of the selected wave
- * " " "" " _abs = selectionA/B not affected by zoom */
- /** TODO - change selectionA to selectionA_rel
- TODO - change selectionB to selectionB_rel */
- int selectionA;
- int selectionB;
- int selectionA_abs;
- int selectionB_abs;
+ int mouseX;
+ int mouseY;
};
void geSoundMeter::draw()
{
- fl_rect(x(), y(), w(), h(), COLOR_BD_0);
+ fl_rect(x(), y(), w(), h(), G_COLOR_GREY_4);
/* peak = the highest value inside the frame */
dbLevel = 20 * log10(peak);
if (dbLevel < dbLevelOld)
- if (dbLevelOld > -G_DB_MIN_SCALE)
+ if (dbLevelOld > -G_MIN_DB_SCALE)
dbLevel = dbLevelOld - 2.0f;
dbLevelOld = dbLevel;
float px_level = 0.0f;
if (dbLevel < 0.0f)
- px_level = ((w()/G_DB_MIN_SCALE) * dbLevel) + w();
+ px_level = ((w()/G_MIN_DB_SCALE) * dbLevel) + w();
else
px_level = w();
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_0);
- fl_rectf(x()+1, y()+1, (int) px_level, h()-2, clip || !kernelAudio::getStatus() ? COLOR_ALERT : COLOR_BD_0);
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_GREY_2);
+ fl_rectf(x()+1, y()+1, (int) px_level, h()-2, clip || !kernelAudio::getStatus() ? G_COLOR_RED_ALERT : G_COLOR_GREY_4);
}
while (!G_quit) {
gu_refreshUI();
#ifdef _WIN32
- Sleep(GUI_SLEEP);
+ Sleep(G_GUI_SLEEP);
#else
- usleep(GUI_SLEEP);
+ usleep(G_GUI_SLEEP);
#endif
}
pthread_exit(nullptr);
#include <sys/stat.h> // stat (gu_dirExists)
#include <errno.h>
#include <cstdlib>
-#ifdef __APPLE__ // our Clans still doesn't know about cstdint (c++11 stuff)
+#ifdef __APPLE__ // our Clang still doesn't know about cstdint (c++11 stuff)
#include <stdint.h>
#else
#include <cstdint>
#include "../gui/dialogs/gd_mainWindow.h"
#include "../gui/dialogs/gd_actionEditor.h"
#include "../gui/dialogs/window.h"
+#include "../gui/dialogs/sampleEditor.h"
#include "../gui/elems/mainWindow/mainIO.h"
#include "../gui/elems/mainWindow/mainTimer.h"
#include "../gui/elems/mainWindow/mainTransport.h"
#include "../gui/elems/mainWindow/beatMeter.h"
#include "../gui/elems/mainWindow/keyboard/keyboard.h"
#include "../gui/elems/mainWindow/keyboard/channel.h"
+#include "../gui/elems/sampleEditor/waveTools.h"
#include "log.h"
#include "string.h"
#include "gui.h"
if (blinker > 12)
blinker = 0;
+ /* If Sample Editor is open, repaint it (for dynamic play head). */
+
+ gdSampleEditor* se = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
+ if (se)
+ se->waveTools->redrawWaveformAsync();
+
/* redraw GUI */
Fl::unlock();