+++ /dev/null
-sudo: required
-
-dist: trusty
-
-language: cpp
-
-compiler: gcc
-
-notifications:
- email:
- recipients:
- - giadaloopmachine@gmail.com
- on_success: never
- on_failure: always
-
-before_install:
- - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y # for gcc 6
- - sudo apt-get update -qq
- - sudo apt-get install -y gcc-6 g++-6 libsndfile1-dev libsamplerate0-dev libfltk1.3-dev libasound2-dev libxpm-dev libpulse-dev libjack-dev libxrandr-dev libx11-dev libxinerama-dev libxcursor-dev
-
-before_script:
- - sudo ln -f -s /usr/bin/g++-6 /usr/bin/g++
-
- # Download and build latest version of RtMidi
-
- - wget http://www.music.mcgill.ca/~gary/rtmidi/release/rtmidi-2.1.0.tar.gz
- - tar -xvf rtmidi-2.1.0.tar.gz
- - cd rtmidi-2.1.0 && ./configure --with-jack --with-alsa && make && sudo make install || true
- - cd ..
-
- # Download and install latest version of Jansson
-
- - wget http://www.digip.org/jansson/releases/jansson-2.7.tar.gz
- - tar -xvf jansson-2.7.tar.gz
- - cd jansson-2.7 && ./configure && make && sudo make install || true
- - sudo ldconfig
- - cd ..
-
- # Download midimaps package for testing purposes
-
- - wget https://github.com/monocasual/giada-midimaps/archive/master.zip -O giada-midimaps-master.zip
- - unzip giada-midimaps-master.zip
- - mkdir -p $HOME/.giada/midimaps
- - cp giada-midimaps-master/midimaps/* $HOME/.giada/midimaps
-
- # Download vst plugin for testing purposes
-
- - wget http://www.discodsp.com/download/?id=18 -O bliss-linux.zip
- - unzip bliss-linux.zip -d bliss-linux
- - cp bliss-linux/64-bit/Bliss64Demo.so .
-
- # Build Giada. Note the CFLAGS: optimization levels are set to O1 in order
- # not to throw up nasty errors from JUCE modules.
-
- - ./autogen.sh
- - ./configure CXXFLAGS='-g -O1' --target=linux --enable-vst
-
-script: make && make check
-
-after_failure: cat $TRAVIS_BUILD_DIR/test-suite.log
--------------------------------------------------------------------------------
+0.13.2 --- 2017 . 01 . 14
+- MIDI learn for plugins parameters
+- Toggle hidden files in File Browser
+- Fix broken compilation when build without VST support
+- Make sure PluginChooser window has a sane size
+- Decouple Recorder from any global variable
+- Better source code organization
+- Make plugin creation more robust
+- More source code reorganization
+- Fix crash on clicking scrollbar arrows (GitHub #53)
+- Fix crash when doubling/dividing length while recording (GitHub #110)
+
+
0.13.1 --- 2016 . 11 . 16
- Input MIDI to MIDI channels/plugins
- Refinements to show/hide 'R' button's dynamics
src/glue/storage.cpp \
src/glue/channel.h \
src/glue/channel.cpp \
+src/glue/plugin.h \
+src/glue/plugin.cpp \
src/gui/dialogs/gd_keyGrabber.h \
src/gui/dialogs/gd_keyGrabber.cpp \
src/gui/dialogs/gd_about.h \
src/gui/dialogs/gd_editor.cpp \
src/gui/dialogs/gd_pluginWindowGUI.h \
src/gui/dialogs/gd_pluginWindowGUI.cpp \
-src/gui/dialogs/gd_midiOutput.h \
-src/gui/dialogs/gd_midiOutput.cpp \
-src/gui/dialogs/gd_midiInput.h \
-src/gui/dialogs/gd_midiInput.cpp \
src/gui/dialogs/gd_actionEditor.h \
src/gui/dialogs/gd_actionEditor.cpp \
src/gui/dialogs/gd_pluginChooser.h \
src/gui/dialogs/gd_pluginChooser.cpp \
-src/gui/elems/ge_column.h \
-src/gui/elems/ge_column.cpp \
-src/gui/elems/sampleChannel.h \
-src/gui/elems/sampleChannel.cpp \
-src/gui/elems/midiChannel.h \
-src/gui/elems/midiChannel.cpp \
-src/gui/elems/ge_midiIoTools.h \
-src/gui/elems/ge_midiIoTools.cpp \
+src/gui/dialogs/midiIO/midiOutputBase.h \
+src/gui/dialogs/midiIO/midiOutputBase.cpp \
+src/gui/dialogs/midiIO/midiOutputSampleCh.h \
+src/gui/dialogs/midiIO/midiOutputSampleCh.cpp \
+src/gui/dialogs/midiIO/midiOutputMidiCh.h \
+src/gui/dialogs/midiIO/midiOutputMidiCh.cpp \
+src/gui/dialogs/midiIO/midiInputBase.h \
+src/gui/dialogs/midiIO/midiInputBase.cpp \
+src/gui/dialogs/midiIO/midiInputChannel.h \
+src/gui/dialogs/midiIO/midiInputChannel.cpp \
+src/gui/dialogs/midiIO/midiInputMaster.h \
+src/gui/dialogs/midiIO/midiInputMaster.cpp \
+src/gui/elems/midiLearner.h \
+src/gui/elems/midiLearner.cpp \
src/gui/elems/ge_mixed.h \
src/gui/elems/ge_mixed.cpp \
src/gui/elems/ge_waveform.h \
src/gui/elems/ge_waveform.cpp \
-src/gui/elems/ge_browser.h \
-src/gui/elems/ge_browser.cpp \
+src/gui/elems/browser.h \
+src/gui/elems/browser.cpp \
src/gui/elems/baseActionEditor.h \
src/gui/elems/baseActionEditor.cpp \
src/gui/elems/envelopeEditor.h \
src/gui/elems/noteEditor.cpp \
src/gui/elems/pianoItem.h \
src/gui/elems/pianoItem.cpp \
-src/gui/elems/channel.h \
-src/gui/elems/channel.cpp \
src/gui/elems/muteEditor.h \
src/gui/elems/muteEditor.cpp \
src/gui/elems/actionEditor.h \
src/gui/elems/actionEditor.cpp \
src/gui/elems/ge_window.h \
src/gui/elems/ge_window.cpp \
-src/gui/elems/ge_status.h \
-src/gui/elems/ge_status.cpp \
-src/gui/elems/ge_keyboard.h \
-src/gui/elems/ge_keyboard.cpp \
src/gui/elems/ge_waveTools.h \
src/gui/elems/ge_waveTools.cpp \
-src/gui/elems/ge_modeBox.h \
-src/gui/elems/ge_modeBox.cpp \
-src/gui/elems/ge_controller.h \
-src/gui/elems/ge_controller.cpp \
-src/gui/elems/channelButton.h \
-src/gui/elems/channelButton.cpp \
src/gui/elems/ge_pluginBrowser.h \
src/gui/elems/ge_pluginBrowser.cpp \
+src/gui/elems/mainWindow/mainIO.h \
+src/gui/elems/mainWindow/mainIO.cpp \
+src/gui/elems/mainWindow/mainMenu.h \
+src/gui/elems/mainWindow/mainMenu.cpp \
+src/gui/elems/mainWindow/mainTimer.h \
+src/gui/elems/mainWindow/mainTimer.cpp \
+src/gui/elems/mainWindow/mainTransport.h \
+src/gui/elems/mainWindow/mainTransport.cpp \
+src/gui/elems/mainWindow/beatMeter.h \
+src/gui/elems/mainWindow/beatMeter.cpp \
+src/gui/elems/mainWindow/keyboard/channelMode.h \
+src/gui/elems/mainWindow/keyboard/channelMode.cpp \
+src/gui/elems/mainWindow/keyboard/channelButton.h \
+src/gui/elems/mainWindow/keyboard/channelButton.cpp \
+src/gui/elems/mainWindow/keyboard/channelStatus.h \
+src/gui/elems/mainWindow/keyboard/channelStatus.cpp \
+src/gui/elems/mainWindow/keyboard/keyboard.h \
+src/gui/elems/mainWindow/keyboard/keyboard.cpp \
+src/gui/elems/mainWindow/keyboard/column.h \
+src/gui/elems/mainWindow/keyboard/column.cpp \
+src/gui/elems/mainWindow/keyboard/sampleChannel.h \
+src/gui/elems/mainWindow/keyboard/sampleChannel.cpp \
+src/gui/elems/mainWindow/keyboard/midiChannel.h \
+src/gui/elems/mainWindow/keyboard/midiChannel.cpp \
+src/gui/elems/mainWindow/keyboard/channel.h \
+src/gui/elems/mainWindow/keyboard/channel.cpp \
+src/gui/elems/basics/scroll.h \
+src/gui/elems/basics/scroll.cpp \
+src/gui/elems/basics/boxtypes.h \
+src/gui/elems/basics/boxtypes.cpp \
src/utils/log.h \
src/utils/log.cpp \
src/utils/gui.h \
if WITH_VST
giada_SOURCES += \
-src/deps/juce/juce_audio_basics/juce_audio_basics.cpp \
-src/deps/juce/juce_audio_processors/juce_audio_processors.cpp \
-src/deps/juce/juce_core/juce_core.cpp \
-src/deps/juce/juce_data_structures/juce_data_structures.cpp \
-src/deps/juce/juce_events/juce_events.cpp \
-src/deps/juce/juce_graphics/juce_graphics.cpp \
-src/deps/juce/juce_gui_basics/juce_gui_basics.cpp \
-src/deps/juce/juce_gui_extra/juce_gui_extra.cpp
+src/deps/juce/modules/juce_audio_basics/juce_audio_basics.cpp \
+src/deps/juce/modules/juce_audio_processors/juce_audio_processors.cpp \
+src/deps/juce/modules/juce_core/juce_core.cpp \
+src/deps/juce/modules/juce_data_structures/juce_data_structures.cpp \
+src/deps/juce/modules/juce_events/juce_events.cpp \
+src/deps/juce/modules/juce_graphics/juce_graphics.cpp \
+src/deps/juce/modules/juce_gui_basics/juce_gui_basics.cpp \
+src/deps/juce/modules/juce_gui_extra/juce_gui_extra.cpp
endif
# Check for environment: WITH_VST, LINUX, WINDOWS and OSX are varibles defined
if WITH_VST
giada_CPPFLAGS += \
- -I./src/deps/juce \
+ -I./src/deps/juce/modules \
-I./src/deps/vst \
-I/usr/include \
-I/usr/include/freetype2 \
if WITH_VST
giada_tests_SOURCES += \
-src/deps/juce/juce_audio_basics/juce_audio_basics.cpp \
-src/deps/juce/juce_audio_processors/juce_audio_processors.cpp \
-src/deps/juce/juce_core/juce_core.cpp \
-src/deps/juce/juce_data_structures/juce_data_structures.cpp \
-src/deps/juce/juce_events/juce_events.cpp \
-src/deps/juce/juce_graphics/juce_graphics.cpp \
-src/deps/juce/juce_gui_basics/juce_gui_basics.cpp \
-src/deps/juce/juce_gui_extra/juce_gui_extra.cpp
+src/deps/juce/modules/juce_audio_basics/juce_audio_basics.cpp \
+src/deps/juce/modules/juce_audio_processors/juce_audio_processors.cpp \
+src/deps/juce/modules/juce_core/juce_core.cpp \
+src/deps/juce/modules/juce_data_structures/juce_data_structures.cpp \
+src/deps/juce/modules/juce_events/juce_events.cpp \
+src/deps/juce/modules/juce_graphics/juce_graphics.cpp \
+src/deps/juce/modules/juce_gui_basics/juce_gui_basics.cpp \
+src/deps/juce/modules/juce_gui_extra/juce_gui_extra.cpp
endif
giada_tests_LDADD = -ljansson -lsndfile -lsamplerate -lfltk -lXext -lX11 -lXft \
if WITH_VST
giada_tests_CPPFLAGS = \
- -I./src/deps/juce \
+ -I./src/deps/juce/modules \
-I./src/deps/vst \
-I/usr/include \
-I/usr/include/freetype2 \
#include "../utils/log.h"
-#include "../gui/elems/channel.h"
+#include "../gui/elems/mainWindow/keyboard/channel.h"
#include "channel.h"
#include "pluginHost.h"
#include "plugin.h"
mute (false),
solo (false),
hasActions (false),
+ readActions (false),
armed (false),
recStatus (REC_STOPPED),
vChan (nullptr),
for (unsigned i=0; i<G_Recorder.global.size(); i++) {
for (unsigned k=0; k<G_Recorder.global.at(i).size(); k++) {
Recorder::action *a = G_Recorder.global.at(i).at(k);
- if (a->chan == src->index)
+ if (a->chan == src->index) {
G_Recorder.rec(index, a->type, a->frame, a->iValue, a->fValue);
+ hasActions = true;
+ }
}
}
}
unsigned numPlugs = pluginHost->countPlugins(PluginHost::CHANNEL, this);
for (unsigned i=0; i<numPlugs; i++) {
Plugin *pPlugin = pluginHost->getPluginByIndex(i, PluginHost::CHANNEL, this);
- if (pPlugin->getStatus()) {
- Patch::plugin_t pp;
- pp.path = pPlugin->getUniqueId();
- pp.bypass = pPlugin->isBypassed();
- for (int k=0; k<pPlugin->getNumParameters(); k++)
- pp.params.push_back(pPlugin->getParameter(k));
- pch.plugins.push_back(pp);
- }
+ Patch::plugin_t pp;
+ pp.path = pPlugin->getUniqueId();
+ pp.bypass = pPlugin->isBypassed();
+ for (int k=0; k<pPlugin->getNumParameters(); k++)
+ pp.params.push_back(pPlugin->getParameter(k));
+ for (unsigned k=0; k<pPlugin->midiInParams.size(); k++)
+ pp.midiInParams.push_back(pPlugin->midiInParams.at(k));
+ pch.plugins.push_back(pp);
}
#endif
for (unsigned k=0; k<pch->actions.size(); k++) {
Patch::action_t *ac = &pch->actions.at(k);
G_Recorder.rec(index, ac->type, ac->frame, ac->iValue, ac->fValue);
+ hasActions = true;
}
#ifdef WITH_VST
Patch::plugin_t *ppl = &pch->plugins.at(k);
Plugin *plugin = pluginHost->addPlugin(ppl->path, PluginHost::CHANNEL,
pluginMutex, this);
- if (plugin != nullptr) {
- plugin->setBypass(ppl->bypass);
- for (unsigned j=0; j<ppl->params.size(); j++)
- plugin->setParameter(j, ppl->params.at(j));
- ret &= 1;
- }
- else
- ret &= 0;
+ if (plugin == nullptr) {
+ ret &= 0;
+ continue;
+ }
+ plugin->setBypass(ppl->bypass);
+ for (unsigned j=0; j<ppl->params.size(); j++)
+ plugin->setParameter(j, ppl->params.at(j));
+ plugin->midiInParams.clear();
+ for (unsigned j=0; j<ppl->midiInParams.size(); j++)
+ plugin->midiInParams.push_back(ppl->midiInParams.at(j));
+ ret &= 1;
}
#endif
#include "recorder.h"
#ifdef WITH_VST
- #include "../deps/juce/config.h"
+ #include "../deps/juce-config.h"
#endif
/* quantize
* start channel according to quantizer. Index = array index of
- * mixer::channels, used by recorder. LocalFrame = frame within buffer.
- * GloalFrame = actual frame from mixer. */
+ * mixer::channels, used by recorder. LocalFrame = frame within the current
+ * buffer. */
- virtual void quantize(int index, int localFrame, int globalFrame) = 0;
+ virtual void quantize(int index, int localFrame, class Mixer *m) = 0;
/* onZero
* action to do when frame goes to zero, i.e. sequencer restart. */
bool mute; // global mute
bool solo;
bool hasActions; // has something recorded
+ bool readActions; // read what's recorded
bool armed; // armed for recording
int recStatus; // status of recordings (waiting, ending, ...)
float *vChan; // virtual channel
sampleEditorW = 640;
sampleEditorH = 480;
+ midiInputX = 0;
+ midiInputY = 0;
+ midiInputW = G_DEFAULT_MIDI_INPUT_UI_W;
+ midiInputH = G_DEFAULT_MIDI_INPUT_UI_H;
+
pianoRollY = -1;
pianoRollH = 422;
if (!setInt(jRoot, CONF_KEY_BEATS_Y, beatsY)) return 0;
if (!setInt(jRoot, CONF_KEY_ABOUT_X, aboutX)) return 0;
if (!setInt(jRoot, CONF_KEY_ABOUT_Y, aboutY)) return 0;
+ if (!setInt(jRoot, CONF_KEY_MIDI_INPUT_X, midiInputX)) return 0;
+ if (!setInt(jRoot, CONF_KEY_MIDI_INPUT_Y, midiInputY)) return 0;
+ if (!setInt(jRoot, CONF_KEY_MIDI_INPUT_W, midiInputW)) return 0;
+ if (!setInt(jRoot, CONF_KEY_MIDI_INPUT_H, midiInputH)) return 0;
#ifdef WITH_VST
json_object_set_new(jRoot, CONF_KEY_BEATS_Y, json_integer(beatsY));
json_object_set_new(jRoot, CONF_KEY_ABOUT_X, json_integer(aboutX));
json_object_set_new(jRoot, CONF_KEY_ABOUT_Y, json_integer(aboutY));
+ json_object_set_new(jRoot, CONF_KEY_MIDI_INPUT_X, json_integer(midiInputX));
+ json_object_set_new(jRoot, CONF_KEY_MIDI_INPUT_Y, json_integer(midiInputY));
+ json_object_set_new(jRoot, CONF_KEY_MIDI_INPUT_W, json_integer(midiInputW));
+ json_object_set_new(jRoot, CONF_KEY_MIDI_INPUT_H, json_integer(midiInputH));
#ifdef WITH_VST
if (sampleEditorH < 292) sampleEditorH = 292;
if (sampleEditorGridVal < 0) sampleEditorGridVal = 0;
if (sampleEditorGridOn < 0) sampleEditorGridOn = 0;
+ if (midiInputX < 0) midiInputX = 0;
+ if (midiInputY < 0) midiInputY = 0;
+ if (midiInputW < G_DEFAULT_MIDI_INPUT_UI_W) midiInputW = G_DEFAULT_MIDI_INPUT_UI_W;
+ if (midiInputH < G_DEFAULT_MIDI_INPUT_UI_H) midiInputH = G_DEFAULT_MIDI_INPUT_UI_H;
if (configX < 0) configX = 0;
if (configY < 0) configY = 0;
if (pluginListX < 0) pluginListX = 0;
if (pluginListY < 0) pluginListY = 0;
- if (bpmX < 0) bpmX = 0;
+#ifdef WITH_VST
+ if (pluginChooserW < 640) pluginChooserW = 640;
+ if (pluginChooserH < 480) pluginChooserW = 480;
+#endif
+ if (bpmX < 0) bpmX = 0;
if (bpmY < 0) bpmY = 0;
if (beatsX < 0) beatsX = 0;
if (beatsY < 0) beatsY = 0;
bool limitOutput;
int rsmpQuality;
- int midiSystem;
- int midiPortOut;
- int midiPortIn;
- bool noNoteOff;
- string midiMapPath;
- string lastFileMap;
- int midiSync; // see const.h
- float midiTCfps;
+ int midiSystem;
+ int midiPortOut;
+ int midiPortIn;
+ bool noNoteOff;
+ string midiMapPath;
+ string lastFileMap;
+ int midiSync; // see const.h
+ float midiTCfps;
uint32_t midiInRewind;
uint32_t midiInStartStop;
string patchPath;
string samplePath;
- int mainWindowX, mainWindowY, mainWindowW, mainWindowH;
+ int mainWindowX, mainWindowY, mainWindowW, mainWindowH;
- int browserX, browserY, browserW, browserH, browserPosition, browserLastValue;
+ int browserX, browserY, browserW, browserH, browserPosition, browserLastValue;
string browserLastPath;
- int actionEditorX, actionEditorY, actionEditorW, actionEditorH, actionEditorZoom;
- int actionEditorGridVal;
- int actionEditorGridOn;
+ int actionEditorX, actionEditorY, actionEditorW, actionEditorH, actionEditorZoom;
+ int actionEditorGridVal;
+ int actionEditorGridOn;
- int sampleEditorX, sampleEditorY, sampleEditorW, sampleEditorH;
- int sampleEditorGridVal;
- int sampleEditorGridOn;
+ int sampleEditorX, sampleEditorY, sampleEditorW, sampleEditorH;
+ int sampleEditorGridVal;
+ int sampleEditorGridOn;
- int pianoRollY, pianoRollH;
- int pluginListX, pluginListY;
- int configX, configY;
- int bpmX, bpmY;
- int beatsX, beatsY;
- int aboutX, aboutY;
+ int midiInputX, midiInputY, midiInputW, midiInputH;
+
+ int pianoRollY, pianoRollH;
+ int pluginListX, pluginListY;
+ int configX, configY;
+ int bpmX, bpmY;
+ int beatsX, beatsY;
+ int aboutX, aboutY;
#ifdef WITH_VST
/* -- version --------------------------------------------------------------- */
-#define G_VERSION_STR "0.13.1"
+#define G_VERSION_STR "0.13.2"
#define G_APP_NAME "Giada"
#define G_VERSION_MAJOR 0
#define G_VERSION_MINOR 13
-#define G_VERSION_PATCH 1
+#define G_VERSION_PATCH 2
#define CONF_FILENAME "giada.conf"
#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
+#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)
+#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
+#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 DEFAULT_BUFSIZE 1024
#define DEFAULT_DELAYCOMP 0
#define DEFAULT_VOL 1.0f
+#define G_DEFAULT_PITCH 1.0f
#define DEFAULT_BOOST 0.0f
-#define gDEFAULT_PITCH 1.0f // ugly and temporary fix to avoid conflicts with wingdi.h (Windows only).
#define DEFAULT_OUT_VOL 1.0f
#define DEFAULT_IN_VOL 1.0f
#define DEFAULT_CHANMODE SINGLE_BASIC
#define DEFAULT_FADEOUT_STEP 0.01f // micro-fadeout speed
#define DEFAULT_COLUMN_WIDTH 380
#define G_DEFAULT_PATCH_NAME "(default patch)"
+#define G_DEFAULT_MIDI_INPUT_UI_W 300
+#define G_DEFAULT_MIDI_INPUT_UI_H 350
-/* -- browser types --------------------------------------------------------- */
-/* TODO - USELESS, remove them */
-#define BROWSER_LOAD_PATCH 0x00
-#define BROWSER_LOAD_SAMPLE 0x01
-#define BROWSER_SAVE_PATCH 0x02
-#define BROWSER_SAVE_SAMPLE 0x04
-#define BROWSER_SAVE_PROJECT 0x08
-#define BROWSER_LOAD_PLUGIN 0x10
-
-
-
/* -- channel types --------------------------------------------------------- */
#define CHANNEL_SAMPLE 0x01
#define CHANNEL_MIDI 0x02
#define PATCH_KEY_PLUGIN_PATH "path"
#define PATCH_KEY_PLUGIN_BYPASS "bypass"
#define PATCH_KEY_PLUGIN_PARAMS "params"
+#define PATCH_KEY_PLUGIN_MIDI_IN_PARAMS "midi_in_params"
#define PATCH_KEY_COLUMN_INDEX "index"
#define PATCH_KEY_COLUMN_WIDTH "width"
#define PATCH_KEY_COLUMN_CHANNELS "channels"
#define CONF_KEY_PLUGIN_CHOOSER_Y "plugin_chooser_y"
#define CONF_KEY_PLUGIN_CHOOSER_W "plugin_chooser_w"
#define CONF_KEY_PLUGIN_CHOOSER_H "plugin_chooser_h"
+#define CONF_KEY_MIDI_INPUT_X "midi_input_x"
+#define CONF_KEY_MIDI_INPUT_Y "midi_input_y"
+#define CONF_KEY_MIDI_INPUT_W "midi_input_w"
+#define CONF_KEY_MIDI_INPUT_H "midi_input_h"
#define CONF_KEY_PLUGIN_SORT_METHOD "plugin_sort_method"
/* JSON midimaps keys */
#include "mixer.h"
#include "wave.h"
#include "const.h"
+#include "channel.h"
#include "mixerHandler.h"
#include "patch_DEPR_.h"
#include "patch.h"
}
G_Recorder.clearAll();
+ for (unsigned i=0; i<G_Mixer.channels.size(); i++) {
+ G_Mixer.channels.at(i)->hasActions = false;
+ G_Mixer.channels.at(i)->readActions = false;
+ //if (G_Mixer.channels.at(i)->type == CHANNEL_SAMPLE)
+ // ((SampleChannel*)G_Mixer.channels.at(i))->readActions = false;
+ }
gu_log("[init] Recorder cleaned up\n");
#ifdef WITH_VST
#include "midiChannel.h"
#include "conf.h"
#include "midiMapConf.h"
-#include "pluginHost.h"
+#ifdef WITH_VST
+ #include "pluginHost.h"
+ #include "plugin.h"
+#endif
#include "kernelMidi.h"
extern Mixer G_Mixer;
extern KernelMidi G_KernelMidi;
extern MidiMapConf G_MidiMap;
+#ifdef WITH_VST
extern PluginHost G_PluginHost;
-
+#endif
using std::string;
using std::vector;
glue_startStopReadingRecs((SampleChannel*)ch, false);
}
- /* redirect full midi message to plugins */
+#ifdef WITH_VST
+
+ /* Process plugins' parameters */
+
+ processPlugins(ch, pure, value);
+
+#endif
+
+ /* Redirect full midi message (pure + value) to plugins */
ch->receiveMidi(pure | value);
}
/* -------------------------------------------------------------------------- */
+#ifdef WITH_VST
+
+void KernelMidi::processPlugins(Channel *ch, uint32_t pure, uint32_t value)
+{
+ /* Plugins' parameters layout reflect the structure of the matrix
+ Channel::midiInPlugins. It is safe to assume then that i and k indexes match
+ both the structure of Channel::midiInPlugins and vector <Plugin *> *plugins. */
+
+ vector <Plugin *> *plugins = G_PluginHost.getStack(PluginHost::CHANNEL, ch);
+
+ for (unsigned i=0; i<plugins->size(); i++)
+ {
+ Plugin *plugin = plugins->at(i);
+ for (unsigned k=0; k<plugin->midiInParams.size(); k++) {
+ uint32_t midiInParam = plugin->midiInParams.at(k);
+ if (pure != midiInParam)
+ continue;
+ float vf = (value >> 8)/127.0f;
+ plugin->setParameter(k, vf);
+ gu_log(" >>> [plugin %d parameter %d] ch=%d (pure=0x%X, value=%d, float=%f)\n",
+ i, k, ch->index, pure, value >> 8, vf);
+ }
+ }
+}
+
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
string KernelMidi::getRtMidiVersion()
{
return midiOut->getVersion();
private:
- int api;
+ int api;
class RtMidiOut *midiOut;
class RtMidiIn *midiIn;
void processMaster(uint32_t pure, uint32_t value);
void processChannels(uint32_t pure, uint32_t value);
+#ifdef WITH_VST
+ void processPlugins(class Channel *ch, uint32_t pure, uint32_t value);
+#endif
};
#endif
#include "../utils/log.h"
#include "midiChannel.h"
#include "channel.h"
-#include "pluginHost.h"
#include "patch_DEPR_.h"
#include "patch.h"
#include "conf.h"
#include "mixer.h"
+#ifdef WITH_VST
+ #include "pluginHost.h"
+#endif
#include "kernelMidi.h"
extern Recorder G_Recorder;
extern KernelMidi G_KernelMidi;
-extern PluginHost G_PluginHost;
extern Mixer G_Mixer;
-
+#ifdef WITH_VST
+extern PluginHost G_PluginHost;
+#endif
MidiChannel::MidiChannel(int bufferSize, MidiMapConf *midiMapConf)
: Channel (CHANNEL_MIDI, STATUS_OFF, bufferSize, midiMapConf),
/* -------------------------------------------------------------------------- */
-void MidiChannel::quantize(int index, int localFrame, int globalFrame) {}
+void MidiChannel::quantize(int index, int localFrame, Mixer *m) {}
/* -------------------------------------------------------------------------- */
{
if (!armed)
return;
+
+#ifdef WITH_VST
+
while (true) {
if (pthread_mutex_trylock(&G_PluginHost.mutex_midi) != 0)
continue;
gu_log("[Channel::processMidi] msg=%X\n", msg);
-#ifdef WITH_VST
addVstMidiEvent(msg, 0);
-#endif
pthread_mutex_unlock(&G_PluginHost.mutex_midi);
break;
}
- if (G_Recorder.canRec(this))
- G_Recorder.rec(index, ACTION_MIDI, G_Mixer.actualFrame, msg);
+#endif
+
+ if (G_Recorder.canRec(this, &G_Mixer)) {
+ G_Recorder.rec(index, ACTION_MIDI, G_Mixer.currentFrame, msg);
+ hasActions = true;
+ }
}
#ifdef WITH_VST
- #include "../deps/juce/config.h"
+ #include "../deps/juce-config.h"
#endif
#include "channel.h"
int readPatch(const string &basePath, int i, class Patch *patch,
pthread_mutex_t *pluginMutex, int samplerate, int rsmpQuality) override;
int writePatch(int i, bool isProject, class Patch *patch) override;
- void quantize(int index, int localFrame, int globalFrame) override;
+ void quantize(int index, int localFrame, class Mixer *m) override;
void onZero(int frame, bool recsStopOnChanHalt) override;
void onBar(int frame) override;
void parseAction(Recorder::action *a, int localFrame, int globalFrame,
void sendMidi(Recorder::action *a, int localFrame);
void sendMidi(uint32_t data);
-
#ifdef WITH_VST
/* addVstMidiEvent
recording = false;
ready = true;
waitRec = 0;
- actualFrame = 0;
+ currentFrame = 0;
bpm = DEFAULT_BPM;
bars = DEFAULT_BARS;
beats = DEFAULT_BEATS;
void Mixer::sendMIDIsync()
{
if (G_Conf.midiSync == MIDI_SYNC_CLOCK_M) {
- if (actualFrame % (framesPerBeat/24) == 0)
+ if (currentFrame % (framesPerBeat/24) == 0)
G_KernelMidi.send(MIDI_CLOCK, -1, -1);
}
else
* 1-4 and 5-8. We check timecode frame's parity: if even, send
* range 1-4, if odd send 5-8. */
- if (actualFrame % midiTCrate == 0) {
+ if (currentFrame % midiTCrate == 0) {
/* frame low nibble
* frame high nibble
testBar(j);
testFirstBeat(j);
readActions(j);
- actualFrame += 2;
+ currentFrame += 2;
testLastBeat(); // this test must be the last one
sendMIDIsync();
}
void Mixer::rewind()
{
- actualFrame = 0;
+ currentFrame = 0;
actualBeat = 0;
if (running)
{
pthread_mutex_lock(&mutex_recs);
for (unsigned i=0; i<G_Recorder.frames.size(); i++) {
- if (G_Recorder.frames.at(i) == actualFrame) {
+ if (G_Recorder.frames.at(i) == currentFrame) {
for (unsigned j=0; j<G_Recorder.global.at(i).size(); j++) {
int index = G_Recorder.global.at(i).at(j)->chan;
Channel *ch = getChannelByIndex(index);
- ch->parseAction(G_Recorder.global.at(i).at(j), frame, actualFrame, quantize, running);
+ ch->parseAction(G_Recorder.global.at(i).at(j), frame, currentFrame, quantize, running);
}
break;
}
{
if (quantize < 0 || quanto <= 0) // if quantizer disabled
return;
- if (actualFrame % (quanto) != 0) // if a quanto has not passed yet
+ if (currentFrame % (quanto) != 0) // if a quanto has not passed yet
return;
if (rewindWait) {
}
pthread_mutex_lock(&mutex_chans);
for (unsigned i=0; i<channels.size(); i++)
- channels.at(i)->quantize(i, frame, actualFrame); // j == localFrame
+ channels.at(i)->quantize(i, frame, this); // j == localFrame
pthread_mutex_unlock(&mutex_chans);
}
void Mixer::testBar(unsigned frame)
{
- if (actualFrame % framesPerBar != 0 || actualFrame == 0)
+ if (currentFrame % framesPerBar != 0 || currentFrame == 0)
return;
if (metronome)
void Mixer::testFirstBeat(unsigned frame)
{
- if (actualFrame != 0)
+ if (currentFrame != 0)
return;
pthread_mutex_lock(&mutex_chans);
for (unsigned k=0; k<channels.size(); k++)
void Mixer::testLastBeat()
{
- /* if actualFrame > totalFrames the sequencer returns to frame 0,
+ /* if currentFrame > totalFrames the sequencer returns to frame 0,
* beat 0. This must be the last operation. */
- if (actualFrame > totalFrames) {
- actualFrame = 0;
+ if (currentFrame > totalFrames) {
+ currentFrame = 0;
actualBeat = 0;
}
else
- if (actualFrame % framesPerBeat == 0 && actualFrame > 0) {
+ if (currentFrame % framesPerBeat == 0 && currentFrame > 0) {
actualBeat++;
/* avoid tick and tock to overlap when a new bar has passed (which
int framesPerBeat; // frames in one beat
int framesInSequencer; // frames in the whole sequencer
int totalFrames; // frames in the selected range (e.g. 4/4)
- int actualFrame;
+ int currentFrame;
int actualBeat;
#define TICKSIZE 38
int ret = 1;
for (unsigned i=0; i<list->size(); i++) {
Patch::plugin_t *ppl = &list->at(i);
+ // TODO use glue_addPlugin()
Plugin *plugin = G_PluginHost.addPlugin(ppl->path.c_str(), type,
&G_Mixer.mutex_plugins, NULL);
if (plugin != NULL) {
if (channelsReady > 0) {
G_Mixer.recording = true;
- /* start to write from the actualFrame, not the beginning */
+ /* start to write from the currentFrame, not the beginning */
/** FIXME: this should be done before wave allocation */
- G_Mixer.inputTracker = G_Mixer.actualFrame;
+ G_Mixer.inputTracker = G_Mixer.currentFrame;
return true;
}
return false;
for (unsigned j=0; j<plugins->size(); j++) {
json_t *jPlugin = json_object();
plugin_t plugin = plugins->at(j);
- json_object_set_new(jPlugin, PATCH_KEY_PLUGIN_PATH, json_string(plugin.path.c_str()));
- json_object_set_new(jPlugin, PATCH_KEY_PLUGIN_BYPASS, json_boolean(plugin.bypass));
+ json_object_set_new(jPlugin, PATCH_KEY_PLUGIN_PATH, json_string(plugin.path.c_str()));
+ json_object_set_new(jPlugin, PATCH_KEY_PLUGIN_BYPASS, json_boolean(plugin.bypass));
json_array_append_new(jPlugins, jPlugin);
/* plugin params */
json_t *jPluginParams = json_array();
- for (unsigned z=0; z<plugin.params.size(); z++) {
+ for (unsigned z=0; z<plugin.params.size(); z++)
json_array_append_new(jPluginParams, json_real(plugin.params.at(z)));
- }
json_object_set_new(jPlugin, PATCH_KEY_PLUGIN_PARAMS, jPluginParams);
+
+ /* midiIn params (midi learning on plugins' parameters) */
+
+ json_t *jPluginMidiInParams = json_array();
+ for (unsigned z=0; z<plugin.midiInParams.size(); z++)
+ json_array_append_new(jPluginMidiInParams, json_integer(plugin.midiInParams.at(z)));
+ json_object_set_new(jPlugin, PATCH_KEY_PLUGIN_MIDI_IN_PARAMS, jPluginMidiInParams);
}
json_object_set_new(jContainer, key, jPlugins);
}
return 0;
plugin_t plugin;
- if (!setString (jPlugin, PATCH_KEY_PLUGIN_PATH, plugin.path)) return 0;
- if (!setBool (jPlugin, PATCH_KEY_PLUGIN_BYPASS, plugin.bypass)) return 0;
+ if (!setString(jPlugin, PATCH_KEY_PLUGIN_PATH, plugin.path)) return 0;
+ if (!setBool (jPlugin, PATCH_KEY_PLUGIN_BYPASS, plugin.bypass)) return 0;
/* read plugin params */
json_array_foreach(jParams, paramIndex, jParam)
plugin.params.push_back(json_real_value(jParam));
+ /* read midiIn params (midi learning on plugins' parameters) */
+
+ json_t *jMidiInParams = json_object_get(jPlugin, PATCH_KEY_PLUGIN_MIDI_IN_PARAMS);
+ if (!checkArray(jMidiInParams, PATCH_KEY_PLUGIN_MIDI_IN_PARAMS)) return 0;
+
+ size_t midiInParamIndex;
+ json_t *jMidiInParam;
+ json_array_foreach(jMidiInParams, midiInParamIndex, jMidiInParam)
+ plugin.midiInParams.push_back(json_integer_value(jMidiInParam));
+
container->push_back(plugin);
}
return 1;
ch->panLeft = ch->panLeft < 0.0f || ch->panLeft > 1.0f ? 1.0f : ch->panLeft;
ch->panRight = ch->panRight < 0.0f || ch->panRight > 1.0f ? 1.0f : ch->panRight;
ch->boost = ch->boost < 1.0f ? DEFAULT_BOOST : ch->boost;
- ch->pitch = ch->pitch < 0.1f || ch->pitch > 4.0f ? gDEFAULT_PITCH : ch->pitch;
+ ch->pitch = ch->pitch < 0.1f || ch->pitch > 4.0f ? G_DEFAULT_PITCH : ch->pitch;
}
}
#ifdef WITH_VST
struct plugin_t
{
- string path;
- bool bypass;
- vector<float> params;
+ string path;
+ bool bypass;
+ vector<float> params;
+ vector<uint32_t> midiInParams;
};
#endif
#include "../utils/log.h"
#include "../utils/fs.h"
#include "../gui/dialogs/gd_mainWindow.h"
-#include "../gui/elems/ge_keyboard.h"
+#include "../gui/elems/mainWindow/keyboard/keyboard.h"
#include "patch_DEPR_.h"
#include "init.h"
#include "recorder.h"
G_Recorder.rec(ch->index, type, frame, iValue_fix, fValue);
else
G_Recorder.rec(ch->index, type, frame, iValue, fValue);
+ ch->hasActions = true;
}
}
}
/* -------------------------------------------------------------------------- */
-void Plugin::init()
+Plugin::Plugin(juce::AudioPluginInstance *plugin, double samplerate,
+ int buffersize)
+ : ui (nullptr),
+ plugin(plugin),
+ id (idGenerator++),
+ bypass(false)
{
- ui = NULL;
- id = idGenerator++;;
- bypass = false;
- status = 1;
+ /* Fill midiInParams. All values are empty (0x0): they will be filled during
+ midi learning process. */
- if (getActiveEditor() != NULL) {
- gu_log("[Plugin::init] plugin has an already active editor!\n");
+ for (int i=0; i<plugin->getNumParameters(); i++)
+ midiInParams.push_back(0x0);
+
+ /* Try to enable editor (i.e. plugin's UI) */
+
+ if (plugin->getActiveEditor() != NULL) {
+ gu_log("[Plugin] plugin has an already active editor!\n");
return;
}
- ui = createEditorIfNeeded();
+ ui = plugin->createEditorIfNeeded();
if (ui == NULL) {
- gu_log("[Plugin::init] unable to create editor, the plugin might be GUI-less!\n");
+ gu_log("[Plugin] unable to create editor, the plugin might be GUI-less!\n");
return;
}
- gu_log("[Plugin::init] editor initialized and ready\n");
+ plugin->prepareToPlay(samplerate, buffersize);
+
+ gu_log("[Plugin] editor initialized and ready\n");
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+Plugin::~Plugin()
+{
+ plugin->suspendProcessing(true);
+ plugin->releaseResources();
}
string Plugin::getUniqueId()
{
- return getPluginDescription().fileOrIdentifier.toStdString();
+ return plugin->getPluginDescription().fileOrIdentifier.toStdString();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int Plugin::getNumParameters()
+{
+ return plugin->getNumParameters();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+float Plugin::getParameter(int paramIndex)
+{
+ return plugin->getParameter(paramIndex);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void Plugin::setParameter(int paramIndex, float value)
+{
+ return plugin->setParameter(paramIndex, value);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void Plugin::prepareToPlay(double samplerate, int buffersize)
+{
+ plugin->prepareToPlay(samplerate, buffersize);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string Plugin::getName()
+{
+ return plugin->getName().toStdString();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+bool Plugin::isSuspended()
+{
+ return plugin->isSuspended();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void Plugin::process(juce::AudioBuffer<float> &b, juce::MidiBuffer &m)
+{
+ plugin->processBlock(b, m);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int Plugin::getNumPrograms()
+{
+ return plugin->getNumPrograms();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int Plugin::getCurrentProgram()
+{
+ return plugin->getCurrentProgram();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void Plugin::setCurrentProgram(int index)
+{
+ plugin->setCurrentProgram(index);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+bool Plugin::hasEditor()
+{
+ return plugin->hasEditor();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string Plugin::getProgramName(int index)
+{
+ return plugin->getProgramName(index).toStdString();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string Plugin::getParameterName(int index)
+{
+ return plugin->getParameterName(index).toStdString();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string Plugin::getParameterText(int index)
+{
+ return plugin->getParameterText(index).toStdString();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string Plugin::getParameterLabel(int index)
+{
+ return plugin->getParameterLabel(index).toStdString();
}
*
* -------------------------------------------------------------------------- */
+
#ifdef WITH_VST
#ifndef __PLUGIN_H__
#define __PLUGIN_H__
-#include "../deps/juce/config.h"
-
+#include "../deps/juce-config.h"
-using std::string;
-
-class Plugin : public juce::AudioPluginInstance
+class Plugin
{
private:
+ static int idGenerator;
+
juce::AudioProcessorEditor *ui; // gui
+ juce::AudioPluginInstance *plugin; // core
- static int idGenerator;
- int id;
- bool bypass;
- bool status;
+ int id;
+ bool bypass;
public:
- void init();
+ Plugin(juce::AudioPluginInstance *p, double samplerate, int buffersize);
+ ~Plugin();
void showEditor(void *parent);
/* getUniqueId
* Return a string-based UID. */
- string getUniqueId();
+ std::string getUniqueId();
+
+ std::string getName();
+
+ bool hasEditor();
+ int getNumParameters();
+ float getParameter(int index);
+ void setParameter(int index, float value);
+ std::string getParameterName(int index);
+ std::string getParameterText(int index);
+ std::string getParameterLabel(int index);
+ void prepareToPlay(double samplerate, int buffersize);
+ bool isSuspended();
+ void process(juce::AudioBuffer<float> &b, juce::MidiBuffer &m);
+ int getNumPrograms();
+ int getCurrentProgram();
+ void setCurrentProgram(int index);
+ std::string getProgramName(int index);
int getId() { return id; }
- bool getStatus() { return status; }
bool isBypassed() { return bypass; }
int getEditorW() { return ui->getWidth(); }
int getEditorH() { return ui->getHeight(); }
void toggleBypass() { bypass = !bypass; }
- void setStatus(int s) { status = s; }
void setBypass(bool b) { bypass = b; }
+
+ /* midiInParams
+ A list of midiIn hex values for parameter automation. */
+
+ std::vector<uint32_t> midiInParams;
};
#endif
return NULL;
}
- Plugin *p = (Plugin *) pluginFormat.createInstanceFromDescription(*pd, samplerate, buffersize);
- if (!p) {
+ juce::AudioPluginInstance *pi = pluginFormat.createInstanceFromDescription(*pd, samplerate, buffersize);
+ if (!pi) {
gu_log("[PluginHost::addPlugin] unable to create instance with fid=%s!\n", fid.c_str());
missingPlugins = true;
return NULL;
}
-
- //p->setStatus(1);
- //p->setId();
- //p->initEditor();
- p->init();
- p->prepareToPlay(samplerate, buffersize);
-
gu_log("[PluginHost::addPlugin] plugin instance with fid=%s created\n", fid.c_str());
+ Plugin *p = new Plugin(pi, samplerate, buffersize);
+
/* Try to inject the plugin as soon as possible. */
- int lockStatus;
while (true) {
- lockStatus = pthread_mutex_trylock(mutex);
- if (lockStatus == 0) {
- pStack->push_back(p);
- pthread_mutex_unlock(mutex);
- break;
- }
+ if (pthread_mutex_trylock(mutex) != 0)
+ continue;
+ pStack->push_back(p);
+ pthread_mutex_unlock(mutex);
+ break;
}
gu_log("[PluginHost::addPlugin] plugin id=%s loaded (%s), stack type=%d, stack size=%d\n",
- fid.c_str(), p->getName().toStdString().c_str(), stackType, pStack->size());
+ fid.c_str(), p->getName().c_str(), stackType, pStack->size());
return p;
}
if (pStack->size() == 0)
return;
- int lockStatus;
while (true) {
- lockStatus = pthread_mutex_trylock(mutex);
- if (lockStatus == 0) {
- for (unsigned i=0; i<pStack->size(); i++) {
- Plugin *pPlugin = pStack->at(i);
- if (pPlugin->getStatus() != 0) { // take care if plugin is in good status
- pPlugin->suspendProcessing(true);
- pPlugin->releaseResources();
- }
- delete pPlugin;
- }
- pStack->clear();
- pthread_mutex_unlock(mutex);
- break;
- }
+ if (pthread_mutex_trylock(mutex) != 0)
+ continue;
+ for (unsigned i=0; i<pStack->size(); i++)
+ delete pStack->at(i);
+ pStack->clear();
+ pthread_mutex_unlock(mutex);
+ break;
}
gu_log("[PluginHost::freeStack] stack type=%d freed\n", stackType);
}
for (unsigned i=0; i<pStack->size(); i++) {
Plugin *plugin = pStack->at(i);
- if (plugin->getStatus() != 1 || plugin->isSuspended() || plugin->isBypassed())
+ if (plugin->isSuspended() || plugin->isBypassed())
continue;
if (ch) { // ch might be null if stackType is MASTER_IN/OUT
pthread_mutex_lock(&mutex_midi);
- plugin->processBlock(audioBuffer, ch->getPluginMidiEvents());
+ plugin->process(audioBuffer, ch->getPluginMidiEvents());
ch->clearMidiBuffer();
pthread_mutex_unlock(&mutex_midi);
}
else {
juce::MidiBuffer midiBuffer; // empty buffer
- plugin->processBlock(audioBuffer, midiBuffer);
+ plugin->process(audioBuffer, midiBuffer);
}
}
pthread_mutex_t *mutex, Channel *ch)
{
vector <Plugin *> *pStack = getStack(stackType, ch);
- int lockStatus;
while (true) {
- lockStatus = pthread_mutex_trylock(mutex);
- if (lockStatus == 0) {
- std::swap(pStack->at(indexA), pStack->at(indexB));
- pthread_mutex_unlock(mutex);
- gu_log("[pluginHost::swapPlugin] plugin at index %d and %d swapped\n", indexA, indexB);
- return;
- }
- //else
- //gu_log("[pluginHost] waiting for mutex...\n");
+ if (pthread_mutex_trylock(mutex) != 0)
+ continue;
+ std::swap(pStack->at(indexA), pStack->at(indexB));
+ pthread_mutex_unlock(mutex);
+ gu_log("[pluginHost::swapPlugin] plugin at index %d and %d swapped\n", indexA, indexB);
+ return;
}
}
/* -------------------------------------------------------------------------- */
-void PluginHost::freePlugin(int id, int stackType, pthread_mutex_t *mutex,
+int PluginHost::freePlugin(int id, int stackType, pthread_mutex_t *mutex,
Channel *ch)
{
vector <Plugin *> *pStack = getStack(stackType, ch);
-
for (unsigned i=0; i<pStack->size(); i++) {
Plugin *pPlugin = pStack->at(i);
if (pPlugin->getId() != id)
continue;
- if (pPlugin->getStatus() == 0) { // no frills if plugin is missing
- delete pPlugin;
- pStack->erase(pStack->begin() + i);
- gu_log("[pluginHost::freePlugin] plugin id=%d removed with no frills, since it had status=0\n", id);
- return;
- }
-
while (true) {
if (pthread_mutex_trylock(mutex) != 0)
continue;
- pPlugin->suspendProcessing(true);
- pPlugin->releaseResources();
delete pPlugin;
pStack->erase(pStack->begin() + i);
pthread_mutex_unlock(mutex);
gu_log("[pluginHost::freePlugin] plugin id=%d removed\n", id);
- return;
+ return i;
}
}
gu_log("[pluginHost::freePlugin] plugin id=%d not found\n", id);
+ return -1;
}
int PluginHost::clonePlugin(Plugin *src, int stackType, pthread_mutex_t *mutex,
Channel *ch)
{
- juce::PluginDescription pd = src->getPluginDescription();
- Plugin *p = addPlugin(pd.fileOrIdentifier.toStdString(), stackType, mutex, ch);
+ Plugin *p = addPlugin(src->getUniqueId(), stackType, mutex, ch);
if (!p) {
gu_log("[PluginHost::clonePlugin] unable to add new plugin to stack!\n");
return 0;
}
- for (int k=0; k<src->getNumParameters(); k++) {
+
+ for (int k=0; k<src->getNumParameters(); k++)
p->setParameter(k, src->getParameter(k));
- }
+
return 1;
}
#include <pthread.h>
-#include "../deps/juce/config.h"
+#include "../deps/juce-config.h"
using std::string;
void swapPlugin(unsigned indexA, unsigned indexB, int stackType,
pthread_mutex_t *mutex, class Channel *ch=NULL);
- /* freePlugin */
+ /* freePlugin.
+ Returns the internal stack index of the deleted plugin. */
- void freePlugin(int id, int stackType, pthread_mutex_t *mutex,
+ int freePlugin(int id, int stackType, pthread_mutex_t *mutex,
class Channel *ch=NULL);
-
/* runDispatchLoop
- * Wake up plugins' GUI manager for N milliseconds. */
+ * Wakes up plugins' GUI manager for N milliseconds. */
void runDispatchLoop();
/* freeAllStacks
- * Free everything. */
+ * Frees everything. */
void freeAllStacks(vector <Channel*> *channels, pthread_mutex_t *mutex);
#include <math.h>
#include "../utils/log.h"
-#include "../utils/fs.h"
-#include "const.h"
#include "mixer.h"
-#include "mixerHandler.h"
-#include "kernelAudio.h"
-#include "kernelMidi.h"
#include "patch_DEPR_.h"
-#include "conf.h"
-#include "channel.h"
#include "sampleChannel.h"
#include "recorder.h"
-extern KernelAudio G_KernelAudio;
-extern Mixer G_Mixer;
-
-
Recorder::Recorder()
: active (false),
sortedActions(false)
/* -------------------------------------------------------------------------- */
-bool Recorder::canRec(Channel *ch)
+bool Recorder::canRec(Channel *ch, Mixer *mixer)
{
/* NO recording if:
* recorder is inactive
* mixer is recording a take somewhere
* channel is empty */
- if (!active ||
- !G_Mixer.running ||
- G_Mixer.recording ||
+ if (!active ||
+ !mixer->running ||
+ mixer->recording ||
(ch->type == CHANNEL_SAMPLE && ((SampleChannel*)ch)->wave == NULL)
)
return false;
global.at(frameToExpand).push_back(a); // expand array
}
- /* don't activate the channel (readActions == false), it's up to
- * the other layers */
-
- G_Mixer.getChannelByIndex(index)->hasActions = true;
-
sortedActions = false;
gu_log("[REC] action recorded, type=%d frame=%d chan=%d iValue=%d (0x%X) fValue=%f\n",
j++;
}
}
-
- Channel *ch = G_Mixer.getChannelByIndex(index);
- ch->hasActions = false;
optimize();
//print();
}
j++;
}
}
- Channel *ch = G_Mixer.getChannelByIndex(index);
- ch->hasActions = false; /// FIXME - why this? Isn't it useless if we call setChanHasActionsStatus?
optimize();
- setChanHasActionsStatus(index); /// FIXME
//print();
}
void Recorder::deleteAction(int chan, int frame, char type, bool checkValues,
- uint32_t iValue, float fValue)
+ pthread_mutex_t *mixerMutex, uint32_t iValue, float fValue)
{
/* make sure frame is even */
bool found = false;
for (unsigned i=0; i<frames.size() && !found; i++) {
- if (frames.at(i) == frame) {
+
+ if (frames.at(i) != frame)
+ continue;
/* find the action in frame i */
- for (unsigned j=0; j<global.at(i).size(); j++) {
- action *a = global.at(i).at(j);
-
- /* action comparison logic */
-
- bool doit = (a->chan == chan && a->type == (type & a->type));
- if (checkValues)
- doit &= (a->iValue == iValue && a->fValue == fValue);
-
- if (doit) {
- // TODO - wft? just do: while (true); if (pthread_mutex_trylock(&G_Mixer.mutex_recs))
- int lockStatus = 0;
- while (lockStatus == 0) {
- lockStatus = pthread_mutex_trylock(&G_Mixer.mutex_recs);
- if (lockStatus == 0) {
- free(a);
- global.at(i).erase(global.at(i).begin() + j);
- pthread_mutex_unlock(&G_Mixer.mutex_recs);
- found = true;
- break;
- }
- else
- gu_log("[REC] delete action: waiting for mutex...\n");
- }
- }
- }
+ for (unsigned j=0; j<global.at(i).size(); j++) {
+ action *a = global.at(i).at(j);
+
+ /* action comparison logic */
+
+ bool doit = (a->chan == chan && a->type == (type & a->type));
+ if (checkValues)
+ doit &= (a->iValue == iValue && a->fValue == fValue);
+
+ if (!doit)
+ continue;
+
+ while (true) {
+ if (pthread_mutex_trylock(mixerMutex)) {
+ free(a);
+ global.at(i).erase(global.at(i).begin() + j);
+ pthread_mutex_unlock(mixerMutex);
+ found = true;
+ break;
+ }
+ else
+ gu_log("[REC] delete action: waiting for mutex...\n");
+ }
}
}
if (found) {
optimize();
- setChanHasActionsStatus(chan);
gu_log("[REC] action deleted, type=%d frame=%d chan=%d iValue=%d (%X) fValue=%f\n",
type, frame, chan, iValue, iValue, fValue);
}
/* -------------------------------------------------------------------------- */
-void Recorder::deleteActions(int chan, int frame_a, int frame_b, char type)
+void Recorder::deleteActions(int chan, int frame_a, int frame_b, char type,
+ pthread_mutex_t *mixerMutex)
{
sortActions();
vector<int> dels;
dels.push_back(frames.at(i));
for (unsigned i=0; i<dels.size(); i++)
- deleteAction(chan, dels.at(i), type, false); // false == don't check values
+ deleteAction(chan, dels.at(i), type, false, mixerMutex); // false == don't check values
}
global.erase(global.begin() + i);
}
}
-
- for (unsigned i=0; i<G_Mixer.channels.size(); i++) {
- G_Mixer.channels.at(i)->hasActions = false;
- if (G_Mixer.channels.at(i)->type == CHANNEL_SAMPLE)
- ((SampleChannel*)G_Mixer.channels.at(i))->readActions = false;
- }
-
global.clear();
frames.clear();
}
/* -------------------------------------------------------------------------- */
-void Recorder::setChanHasActionsStatus(int index)
+bool Recorder::hasActions(int chanIndex)
{
- Channel *ch = G_Mixer.getChannelByIndex(index);
- if (global.size() == 0) {
- ch->hasActions = false;
- return;
- }
+ if (global.size() == 0)
+ return false;
for (unsigned i=0; i<global.size(); i++) {
for (unsigned j=0; j<global.at(i).size(); j++) {
- if (global.at(i).at(j)->chan == index) {
- ch->hasActions = true;
- return;
- }
+ if (global.at(i).at(j)->chan == chanIndex)
+ return true;
}
}
- ch->hasActions = false;
+ return false;
}
/* -------------------------------------------------------------------------- */
-void Recorder::startOverdub(int index, char actionMask, int frame)
+void Recorder::startOverdub(int index, char actionMask, int frame,
+ unsigned bufferSize)
{
/* prepare the composite struct */
int res = getNextAction(index, cmp.a1.type | cmp.a2.type, cmp.a1.frame, &act);
if (res == 1) {
if (act->type == cmp.a2.type) {
- int truncFrame = cmp.a1.frame - G_KernelAudio.realBufsize;
+ int truncFrame = cmp.a1.frame - bufferSize;
if (truncFrame < 0)
truncFrame = 0;
gu_log("[REC] add truncation at frame %d, type=%d\n", truncFrame, cmp.a2.type);
rec(index, cmp.a2.type, truncFrame);
}
}
-
- SampleChannel *ch = (SampleChannel*) G_Mixer.getChannelByIndex(index);
- ch->readActions = false; // don't use disableRead()
}
/* -------------------------------------------------------------------------- */
-void Recorder::stopOverdub(int frame)
+void Recorder::stopOverdub(Mixer *mixer)
{
- cmp.a2.frame = frame;
+ cmp.a2.frame = mixer->currentFrame;
bool ringLoop = false;
bool nullLoop = false;
if (cmp.a2.frame < cmp.a1.frame) {
ringLoop = true;
gu_log("[REC] ring loop! frame1=%d < frame2=%d\n", cmp.a1.frame, cmp.a2.frame);
- rec(cmp.a2.chan, cmp.a2.type, G_Mixer.totalFrames); // record at the end of the sequencer
+ rec(cmp.a2.chan, cmp.a2.type, mixer->totalFrames); // record at the end of the sequencer
}
else
if (cmp.a2.frame == cmp.a1.frame) {
nullLoop = true;
gu_log("[REC] null loop! frame1=%d == frame2=%d\n", cmp.a1.frame, cmp.a2.frame);
- deleteAction(cmp.a1.chan, cmp.a1.frame, cmp.a1.type, false); // false == don't check values
+ deleteAction(cmp.a1.chan, cmp.a1.frame, cmp.a1.type, false, &mixer->mutex_recs); // false == don't check values
}
- SampleChannel *ch = (SampleChannel*) G_Mixer.getChannelByIndex(cmp.a2.chan);
- ch->readActions = false; // don't use disableRead()
-
/* remove any nested action between keypress----keyrel, then record */
if (!nullLoop) {
- deleteActions(cmp.a2.chan, cmp.a1.frame, cmp.a2.frame, cmp.a1.type);
- deleteActions(cmp.a2.chan, cmp.a1.frame, cmp.a2.frame, cmp.a2.type);
+ deleteActions(cmp.a2.chan, cmp.a1.frame, cmp.a2.frame, cmp.a1.type, &mixer->mutex_recs);
+ deleteActions(cmp.a2.chan, cmp.a1.frame, cmp.a2.frame, cmp.a2.type, &mixer->mutex_recs);
}
if (!ringLoop && !nullLoop) {
action *act = NULL;
int res = getNextAction(cmp.a2.chan, cmp.a1.type | cmp.a2.type, cmp.a2.frame, &act);
- if (res == 1) {
- if (act->type == cmp.a2.type) {
- gu_log("[REC] add truncation at frame %d, type=%d\n", act->frame, act->type);
- deleteAction(act->chan, act->frame, act->type, false); // false == don't check values
- }
+ if (res == 1 && act->type == cmp.a2.type) {
+ gu_log("[REC] add truncation at frame %d, type=%d\n", act->frame, act->type);
+ deleteAction(act->chan, act->frame, act->type, false, &mixer->mutex_recs); // false == don't check values
}
}
}
for (unsigned i=0; i<global.size(); i++) {
gu_log(" frame %d\n", frames.at(i));
for (unsigned j=0; j<global.at(i).size(); j++) {
- gu_log(" action %d | chan %d | frame %d\n", global.at(i).at(j)->type, global.at(i).at(j)->chan, global.at(i).at(j)->frame);
+ gu_log(" action %d | chan %d | frame %d\n", global.at(i).at(j)->type,
+ global.at(i).at(j)->chan, global.at(i).at(j)->frame);
}
}
}
#include <cstdint>
#endif
#include <vector>
+#include <pthread.h>
using std::vector;
void init();
- /* setChanHasActionsStatus
- * Check if the channel has at least one action recorded. If false, sets
- * ch->hasActions = false. Used after an action deletion. */
+ /* hasActions
+ Checks if the channel has at least one action recorded. Used after an
+ action deletion. */
- void setChanHasActionsStatus(int chan);
+ bool hasActions(int chanIndex);
/* canRec
* can a channel rec an action? Call this one BEFORE rec(). */
- bool canRec(class Channel *ch);
+ bool canRec(class Channel *ch, class Mixer *m);
/* rec
* record an action. */
* delete ONE action. Useful in the action editor. 'type' can be a mask. */
void deleteAction(int chan, int frame, char type, bool checkValues,
- uint32_t iValue=0, float fValue=0.0);
+ pthread_mutex_t *mixerMutex, uint32_t iValue=0, float fValue=0.0);
/* deleteActions
* delete A RANGE of actions from frame_a to frame_b in channel 'chan'.
* 'type' can be a bitmask. Exclusive range (frame_a, frame_b). */
- void deleteActions(int chan, int frame_a, int frame_b, char type);
+ void deleteActions(int chan, int frame_a, int frame_b, char type,
+ pthread_mutex_t *mixerMutex);
/* clearAll
* delete everything. */
/* start/endOverdub */
- void startOverdub(int chan, char action, int frame);
- void stopOverdub(int frame);
+ void startOverdub(int chan, char action, int frame, unsigned bufferSize);
+ void stopOverdub(class Mixer *m);
private:
#include "patch_DEPR_.h"
#include "patch.h"
#include "conf.h"
+#include "mixer.h"
#include "wave.h"
#include "pluginHost.h"
#include "waveFx.h"
tracker (0),
begin (0),
end (0),
- pitch (gDEFAULT_PITCH),
+ pitch (G_DEFAULT_PITCH),
boost (1.0f),
mode (DEFAULT_CHANMODE),
qWait (false),
fadeoutVol (1.0f),
fadeoutTracker (0),
fadeoutStep (DEFAULT_FADEOUT_STEP),
- readActions (false),
midiInReadActions(0x0),
midiInPitch (0x0)
{
/* -------------------------------------------------------------------------- */
-void SampleChannel::quantize(int index, int localFrame, int globalFrame)
+void SampleChannel::quantize(int index, int localFrame, Mixer *mixer)
{
/* skip if LOOP_ANY or not in quantizer-wait mode */
/* this is the moment in which we record the keypress, if the
* quantizer is on. SINGLE_PRESS needs overdub */
- if (G_Recorder.canRec(this)) {
- if (mode == SINGLE_PRESS)
- G_Recorder.startOverdub(index, ACTION_KEYS, globalFrame);
+ if (G_Recorder.canRec(this, mixer)) {
+ if (mode == SINGLE_PRESS) {
+ G_Recorder.startOverdub(index, ACTION_KEYS, mixer->currentFrame,
+ G_KernelAudio.realBufsize);
+ readActions = false; // don't read actions while overdubbing
+ }
else
- G_Recorder.rec(index, ACTION_KEYPRESS, globalFrame);
+ G_Recorder.rec(index, ACTION_KEYPRESS, mixer->currentFrame);
+ hasActions = true;
}
}
int readPatch(const string &basePath, int i, class Patch *patch,
pthread_mutex_t *pluginMutex, int samplerate, int rsmpQuality) override;
int writePatch(int i, bool isProject, class Patch *patch) override;
- void quantize(int index, int localFrame, int globalFrame) override;
+ void quantize(int index, int localFrame, class Mixer *m) override;
void onZero(int frame, bool recsStopOnChanHalt) override;
void onBar(int frame) override;
void parseAction(Recorder::action *a, int localFrame, int globalFrame,
int fadeoutType; // xfade or fadeout
int fadeoutEnd; // what to do when fadeout ends
- /* recorder:: stuff */
-
- bool readActions; // read actions or not
-
/* midi stuff */
uint32_t midiInReadActions;
--- /dev/null
+#ifndef __JUCE_APPCONFIG_H__
+#define __JUCE_APPCONFIG_H__
+
+
+#ifdef _WIN32
+ #include <sys/types.h>
+ #include <sys/time.h>
+#endif
+
+
+#include "juce/modules/juce_audio_basics/juce_audio_basics.h"
+#include "juce/modules/juce_audio_processors/juce_audio_processors.h"
+#include "juce/modules/juce_core/juce_core.h"
+#include "juce/modules/juce_data_structures/juce_data_structures.h"
+#include "juce/modules/juce_events/juce_events.h"
+#include "juce/modules/juce_graphics/juce_graphics.h"
+#include "juce/modules/juce_gui_basics/juce_gui_basics.h"
+#include "juce/modules/juce_gui_extra/juce_gui_extra.h"
+
+
+#endif
#include "../gui/dialogs/gd_mainWindow.h"
#include "../gui/dialogs/gd_editor.h"
-#include "../gui/elems/ge_keyboard.h"
#include "../gui/elems/ge_waveTools.h"
#include "../gui/elems/ge_waveform.h"
-#include "../gui/elems/channel.h"
+#include "../gui/elems/ge_mixed.h"
+#include "../gui/elems/mainWindow/keyboard/keyboard.h"
+#include "../gui/elems/mainWindow/keyboard/channel.h"
#include "../utils/gui.h"
#include "../core/mixerHandler.h"
#include "../core/mixer.h"
#include "../core/channel.h"
#include "../core/sampleChannel.h"
#include "../core/midiChannel.h"
+#include "../core/plugin.h"
#include "main.h"
#include "channel.h"
extern gdMainWindow *G_MainWin;
extern Conf G_Conf;
+extern KernelAudio G_KernelAudio;
extern Recorder G_Recorder;
extern Mixer G_Mixer;
#ifdef WITH_VST
-extern PluginHost G_PluginHost;
+extern PluginHost G_PluginHost;
#endif
void glue_deleteChannel(Channel *ch)
{
G_Recorder.clearChan(ch->index);
+ ch->hasActions = false;
#ifdef WITH_VST
G_PluginHost.freeStack(PluginHost::CHANNEL, &G_Mixer.mutex_plugins, ch);
#endif
#endif
G_MainWin->keyboard->freeChannel(ch->guiChannel);
G_Recorder.clearChan(ch->index);
+ ch->hasActions = false;
ch->empty();
}
void glue_setMute(Channel *ch, bool gui)
{
- if (G_Recorder.active && G_Recorder.canRec(ch)) {
- if (!ch->mute)
- G_Recorder.startOverdub(ch->index, ACTION_MUTES, G_Mixer.actualFrame);
+ if (G_Recorder.active && G_Recorder.canRec(ch, &G_Mixer)) {
+ if (!ch->mute) {
+ G_Recorder.startOverdub(ch->index, ACTION_MUTES, G_Mixer.currentFrame,
+ G_KernelAudio.realBufsize);
+ ch->readActions = false; // don't read actions while overdubbing
+ }
else
- G_Recorder.stopOverdub(G_Mixer.actualFrame);
+ G_Recorder.stopOverdub(&G_Mixer);
}
ch->mute ? ch->unsetMute(false) : ch->setMute(false);
/* -------------------------------------------------------------------------- */
-void glue_setVolEditor(class gdEditor *win, SampleChannel *ch, float val,
- bool numeric)
+void glue_setVolEditor(gdEditor *win, SampleChannel *ch, float val, bool numeric)
{
if (numeric) {
if (val > 0.0f)
void glue_setVolEditor(class gdEditor *win, class SampleChannel *ch, float val,
bool numeric);
+
#endif
#include <FL/Fl.H>
#include "../gui/dialogs/gd_mainWindow.h"
#include "../gui/dialogs/gd_warnings.h"
-#include "../gui/elems/ge_keyboard.h"
-#include "../gui/elems/channel.h"
-#include "../gui/elems/sampleChannel.h"
+#include "../gui/elems/mainWindow/mainTransport.h"
+#include "../gui/elems/mainWindow/mainTimer.h"
+#include "../gui/elems/mainWindow/keyboard/keyboard.h"
+#include "../gui/elems/mainWindow/keyboard/channel.h"
+#include "../gui/elems/mainWindow/keyboard/sampleChannel.h"
#include "../utils/gui.h"
#include "../utils/log.h"
#include "../core/recorder.h"
extern Recorder G_Recorder;
+extern KernelAudio G_KernelAudio;
extern bool G_audio_status;
extern Mixer G_Mixer;
extern gdMainWindow *G_MainWin;
if (G_Recorder.active) {
if (G_Mixer.running) {
ch->kill(0); // on frame 0: user-generated event
- if (G_Recorder.canRec(ch) && !(ch->mode & LOOP_ANY)) // don't record killChan actions for LOOP channels
- G_Recorder.rec(ch->index, ACTION_KILLCHAN, G_Mixer.actualFrame);
+ if (G_Recorder.canRec(ch, &G_Mixer) && !(ch->mode & LOOP_ANY)) { // don't record killChan actions for LOOP channels
+ G_Recorder.rec(ch->index, ACTION_KILLCHAN, G_Mixer.currentFrame);
+ ch->hasActions = true;
+ }
}
}
else {
* when a quantoWait has passed. Moreover, KEYPRESS and KEYREL are
* meaningless for loop modes */
- if (G_Mixer.quantize == 0 &&
- G_Recorder.canRec(ch) &&
+ if (G_Mixer.quantize == 0 &&
+ G_Recorder.canRec(ch, &G_Mixer) &&
!(ch->mode & LOOP_ANY))
{
- if (ch->mode == SINGLE_PRESS)
- G_Recorder.startOverdub(ch->index, ACTION_KEYS, G_Mixer.actualFrame);
+ if (ch->mode == SINGLE_PRESS) {
+ G_Recorder.startOverdub(ch->index, ACTION_KEYS, G_Mixer.currentFrame,
+ G_KernelAudio.realBufsize);
+ ch->readActions = false; // don't read actions while overdubbing
+ }
else {
- G_Recorder.rec(ch->index, ACTION_KEYPRESS, G_Mixer.actualFrame);
+ G_Recorder.rec(ch->index, ACTION_KEYPRESS, G_Mixer.currentFrame);
+ ch->hasActions = true;
/* Why return here? You record an action (as done on line 148) and then
you call ch->start (line 165): Mixer, which is on another thread, reads
/* record a key release only if channel is single_press. For any
* other mode the KEY REL is meaningless. */
- if (ch->mode == SINGLE_PRESS && G_Recorder.canRec(ch))
- G_Recorder.stopOverdub(G_Mixer.actualFrame);
+ if (ch->mode == SINGLE_PRESS && G_Recorder.canRec(ch, &G_Mixer))
+ G_Recorder.stopOverdub(&G_Mixer);
/* the GUI update is done by gui_refresh() */
if (!gui) {
Fl::lock();
- G_MainWin->controller->updateRecAction(1);
+ G_MainWin->mainTransport->updateRecAction(1);
Fl::unlock();
}
}
if (!gui) {
Fl::lock();
- G_MainWin->controller->updateRecAction(0);
+ G_MainWin->mainTransport->updateRecAction(0);
Fl::unlock();
}
if (!mh_startInputRec()) {
Fl::lock();
- G_MainWin->controller->updateRecInput(0); // set it off, anyway
+ G_MainWin->mainTransport->updateRecInput(0); // set it off, anyway
Fl::unlock();
return false;
}
if (!G_Mixer.running)
glue_startSeq(false); // update gui anyway
- if (!gui) {
- Fl::lock();
- G_MainWin->controller->updateRecInput(1);
- Fl::unlock();
- }
+ Fl::lock();
+ if (!gui)
+ G_MainWin->mainTransport->updateRecInput(1);
+ G_MainWin->mainTimer->setLock(true);
+ Fl::unlock();
/* Update sample name inside sample channels' main button. This is useless for
midi channel, but let's do it anyway. */
continue;
SampleChannel *ch = (SampleChannel*) G_Mixer.channels.at(i);
if (ch->mode & (LOOP_ANY) && ch->status == STATUS_OFF && ch->armed)
- ch->start(G_Mixer.actualFrame, true, G_Mixer.quantize, G_Mixer.running, true, true);
+ ch->start(G_Mixer.currentFrame, true, G_Mixer.quantize, G_Mixer.running, true, true);
}
- if (!gui) {
- Fl::lock();
- G_MainWin->controller->updateRecInput(0);
- Fl::unlock();
- }
+ Fl::lock();
+ if (!gui)
+ G_MainWin->mainTransport->updateRecInput(0);
+ G_MainWin->mainTimer->setLock(false);
+ Fl::unlock();
return 1;
}
#include <cmath>
#include "../gui/elems/ge_waveform.h"
#include "../gui/elems/ge_mixed.h"
-#include "../gui/elems/channel.h"
-#include "../gui/elems/sampleChannel.h"
#include "../gui/elems/ge_waveTools.h"
-#include "../gui/elems/ge_keyboard.h"
+#include "../gui/elems/mainWindow/mainTransport.h"
+#include "../gui/elems/mainWindow/mainIO.h"
+#include "../gui/elems/mainWindow/mainTimer.h"
+#include "../gui/elems/mainWindow/keyboard/channel.h"
+#include "../gui/elems/mainWindow/keyboard/sampleChannel.h"
+#include "../gui/elems/mainWindow/keyboard/keyboard.h"
#include "../gui/dialogs/gd_mainWindow.h"
#include "../gui/dialogs/gd_editor.h"
#include "../gui/dialogs/gd_warnings.h"
void glue_setBpm(const char *v1, const char *v2)
{
+ /* Never change this stuff while recording audio */
+
+ if (G_Mixer.recording)
+ return;
+
char buf[6];
float value = atof(v1) + (atof(v2)/10);
if (value < 20.0f) {
G_Recorder.updateBpm(old_bpm, value, G_Mixer.quanto);
gu_refreshActionEditor();
- G_MainWin->timing->setBpm(buf);
+ G_MainWin->mainTimer->setBpm(buf);
gu_log("[glue] Bpm changed to %s (real=%f)\n", buf, G_Mixer.bpm);
}
void glue_setBeats(int beats, int bars, bool expand)
{
- /* temp vars to store old data (they are necessary) */
+ /* Never change this stuff while recording audio */
+
+ if (G_Mixer.recording)
+ return;
+
+ /* Temp vars to store old data (they are necessary) */
int oldvalue = G_Mixer.beats;
unsigned oldfpb = G_Mixer.totalFrames;
// G_Recorder.shrink(G_Mixer.totalFrames);
}
- G_MainWin->timing->setMeter(G_Mixer.beats, G_Mixer.bars);
+ G_MainWin->mainTimer->setMeter(G_Mixer.beats, G_Mixer.bars);
gu_refreshActionEditor(); // in case the action editor is open
}
if (!gui) {
Fl::lock();
- G_MainWin->controller->updatePlay(1);
+ G_MainWin->mainTransport->updatePlay(1);
Fl::unlock();
}
}
if (G_Recorder.active) {
G_Recorder.active = false;
Fl::lock();
- G_MainWin->controller->updateRecAction(0);
+ G_MainWin->mainTransport->updateRecAction(0);
Fl::unlock();
}
if (G_Mixer.recording) {
mh_stopInputRec();
Fl::lock();
- G_MainWin->controller->updateRecInput(0);
+ G_MainWin->mainTransport->updateRecInput(0);
Fl::unlock();
}
if (!gui) {
Fl::lock();
- G_MainWin->controller->updatePlay(0);
+ G_MainWin->mainTransport->updatePlay(0);
Fl::unlock();
}
}
G_Mixer.outVol = v;
if (!gui) {
Fl::lock();
- G_MainWin->inOut->setOutVol(v);
+ G_MainWin->mainIO->setOutVol(v);
Fl::unlock();
}
}
G_Mixer.inVol = v;
if (!gui) {
Fl::lock();
- G_MainWin->inOut->setInVol(v);
+ G_MainWin->mainIO->setInVol(v);
Fl::unlock();
}
}
G_Mixer.metronome = !G_Mixer.metronome;
if (!gui) {
Fl::lock();
- G_MainWin->controller->updateMetronome(G_Mixer.metronome);
+ G_MainWin->mainTransport->updateMetronome(G_Mixer.metronome);
Fl::unlock();
}
}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * glue
+ * Intermediate layer GUI <-> CORE.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include "../core/pluginHost.h"
+#include "../core/mixer.h"
+#include "../core/plugin.h"
+#include "../core/channel.h"
+#include "plugin.h"
+
+
+extern Mixer G_Mixer;
+extern PluginHost G_PluginHost;
+
+
+Plugin *glue_addPlugin(Channel *ch, int index, int stackType)
+{
+ if (index >= G_PluginHost.countAvailablePlugins())
+ return nullptr;
+
+ return G_PluginHost.addPlugin(index, stackType, &G_Mixer.mutex_plugins, ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_swapPlugins(Channel *ch, int index1, int index2, int stackType)
+{
+ G_PluginHost.swapPlugin(index1, index2, stackType, &G_Mixer.mutex_plugins,
+ ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_freePlugin(Channel *ch, int index, int stackType)
+{
+ G_PluginHost.freePlugin(index, stackType, &G_Mixer.mutex_plugins, ch);
+}
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * glue
+ * Intermediate layer GUI <-> CORE.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 __GLUE_PLUGIN_H__
+#define __GLUE_PLUGIN_H__
+
+
+#ifdef WITH_VST
+
+class Plugin *glue_addPlugin(class Channel *ch, int index, int stackType);
+
+void glue_swapPlugins(class Channel *ch, int indexP1, int indexP2, int stackType);
+
+void glue_freePlugin(class Channel *ch, int index, int stackType);
+
+#endif
+
+
+#endif
* -------------------------------------------------------------------------- */
-#include "../gui/elems/ge_column.h"
-#include "../gui/elems/ge_keyboard.h"
-#include "../gui/dialogs/gd_mainWindow.h"
-#include "../gui/dialogs/gd_warnings.h"
-#include "../gui/dialogs/gd_browser.h"
#include "../core/mixer.h"
#include "../core/mixerHandler.h"
#include "../core/channel.h"
#include "../core/wave.h"
#include "../utils/gui.h"
#include "../utils/log.h"
+#include "../gui/elems/mainWindow/keyboard/column.h"
+#include "../gui/elems/mainWindow/keyboard/keyboard.h"
+#include "../gui/dialogs/gd_mainWindow.h"
+#include "../gui/dialogs/gd_warnings.h"
+#include "../gui/dialogs/gd_browser.h"
#include "main.h" // TODO - remove, used only for DEPR calls
#include "channel.h"
#include "storage.h"
static void __glue_fillPatchColumns__()
{
for (unsigned i=0; i<G_MainWin->keyboard->getTotalColumns(); i++) {
- gColumn *gCol = G_MainWin->keyboard->getColumn(i);
+ geColumn *gCol = G_MainWin->keyboard->getColumn(i);
Patch::column_t pCol;
pCol.index = gCol->getIndex();
pCol.width = gCol->w();
#include "../../core/kernelAudio.h"
#include "../../core/kernelMidi.h"
#include "../../core/graphics.h"
-#include "../../deps/juce/config.h"
+#ifdef WITH_VST
+ #include "../../deps/juce-config.h"
+#endif
#include "../../utils/gui.h"
#include "../elems/ge_mixed.h"
#include "gd_about.h"
#include "../elems/muteEditor.h"
#include "../elems/noteEditor.h"
#include "../elems/ge_mixed.h"
+#include "../elems/basics/scroll.h"
#include "gd_actionEditor.h"
/* main scroller: contains all widgets */
- scroller = new gScroll(8, 36, w()-16, h()-44);
+ scroller = new geScroll(8, 36, w()-16, h()-44);
if (chan->type == CHANNEL_SAMPLE) {
class gGridTool *gridTool;
class gClick *zoomIn;
class gClick *zoomOut;
- class gScroll *scroller; // widget container
+ class geScroll *scroller; // widget container
class geActionEditor *ac;
class geMuteEditor *mc;
#include "../../core/conf.h"
#include "../../core/const.h"
#include "../../glue/main.h"
+#include "../elems/ge_mixed.h"
#include "gd_beatsInput.h"
#include "gd_mainWindow.h"
#include "../../core/graphics.h"
-#include "../../core/wave.h"
-#include "../../core/channel.h"
-#include "../../core/sampleChannel.h"
#include "../../core/conf.h"
#include "../../core/const.h"
-#include "../../glue/main.h"
-#include "../../glue/channel.h"
-#include "../../glue/storage.h"
#include "../../utils/gui.h"
-#include "../elems/ge_browser.h"
-#include "../elems/channel.h"
+#include "../elems/ge_mixed.h"
+#include "../elems/browser.h"
#include "gd_browser.h"
{
set_non_modal();
- groupTop = new Fl_Group(8, 8, w-16, 20);
- where = new gInput(groupTop->x(), groupTop->y(), 152, 20);
- updir = new gClick(groupTop->x()+groupTop->w()-20, groupTop->y(), 20, 20, "", updirOff_xpm, updirOn_xpm);
+ groupTop = new Fl_Group(8, 8, w-16, 40);
+ hiddenFiles = new gCheck(groupTop->x(), groupTop->y(), 400, 20, "Show hidden files");
+ where = new gInput(groupTop->x(), hiddenFiles->y()+hiddenFiles->h(), 152, 20);
+ updir = new gClick(groupTop->x()+groupTop->w()-20, where->y(), 20, 20, "", updirOff_xpm, updirOn_xpm);
groupTop->end();
groupTop->resizable(where);
+ hiddenFiles->callback(cb_toggleHiddenFiles, (void*) this);
+
where->readonly(true);
where->cursor_color(COLOR_BG_DARK);
where->value(path.c_str());
updir->callback(cb_up, (void*) this);
- browser = new gBrowser(8, groupTop->y()+groupTop->h()+8, w-16, h-73);
+ browser = new geBrowser(8, groupTop->y()+groupTop->h()+8, w-16, h-93);
browser->loadDir(path);
if (path == G_Conf.browserLastPath)
browser->preselect(G_Conf.browserPosition, G_Conf.browserLastValue);
void gdBaseBrowser::cb_up (Fl_Widget *v, void *p) { ((gdBaseBrowser*)p)->__cb_up(); }
void gdBaseBrowser::cb_close(Fl_Widget *v, void *p) { ((gdBaseBrowser*)p)->__cb_close(); }
+void gdBaseBrowser::cb_toggleHiddenFiles(Fl_Widget *v, void *p) { ((gdBaseBrowser*)p)->__cb_toggleHiddenFiles(); }
/* -------------------------------------------------------------------------- */
-void gdBaseBrowser::__cb_up() {
+void gdBaseBrowser::__cb_up()
+{
string dir = browser->getCurrentDir();
dir = dir.substr(0, dir.find_last_of(G_SLASH_STR)); // remove up to the next slash
browser->loadDir(dir);
/* -------------------------------------------------------------------------- */
-void gdBaseBrowser::__cb_close() {
+void gdBaseBrowser::__cb_close()
+{
do_callback();
}
/* -------------------------------------------------------------------------- */
+void gdBaseBrowser::__cb_toggleHiddenFiles()
+{
+ browser->toggleHiddenFiles();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
void gdBaseBrowser::setStatusBar(float v)
{
status->value(status->value() + v);
/* -------------------------------------------------------------------------- */
+void gdBaseBrowser::showStatusBar()
+{
+ status->show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdBaseBrowser::hideStatusBar()
+{
+ status->hide();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string gdBaseBrowser::getCurrentPath()
+{
+ return where->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
string gdBaseBrowser::getSelectedItem()
{
return browser->getSelectedItem();
where->size(groupTop->w()-236, 20);
- name = new gInput(where->x()+where->w()+8, 8, 200, 20);
+ name = new gInput(where->x()+where->w()+8, where->y(), 200, 20);
name->value(_name.c_str());
groupTop->add(name);
/* -------------------------------------------------------------------------- */
+string gdSaveBrowser::getName()
+{
+ return name->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
void gdSaveBrowser::__cb_save()
{
callback((void*) this);
#define GD_BROWSER_H
-#include <FL/Fl.H>
-#include <FL/Fl_Double_Window.H>
-#include "../elems/ge_mixed.h"
#include "../elems/ge_window.h"
protected:
class Fl_Group *groupTop;
- class gBrowser *browser;
+ class gCheck *hiddenFiles;
+ class geBrowser *browser;
class gClick *ok;
class gClick *cancel;
class gInput *where;
class gClick *updir;
class gProgress *status;
- static void cb_up (Fl_Widget *v, void *p);
- static void cb_close(Fl_Widget *w, void *p);
+ static void cb_up (Fl_Widget *v, void *p);
+ static void cb_close (Fl_Widget *w, void *p);
+ static void cb_toggleHiddenFiles(Fl_Widget *w, void *p);
- inline void __cb_up ();
- inline void __cb_close();
+ inline void __cb_up ();
+ inline void __cb_close ();
+ inline void __cb_toggleHiddenFiles();
/* Callback
* Fired when the save/load button is pressed. */
void setStatusBar(float v);
- inline gProgress *getStatusBar() { return status; } // TODO - remove with Patch_DEPR_
- inline void showStatusBar() { status->show(); }
- inline void hideStatusBar() { status->hide(); }
- inline Channel *getChannel() { return channel; }
- inline void fireCallback() { callback((void*) this); }
- inline string getCurrentPath() { return where->value(); }
+ gProgress *getStatusBar() { return status; } // TODO - remove with Patch_DEPR_
+ void showStatusBar();
+ void hideStatusBar();
+ string getCurrentPath();
+
+ Channel *getChannel() { return channel; }
+ void fireCallback() { callback((void*) this); }
};
const string &path, const string &name, void (*callback)(void*),
class Channel *ch);
- string getName() { return name->value(); }
+ string getName();
};
#include "../../utils/log.h"
#include "../../utils/string.h"
#include "../elems/ge_mixed.h"
+#include "../elems/basics/boxtypes.h"
#include "gd_config.h"
#include "gd_keyGrabber.h"
#include "gd_devInfo.h"
resize(G_Conf.configX, G_Conf.configY, this->w(), this->h());
Fl_Tabs *tabs = new Fl_Tabs(8, 8, w-16, h-44);
+ tabs->box(G_CUSTOM_BORDER_BOX);
+ tabs->labelcolor(COLOR_TEXT_0);
+ tabs->begin();
+
tabAudio = new gTabAudio(tabs->x()+10, tabs->y()+20, tabs->w()-20, tabs->h()-40);
tabMidi = new gTabMidi(tabs->x()+10, tabs->y()+20, tabs->w()-20, tabs->h()-40);
tabBehaviors = new gTabBehaviors(tabs->x()+10, tabs->y()+20, tabs->w()-20, tabs->h()-40);
end();
- tabs->box(FL_FLAT_BOX); // TODO - G_BOX crashes FLTK 1.3.3
-
- tabs->labelcolor(COLOR_TEXT_0);
-
save->callback(cb_save_config, (void*)this);
cancel->callback(cb_cancel, (void*)this);
#include "../../core/sampleChannel.h"
#include "../../core/mixer.h"
#include "../../core/wave.h"
-#include "../elems/channel.h"
#include "../elems/ge_waveform.h"
#include "../elems/ge_mixed.h"
#include "../elems/ge_waveTools.h"
+#include "../elems/mainWindow/keyboard/channel.h"
#include "gd_warnings.h"
#include "gd_editor.h"
ch->load(ch->wave->pathfile.c_str(), G_Conf.samplerate, G_Conf.rsmpQuality);
glue_setBoost(this, ch, DEFAULT_BOOST, true);
- glue_setPitch(this, ch, gDEFAULT_PITCH, true);
+ glue_setPitch(this, ch, G_DEFAULT_PITCH, true);
glue_setPanning(this, ch, 1.0f);
pan->value(1.0f); // glue_setPanning doesn't do it
pan->redraw(); // glue_setPanning doesn't do it
#include "../../core/sampleChannel.h"
#include "../../core/midiChannel.h"
#include "../../utils/log.h"
-#include "../elems/ge_keyboard.h"
#include "../elems/ge_mixed.h"
-#include "../elems/channel.h"
-#include "../elems/channelButton.h"
+#include "../elems/mainWindow/keyboard/keyboard.h"
+#include "../elems/mainWindow/keyboard/channel.h"
+#include "../elems/mainWindow/keyboard/channelButton.h"
#include "gd_keyGrabber.h"
#include "gd_config.h"
#include "gd_mainWindow.h"
* -------------------------------------------------------------------------- */
-#ifdef __linux__
- #include <sys/stat.h> // for mkdir
-#endif
-
-
-#include "../../core/graphics.h"
-#include "../../core/mixer.h"
-#include "../../core/recorder.h"
-#include "../../core/mixerHandler.h"
-#include "../../core/channel.h"
-#include "../../core/sampleChannel.h"
+#include <FL/Fl.H>
+#include "../../core/const.h"
#include "../../core/init.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/patch.h"
-#include "../../core/conf.h"
-#include "../../core/pluginHost.h"
-#include "../../glue/main.h"
-#include "../../glue/storage.h"
-#include "../elems/ge_keyboard.h"
+#include "../../utils/gui.h"
+#include "../elems/ge_mixed.h"
+#include "../elems/basics/boxtypes.h"
+#include "../elems/mainWindow/mainIO.h"
+#include "../elems/mainWindow/mainMenu.h"
+#include "../elems/mainWindow/mainTimer.h"
+#include "../elems/mainWindow/mainTransport.h"
+#include "../elems/mainWindow/beatMeter.h"
+#include "../elems/mainWindow/keyboard/keyboard.h"
#include "gd_warnings.h"
-#include "gd_bpmInput.h"
-#include "gd_beatsInput.h"
-#include "gd_midiInput.h"
-#include "gd_about.h"
-#include "gd_config.h"
-#include "gd_browser.h"
#include "gd_mainWindow.h"
-#include "gd_pluginList.h"
-extern Mixer G_Mixer;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern Patch G_Patch;
-extern Conf G_Conf;
extern gdMainWindow *G_MainWin;
-extern bool G_quit;
-extern bool G_audio_status;
gdMainWindow::gdMainWindow(int W, int H, const char *title, int argc, char **argv)
Fl::visible_focus(0);
Fl::background(25, 25, 25);
- Fl::set_boxtype(G_BOX, gDrawBox, 1, 1, 2, 2); // custom box G_BOX
+
+ Fl::set_boxtype(G_CUSTOM_BORDER_BOX, g_customBorderBox, 1, 1, 2, 2);
+ Fl::set_boxtype(G_CUSTOM_UP_BOX, g_customUpBox, 1, 1, 2, 2);
+ Fl::set_boxtype(G_CUSTOM_DOWN_BOX, g_customDownBox, 1, 1, 2, 2);
+
+ Fl::set_boxtype(FL_BORDER_BOX, G_CUSTOM_BORDER_BOX);
+ 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);
- menu = new gMenu(8, -1);
- inOut = new gInOut(412, 8);
- controller = new gController(8, 39);
- timing = new gTiming(628, 44);
- beatMeter = new gBeatMeter(100, 83, 609, 20);
- keyboard = new gKeyboard(8, 122, w()-16, 380);
+ mainMenu = new geMainMenu(8, -1);
+ mainIO = new geMainIO(412, 8);
+ mainTransport = new geMainTransport(8, 39);
+ mainTimer = new geMainTimer(628, 44);
+ beatMeter = new geBeatMeter(100, 83, 609, 20);
+ keyboard = new geKeyboard(8, 122, w()-16, 380);
/* zone 1 - menus, and I/O tools */
Fl_Group *zone1 = new Fl_Group(8, 8, W-16, 20);
- zone1->add(menu);
+ zone1->add(mainMenu);
zone1->resizable(new Fl_Box(300, 8, 80, 20));
- zone1->add(inOut);
+ zone1->add(mainIO);
- /* zone 2 - controller and timing tools */
+ /* zone 2 - mainTransport and timing tools */
- Fl_Group *zone2 = new Fl_Group(8, controller->y(), W-16, controller->h());
- zone2->add(controller);
- zone2->resizable(new Fl_Box(controller->x()+controller->w()+4, zone2->y(), 80, 20));
- zone2->add(timing);
+ Fl_Group *zone2 = new Fl_Group(8, mainTransport->y(), W-16, mainTransport->h());
+ zone2->add(mainTransport);
+ zone2->resizable(new Fl_Box(mainTransport->x()+mainTransport->w()+4, zone2->y(), 80, 20));
+ zone2->add(mainTimer);
/* zone 3 - beat meter */
hide();
delete this;
}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gInOut::gInOut(int x, int y)
- : Fl_Group(x, y, 396, 20)
-{
- begin();
-
-#if defined(WITH_VST)
- masterFxIn = new gFxButton (x, y, 20, 20, fxOff_xpm, fxOn_xpm);
- inVol = new gDial (masterFxIn->x()+masterFxIn->w()+4, y, 20, 20);
- inMeter = new gSoundMeter(inVol->x()+inVol->w()+4, y+4, 140, 12);
- inToOut = new gClick (inMeter->x()+inMeter->w()+4, y+4, 12, 12, "", inputToOutputOff_xpm, inputToOutputOn_xpm);
- outMeter = new gSoundMeter(inToOut->x()+inToOut->w()+4, y+4, 140, 12);
- outVol = new gDial (outMeter->x()+outMeter->w()+4, y, 20, 20);
- masterFxOut = new gFxButton (outVol->x()+outVol->w()+4, y, 20, 20, fxOff_xpm, fxOn_xpm);
-#else
- inVol = new gDial (x+62, y, 20, 20);
- inMeter = new gSoundMeter(inVol->x()+inVol->w()+4, y+5, 140, 12);
- outMeter = new gSoundMeter(inMeter->x()+inMeter->w()+4, y+5, 140, 12);
- outVol = new gDial (outMeter->x()+outMeter->w()+4, y, 20, 20);
-#endif
-
- end();
-
- resizable(NULL); // don't resize any widget
-
- outVol->callback(cb_outVol, (void*)this);
- outVol->value(G_Mixer.outVol);
- inVol->callback(cb_inVol, (void*)this);
- inVol->value(G_Mixer.inVol);
-
-#ifdef WITH_VST
- masterFxOut->callback(cb_masterFxOut, (void*)this);
- masterFxIn->callback(cb_masterFxIn, (void*)this);
- inToOut->callback(cb_inToOut, (void*)this);
- inToOut->type(FL_TOGGLE_BUTTON);
-#endif
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gInOut::cb_outVol (Fl_Widget *v, void *p) { ((gInOut*)p)->__cb_outVol(); }
-void gInOut::cb_inVol (Fl_Widget *v, void *p) { ((gInOut*)p)->__cb_inVol(); }
-#ifdef WITH_VST
-void gInOut::cb_masterFxOut(Fl_Widget *v, void *p) { ((gInOut*)p)->__cb_masterFxOut(); }
-void gInOut::cb_masterFxIn (Fl_Widget *v, void *p) { ((gInOut*)p)->__cb_masterFxIn(); }
-void gInOut::cb_inToOut (Fl_Widget *v, void *p) { ((gInOut*)p)->__cb_inToOut(); }
-#endif
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gInOut::__cb_outVol()
-{
- glue_setOutVol(outVol->value());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gInOut::__cb_inVol()
-{
- glue_setInVol(inVol->value());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-void gInOut::__cb_masterFxOut()
-{
- gu_openSubWindow(G_MainWin, new gdPluginList(PluginHost::MASTER_OUT), WID_FX_LIST);
-}
-
-void gInOut::__cb_masterFxIn()
-{
- gu_openSubWindow(G_MainWin, new gdPluginList(PluginHost::MASTER_IN), WID_FX_LIST);
-}
-
-void gInOut::__cb_inToOut()
-{
- G_Mixer.inToOut = inToOut->value();
-}
-#endif
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gInOut::refresh()
-{
- outMeter->mixerPeak = G_Mixer.peakOut;
- inMeter->mixerPeak = G_Mixer.peakIn;
- outMeter->redraw();
- inMeter->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gMenu::gMenu(int x, int y)
- : Fl_Group(x, y, 300, 20)
-{
- begin();
-
- file = new gClick(x, y, 70, 21, "file");
- edit = new gClick(file->x()+file->w()+4, y, 70, 21, "edit");
- config = new gClick(edit->x()+edit->w()+4, y, 70, 21, "config");
- about = new gClick(config->x()+config->w()+4, y, 70, 21, "about");
-
- end();
-
- resizable(NULL); // don't resize any widget
-
- about->callback(cb_about, (void*)this);
- file->callback(cb_file, (void*)this);
- edit->callback(cb_edit, (void*)this);
- config->callback(cb_config, (void*)this);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gMenu::cb_about (Fl_Widget *v, void *p) { ((gMenu*)p)->__cb_about(); }
-void gMenu::cb_config(Fl_Widget *v, void *p) { ((gMenu*)p)->__cb_config(); }
-void gMenu::cb_file (Fl_Widget *v, void *p) { ((gMenu*)p)->__cb_file(); }
-void gMenu::cb_edit (Fl_Widget *v, void *p) { ((gMenu*)p)->__cb_edit(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gMenu::__cb_about()
-{
- gu_openSubWindow(G_MainWin, new gdAbout(), WID_ABOUT);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gMenu::__cb_config()
-{
- gu_openSubWindow(G_MainWin, new gdConfig(380, 370), WID_CONFIG);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gMenu::__cb_file()
-{
- /* An Fl_Menu_Button is made of many Fl_Menu_Item */
-
- Fl_Menu_Item menu[] = {
- {"Open patch or project..."},
- {"Save patch..."},
- {"Save project..."},
- {"Quit Giada"},
- {0}
- };
-
- Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
-
- const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
- if (!m) return;
-
-
- if (strcmp(m->label(), "Open patch or project...") == 0) {
- //gWindow *childWin = new gdBrowser("Load Patch", G_Conf.patchPath.c_str(), 0, BROWSER_LOAD_PATCH);
- //gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
- gWindow *childWin = new gdLoadBrowser(G_Conf.browserX, G_Conf.browserY,
- G_Conf.browserW, G_Conf.browserH, "Load patch or project",
- G_Conf.patchPath, glue_loadPatch, NULL);
- gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
- return;
- }
- if (strcmp(m->label(), "Save patch...") == 0) {
- if (G_Mixer.hasLogicalSamples() || G_Mixer.hasEditedSamples())
- if (!gdConfirmWin("Warning", "You should save a project in order to store\nyour takes and/or processed samples."))
- return;
- gWindow *childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
- G_Conf.browserW, G_Conf.browserH, "Save patch",
- G_Conf.patchPath, G_Patch.name, glue_savePatch, NULL);
- gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
- return;
- }
- if (strcmp(m->label(), "Save project...") == 0) {
- gWindow *childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
- G_Conf.browserW, G_Conf.browserH, "Save project",
- G_Conf.patchPath, G_Patch.name, glue_saveProject, NULL);
- gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
- return;
- }
- if (strcmp(m->label(), "Quit Giada") == 0) {
- G_MainWin->do_callback();
- return;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gMenu::__cb_edit()
-{
- Fl_Menu_Item menu[] = {
- {"Clear all samples"},
- {"Clear all actions"},
- {"Remove empty columns"},
- {"Reset to init state"},
- {"Setup global MIDI input..."},
- {0}
- };
-
- /* clear all actions disabled if no recs, clear all samples disabled
- * if no samples. */
-
- menu[1].deactivate();
-
- for (unsigned i=0; i<G_Mixer.channels.size(); i++)
- if (G_Mixer.channels.at(i)->hasActions) {
- menu[1].activate();
- break;
- }
- for (unsigned i=0; i<G_Mixer.channels.size(); i++)
- if (G_Mixer.channels.at(i)->type == CHANNEL_SAMPLE)
- if (((SampleChannel*)G_Mixer.channels.at(i))->wave != NULL) {
- menu[0].activate();
- break;
- }
-
- Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
-
- const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
- if (!m) return;
-
- if (strcmp(m->label(), "Clear all samples") == 0) {
- if (!gdConfirmWin("Warning", "Clear all samples: are you sure?"))
- return;
- G_MainWin->delSubWindow(WID_SAMPLE_EDITOR);
- glue_clearAllSamples();
- return;
- }
- if (strcmp(m->label(), "Clear all actions") == 0) {
- if (!gdConfirmWin("Warning", "Clear all actions: are you sure?"))
- return;
- G_MainWin->delSubWindow(WID_ACTION_EDITOR);
- glue_clearAllRecs();
- return;
- }
- if (strcmp(m->label(), "Reset to init state") == 0) {
- if (!gdConfirmWin("Warning", "Reset to init state: are you sure?"))
- return;
- gu_closeAllSubwindows();
- glue_resetToInitState();
- return;
- }
- if (strcmp(m->label(), "Remove empty columns") == 0) {
- G_MainWin->keyboard->organizeColumns();
- return;
- }
- if (strcmp(m->label(), "Setup global MIDI input...") == 0) {
- gu_openSubWindow(G_MainWin, new gdMidiInputMaster(), 0);
- return;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gTiming::gTiming(int x, int y)
- : Fl_Group(x, y, 180, 20)
-{
- begin();
-
- quantizer = new gChoice(x, y, 40, 20, "", false);
- bpm = new gClick (quantizer->x()+quantizer->w()+4, y, 40, 20);
- meter = new gClick (bpm->x()+bpm->w()+8, y, 40, 20, "4/1");
- multiplier = new gClick (meter->x()+meter->w()+4, y, 20, 20, "", multiplyOff_xpm, multiplyOn_xpm);
- divider = new gClick (multiplier->x()+multiplier->w()+4, y, 20, 20, "", divideOff_xpm, divideOn_xpm);
-
- end();
-
- resizable(NULL); // don't resize any widget
-
- char buf[6]; snprintf(buf, 6, "%f", G_Mixer.bpm);
- bpm->copy_label(buf);
-
- bpm->callback(cb_bpm, (void*)this);
- meter->callback(cb_meter, (void*)this);
- multiplier->callback(cb_multiplier, (void*)this);
- divider->callback(cb_divider, (void*)this);
-
- quantizer->add("off", 0, cb_quantizer, (void*)this);
- quantizer->add("1b", 0, cb_quantizer, (void*)this);
- quantizer->add("2b", 0, cb_quantizer, (void*)this);
- quantizer->add("3b", 0, cb_quantizer, (void*)this);
- quantizer->add("4b", 0, cb_quantizer, (void*)this);
- quantizer->add("6b", 0, cb_quantizer, (void*)this);
- quantizer->add("8b", 0, cb_quantizer, (void*)this);
- quantizer->value(0); // "off" by default
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::cb_bpm (Fl_Widget *v, void *p) { ((gTiming*)p)->__cb_bpm(); }
-void gTiming::cb_meter (Fl_Widget *v, void *p) { ((gTiming*)p)->__cb_meter(); }
-void gTiming::cb_quantizer (Fl_Widget *v, void *p) { ((gTiming*)p)->__cb_quantizer(); }
-void gTiming::cb_multiplier(Fl_Widget *v, void *p) { ((gTiming*)p)->__cb_multiplier(); }
-void gTiming::cb_divider (Fl_Widget *v, void *p) { ((gTiming*)p)->__cb_divider(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::__cb_bpm()
-{
- gu_openSubWindow(G_MainWin, new gdBpmInput(bpm->label()), WID_BPM);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::__cb_meter()
-{
- gu_openSubWindow(G_MainWin, new gdBeatsInput(), WID_BEATS);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::__cb_quantizer()
-{
- glue_quantize(quantizer->value());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::__cb_multiplier()
-{
- glue_beatsMultiply();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::__cb_divider()
-{
- glue_beatsDivide();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::setBpm(const char *v)
-{
- bpm->copy_label(v);
-}
-
-
-void gTiming::setBpm(float v)
-{
- char buf[6];
- sprintf(buf, "%.01f", v); // only 1 decimal place (e.g. 120.0)
- bpm->copy_label(buf);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gTiming::setMeter(int beats, int bars)
-{
- char buf[8];
- sprintf(buf, "%d/%d", beats, bars);
- meter->copy_label(buf);
-}
#define GD_MAINWINDOW_H
-#include <FL/Fl.H>
-#include <FL/x.H>
-#include "../elems/ge_mixed.h"
#include "../elems/ge_window.h"
-#include "../elems/ge_controller.h"
-
-
-/* -------------------------------------------------------------------------- */
class gdMainWindow : public gWindow
{
private:
- static void cb_endprogram (Fl_Widget *v, void *p);
+ static void cb_endprogram (class Fl_Widget *v, void *p);
inline void __cb_endprogram();
public:
- class gKeyboard *keyboard;
- class gBeatMeter *beatMeter;
- class gMenu *menu;
- class gInOut *inOut;
- class gController *controller;
- class gTiming *timing;
+ class geKeyboard *keyboard;
+ class geBeatMeter *beatMeter;
+ class geMainMenu *mainMenu;
+ class geMainIO *mainIO;
+ class geMainTimer *mainTimer;
+ class geMainTransport *mainTransport;
gdMainWindow(int w, int h, const char *title, int argc, char **argv);
};
-/* -------------------------------------------------------------------------- */
-
-
-class gInOut : public Fl_Group
-{
-private:
-
- class gSoundMeter *outMeter;
- class gSoundMeter *inMeter;
- class gDial *outVol;
- class gDial *inVol;
-#ifdef WITH_VST
- class gFxButton *masterFxOut;
- class gFxButton *masterFxIn;
- class gClick *inToOut;
-#endif
-
- static void cb_outVol (Fl_Widget *v, void *p);
- static void cb_inVol (Fl_Widget *v, void *p);
-#ifdef WITH_VST
- static void cb_masterFxOut(Fl_Widget *v, void *p);
- static void cb_masterFxIn (Fl_Widget *v, void *p);
- static void cb_inToOut (Fl_Widget *v, void *p);
-#endif
-
- inline void __cb_outVol ();
- inline void __cb_inVol ();
-#ifdef WITH_VST
- inline void __cb_masterFxOut();
- inline void __cb_masterFxIn ();
- inline void __cb_inToOut ();
-#endif
-
-public:
-
- gInOut(int x, int y);
-
- void refresh();
-
- inline void setOutVol(float v) { outVol->value(v); }
- inline void setInVol (float v) { inVol->value(v); }
-#ifdef WITH_VST
- inline void setMasterFxOutFull(bool v) { masterFxOut->full = v; masterFxOut->redraw(); }
- inline void setMasterFxInFull(bool v) { masterFxIn->full = v; masterFxIn->redraw(); }
-#endif
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gMenu : public Fl_Group
-{
-private:
-
- class gClick *file;
- class gClick *edit;
- class gClick *config;
- class gClick *about;
-
- static void cb_about (Fl_Widget *v, void *p);
- static void cb_config(Fl_Widget *v, void *p);
- static void cb_file (Fl_Widget *v, void *p);
- static void cb_edit (Fl_Widget *v, void *p);
-
- inline void __cb_about ();
- inline void __cb_config();
- inline void __cb_file ();
- inline void __cb_edit ();
-
-public:
-
- gMenu(int x, int y);
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gTiming : public Fl_Group
-{
-private:
-
- class gClick *bpm;
- class gClick *meter;
- class gChoice *quantizer;
- class gClick *multiplier;
- class gClick *divider;
-
- static void cb_bpm (Fl_Widget *v, void *p);
- static void cb_meter (Fl_Widget *v, void *p);
- static void cb_quantizer (Fl_Widget *v, void *p);
- static void cb_multiplier(Fl_Widget *v, void *p);
- static void cb_divider (Fl_Widget *v, void *p);
-
- inline void __cb_bpm();
- inline void __cb_meter();
- inline void __cb_quantizer();
- inline void __cb_multiplier();
- inline void __cb_divider();
-
-public:
-
- gTiming(int x, int y);
-
- void setBpm(const char *v);
- void setBpm(float v);
- void setMeter(int beats, int bars);
-};
-
-
#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gd_midiInput
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../utils/gui.h"
-#include "../../core/kernelMidi.h"
-#include "../../core/conf.h"
-#include "../../core/const.h"
-#include "../../core/sampleChannel.h"
-#include "../../utils/log.h"
-#include "../../utils/string.h"
-#include "../elems/ge_mixed.h"
-#include "../elems/ge_midiIoTools.h"
-#include "gd_midiInput.h"
-
-
-extern Conf G_Conf;
-extern KernelMidi G_KernelMidi;
-
-
-using std::string;
-
-
-gdMidiInput::gdMidiInput(int w, int h, const char *title)
- : gWindow(w, h, title)
-{
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gdMidiInput::~gdMidiInput()
-{
- G_KernelMidi.stopMidiLearn();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInput::stopMidiLearn(gLearner *learner)
-{
- G_KernelMidi.stopMidiLearn();
- learner->updateValue();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInput::__cb_learn(uint32_t *param, uint32_t msg, gLearner *l)
-{
- *param = msg;
- stopMidiLearn(l);
- gu_log("[gdMidiGrabber] MIDI learn done - message=0x%X\n", msg);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInput::cb_learn(uint32_t msg, void *d)
-{
- cbData *data = (cbData*) d;
- gdMidiInput *window = (gdMidiInput*) data->window;
- gLearner *learner = data->learner;
- uint32_t *param = learner->param;
- window->__cb_learn(param, msg, learner);
- free(data);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInput::cb_close(Fl_Widget *w, void *p) { ((gdMidiInput*)p)->__cb_close(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInput::__cb_close()
-{
- do_callback();
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gdMidiInputChannel::gdMidiInputChannel(Channel *ch)
- : gdMidiInput(300, 230, "MIDI Input Setup"),
- ch(ch)
-{
- string title = "MIDI Input Setup (channel " + gu_itoa(ch->index+1) + ")";
- label(title.c_str());
-
- set_modal();
-
- enable = new gCheck(8, 8, 120, 20, "enable MIDI input");
- new gLearner(8, 30, w()-16, "key press", cb_learn, &ch->midiInKeyPress);
- new gLearner(8, 54, w()-16, "key release", cb_learn, &ch->midiInKeyRel);
- new gLearner(8, 78, w()-16, "key kill", cb_learn, &ch->midiInKill);
- new gLearner(8, 102, w()-16, "arm", cb_learn, &ch->midiInArm);
- new gLearner(8, 126, w()-16, "mute", cb_learn, &ch->midiInMute);
- new gLearner(8, 150, w()-16, "solo", cb_learn, &ch->midiInSolo);
- new gLearner(8, 174, w()-16, "volume", cb_learn, &ch->midiInVolume);
- int yy = 202;
-
- if (ch->type == CHANNEL_SAMPLE) {
- size(300, 278);
- new gLearner(8, 198, w()-16, "pitch", cb_learn, &((SampleChannel*)ch)->midiInPitch);
- new gLearner(8, 222, w()-16, "read actions", cb_learn, &((SampleChannel*)ch)->midiInReadActions);
- yy = 250;
- }
-
- ok = new gButton(w()-88, yy, 80, 20, "Close");
- ok->callback(cb_close, (void*)this);
-
- enable->value(ch->midiIn);
- enable->callback(cb_enable, (void*)this);
-
- gu_setFavicon(this);
- show();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInputChannel::cb_enable(Fl_Widget *w, void *p) { ((gdMidiInputChannel*)p)->__cb_enable(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiInputChannel::__cb_enable()
-{
- ch->midiIn = enable->value();
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gdMidiInputMaster::gdMidiInputMaster()
- : gdMidiInput(300, 256, "MIDI Input Setup (global)")
-{
- set_modal();
-
- new gLearner(8, 8, w()-16, "rewind", &cb_learn, &G_Conf.midiInRewind);
- new gLearner(8, 32, w()-16, "play/stop", &cb_learn, &G_Conf.midiInStartStop);
- new gLearner(8, 56, w()-16, "action recording", &cb_learn, &G_Conf.midiInActionRec);
- new gLearner(8, 80, w()-16, "input recording", &cb_learn, &G_Conf.midiInInputRec);
- new gLearner(8, 104, w()-16, "metronome", &cb_learn, &G_Conf.midiInMetronome);
- new gLearner(8, 128, w()-16, "input volume", &cb_learn, &G_Conf.midiInVolumeIn);
- new gLearner(8, 152, w()-16, "output volume", &cb_learn, &G_Conf.midiInVolumeOut);
- new gLearner(8, 176, w()-16, "sequencer ×2", &cb_learn, &G_Conf.midiInBeatDouble);
- new gLearner(8, 200, w()-16, "sequencer ÷2", &cb_learn, &G_Conf.midiInBeatHalf);
- ok = new gButton(w()-88, 228, 80, 20, "Close");
-
- ok->callback(cb_close, (void*)this);
-
- gu_setFavicon(this);
- show();
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gd_midiInput
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GD_MIDI_INPUT_H
-#define GD_MIDI_INPUT_H
-
-
-#include "../elems/ge_window.h"
-
-
-class gdMidiInput : public gWindow
-{
-protected:
-
- class gClick *ok;
-
- void stopMidiLearn(class gLearner *l);
-
- /* cb_learn
- * callback attached to kernelMidi to learn various actions. */
-
- static void cb_learn (uint32_t msg, void *data);
- inline void __cb_learn(uint32_t *param, uint32_t msg, gLearner *l);
-
- static void cb_close (Fl_Widget *w, void *p);
- inline void __cb_close();
-
-public:
-
- gdMidiInput(int w, int h, const char *title);
- ~gdMidiInput();
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gdMidiInputChannel : public gdMidiInput
-{
-private:
-
- class Channel *ch;
-
- class gCheck *enable;
-
- //gVector <gLearner *> items; for future use, with vst parameters
-
- static void cb_enable (Fl_Widget *w, void *p);
- inline void __cb_enable();
-
-public:
-
- gdMidiInputChannel(class Channel *ch);
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gdMidiInputMaster : public gdMidiInput
-{
-public:
-
- gdMidiInputMaster();
-};
-
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gd_midiOutput
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/channel.h"
-#include "../../core/sampleChannel.h"
-#include "../../core/conf.h"
-#include "../../core/midiChannel.h"
-#include "../../utils/gui.h"
-#include "../../utils/log.h"
-#include "../elems/ge_mixed.h"
-#include "../elems/channel.h"
-#include "../elems/ge_midiIoTools.h"
-#include "../elems/ge_keyboard.h"
-#include "gd_midiOutput.h"
-
-
-extern Conf G_Conf;
-extern KernelMidi G_KernelMidi;
-
-
-gdMidiOutput::gdMidiOutput(int w, int h)
- : gWindow(w, h, "Midi Output Setup")
-{
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::stopMidiLearn(gLearner *learner)
-{
- G_KernelMidi.stopMidiLearn();
- learner->updateValue();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::__cb_learn(uint32_t *param, uint32_t msg, gLearner *l)
-{
- *param = msg;
- stopMidiLearn(l);
- gu_log("[gdMidiGrabber] MIDI learn done - message=0x%X\n", msg);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::cb_learn(uint32_t msg, void *d)
-{
- cbData *data = (cbData*) d;
- gdMidiOutput *window = (gdMidiOutput*) data->window;
- gLearner *learner = data->learner;
- uint32_t *param = learner->param;
- window->__cb_learn(param, msg, learner);
- free(data);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::cb_close(Fl_Widget *w, void *p) { ((gdMidiOutput*)p)->__cb_close(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::__cb_close()
-{
- do_callback();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::cb_enableLightning(Fl_Widget *w, void *p)
-{
- ((gdMidiOutput*)p)->__cb_enableLightning();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::__cb_enableLightning() {}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutput::setTitle(int chanNum)
-{
- char title[64];
- sprintf(title, "MIDI Output Setup (channel %d)", chanNum);
- copy_label(title);
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gdMidiOutputMidiCh::gdMidiOutputMidiCh(MidiChannel *ch)
- : gdMidiOutput(300, 168), ch(ch)
-{
- setTitle(ch->index+1);
- begin();
-
- enableOut = new gCheck(x()+8, y()+8, 150, 20, "Enable MIDI output");
- chanListOut = new gChoice(w()-108, y()+8, 100, 20);
-
- enableLightning = new gCheck(x()+8, chanListOut->y()+chanListOut->h()+8, 120, 20, "Enable MIDI lightning output");
- new gLearner(x()+8, enableLightning->y()+enableLightning->h()+8, w()-16, "playing", cb_learn, &ch->midiOutLplaying);
- new gLearner(x()+8, enableLightning->y()+enableLightning->h()+32, w()-16, "mute", cb_learn, &ch->midiOutLmute);
- new gLearner(x()+8, enableLightning->y()+enableLightning->h()+56, w()-16, "solo", cb_learn, &ch->midiOutLsolo);
-
- close = new gButton(w()-88, enableLightning->y()+enableLightning->h()+84, 80, 20, "Close");
-
- end();
-
- chanListOut->add("Channel 1");
- chanListOut->add("Channel 2");
- chanListOut->add("Channel 3");
- chanListOut->add("Channel 4");
- chanListOut->add("Channel 5");
- chanListOut->add("Channel 6");
- chanListOut->add("Channel 7");
- chanListOut->add("Channel 8");
- chanListOut->add("Channel 9");
- chanListOut->add("Channel 10");
- chanListOut->add("Channel 11");
- chanListOut->add("Channel 12");
- chanListOut->add("Channel 13");
- chanListOut->add("Channel 14");
- chanListOut->add("Channel 15");
- chanListOut->add("Channel 16");
- chanListOut->value(0);
-
- if (ch->midiOut)
- enableOut->value(1);
- else
- chanListOut->deactivate();
-
- if (ch->midiOutL)
- enableLightning->value(1);
-
- chanListOut->value(ch->midiOutChan);
-
- enableOut->callback(cb_enableChanList, (void*)this);
- close->callback(cb_close, (void*)this);
-
- set_modal();
- gu_setFavicon(this);
- show();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutputMidiCh::cb_close (Fl_Widget *w, void *p) { ((gdMidiOutputMidiCh*)p)->__cb_close(); }
-void gdMidiOutputMidiCh::cb_enableChanList(Fl_Widget *w, void *p) { ((gdMidiOutputMidiCh*)p)->__cb_enableChanList(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutputMidiCh::__cb_enableChanList()
-{
- enableOut->value() ? chanListOut->activate() : chanListOut->deactivate();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutputMidiCh::__cb_close()
-{
- ch->midiOut = enableOut->value();
- ch->midiOutChan = chanListOut->value();
- ch->midiOutL = enableLightning->value();
- ch->guiChannel->update();
- do_callback();
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gdMidiOutputSampleCh::gdMidiOutputSampleCh(SampleChannel *ch)
- : gdMidiOutput(300, 140), ch(ch)
-{
- setTitle(ch->index+1);
-
- enableLightning = new gCheck(8, 8, 120, 20, "Enable MIDI lightning output");
- new gLearner(8, enableLightning->y()+enableLightning->h()+8, w()-16, "playing", cb_learn, &ch->midiOutLplaying);
- new gLearner(8, enableLightning->y()+enableLightning->h()+32, w()-16, "mute", cb_learn, &ch->midiOutLmute);
- new gLearner(8, enableLightning->y()+enableLightning->h()+56, w()-16, "solo", cb_learn, &ch->midiOutLsolo);
-
- close = new gButton(w()-88, enableLightning->y()+enableLightning->h()+84, 80, 20, "Close");
- close->callback(cb_close, (void*)this);
-
- enableLightning->value(ch->midiOutL);
- enableLightning->callback(cb_enableLightning, (void*)this);
-
- set_modal();
- gu_setFavicon(this);
- show();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutputSampleCh::cb_close(Fl_Widget *w, void *p) { ((gdMidiOutputSampleCh*)p)->__cb_close(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdMidiOutputSampleCh::__cb_close()
-{
- ch->midiOutL = enableLightning->value();
- do_callback();
-}
+++ /dev/null
-/* ----------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gd_midiOutput
- *
- * ---------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GD_MIDI_OUTPUT_H
-#define GD_MIDI_OUTPUT_H
-
-
-#include <FL/Fl.H>
-#include <stdint.h>
-#include "../elems/ge_window.h"
-
-
-/* There's no such thing as a gdMidiOutputMaster vs gdMidiOutputChannel. MIDI
-output master is managed by the configuration window, hence gdMidiOutput deals
-only with channels.
-
-Both MidiOutputMidiCh and MidiOutputSampleCh have the MIDI lighting widget set.
-In addition MidiOutputMidiCh has the MIDI message output box. */
-
-/* TODO - gdMidiOutput is almost the same thing of gdMidiInput. Create another
-parent class gdMidiIO to inherit from */
-
-class gdMidiOutput : public gWindow
-{
-protected:
-
- class gClick *close;
- class gCheck *enableLightning;
-
- void stopMidiLearn(class gLearner *l);
-
- /* cb_learn
- * callback attached to kernelMidi to learn various actions. */
-
- static void cb_learn (uint32_t msg, void *data);
- inline void __cb_learn(uint32_t *param, uint32_t msg, class gLearner *l);
-
- /* cb_close
- close current window. */
-
- static void cb_close (Fl_Widget *w, void *p);
- inline void __cb_close();
-
- /* cb_enableLightning
- enable MIDI lightning output. */
-
- static void cb_enableLightning (Fl_Widget *w, void *p);
- inline void __cb_enableLightning();
-
- /* setTitle
- * set window title. */
-
- void setTitle(int chanNum);
-
-public:
-
- gdMidiOutput(int w, int h);
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gdMidiOutputMidiCh : public gdMidiOutput
-{
-private:
-
- static void cb_enableChanList (Fl_Widget *w, void *p);
- inline void __cb_enableChanList();
-
- /* __cb_close
- override parent method, we need to do more stuff on close. */
-
- static void cb_close (Fl_Widget *w, void *p);
- inline void __cb_close();
-
- class gCheck *enableOut;
- class gChoice *chanListOut;
-
- class MidiChannel *ch;
-
-public:
-
- gdMidiOutputMidiCh(class MidiChannel *ch);
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gdMidiOutputSampleCh : public gdMidiOutput
-{
-private:
-
- class SampleChannel *ch;
-
- /* __cb_close
- override parent method, we need to do more stuff on close. */
-
- static void cb_close (Fl_Widget *w, void *p);
- inline void __cb_close();
-
-public:
-
- gdMidiOutputSampleCh(class SampleChannel *ch);
-};
-
-#endif
#ifdef WITH_VST
+#include "../../glue/plugin.h"
#include "../../utils/gui.h"
#include "../../core/channel.h"
-#include "../../core/mixer.h"
#include "../../core/conf.h"
#include "../../core/pluginHost.h"
#include "../elems/ge_pluginBrowser.h"
extern PluginHost G_PluginHost;
-extern Mixer G_Mixer;
extern Conf G_Conf;
/* -------------------------------------------------------------------------- */
-void gdPluginChooser::__cb_close() {
+void gdPluginChooser::__cb_close()
+{
do_callback();
}
/* -------------------------------------------------------------------------- */
-void gdPluginChooser::__cb_sort() {
+void gdPluginChooser::__cb_sort()
+{
G_PluginHost.sortPlugins(sortMethod->value());
browser->refresh();
}
/* -------------------------------------------------------------------------- */
-void gdPluginChooser::__cb_add() {
+void gdPluginChooser::__cb_add()
+{
int index = browser->value() - 3; // subtract header lines
- if (index >= 0 && index < G_PluginHost.countAvailablePlugins()) {
- G_PluginHost.addPlugin(index, stackType, &G_Mixer.mutex_plugins, ch);
- do_callback();
- }
+ if (index < 0)
+ return;
+ glue_addPlugin(ch, index, stackType);
+ do_callback();
}
#endif // #ifdef WITH_VST
#include "../../core/plugin.h"
#include "../../core/mixer.h"
#include "../../core/channel.h"
+#include "../../glue/plugin.h"
#include "../../utils/log.h"
#include "../../utils/string.h"
#include "../elems/ge_mixed.h"
-#include "../elems/channel.h"
+#include "../elems/basics/boxtypes.h"
+#include "../elems/mainWindow/mainIO.h"
+#include "../elems/mainWindow/keyboard/channel.h"
#include "gd_pluginList.h"
#include "gd_pluginChooser.h"
#include "gd_pluginWindow.h"
list->scrollbar.color(COLOR_BG_0);
list->scrollbar.selection_color(COLOR_BG_1);
list->scrollbar.labelcolor(COLOR_BD_1);
- list->scrollbar.slider(G_BOX);
+ list->scrollbar.slider(G_CUSTOM_BORDER_BOX);
list->begin();
refreshList();
/* -------------------------------------------------------------------------- */
-gdPluginList::~gdPluginList() {
+gdPluginList::~gdPluginList()
+{
G_Conf.pluginListX = x();
G_Conf.pluginListY = y();
}
/* -------------------------------------------------------------------------- */
-void gdPluginList::cb_refreshList(Fl_Widget *v, void *p) {
-
+void gdPluginList::cb_refreshList(Fl_Widget *v, void *p)
+{
/* note: this callback is fired by gdBrowser. Close its window first,
* by calling the parent (pluginList) and telling it to delete its
* subwindow (i.e. gdBrowser). */
/* -------------------------------------------------------------------------- */
-void gdPluginList::__cb_addPlugin() {
-
+void gdPluginList::__cb_addPlugin()
+{
/* the usual callback that gWindow adds to each subwindow in this case
* is not enough, because when we close the browser the plugin list
* must be redrawn. We have a special callback, cb_refreshList, which
/* -------------------------------------------------------------------------- */
-void gdPluginList::refreshList() {
-
+void gdPluginList::refreshList()
+{
/* delete the previous list */
list->clear();
gdPluginListMaster */
if (stackType == PluginHost::MASTER_OUT) {
- G_MainWin->inOut->setMasterFxOutFull(
+ G_MainWin->mainIO->setMasterFxOutFull(
G_PluginHost.countPlugins(stackType, ch) > 0);
}
else
if (stackType == PluginHost::MASTER_IN) {
- G_MainWin->inOut->setMasterFxInFull(
+ G_MainWin->mainIO->setMasterFxInFull(
G_PluginHost.countPlugins(stackType, ch) > 0);
}
else {
remove = new gButton(shiftDown->x()+shiftDown->w()+4, y(), 20, 20, "", fxRemoveOff_xpm, fxRemoveOn_xpm);
end();
- if (pPlugin->getStatus() != 1) { // bad state
- string l = "* " + pPlugin->getName().toStdString() + " *";
- button->copy_label(l.c_str());
- }
- else {
- button->copy_label(pPlugin->getName().toStdString().c_str());
- button->callback(cb_openPluginWindow, (void*)this);
+ button->copy_label(pPlugin->getName().c_str());
+ button->callback(cb_openPluginWindow, (void*)this);
- program->callback(cb_setProgram, (void*)this);
-
- for (int i=0; i<pPlugin->getNumPrograms(); i++) {
- string name = gu_removeFltkChars(pPlugin->getProgramName(i).toStdString());
- program->add(name.c_str());
- }
+ program->callback(cb_setProgram, (void*)this);
- if (program->size() == 0) {
- program->add("-- no programs --\0");
- program->deactivate();
- }
- else
- program->value(pPlugin->getCurrentProgram());
+ for (int i=0; i<pPlugin->getNumPrograms(); i++)
+ program->add(gu_removeFltkChars(pPlugin->getProgramName(i)).c_str());
- bypass->callback(cb_setBypass, (void*)this);
- bypass->type(FL_TOGGLE_BUTTON);
- bypass->value(pPlugin->isBypassed() ? 0 : 1);
+ if (program->size() == 0) {
+ program->add("-- no programs --\0");
+ program->deactivate();
}
+ else
+ program->value(pPlugin->getCurrentProgram());
+
+ bypass->callback(cb_setBypass, (void*)this);
+ bypass->type(FL_TOGGLE_BUTTON);
+ bypass->value(pPlugin->isBypassed() ? 0 : 1);
shiftUp->callback(cb_shiftUp, (void*)this);
shiftDown->callback(cb_shiftDown, (void*)this);
/* -------------------------------------------------------------------------- */
-void gdPlugin::__cb_shiftUp() {
-
+void gdPlugin::__cb_shiftUp()
+{
/*nothing to do if there's only one plugin */
if (G_PluginHost.countPlugins(pParent->stackType, pParent->ch) == 1)
return;
- int pluginIndex = G_PluginHost.getPluginIndex(pPlugin->getId(), pParent->stackType, pParent->ch);
+ int pluginIndex = G_PluginHost.getPluginIndex(pPlugin->getId(),
+ pParent->stackType, pParent->ch);
if (pluginIndex == 0) // first of the stack, do nothing
return;
- G_PluginHost.swapPlugin(pluginIndex, pluginIndex - 1, pParent->stackType,
- &G_Mixer.mutex_plugins, pParent->ch);
+ glue_swapPlugins(pParent->ch, pluginIndex, pluginIndex-1, pParent->stackType);
pParent->refreshList();
}
/* -------------------------------------------------------------------------- */
-void gdPlugin::__cb_shiftDown() {
-
+void gdPlugin::__cb_shiftDown()
+{
/*nothing to do if there's only one plugin */
if (G_PluginHost.countPlugins(pParent->stackType, pParent->ch) == 1)
if (pluginIndex == stackSize-1) // last one in the stack, do nothing
return;
- G_PluginHost.swapPlugin(pluginIndex, pluginIndex + 1, pParent->stackType,
- &G_Mixer.mutex_plugins, pParent->ch);
+ glue_swapPlugins(pParent->ch, pluginIndex, pluginIndex+1, pParent->stackType);
pParent->refreshList();
}
/* -------------------------------------------------------------------------- */
-void gdPlugin::__cb_removePlugin() {
-
- /* any subwindow linked to the plugin must be destroyed */
+void gdPlugin::__cb_removePlugin()
+{
+ /* any subwindow linked to the plugin must be destroyed first */
pParent->delSubWindow(pPlugin->getId());
- G_PluginHost.freePlugin(pPlugin->getId(), pParent->stackType,
- &G_Mixer.mutex_plugins, pParent->ch);
-
+ glue_freePlugin(pParent->ch, pPlugin->getId(), pParent->stackType);
pParent->refreshList();
}
/* -------------------------------------------------------------------------- */
-void gdPlugin::__cb_setBypass() {
+void gdPlugin::__cb_setBypass()
+{
pPlugin->toggleBypass();
}
/* -------------------------------------------------------------------------- */
-void gdPlugin::__cb_setProgram() {
+void gdPlugin::__cb_setProgram()
+{
pPlugin->setCurrentProgram(program->value());
}
#include "../../utils/gui.h"
#include "../../core/plugin.h"
#include "../elems/ge_mixed.h"
+#include "../elems/basics/boxtypes.h"
#include "gd_pluginWindow.h"
begin();
label = new gBox(x(), y(), 60, 20);
- label->copy_label(pPlugin->getParameterName(paramIndex).toRawUTF8());
+ label->copy_label(pPlugin->getParameterName(paramIndex).c_str());
label->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
slider = new gSlider(label->x()+label->w()+8, y(), W-200, 20);
value = new gBox(slider->x()+slider->w()+8, y(), 100, 20);
value->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
- value->box(G_BOX);
+ value->box(G_CUSTOM_BORDER_BOX);
updateValue();
resizable(slider);
void Parameter::updateValue()
{
- string v = pPlugin->getParameterText(paramIndex).toStdString() + " " +
- pPlugin->getParameterLabel(paramIndex).toStdString();
+ string v = pPlugin->getParameterText(paramIndex) + " " +
+ pPlugin->getParameterLabel(paramIndex);
value->copy_label(v.c_str());
}
end();
- label(pPlugin->getName().toRawUTF8());
+ label(pPlugin->getName().c_str());
size_range(400, (24*1)+12);
resizable(list);
Fl::add_timeout(GUI_PLUGIN_RATE, cb_refresh, (void*) this);
- copy_label(pPlugin->getName().toRawUTF8());
+ copy_label(pPlugin->getName().c_str());
}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiInputBase
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/kernelMidi.h"
+#include "../../../utils/log.h"
+#include "../../elems/midiLearner.h"
+#include "midiInputBase.h"
+
+
+extern KernelMidi G_KernelMidi;
+
+
+using std::string;
+
+
+gdMidiInputBase::gdMidiInputBase(int x, int y, int w, int h, const char *title)
+ : gWindow(x, y, w, h, title)
+{
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdMidiInputBase::~gdMidiInputBase()
+{
+ G_KernelMidi.stopMidiLearn();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputBase::stopMidiLearn(geMidiLearner *learner)
+{
+ G_KernelMidi.stopMidiLearn();
+ learner->updateValue();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputBase::__cb_learn(uint32_t *param, uint32_t msg, geMidiLearner *l)
+{
+ *param = msg;
+ stopMidiLearn(l);
+ gu_log("[gdMidiGrabber] MIDI learn done - message=0x%X\n", msg);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputBase::cb_learn(uint32_t msg, void *d)
+{
+ geMidiLearner::cbData_t *data = (geMidiLearner::cbData_t *) d;
+ gdMidiInputBase *window = (gdMidiInputBase*) data->window;
+ geMidiLearner *learner = data->learner;
+ uint32_t *param = learner->param;
+ window->__cb_learn(param, msg, learner);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputBase::cb_close(Fl_Widget *w, void *p) { ((gdMidiInputBase*)p)->__cb_close(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputBase::__cb_close()
+{
+ do_callback();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiInputBase
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GD_MIDI_INPUT_BASE_H
+#define GD_MIDI_INPUT_BASE_H
+
+
+#include "../../elems/ge_window.h"
+
+
+class gdMidiInputBase : public gWindow
+{
+protected:
+
+ class gClick *ok;
+
+ void stopMidiLearn(class geMidiLearner *l);
+
+ /* cb_learn
+ * callback attached to kernelMidi to learn various actions. */
+
+ static void cb_learn (uint32_t msg, void *data);
+ inline void __cb_learn(uint32_t *param, uint32_t msg, geMidiLearner *l);
+
+ static void cb_close (Fl_Widget *w, void *p);
+ inline void __cb_close();
+
+public:
+
+ gdMidiInputBase(int x, int y, int w, int h, const char *title);
+ ~gdMidiInputBase();
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiInputChannel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 <FL/Fl_Pack.H>
+#include "../../../utils/gui.h"
+#include "../../../core/const.h"
+#include "../../../core/conf.h"
+#include "../../../core/sampleChannel.h"
+#ifdef WITH_VST
+ #include "../../../core/pluginHost.h"
+ #include "../../../core/plugin.h"
+#endif
+#include "../../../utils/string.h"
+#include "../../elems/ge_mixed.h"
+#include "../../elems/midiLearner.h"
+#include "../../elems/basics/scroll.h"
+#include "midiInputChannel.h"
+
+
+#ifdef WITH_VST
+extern PluginHost G_PluginHost;
+#endif
+extern Conf G_Conf;
+
+
+using std::string;
+
+
+gdMidiInputChannel::gdMidiInputChannel(Channel *ch)
+ : gdMidiInputBase(G_Conf.midiInputX, G_Conf.midiInputY, G_Conf.midiInputW,
+ G_Conf.midiInputH, "MIDI Input Setup"),
+ ch(ch)
+{
+ string title = "MIDI Input Setup (channel " + gu_itoa(ch->index+1) + ")";
+ label(title.c_str());
+ size_range(G_DEFAULT_MIDI_INPUT_UI_W, G_DEFAULT_MIDI_INPUT_UI_H);
+
+ enable = new gCheck(8, 8, 120, 20, "enable MIDI input");
+
+ container = new geScroll(8, enable->y()+enable->h()+4, w()-16, h()-70);
+ container->begin();
+
+ addChannelLearners();
+#ifdef WITH_VST
+ addPluginLearners();
+#endif
+
+ container->end();
+
+ ok = new gButton(w()-88, container->y()+container->h()+8, 80, 20, "Close");
+ ok->callback(cb_close, (void*)this);
+
+ enable->value(ch->midiIn);
+ enable->callback(cb_enable, (void*)this);
+
+ resizable(container);
+
+ gu_setFavicon(this);
+ set_modal();
+ show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdMidiInputChannel::~gdMidiInputChannel()
+{
+ G_Conf.midiInputX = x();
+ G_Conf.midiInputY = y();
+ G_Conf.midiInputW = w();
+ G_Conf.midiInputH = h();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputChannel::addChannelLearners()
+{
+ Fl_Pack *pack = new Fl_Pack(container->x(), container->y(), LEARNER_WIDTH, 200);
+ pack->spacing(4);
+ pack->begin();
+
+ gBox *header = new gBox(0, 0, LEARNER_WIDTH, 20, "channel");
+ header->box(FL_BORDER_BOX);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "key press", cb_learn, &ch->midiInKeyPress);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "key release", cb_learn, &ch->midiInKeyRel);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "key kill", cb_learn, &ch->midiInKill);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "arm", cb_learn, &ch->midiInArm);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "mute", cb_learn, &ch->midiInMute);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "solo", cb_learn, &ch->midiInSolo);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "volume", cb_learn, &ch->midiInVolume);
+ if (ch->type == CHANNEL_SAMPLE) {
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "pitch", cb_learn, &((SampleChannel*)ch)->midiInPitch);
+ new geMidiLearner(0, 0, LEARNER_WIDTH, "read actions", cb_learn, &((SampleChannel*)ch)->midiInReadActions);
+ }
+
+ pack->end();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+void gdMidiInputChannel::addPluginLearners()
+{
+ vector <Plugin *> *plugins = G_PluginHost.getStack(PluginHost::CHANNEL, ch);
+ for (unsigned i=0; i<plugins->size(); i++) {
+
+ Fl_Pack *pack = new Fl_Pack(container->x() + ((i + 1) * (LEARNER_WIDTH + 8)),
+ container->y(), LEARNER_WIDTH, 200);
+ pack->spacing(4);
+ pack->begin();
+
+ Plugin *plugin = plugins->at(i);
+
+ gBox *header = new gBox(0, 0, LEARNER_WIDTH, 20, plugin->getName().c_str());
+ header->box(FL_BORDER_BOX);
+
+ for (int k=0; k<plugin->getNumParameters(); k++)
+ new geMidiLearner(0, 0, LEARNER_WIDTH, plugin->getParameterName(k).c_str(),
+ cb_learn, &plugin->midiInParams.at(k));
+
+ pack->end();
+ }
+}
+
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputChannel::cb_enable(Fl_Widget *w, void *p) { ((gdMidiInputChannel*)p)->__cb_enable(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiInputChannel::__cb_enable()
+{
+ ch->midiIn = enable->value();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiInputChannel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GD_MIDI_INPUT_CHANNEL_H
+#define GD_MIDI_INPUT_CHANNEL_H
+
+
+#include "midiInputBase.h"
+
+
+class gdMidiInputChannel : public gdMidiInputBase
+{
+private:
+
+ static const int LEARNER_WIDTH = 284;
+
+ class Channel *ch;
+
+ class geScroll *container;
+ class gCheck *enable;
+
+ //gVector <geMidiLearner *> items; // plugins parameters
+
+ static void cb_enable (Fl_Widget *w, void *p);
+ inline void __cb_enable();
+
+ void addChannelLearners();
+
+#ifdef WITH_VST
+
+ void addPluginLearners();
+
+#endif
+
+public:
+
+ gdMidiInputChannel(class Channel *ch);
+ ~gdMidiInputChannel();
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiInputMaster
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../utils/gui.h"
+#include "../../../core/conf.h"
+#include "../../elems/ge_mixed.h"
+#include "../../elems/midiLearner.h"
+#include "midiInputMaster.h"
+
+
+extern Conf G_Conf;
+
+
+gdMidiInputMaster::gdMidiInputMaster()
+ : gdMidiInputBase(0, 0, 300, 256, "MIDI Input Setup (global)")
+{
+ set_modal();
+
+ new geMidiLearner(8, 8, w()-16, "rewind", &cb_learn, &G_Conf.midiInRewind);
+ new geMidiLearner(8, 32, w()-16, "play/stop", &cb_learn, &G_Conf.midiInStartStop);
+ new geMidiLearner(8, 56, w()-16, "action recording", &cb_learn, &G_Conf.midiInActionRec);
+ new geMidiLearner(8, 80, w()-16, "input recording", &cb_learn, &G_Conf.midiInInputRec);
+ new geMidiLearner(8, 104, w()-16, "metronome", &cb_learn, &G_Conf.midiInMetronome);
+ new geMidiLearner(8, 128, w()-16, "input volume", &cb_learn, &G_Conf.midiInVolumeIn);
+ new geMidiLearner(8, 152, w()-16, "output volume", &cb_learn, &G_Conf.midiInVolumeOut);
+ new geMidiLearner(8, 176, w()-16, "sequencer ×2", &cb_learn, &G_Conf.midiInBeatDouble);
+ new geMidiLearner(8, 200, w()-16, "sequencer ÷2", &cb_learn, &G_Conf.midiInBeatHalf);
+ ok = new gButton(w()-88, 228, 80, 20, "Close");
+
+ ok->callback(cb_close, (void*)this);
+
+ gu_setFavicon(this);
+ show();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiInputMaster
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GD_MIDI_INPUT_MASTER_H
+#define GD_MIDI_INPUT_MASTER_H
+
+
+#include "midiInputBase.h"
+
+
+class gdMidiInputMaster : public gdMidiInputBase
+{
+public:
+
+ gdMidiInputMaster();
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * gd_midiOutput
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../utils/log.h"
+#include "../../elems/midiLearner.h"
+#include "midiOutputBase.h"
+
+
+extern KernelMidi G_KernelMidi;
+
+
+gdMidiOutputBase::gdMidiOutputBase(int w, int h)
+ : gWindow(w, h, "Midi Output Setup")
+{
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::stopMidiLearn(geMidiLearner *learner)
+{
+ G_KernelMidi.stopMidiLearn();
+ learner->updateValue();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::__cb_learn(uint32_t *param, uint32_t msg, geMidiLearner *l)
+{
+ *param = msg;
+ stopMidiLearn(l);
+ gu_log("[gdMidiGrabber] MIDI learn done - message=0x%X\n", msg);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::cb_learn(uint32_t msg, void *d)
+{
+ geMidiLearner::cbData_t *data = (geMidiLearner::cbData_t*) d;
+ gdMidiOutputBase *window = (gdMidiOutputBase*) data->window;
+ geMidiLearner *learner = data->learner;
+ uint32_t *param = learner->param;
+ window->__cb_learn(param, msg, learner);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::cb_close(Fl_Widget *w, void *p) { ((gdMidiOutputBase*)p)->__cb_close(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::__cb_close()
+{
+ do_callback();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::cb_enableLightning(Fl_Widget *w, void *p)
+{
+ ((gdMidiOutputBase*)p)->__cb_enableLightning();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::__cb_enableLightning() {}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputBase::setTitle(int chanNum)
+{
+ char title[64];
+ sprintf(title, "MIDI Output Setup (channel %d)", chanNum);
+ copy_label(title);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * gd_midiOutput
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GD_MIDI_OUTPUT_BASE_H
+#define GD_MIDI_OUTPUT_BASE_H
+
+
+#include <FL/Fl.H>
+#include "../../elems/ge_window.h"
+
+
+/* There's no such thing as a gdMidiOutputMaster vs gdMidiOutputChannel. MIDI
+output master is managed by the configuration window, hence gdMidiOutput deals
+only with channels.
+
+Both MidiOutputMidiCh and MidiOutputSampleCh have the MIDI lighting widget set.
+In addition MidiOutputMidiCh has the MIDI message output box. */
+
+/* TODO - gdMidiOutput is almost the same thing of gdMidiInput. Create another
+parent class gdMidiIO to inherit from */
+
+class gdMidiOutputBase : public gWindow
+{
+protected:
+
+ class gClick *close;
+ class gCheck *enableLightning;
+
+ void stopMidiLearn(class geMidiLearner *l);
+
+ /* cb_learn
+ * callback attached to kernelMidi to learn various actions. */
+
+ static void cb_learn (uint32_t msg, void *data);
+ inline void __cb_learn(uint32_t *param, uint32_t msg, class geMidiLearner *l);
+
+ /* cb_close
+ close current window. */
+
+ static void cb_close (Fl_Widget *w, void *p);
+ inline void __cb_close();
+
+ /* cb_enableLightning
+ enable MIDI lightning output. */
+
+ static void cb_enableLightning (Fl_Widget *w, void *p);
+ inline void __cb_enableLightning();
+
+ /* setTitle
+ * set window title. */
+
+ void setTitle(int chanNum);
+
+public:
+
+ gdMidiOutputBase(int w, int h);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiOutputMidiCh
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/midiChannel.h"
+#include "../../../utils/gui.h"
+#include "../../elems/ge_mixed.h"
+#include "../../elems/midiLearner.h"
+#include "../../elems/mainWindow/keyboard/channel.h"
+#include "midiOutputMidiCh.h"
+
+
+gdMidiOutputMidiCh::gdMidiOutputMidiCh(MidiChannel *ch)
+ : gdMidiOutputBase(300, 168), ch(ch)
+{
+ setTitle(ch->index+1);
+ begin();
+
+ enableOut = new gCheck(x()+8, y()+8, 150, 20, "Enable MIDI output");
+ chanListOut = new gChoice(w()-108, y()+8, 100, 20);
+
+ enableLightning = new gCheck(x()+8, chanListOut->y()+chanListOut->h()+8, 120, 20, "Enable MIDI lightning output");
+ new geMidiLearner(x()+8, enableLightning->y()+enableLightning->h()+8, w()-16, "playing", cb_learn, &ch->midiOutLplaying);
+ new geMidiLearner(x()+8, enableLightning->y()+enableLightning->h()+32, w()-16, "mute", cb_learn, &ch->midiOutLmute);
+ new geMidiLearner(x()+8, enableLightning->y()+enableLightning->h()+56, w()-16, "solo", cb_learn, &ch->midiOutLsolo);
+
+ close = new gButton(w()-88, enableLightning->y()+enableLightning->h()+84, 80, 20, "Close");
+
+ end();
+
+ chanListOut->add("Channel 1");
+ chanListOut->add("Channel 2");
+ chanListOut->add("Channel 3");
+ chanListOut->add("Channel 4");
+ chanListOut->add("Channel 5");
+ chanListOut->add("Channel 6");
+ chanListOut->add("Channel 7");
+ chanListOut->add("Channel 8");
+ chanListOut->add("Channel 9");
+ chanListOut->add("Channel 10");
+ chanListOut->add("Channel 11");
+ chanListOut->add("Channel 12");
+ chanListOut->add("Channel 13");
+ chanListOut->add("Channel 14");
+ chanListOut->add("Channel 15");
+ chanListOut->add("Channel 16");
+ chanListOut->value(0);
+
+ if (ch->midiOut)
+ enableOut->value(1);
+ else
+ chanListOut->deactivate();
+
+ if (ch->midiOutL)
+ enableLightning->value(1);
+
+ chanListOut->value(ch->midiOutChan);
+
+ enableOut->callback(cb_enableChanList, (void*)this);
+ close->callback(cb_close, (void*)this);
+
+ set_modal();
+ gu_setFavicon(this);
+ show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputMidiCh::cb_close (Fl_Widget *w, void *p) { ((gdMidiOutputMidiCh*)p)->__cb_close(); }
+void gdMidiOutputMidiCh::cb_enableChanList(Fl_Widget *w, void *p) { ((gdMidiOutputMidiCh*)p)->__cb_enableChanList(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputMidiCh::__cb_enableChanList()
+{
+ enableOut->value() ? chanListOut->activate() : chanListOut->deactivate();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputMidiCh::__cb_close()
+{
+ ch->midiOut = enableOut->value();
+ ch->midiOutChan = chanListOut->value();
+ ch->midiOutL = enableLightning->value();
+ ch->guiChannel->update();
+ do_callback();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiOutputMidiCh
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GD_MIDI_OUTPUT_MIDI_CH_H
+#define GD_MIDI_OUTPUT_MIDI_CH_H
+
+
+#include "midiOutputBase.h"
+
+
+class gdMidiOutputMidiCh : public gdMidiOutputBase
+{
+private:
+
+ static void cb_enableChanList (Fl_Widget *w, void *p);
+ inline void __cb_enableChanList();
+
+ /* __cb_close
+ override parent method, we need to do more stuff on close. */
+
+ static void cb_close (Fl_Widget *w, void *p);
+ inline void __cb_close();
+
+ class gCheck *enableOut;
+ class gChoice *chanListOut;
+
+ class MidiChannel *ch;
+
+public:
+
+ gdMidiOutputMidiCh(class MidiChannel *ch);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiOutputSampleCh
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/sampleChannel.h"
+#include "../../../utils/gui.h"
+#include "../../elems/ge_mixed.h"
+#include "../../elems/midiLearner.h"
+#include "midiOutputSampleCh.h"
+
+
+gdMidiOutputSampleCh::gdMidiOutputSampleCh(SampleChannel *ch)
+ : gdMidiOutputBase(300, 140), ch(ch)
+{
+ setTitle(ch->index+1);
+
+ enableLightning = new gCheck(8, 8, 120, 20, "Enable MIDI lightning output");
+ new geMidiLearner(8, enableLightning->y()+enableLightning->h()+8, w()-16, "playing", cb_learn, &ch->midiOutLplaying);
+ new geMidiLearner(8, enableLightning->y()+enableLightning->h()+32, w()-16, "mute", cb_learn, &ch->midiOutLmute);
+ new geMidiLearner(8, enableLightning->y()+enableLightning->h()+56, w()-16, "solo", cb_learn, &ch->midiOutLsolo);
+
+ close = new gButton(w()-88, enableLightning->y()+enableLightning->h()+84, 80, 20, "Close");
+ close->callback(cb_close, (void*)this);
+
+ enableLightning->value(ch->midiOutL);
+ enableLightning->callback(cb_enableLightning, (void*)this);
+
+ set_modal();
+ gu_setFavicon(this);
+ show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputSampleCh::cb_close(Fl_Widget *w, void *p) { ((gdMidiOutputSampleCh*)p)->__cb_close(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdMidiOutputSampleCh::__cb_close()
+{
+ ch->midiOutL = enableLightning->value();
+ do_callback();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiOutputSampleCh
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GD_MIDI_OUTPUT_SAMPLE_CH_H
+#define GD_MIDI_OUTPUT_SAMPLE_CH_H
+
+
+#include "midiOutputBase.h"
+
+
+class gdMidiOutputSampleCh : public gdMidiOutputBase
+{
+private:
+
+ class SampleChannel *ch;
+
+ /* __cb_close
+ override parent method, we need to do more stuff on close. */
+
+ static void cb_close (Fl_Widget *w, void *p);
+ inline void __cb_close();
+
+public:
+
+ gdMidiOutputSampleCh(class SampleChannel *ch);
+};
+
+#endif
#include "../../utils/log.h"
#include "../dialogs/gd_mainWindow.h"
#include "../dialogs/gd_actionEditor.h"
-#include "ge_keyboard.h"
+#include "mainWindow/keyboard/keyboard.h"
#include "actionEditor.h"
//gu_log("action added, [%d]\n", frame_a);
}
+ parent->chan->hasActions = true;
+
G_Recorder.sortActions();
index++; // important!
* actions. */
if (ch->mode == SINGLE_PRESS) {
- G_Recorder.deleteAction(parent->chan->index, frame_a, ACTION_KEYPRESS, false);
- G_Recorder.deleteAction(parent->chan->index, frame_b, ACTION_KEYREL, false);
+ G_Recorder.deleteAction(parent->chan->index, frame_a, ACTION_KEYPRESS,
+ false, &G_Mixer.mutex_recs);
+ G_Recorder.deleteAction(parent->chan->index, frame_b, ACTION_KEYREL,
+ false, &G_Mixer.mutex_recs);
}
else
- G_Recorder.deleteAction(parent->chan->index, frame_a, type, false);
+ G_Recorder.deleteAction(parent->chan->index, frame_a, type, false,
+ &G_Mixer.mutex_recs);
+
+ parent->chan->hasActions = G_Recorder.hasActions(parent->chan->index);
+
/* restore the initial cursor shape, in case you delete an action and
* the double arrow (for resizing) is displayed */
G_Recorder.rec(parent->chan->index, ACTION_KEYREL, frame_b);
}
+ parent->chan->hasActions = true;
+
G_Recorder.sortActions();
}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * boxtypes
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 <FL/fl_draw.H>
+#include "../../../core/const.h"
+#include "boxtypes.h"
+
+
+void g_customBorderBox(int x, int y, int w, int h, Fl_Color c)
+{
+ fl_color(c);
+ fl_rectf(x, y, w, h);
+ fl_color(COLOR_BD_0);
+ 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_rectf(x, y, w, h);
+ fl_color(COLOR_BG_0);
+ fl_rect(x, y, w, h);
+}
+
+
+void g_customDownBox(int x, int y, int w, int h, Fl_Color c)
+{
+ fl_color(c);
+ fl_rectf(x, y, w, h);
+ fl_color(COLOR_BG_0);
+ fl_rect(x, y, w, h);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * boxtypes
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 __BOXTYPES_H__
+#define __BOXTYPES_H__
+
+
+#include <FL/Fl.H>
+
+
+#define G_CUSTOM_BORDER_BOX FL_FREE_BOXTYPE
+#define G_CUSTOM_UP_BOX (Fl_Boxtype)(FL_FREE_BOXTYPE + 1)
+#define G_CUSTOM_DOWN_BOX (Fl_Boxtype)(FL_FREE_BOXTYPE + 3)
+
+
+void g_customBorderBox(int x, int y, int w, int h, Fl_Color c);
+void g_customUpBox (int x, int y, int w, int h, Fl_Color c);
+void g_customDownBox (int x, int y, int w, int h, Fl_Color c);
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * geScroll
+ * Custom scroll with nice scrollbars and something else.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/const.h"
+#include "boxtypes.h"
+#include "scroll.h"
+
+
+geScroll::geScroll(int x, int y, int w, int h, int t)
+ : Fl_Scroll(x, y, w, h)
+{
+ type(t);
+
+ scrollbar.color(COLOR_BG_0);
+ scrollbar.selection_color(COLOR_BG_1);
+ scrollbar.labelcolor(COLOR_BD_1);
+ scrollbar.slider(G_CUSTOM_BORDER_BOX);
+
+ hscrollbar.color(COLOR_BG_0);
+ hscrollbar.selection_color(COLOR_BG_1);
+ hscrollbar.labelcolor(COLOR_BD_1);
+ hscrollbar.slider(G_CUSTOM_BORDER_BOX);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * geScroll
+ * Custom scroll with nice scrollbars and something else.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 __GE_SCROLL_H__
+#define __GE_SCROLL_H__
+
+
+#include <FL/Fl_Scroll.H>
+
+
+class geScroll : public Fl_Scroll
+{
+public:
+
+ geScroll(int x, int y, int w, int h, int type=Fl_Scroll::BOTH);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_browser
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../core/const.h"
+#include "../../utils/string.h"
+#include "../dialogs/gd_browser.h"
+#include "../elems/ge_mixed.h"
+#include "basics/boxtypes.h"
+#include "browser.h"
+
+
+geBrowser::geBrowser(int x, int y, int w, int h)
+ : Fl_File_Browser(x, y, w, h),
+ 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);
+ 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.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.slider(G_CUSTOM_BORDER_BOX);
+
+ take_focus(); // let it have focus on startup
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geBrowser::toggleHiddenFiles()
+{
+ showHiddenFiles = !showHiddenFiles;
+ loadDir(currentDir);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geBrowser::loadDir(const string &dir)
+{
+ currentDir = dir;
+ load(currentDir.c_str());
+
+ /* Clean up unwanted elements. Hide "../" first, it just screws up things.
+ Also remove hidden files, if requested. */
+
+ for (int i=size(); i>=0; i--) {
+ if (text(i) == nullptr)
+ continue;
+ if (strcmp(text(i), "../") == 0 || (!showHiddenFiles && strncmp(text(i), ".", 1) == 0))
+ remove(i);
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+int geBrowser::handle(int e)
+{
+ int ret = Fl_File_Browser::handle(e);
+ switch (e) {
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ ret = 1; // enables receiving Keyboard events
+ break;
+ case FL_KEYDOWN: // keyboard
+ if (Fl::event_key(FL_Down))
+ select(value() + 1);
+ else
+ if (Fl::event_key(FL_Up))
+ select(value() - 1);
+ else
+ if (Fl::event_key(FL_Enter))
+ ((gdBaseBrowser*) parent())->fireCallback();
+ ret = 1;
+ break;
+ case FL_PUSH: // mouse
+ if (Fl::event_clicks() > 0) // double click
+ ((gdBaseBrowser*) parent())->fireCallback();
+ ret = 1;
+ break;
+ case FL_RELEASE: // mouse
+ /* nasty trick to keep the selection on mouse release */
+ if (value() > 1) {
+ select(value() - 1);
+ select(value() + 1);
+ }
+ else {
+ select(value() + 1);
+ select(value() - 1);
+ }
+ ret = 1;
+ break;
+ }
+ return ret;
+}
+
+/* -------------------------------------------------------------------------- */
+
+
+string geBrowser::getCurrentDir()
+{
+ return normalize(gu_getRealPath(currentDir));
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string geBrowser::getSelectedItem(bool fullPath)
+{
+ if (!fullPath) // no full path requested? return the selected text
+ return normalize(text(value()));
+ else
+ if (value() == 0) // no rows selected? return current directory
+ return normalize(currentDir);
+ else
+ return normalize(gu_getRealPath(currentDir + G_SLASH + normalize(text(value()))));
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geBrowser::preselect(int pos, int line)
+{
+ position(pos);
+ select(line);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string geBrowser::normalize(const string &s)
+{
+ string out = s;
+
+ /* If string ends with G_SLASH, remove it. Don't do it if has length > 1, it
+ means that the string is just '/'. Note: our crappy version of Clang doesn't
+ seem to support std::string::back() */
+
+#ifdef __APPLE__
+ if (out[out.length() - 1] == G_SLASH && out.length() > 1)
+#else
+ if (out.back() == G_SLASH && out.length() > 1)
+#endif
+
+ out = out.substr(0, out.size()-1);
+ return out;
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_browser
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_BROWSER_H
+#define GE_BROWSER_H
+
+
+#include <string>
+#include <FL/Fl_File_Browser.H>
+
+
+using std::string;
+
+
+class geBrowser : public Fl_File_Browser
+{
+private:
+
+ string currentDir;
+ bool showHiddenFiles;
+
+ /* normalize
+ * Make sure the string never ends with a trailing slash. */
+
+ string normalize(const string &s);
+
+public:
+
+ geBrowser(int x, int y, int w, int h);
+
+ void toggleHiddenFiles();
+
+ /* init
+ * Initialize browser and show 'dir' as initial directory. */
+
+ void loadDir(const string &dir);
+
+ /* getSelectedItem
+ * Return the full path or just the displayed name of the i-th selected item.
+ * Always with the trailing slash! */
+
+ string getSelectedItem(bool fullPath=true);
+
+ string getCurrentDir();
+
+ void preselect(int position, int line);
+
+ int handle(int e);
+};
+
+#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_channel
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/mixer.h"
-#include "../../core/conf.h"
-#include "../../core/channel.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/graphics.h"
-#include "../../core/pluginHost.h"
-#include "../../utils/gui.h"
-#include "../../glue/channel.h"
-#include "../../glue/main.h"
-#include "../dialogs/gd_mainWindow.h"
-#include "../dialogs/gd_pluginList.h"
-#include "ge_column.h"
-#include "channelButton.h"
-#include "channel.h"
-
-
-extern Mixer G_Mixer;
-extern Conf G_Conf;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern gdMainWindow *G_MainWin;
-
-
-geChannel::geChannel(int X, int Y, int W, int H, int type, Channel *ch)
- : Fl_Group(X, Y, W, H, NULL),
- ch (ch),
- type (type)
-{
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::cb_arm(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_arm(); }
-void geChannel::cb_mute(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_mute(); }
-void geChannel::cb_solo(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_solo(); }
-void geChannel::cb_changeVol(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_changeVol(); }
-#ifdef WITH_VST
-void geChannel::cb_openFxWindow(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_openFxWindow(); }
-#endif
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::__cb_arm()
-{
- glue_toggleArm(ch, true);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::__cb_mute()
-{
- glue_setMute(ch);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::__cb_solo()
-{
- solo->value() ? glue_setSoloOn(ch) : glue_setSoloOff(ch);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::__cb_changeVol()
-{
- glue_setChanVol(ch, vol->value());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-void geChannel::__cb_openFxWindow()
-{
- gu_openSubWindow(G_MainWin, new gdPluginList(PluginHost::CHANNEL, ch), WID_FX_LIST);
-}
-#endif
-
-
-/* -------------------------------------------------------------------------- */
-
-
-int geChannel::keyPress(int e)
-{
- return handleKey(e, ch->key);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-
-int geChannel::getColumnIndex()
-{
- return ((gColumn*)parent())->getIndex();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::blink()
-{
- if (gu_getBlinker() > 6)
- mainButton->setPlayMode();
- else
- mainButton->setDefaultMode();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::setColorsByStatus(int playStatus, int recStatus)
-{
- switch (playStatus) {
- case STATUS_OFF:
- case STATUS_EMPTY:
- mainButton->setDefaultMode();
- button->imgOn = channelPlay_xpm;
- button->imgOff = channelStop_xpm;
- button->redraw();
- break;
- case STATUS_PLAY:
- mainButton->setPlayMode();
- button->imgOn = channelStop_xpm;
- button->imgOff = channelPlay_xpm;
- button->redraw();
- break;
- case STATUS_WAIT:
- blink();
- break;
- case STATUS_ENDING:
- mainButton->setEndingMode();
- break;
- }
-
- switch (recStatus) {
- case REC_WAITING:
- blink();
- break;
- case REC_ENDING:
- mainButton->setEndingMode();
- break;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannel::packWidgets()
-{
- /* Count visible widgets and resize mainButton according to how many widgets
- are visible. */
-
- int visibles = 0;
- for (int i=0; i<children(); i++) {
- child(i)->size(20, 20); // also normalize widths
- if (child(i)->visible())
- visibles++;
- }
- mainButton->size(w() - ((visibles - 1) * (24)), 20); // -1: exclude itself
-
- /* Reposition everything else */
-
- for (int i=1, p=0; i<children(); i++) {
- if (!child(i)->visible())
- continue;
- for (int k=i-1; k>=0; k--) // Get the first visible item prior to i
- if (child(k)->visible()) {
- p = k;
- break;
- }
- child(i)->position(child(p)->x() + child(p)->w() + 4, y());
- }
-
- init_sizes(); // Resets the internal array of widget sizes and positions
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-int geChannel::handleKey(int e, int key)
-{
- int ret;
- if (e == FL_KEYDOWN && button->value()) // key already pressed! skip it
- ret = 1;
- else
- if (Fl::event_key() == key && !button->value()) {
- button->take_focus(); // move focus to this button
- button->value((e == FL_KEYDOWN || e == FL_SHORTCUT) ? 1 : 0); // change the button's state
- button->do_callback(); // invoke the button's callback
- ret = 1;
- }
- else
- ret = 0;
-
- if (Fl::event_key() == key)
- button->value((e == FL_KEYDOWN || e == FL_SHORTCUT) ? 1 : 0); // change the button's state
-
- return ret;
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_channel
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_CHANNEL_H
-#define GE_CHANNEL_H
-
-
-#include <FL/Fl_Group.H>
-
-
-class geChannel : public Fl_Group
-{
-protected:
-
- /* Define some breakpoints for dynamic resize. BREAK_DELTA: base amount of
- pixels to shrink sampleButton. */
-
-#ifdef WITH_VST
- static const int BREAK_READ_ACTIONS = 240;
- static const int BREAK_MODE_BOX = 216;
- static const int BREAK_FX = 192;
- static const int BREAK_ARM = 168;
-#else
- static const int BREAK_READ_ACTIONS = 216;
- static const int BREAK_MODE_BOX = 192;
- static const int BREAK_ARM = 168;
-#endif
-
- static void cb_arm (Fl_Widget *v, void *p);
- static void cb_mute (Fl_Widget *v, void *p);
- static void cb_solo (Fl_Widget *v, void *p);
- static void cb_changeVol (Fl_Widget *v, void *p);
-#ifdef WITH_VST
- static void cb_openFxWindow(Fl_Widget *v, void *p);
-#endif
-
- inline void __cb_mute();
- inline void __cb_arm();
- inline void __cb_solo();
- inline void __cb_changeVol();
-#ifdef WITH_VST
- inline void __cb_openFxWindow();
-#endif
-
- /* blink
- * blink button when channel is in wait/ending status. */
-
- void blink();
-
- /* setColorByStatus
- * update colors depending on channel status. */
-
- void setColorsByStatus(int playStatus, int recStatus);
-
- /* handleKey
- * method wrapped by virtual handle(int e). */
-
- int handleKey(int e, int key);
-
- /* packWidgets
- Spread widgets across available space. */
-
- void packWidgets();
-
-public:
-
- geChannel(int x, int y, int w, int h, int type, class Channel *ch);
-
- /* reset
- * reset channel to initial status. */
-
- virtual void reset() = 0;
-
- /* update
- * update the label of sample button and everything else such as 'R'
- * button, key box and so on, according to global values. */
-
- virtual void update() = 0;
-
- /* refresh
- * update graphics. */
-
- virtual void refresh() = 0;
-
- /* keypress
- * what to do when the corresponding key is pressed. */
-
- int keyPress(int event);
-
- /* getColumnIndex
- * return the numeric index of the column in which this channel is
- * located. */
-
- int getColumnIndex();
-
- class Channel *ch;
-
- class gButton *button;
- class gStatus *status;
- class gClick *arm;
- class geChannelButton *mainButton;
- class gClick *mute;
- class gClick *solo;
- class gDial *vol;
-#ifdef WITH_VST
- class gFxButton *fx;
-#endif
-
- int type;
-};
-
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_channelButton
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/const.h"
-#include "../../utils/fs.h"
-#include "channelButton.h"
-
-
-using std::string;
-
-
-geChannelButton::geChannelButton(int x, int y, int w, int h, const char *l)
- : gClick(x, y, w, h, l), key("") {}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setKey(const string &k)
-{
- key = k;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setKey(int k)
-{
- if (k == 0)
- key = "";
- else {
- // FIXME - this crap won't work with unicode/utf-8
- char c = (char) k;
- key = c;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::draw()
-{
- gClick::draw();
-
- if (key == "")
- return;
-
- /* draw background */
-
- fl_rectf(x()+1, y()+1, 18, h()-2, bgColor0);
-
- /* draw key */
-
- fl_color(COLOR_TEXT_0);
- fl_font(FL_HELVETICA, 11);
- fl_draw(key.c_str(), x(), y(), 18, h(), FL_ALIGN_CENTER);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setInputRecordMode()
-{
- bgColor0 = COLOR_BG_3;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setActionRecordMode()
-{
- bgColor0 = COLOR_BG_4;
- txtColor = COLOR_TEXT_0;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setDefaultMode(const char *l)
-{
- bgColor0 = COLOR_BG_0;
- bdColor = COLOR_BD_0;
- txtColor = COLOR_TEXT_0;
- if (l)
- label(l);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setPlayMode()
-{
- bgColor0 = COLOR_BG_2;
- bdColor = COLOR_BD_1;
- txtColor = COLOR_TEXT_1;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geChannelButton::setEndingMode()
-{
- bgColor0 = COLOR_BD_0;
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_channelButton
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_CHANNEL_BUTTON_H
-#define GE_CHANNEL_BUTTON_H
-
-
-#include "ge_mixed.h"
-
-
-using std::string;
-
-
-class geChannelButton : public gClick
-{
-private:
-
- string key;
-
-public:
-
- geChannelButton(int x, int y, int w, int h, const char *l=0);
-
- virtual int handle(int e) = 0;
-
- void draw();
- void setKey(const string &k);
- void setKey(int k);
- void setPlayMode();
- void setEndingMode();
- void setDefaultMode(const char *l=0);
- void setInputRecordMode();
- void setActionRecordMode();
-};
-
-
-#endif
#include "../../core/mixer.h"
#include "../dialogs/gd_actionEditor.h"
#include "../dialogs/gd_mainWindow.h"
-#include "ge_keyboard.h"
+#include "mainWindow/keyboard/keyboard.h"
#include "envelopeEditor.h"
G_Recorder.rec(pParent->chan->index, type, 0, 0, 1.0f);
addPoint(G_Mixer.totalFrames, 0, 1.0f, pParent->coverX, 1);
G_Recorder.rec(pParent->chan->index, type, G_Mixer.totalFrames, 0, 1.0f);
+ pParent->chan->hasActions = true;
}
/* line between 2 points y = (x-a) / (b-a); a = h() - 8; b = 1 */
float value = (my - h() + 8) / (float) (1 - h() + 8);
addPoint(frame, 0, value, mx, my);
G_Recorder.rec(pParent->chan->index, type, frame, 0, value);
+ pParent->chan->hasActions = true;
G_Recorder.sortActions();
sortPoints();
}
if (selectedPoint != -1) {
if (selectedPoint == 0 || (unsigned) selectedPoint == points.size()-1) {
G_Recorder.clearAction(pParent->chan->index, type);
+ pParent->chan->hasActions = G_Recorder.hasActions(pParent->chan->index);
points.clear();
}
else {
- G_Recorder.deleteAction(pParent->chan->index, points.at(selectedPoint).frame, type, false);
- G_Recorder.sortActions();
+ G_Recorder.deleteAction(pParent->chan->index,
+ points.at(selectedPoint).frame, type, false, &G_Mixer.mutex_recs);
+ pParent->chan->hasActions = G_Recorder.hasActions(pParent->chan->index);
+ G_Recorder.sortActions();
points.erase(points.begin() + selectedPoint);
}
G_MainWin->keyboard->setChannelWithActions((geSampleChannel*)pParent->chan->guiChannel); // update mainWindow
/* delete previous point and record a new one */
- G_Recorder.deleteAction(pParent->chan->index, points.at(draggedPoint).frame, type, false);
+ G_Recorder.deleteAction(pParent->chan->index,
+ points.at(draggedPoint).frame, type, false, &G_Mixer.mutex_recs);
+ pParent->chan->hasActions = G_Recorder.hasActions(pParent->chan->index);
if (range == RANGE_FLOAT) {
float value = (points.at(draggedPoint).y - h() + 8) / (float) (1 - h() + 8);
G_Recorder.rec(pParent->chan->index, type, newFrame, 0, value);
+ pParent->chan->hasActions = true;
}
else {
/// TODO
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gd_browser
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 <limits.h>
-#include "../../core/const.h"
-#include "../../utils/fs.h"
-#include "../../utils/string.h"
-#include "../../utils/log.h"
-#include "../dialogs/gd_browser.h"
-#include "ge_browser.h"
-
-
-gBrowser::gBrowser(int x, int y, int w, int h)
- : Fl_File_Browser(x, y, w, h)
-{
- box(G_BOX);
- textsize(GUI_FONT_SIZE_BASE);
- textcolor(COLOR_TEXT_0);
- selection_color(COLOR_BG_1);
- color(COLOR_BG_0);
- 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.slider(G_BOX);
-
- this->hscrollbar.color(COLOR_BG_0);
- this->hscrollbar.selection_color(COLOR_BG_1);
- this->hscrollbar.labelcolor(COLOR_BD_1);
- this->hscrollbar.slider(G_BOX);
-
- take_focus(); // let it have focus on startup
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gBrowser::loadDir(const string &dir)
-{
- currentDir = dir;
- load(currentDir.c_str());
-
- /* hide "../", it just screws up things */
-
- if (text(1) != NULL && strcmp(text(1), "../") == 0)
- remove(1);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-int gBrowser::handle(int e)
-{
- int ret = Fl_File_Browser::handle(e);
- switch (e) {
- case FL_FOCUS:
- case FL_UNFOCUS:
- ret = 1; // enables receiving Keyboard events
- break;
- case FL_KEYDOWN: // keyboard
- if (Fl::event_key(FL_Down))
- select(value() + 1);
- else
- if (Fl::event_key(FL_Up))
- select(value() - 1);
- else
- if (Fl::event_key(FL_Enter))
- ((gdBaseBrowser*) parent())->fireCallback();
- ret = 1;
- break;
- case FL_PUSH: // mouse
- if (Fl::event_clicks() > 0) // double click
- ((gdBaseBrowser*) parent())->fireCallback();
- ret = 1;
- break;
- case FL_RELEASE: // mouse
- /* nasty trick to keep the selection on mouse release */
- if (value() > 1) {
- select(value() - 1);
- select(value() + 1);
- }
- else {
- select(value() + 1);
- select(value() - 1);
- }
- ret = 1;
- break;
- }
- return ret;
-}
-
-/* -------------------------------------------------------------------------- */
-
-
-string gBrowser::getCurrentDir()
-{
- return normalize(gu_getRealPath(currentDir));
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-string gBrowser::getSelectedItem(bool fullPath)
-{
- if (!fullPath) // no full path requested? return the selected text
- return normalize(text(value()));
- else
- if (value() == 0) // no rows selected? return current directory
- return normalize(currentDir);
- else
- return normalize(gu_getRealPath(currentDir + G_SLASH + normalize(text(value()))));
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gBrowser::preselect(int pos, int line)
-{
- position(pos);
- select(line);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-string gBrowser::normalize(const string &s)
-{
- string out = s;
-
- /* If string ends with G_SLASH, remove it. Don't do it if has length > 1, it
- means that the string is just '/'. Note: our crappy version of Clang doesn't
- seem to support std::string::back() */
-
-#ifdef __APPLE__
- if (out[out.length() - 1] == G_SLASH && out.length() > 1)
-#else
- if (out.back() == G_SLASH && out.length() > 1)
-#endif
-
- out = out.substr(0, out.size()-1);
- return out;
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_browser
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_BROWSER_H
-#define GE_BROWSER_H
-
-#include <FL/Fl.H>
-#include <FL/Fl_File_Browser.H>
-#include <string>
-#include "ge_mixed.h"
-
-
-using std::string;
-
-
-class gBrowser : public Fl_File_Browser
-{
-private:
-
- string currentDir;
-
- /* normalize
- * Make sure the string never ends with a trailing slash. */
-
- string normalize(const string &s);
-
-public:
-
- gBrowser(int x, int y, int w, int h);
-
- /* init
- * Initialize browser and show 'dir' as initial directory. */
-
- void loadDir(const string &dir);
-
- /* getSelectedItem
- * Return the full path or just the displayed name of the i-th selected item.
- * Always with the trailing slash! */
-
- string getSelectedItem(bool fullPath=true);
-
- string getCurrentDir();
-
- void preselect(int position, int line);
-
- int handle(int e);
-};
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_column
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/mixer.h"
-#include "../../core/conf.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/channel.h"
-#include "../../core/sampleChannel.h"
-#include "../../core/midiChannel.h"
-#include "../../glue/main.h"
-#include "../../glue/channel.h"
-#include "../../utils/log.h"
-#include "../../utils/string.h"
-#include "../dialogs/gd_mainWindow.h"
-#include "../dialogs/gd_warnings.h"
-#include "../elems/ge_keyboard.h"
-#include "ge_column.h"
-#include "channel.h"
-#include "sampleChannel.h"
-#include "midiChannel.h"
-
-
-extern Mixer G_Mixer;
-extern Conf G_Conf;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern gdMainWindow *mainWin;
-
-
-gColumn::gColumn(int X, int Y, int W, int H, int index, gKeyboard *parent)
- : Fl_Group(X, Y, W, H), parent(parent), index(index)
-{
- /* gColumn does a bit of a mess: we pass a pointer to its parent (gKeyboard) and
- the gColumn itself deals with the creation of another widget, outside gColumn
- and inside gKeyboard, which handles the vertical resize bar (gResizerBar).
- The resizer cannot stay inside gColumn: it needs a broader view on the other
- side widgets. The view can be obtained from gKeyboard only (the upper level).
- Unfortunately, parent() can be NULL: at this point (i.e the constructor)
- gColumn is still detached from any parent. We use a custom gKeyboard *parent
- instead. */
-
- begin();
- addChannelBtn = new gClick(x(), y(), w(), 20, "Add new channel");
- end();
-
- resizer = new gResizerBar(x()+w(), y(), 16, h(), false);
- resizer->setMinSize(MIN_COLUMN_WIDTH);
- parent->add(resizer);
-
- addChannelBtn->callback(cb_addChannel, (void*)this);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gColumn::~gColumn()
-{
- /* FIXME - this could actually cause a memory leak. resizer is
- just removed, not deleted. But we cannot delete it right now. */
-
- parent->remove(resizer);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-
-int gColumn::handle(int e)
-{
- switch (e) {
- case FL_RELEASE: {
- if (Fl::event_button() == FL_RIGHT_MOUSE) {
- __cb_addChannel();
- return 1;
- }
- }
- case FL_DND_ENTER: // return(1) for these events to 'accept' dnd
- case FL_DND_DRAG:
- case FL_DND_RELEASE: {
- return 1;
- }
- case FL_PASTE: { // handle actual drop (paste) operation
- vector<std::string> paths;
- gu_split(Fl::event_text(), "\n", &paths);
- bool fails = false;
- int result = 0;
- for (unsigned i=0; i<paths.size(); i++) {
- gu_log("[gColumn::handle] loading %s...\n", paths.at(i).c_str());
- SampleChannel *c = (SampleChannel*) glue_addChannel(index, CHANNEL_SAMPLE);
- result = glue_loadChannel(c, gu_stripFileUrl(paths.at(i)).c_str());
- if (result != SAMPLE_LOADED_OK) {
- deleteChannel(c->guiChannel);
- fails = true;
- }
- }
- if (fails) {
- if (paths.size() > 1)
- gdAlert("Some files were not loaded successfully.");
- else
- parent->printChannelMessage(result);
- }
- return 1;
- }
- }
-
- /* we return fl_Group::handle only if none of the cases above are fired. That
- is because we don't want to propagate a dnd drop to all the sub widgets. */
-
- return Fl_Group::handle(e);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::resize(int X, int Y, int W, int H)
-{
- /* resize all children */
-
- int ch = children();
- for (int i=0; i<ch; i++) {
- Fl_Widget *c = child(i);
- c->resize(X, Y + (i * (c->h() + 4)), W, c->h());
- }
-
- /* resize group itself */
-
- x(X); y(Y); w(W); h(H);
-
- /* resize resizerBar */
-
- resizer->size(16, H);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::refreshChannels()
-{
- for (int i=1; i<children(); i++)
- ((geChannel*) child(i))->refresh();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::draw()
-{
- fl_color(fl_rgb_color(27, 27, 27));
- fl_rectf(x(), y(), w(), h());
-
- /* call draw and then redraw in order to avoid channel corruption when
- scrolling horizontally */
-
- for (int i=0; i<children(); i++) {
- child(i)->draw();
- child(i)->redraw();
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::cb_addChannel(Fl_Widget *v, void *p) { ((gColumn*)p)->__cb_addChannel(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-geChannel *gColumn::addChannel(Channel *ch)
-{
- int currentY = y() + children() * 24;
- geChannel *gch = NULL;
- if (ch->type == CHANNEL_SAMPLE)
- gch = (geSampleChannel*) new geSampleChannel(x(), currentY, w(), 20, (SampleChannel*) ch);
- else
- gch = (geMidiChannel*) new geMidiChannel(x(), currentY, w(), 20, (MidiChannel*) ch);
-
- add(gch);
- resize(x(), y(), w(), (children() * 24) + 66); // evil space for drag n drop
- gch->redraw(); // avoid corruption
- parent->redraw(); // redraw Keyboard
- return gch;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::deleteChannel(geChannel *gch)
-{
- gch->hide();
- remove(gch);
- delete gch;
-
- /* reposition all other channels and resize this group */
- /** TODO
- * reposition is useless when called by gColumn::clear(). Add a new
- * parameter to skip the operation */
-
- for (int i=0; i<children(); i++) {
- gch = (geChannel*) child(i);
- gch->position(gch->x(), y()+(i*24));
- }
- size(w(), children() * 24 + 66); // evil space for drag n drop
- redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::__cb_addChannel()
-{
- gu_log("[gColumn::__cb_addChannel] index = %d\n", index);
- int type = openTypeMenu();
- if (type)
- glue_addChannel(index, type);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-int gColumn::openTypeMenu()
-{
- Fl_Menu_Item rclick_menu[] = {
- {"Sample channel"},
- {"MIDI channel"},
- {0}
- };
-
- Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
-
- const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
- if (!m) return 0;
-
- if (strcmp(m->label(), "Sample channel") == 0)
- return CHANNEL_SAMPLE;
- if (strcmp(m->label(), "MIDI channel") == 0)
- return CHANNEL_MIDI;
- return 0;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gColumn::clear(bool full)
-{
- if (full)
- Fl_Group::clear();
- else {
- while (children() >= 2) { // skip "add new channel" btn
- int i = children()-1;
- deleteChannel((geChannel*)child(i));
- }
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-Channel *gColumn::getChannel(int i)
-{
- geChannel *gch = (geChannel*) child(i);
- if (gch->type == CHANNEL_SAMPLE)
- return ((geSampleChannel*) child(i))->ch;
- else
- return ((geMidiChannel*) child(i))->ch;
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_column
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_COLUMN_H
-#define GE_COLUMN_H
-
-
-#include <FL/Fl.H>
-#include <FL/Fl_Group.H>
-
-
-class gColumn : public Fl_Group
-{
-private:
-
- static void cb_addChannel (Fl_Widget *v, void *p);
- inline void __cb_addChannel();
-
- int openTypeMenu();
-
- class gClick *addChannelBtn;
- class gResizerBar *resizer;
- class gKeyboard *parent;
-
- int index;
-
-public:
-
- gColumn(int x, int y, int w, int h, int index, class gKeyboard *parent);
- ~gColumn();
-
- /* addChannel
- * add a new channel in this column and set the internal pointer
- * to channel to 'ch'. */
-
- class geChannel *addChannel(class Channel *ch);
-
- /* handle */
-
- int handle(int e);
-
- /* resize
- * custom resize behavior. */
-
- void resize(int x, int y, int w, int h);
-
- /* deleteChannel
- * remove the channel 'gch' from this column. */
-
- void deleteChannel(geChannel *gch);
-
- /* refreshChannels
- * update channels' graphical statues. Called on each GUI cycle. */
-
- void refreshChannels();
-
- /* getChannel */
-
- Channel *getChannel(int i);
-
- /* clear
- * remove all channels from the column. If full==true, delete also the
- * "add new channel" button. This method ovverrides the inherited one
- * from Fl_Group. */
-
- void clear(bool full=false);
-
- void draw();
-
- inline int getIndex() { return index; }
- inline void setIndex(int i) { index = i; }
- inline bool isEmpty() { return children() == 1; }
- inline int countChannels() { return children(); }
-};
-
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- * ge_controller
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/graphics.h"
-#include "../../glue/main.h"
-#include "../../glue/io.h"
-#include "ge_mixed.h"
-#include "ge_controller.h"
-
-
-gController::gController(int x, int y)
- : Fl_Group(x, y, 131, 25)
-{
- begin();
-
- rewind = new gClick(x, y, 25, 25, "", rewindOff_xpm, rewindOn_xpm);
- play = new gClick(rewind->x()+rewind->w()+4, y, 25, 25, "", play_xpm, pause_xpm);
- recAction = new gClick(play->x()+play->w()+4, y, 25, 25, "", recOff_xpm, recOn_xpm);
- recInput = new gClick(recAction->x()+recAction->w()+4, y, 25, 25, "", inputRecOff_xpm, inputRecOn_xpm);
- metronome = new gClick(recInput->x()+recInput->w()+4, y+10, 15, 15, "", metronomeOff_xpm, metronomeOn_xpm);
-
- end();
-
- resizable(NULL); // don't resize any widget
-
- rewind->callback(cb_rewind, (void*)this);
-
- play->callback(cb_play);
- play->type(FL_TOGGLE_BUTTON);
-
- recAction->callback(cb_recAction, (void*)this);
- recAction->type(FL_TOGGLE_BUTTON);
-
- recInput->callback(cb_recInput, (void*)this);
- recInput->type(FL_TOGGLE_BUTTON);
-
- metronome->callback(cb_metronome);
- metronome->type(FL_TOGGLE_BUTTON);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::cb_rewind (Fl_Widget *v, void *p) { ((gController*)p)->__cb_rewind(); }
-void gController::cb_play (Fl_Widget *v, void *p) { ((gController*)p)->__cb_play(); }
-void gController::cb_recAction(Fl_Widget *v, void *p) { ((gController*)p)->__cb_recAction(); }
-void gController::cb_recInput (Fl_Widget *v, void *p) { ((gController*)p)->__cb_recInput(); }
-void gController::cb_metronome(Fl_Widget *v, void *p) { ((gController*)p)->__cb_metronome(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::__cb_rewind()
-{
- glue_rewindSeq();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::__cb_play()
-{
- glue_startStopSeq(true);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::__cb_recAction()
-{
- glue_startStopActionRec(true);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::__cb_recInput()
-{
- glue_startStopInputRec(true);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::__cb_metronome()
-{
- glue_startStopMetronome(true);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::updatePlay(int v)
-{
- play->value(v);
- play->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::updateMetronome(int v)
-{
- metronome->value(v);
- metronome->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::updateRecInput(int v)
-{
- recInput->value(v);
- recInput->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gController::updateRecAction(int v)
-{
- recAction->value(v);
- recAction->redraw();
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- * ge_controller
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_CONTROLLER_H
-#define GE_CONTROLLER_H
-
-
-#include <FL/Fl_Group.H>
-
-
-class gController : public Fl_Group
-{
-private:
-
- class gClick *rewind;
- class gClick *play;
- class gClick *recAction;
- class gClick *recInput;
- class gClick *metronome;
-
- static void cb_rewind (Fl_Widget *v, void *p);
- static void cb_play (Fl_Widget *v, void *p);
- static void cb_recAction(Fl_Widget *v, void *p);
- static void cb_recInput (Fl_Widget *v, void *p);
- static void cb_metronome(Fl_Widget *v, void *p);
-
- inline void __cb_rewind ();
- inline void __cb_play ();
- inline void __cb_recAction();
- inline void __cb_recInput ();
- inline void __cb_metronome();
-
-public:
-
- gController(int x, int y);
-
- void updatePlay (int v);
- void updateMetronome(int v);
- void updateRecInput (int v);
- void updateRecAction(int v);
-};
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gg_keyboard
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/mixer.h"
-#include "../../core/conf.h"
-#include "../../core/const.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/channel.h"
-#include "../../core/sampleChannel.h"
-#include "../../glue/main.h"
-#include "../../glue/io.h"
-#include "../../utils/log.h"
-#include "../dialogs/gd_browser.h"
-#include "../dialogs/gd_mainWindow.h"
-#include "../dialogs/gd_editor.h"
-#include "../dialogs/gd_warnings.h"
-#include "channel.h"
-#include "sampleChannel.h"
-#include "ge_keyboard.h"
-
-
-extern Mixer G_Mixer;
-extern Conf G_Conf;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern gdMainWindow *mainWin;
-
-
-int gKeyboard::indexColumn = 0;
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gKeyboard::gKeyboard(int X, int Y, int W, int H)
-: Fl_Scroll (X, Y, W, H),
- bckspcPressed(false),
- endPressed (false),
- spacePressed (false),
- addColumnBtn (NULL)
-{
- color(COLOR_BG_MAIN);
- type(Fl_Scroll::BOTH_ALWAYS);
- scrollbar.color(COLOR_BG_0);
- scrollbar.selection_color(COLOR_BG_1);
- scrollbar.labelcolor(COLOR_BD_1);
- scrollbar.slider(G_BOX);
- hscrollbar.color(COLOR_BG_0);
- hscrollbar.selection_color(COLOR_BG_1);
- hscrollbar.labelcolor(COLOR_BD_1);
- hscrollbar.slider(G_BOX);
-
- addColumnBtn = new gClick(8, y(), 200, 20, "Add new column");
- addColumnBtn->callback(cb_addColumn, (void*) this);
- add(addColumnBtn);
-
- init();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::init()
-{
- /* add 6 empty columns as init layout */
-
- __cb_addColumn();
- __cb_addColumn();
- __cb_addColumn();
- __cb_addColumn();
- __cb_addColumn();
- __cb_addColumn();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::freeChannel(geChannel *gch)
-{
- gch->reset();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::deleteChannel(geChannel *gch)
-{
- for (unsigned i=0; i<columns.size(); i++) {
- int k = columns.at(i)->find(gch);
- if (k != columns.at(i)->children()) {
- columns.at(i)->deleteChannel(gch);
- return;
- }
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::updateChannel(geChannel *gch)
-{
- gch->update();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::organizeColumns()
-{
- /* if only one column exists don't cleanup: the initial column must
- * stay here. */
-
- if (columns.size() == 1)
- return;
-
- /* otherwise delete all empty columns */
- /** FIXME - this for loop might not work correctly! */
-
- for (unsigned i=columns.size()-1; i>=1; i--) {
- if (columns.at(i)->isEmpty()) {
- //Fl::delete_widget(columns.at(i));
- delete columns.at(i);
- columns.erase(columns.begin() + i);
- }
- }
-
- /* compact column, avoid empty spaces */
-
- for (unsigned i=1; i<columns.size(); i++)
- columns.at(i)->position(columns.at(i-1)->x() + columns.at(i-1)->w() + 16, y());
-
- addColumnBtn->position(columns.back()->x() + columns.back()->w() + 16, y());
-
- /* recompute col indexes */
-
- refreshColIndexes();
-
- redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::cb_addColumn(Fl_Widget *v, void *p)
-{
- ((gKeyboard*)p)->__cb_addColumn(DEFAULT_COLUMN_WIDTH);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-geChannel *gKeyboard::addChannel(int colIndex, Channel *ch, bool build)
-{
- gColumn *col = getColumnByIndex(colIndex);
-
- /* no column with index 'colIndex' found? Just create it and set its index
- to 'colIndex'. */
-
- if (!col) {
- __cb_addColumn();
- col = columns.back();
- col->setIndex(colIndex);
- gu_log("[gKeyboard::addChannel] created new column with index=%d\n", colIndex);
- }
-
- gu_log("[gKeyboard::addChannel] add to column with index = %d\n", col->getIndex());
- return col->addChannel(ch);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::refreshColumns()
-{
- for (unsigned i=0; i<columns.size(); i++)
- columns.at(i)->refreshChannels();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gColumn *gKeyboard::getColumnByIndex(int index)
-{
- for (unsigned i=0; i<columns.size(); i++)
- if (columns.at(i)->getIndex() == index)
- return columns.at(i);
- return NULL;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-/* TODO - the following event handling for play, stop, rewind, start rec and
-so on should be moved to the proper widget: gdMainWindow or (better) geController. */
-
-int gKeyboard::handle(int e)
-{
- int ret = Fl_Group::handle(e); // assume the buttons won't handle the Keyboard events
- switch (e) {
- case FL_FOCUS:
- case FL_UNFOCUS: {
- ret = 1; // enables receiving Keyboard events
- break;
- }
- case FL_SHORTCUT: // in case widget that isn't ours has focus
- case FL_KEYDOWN: // Keyboard key pushed
- case FL_KEYUP: { // Keyboard key released
-
- /* rewind session. Avoid retrigs */
-
- if (e == FL_KEYDOWN) {
- if (Fl::event_key() == FL_BackSpace && !bckspcPressed) {
- bckspcPressed = true;
- glue_rewindSeq();
- ret = 1;
- break;
- }
- else if (Fl::event_key() == FL_End && !endPressed) {
- endPressed = true;
- glue_startStopInputRec(false); // update gui
- ret = 1;
- break;
- }
- else if (Fl::event_key() == FL_Enter && !enterPressed) {
- enterPressed = true;
- glue_startStopActionRec(false); // update gui
- ret = 1;
- break;
- }
- else if (Fl::event_key() == ' ' && !spacePressed) {
- spacePressed = true;
- glue_startStopSeq(false); // update gui
- ret = 1;
- break;
- }
- }
- else if (e == FL_KEYUP) {
- if (Fl::event_key() == FL_BackSpace)
- bckspcPressed = false;
- else if (Fl::event_key() == FL_End)
- endPressed = false;
- else if (Fl::event_key() == ' ')
- spacePressed = false;
- else if (Fl::event_key() == FL_Enter)
- enterPressed = false;
- }
-
- /* Walk button arrays, trying to match button's label with the Keyboard event.
- * If found, set that button's value() based on up/down event,
- * and invoke that button's callback() */
-
- for (unsigned i=0; i<columns.size(); i++)
- for (int k=1; k<columns.at(i)->children(); k++)
- ret &= ((geChannel*)columns.at(i)->child(k))->keyPress(e);
- break;
- }
- }
- return ret;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::clear()
-{
- for (unsigned i=0; i<columns.size(); i++)
- delete columns.at(i);
- columns.clear();
- indexColumn = 0; // new columns will start from index=0
- addColumnBtn->position(8, y());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::setChannelWithActions(geSampleChannel *gch)
-{
- if (gch->ch->hasActions)
- gch->showActionButton();
- else
- gch->hideActionButton();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::printChannelMessage(int res)
-{
- if (res == SAMPLE_NOT_VALID)
- gdAlert("This is not a valid WAVE file.");
- else if (res == SAMPLE_MULTICHANNEL)
- gdAlert("Multichannel samples not supported.");
- else if (res == SAMPLE_WRONG_BIT)
- gdAlert("This sample has an\nunsupported bit-depth (> 32 bit).");
- else if (res == SAMPLE_WRONG_ENDIAN)
- gdAlert("This sample has a wrong\nbyte order (not little-endian).");
- else if (res == SAMPLE_WRONG_FORMAT)
- gdAlert("This sample is encoded in\nan unsupported audio format.");
- else if (res == SAMPLE_READ_ERROR)
- gdAlert("Unable to read this sample.");
- else if (res == SAMPLE_PATH_TOO_LONG)
- gdAlert("File path too long.");
- else
- gdAlert("Unknown error.");
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::__cb_addColumn(int width)
-{
- int colx;
- int colxw;
- int gap = 16;
- if (columns.size() == 0) {
- colx = x() - xposition(); // mind the offset with xposition()
- colxw = colx + width;
- }
- else {
- gColumn *prev = columns.back();
- colx = prev->x()+prev->w() + gap;
- colxw = colx + width;
- }
-
- /* add gColumn to gKeyboard and to columns vector */
-
- gColumn *gc = new gColumn(colx, y(), width, 2000, indexColumn, this);
- add(gc);
- columns.push_back(gc);
- indexColumn++;
-
- /* move addColumn button */
-
- addColumnBtn->position(colxw + gap, y());
- redraw();
-
- gu_log("[gKeyboard::__cb_addColumn] new column added (index=%d, w=%d), total count=%d, addColumn(x)=%d\n",
- gc->getIndex(), width, columns.size(), addColumnBtn->x());
-
- /* recompute col indexes */
-
- refreshColIndexes();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::addColumn(int width)
-{
- __cb_addColumn(width);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gKeyboard::refreshColIndexes()
-{
- for (unsigned i=0; i<columns.size(); i++)
- columns.at(i)->setIndex(i);
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gg_keyboard
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_KEYBOARD_H
-#define GE_KEYBOARD_H
-
-
-#include <FL/Fl.H>
-#include <FL/Fl_Scroll.H>
-#include <FL/Fl_Group.H>
-#include <FL/Fl_Box.H>
-#include <FL/Fl_Menu_Button.H>
-#include <vector>
-#include "../elems/ge_column.h"
-#include "../../core/const.h"
-#include "../../utils/fs.h"
-
-
-using std::vector;
-
-
-class gKeyboard : public Fl_Scroll
-{
-private:
-
- /* refreshColIndexes
- * Recompute all column indexes in order to avoid any gaps between them.
- * Indexes must always be contiguous! */
-
- void refreshColIndexes();
-
- static void cb_addColumn (Fl_Widget *v, void *p);
- inline void __cb_addColumn(int width=DEFAULT_COLUMN_WIDTH);
-
- bool bckspcPressed;
- bool endPressed;
- bool spacePressed;
- bool enterPressed;
-
- /* indexColumn
- * the last index used for column. */
-
- static int indexColumn;
-
- class gClick *addColumnBtn;
-
- /* columns
- * a vector of columns which in turn contain channels. */
-
- vector<gColumn*> columns;
-
-public:
-
- gKeyboard(int X, int Y, int W, int H);
-
- int handle(int e);
-
- /* init
- * build the initial setup of empty channels. */
-
- void init();
-
- /* addChannel
- * add a new channel to geChannels. Used by callbacks and during
- * patch loading. Requires Channel (and not geChannel). If build is
- * set to true, also generate the corresponding column if column (index) does
- * not exist yet. */
-
- class geChannel *addChannel(int column, class Channel *ch, bool build=false);
-
- /* addColumn
- * add a new column to the top of the stack. */
-
- void addColumn(int width=380);
-
- /* deleteChannel
- * delete a channel from geChannels<> where geChannel->ch == ch and remove
- * it from the stack. */
-
- void deleteChannel(geChannel *gch);
-
- /* freeChannel
- * free a channel from geChannels<> where geChannel->ch == ch. No channels
- * are deleted */
-
- void freeChannel(geChannel *gch);
-
- /* updateChannel
- * wrapper function to call gch->update(). */
-
- void updateChannel(geChannel *gch);
-
- /* organizeColumns
- * reorganize columns layout by removing empty gaps. */
-
- void organizeColumns();
-
- /* refreshColumns
- * refresh each column's channel, called on each GUI cycle. */
-
- void refreshColumns();
-
- /* getColumnByIndex
- * return the column with index 'index', or NULL if not found. */
-
- gColumn *getColumnByIndex(int index);
-
- /* getColumn
- * return the column with from columns->at(i). */
-
- inline gColumn *getColumn(int i) { return columns.at(i); }
-
- /* clear
- * delete all channels and groups. */
-
- void clear();
-
- /* setChannelWithActions
- * add 'R' button if channel has actions, and set recorder to active. */
-
- void setChannelWithActions(class geSampleChannel *gch);
-
- /* printChannelMessage
- * given any output by glue_loadChannel, print the message on screen
- * on a gdAlert subwindow. */
-
- void printChannelMessage(int res);
-
- /* getTotalColumns */
-
- inline unsigned getTotalColumns() { return columns.size(); }
-
- /* getColumnWidth
- * return the width in pixel of i-th column. Warning: 'i' is the i-th column
- * in the column array, NOT the index. */
-
- inline int getColumnWidth(int i) { return getColumnByIndex(i)->w(); }
-};
-
-
-#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_midiIoTools
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "ge_mixed.h"
-#include "ge_midiIoTools.h"
-
-
-extern KernelMidi G_KernelMidi;
-
-
-gLearner::gLearner(int X, int Y, int W, const char *l, KernelMidi::cb_midiLearn *cb,
- uint32_t *param)
- : Fl_Group(X, Y, W, 20),
- callback(cb),
- param (param)
-{
- begin();
- text = new gBox(x(), y(), 156, 20, l);
- value = new gClick(text->x()+text->w()+4, y(), 80, 20, "(not set)");
- button = new gButton(value->x()+value->w()+4, y(), 40, 20, "learn");
- end();
-
- text->box(G_BOX);
- text->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
-
- value->box(G_BOX);
- value->callback(cb_value, (void*)this);
- value->when(FL_WHEN_RELEASE);
- updateValue();
-
- button->type(FL_TOGGLE_BUTTON);
- button->callback(cb_button, (void*)this);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gLearner::updateValue() {
- char buf[16];
- if (*param != 0x0)
- snprintf(buf, 9, "0x%X", *param);
- else
- snprintf(buf, 16, "(not set)");
- value->copy_label(buf);
- button->value(0);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gLearner::cb_button(Fl_Widget *v, void *p) { ((gLearner*)p)->__cb_button(); }
-void gLearner::cb_value(Fl_Widget *v, void *p) { ((gLearner*)p)->__cb_value(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gLearner::__cb_value() {
- if (Fl::event_button() == FL_RIGHT_MOUSE) {
- *param = 0x0;
- updateValue();
- }
- /// TODO - elif (LEFT_MOUSE) : insert values by hand
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-/* FIXME - do not malloc on each callback! do it on the constructor! */
-
-void gLearner::__cb_button() {
- if (button->value() == 1) {
- cbData *data = (cbData*) malloc(sizeof(cbData));
- data->window = (gdMidiInput*) parent(); // parent = gdMidiGrabberChannel
- data->learner = this;
- G_KernelMidi.startMidiLearn(callback, (void*)data);
- }
- else
- G_KernelMidi.stopMidiLearn();
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_midiIoTools
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_LEARNER_H
-#define GE_LEARNER_H
-
-
-#include <FL/Fl_Group.H>
-#include "../../core/kernelMidi.h"
-#include "../dialogs/gd_midiInput.h"
-
-
-extern KernelMidi G_KernelMidi;
-
-
-class gLearner : public Fl_Group
-{
-private:
-
- /* callback
- * cb to pass to kernelMidi. Requires two parameters:
- * uint32_t msg - MIDI message
- * void *data - extra data */
-
- KernelMidi::cb_midiLearn *callback;
-
- class gBox *text;
- class gClick *value;
- class gButton *button;
-
- static void cb_button(Fl_Widget *v, void *p);
- static void cb_value (Fl_Widget *v, void *p);
- inline void __cb_button();
- inline void __cb_value();
-
-public:
-
- /* param
- * pointer to ch->midiIn[value] */
-
- uint32_t *param;
-
- gLearner(int x, int y, int w, const char *l, KernelMidi::cb_midiLearn *cb, uint32_t *param);
-
- void updateValue();
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-/* cbData
- * struct we pass to kernelMidi as extra parameter. Local scope made
- * with unnamed namespace. Infos:
- * http://stackoverflow.com/questions/4422507/superiority-of-unnamed-namespace-over-static */
-
-/* TODO - instead of the unnamed namespace, why don't we make the struct as a
-(static) member of gLearner? */
-
-namespace {
- struct cbData {
- gdMidiInput *window;
- gLearner *learner;
- };
-}
-
-
-#endif
#include "../../core/sampleChannel.h"
#include "../../utils/gui.h"
#include "../dialogs/gd_mainWindow.h"
+#include "basics/boxtypes.h"
#include "ge_mixed.h"
gInput::gInput(int x, int y, int w, int h, const char *L)
: Fl_Input(x, y, w, h, L)
{
- //Fl::set_boxtype(G_BOX, gDrawBox, 1, 1, 2, 2);
- box(G_BOX);
+ //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);
gBox::gBox(int x, int y, int w, int h, const char *L, Fl_Align al)
-: Fl_Box(x, y, w, h, L)
+: Fl_Box(x, y, w, h)
{
+ copy_label(L);
labelsize(GUI_FONT_SIZE_BASE);
box(FL_NO_BOX);
labelcolor(COLOR_TEXT_0);
gProgress::gProgress(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);
- box(G_BOX);
+ box(G_CUSTOM_BORDER_BOX);
}
fl_rectf(x()+1, y()+1, (int) px_level, h()-2, clip || !G_audio_status ? COLOR_ALERT : COLOR_BD_0);
}
-/* -------------------------------------------------------------------------- */
-
-gBeatMeter::gBeatMeter(int x, int y, int w, int h, const char *L)
- : Fl_Box(x, y, w, h, L) {}
-
-void gBeatMeter::draw()
-{
- int cursorW = w() / MAX_BEATS;
- int greyX = G_Mixer.beats * cursorW;
-
- fl_rect(x(), y(), w(), h(), COLOR_BD_0); // border
- fl_rectf(x()+1, y()+1, w()-2, h()-2, FL_BACKGROUND_COLOR); // bg
- fl_rectf(x()+(G_Mixer.actualBeat*cursorW)+3, y()+3, cursorW-5, h()-6, COLOR_BG_2); // cursor
-
- /* beat cells */
-
- fl_color(COLOR_BD_0);
- for (int i=1; i<=G_Mixer.beats; i++)
- fl_line(x()+cursorW*i, y()+1, x()+cursorW*i, y()+h()-2);
-
- /* bar line */
-
- fl_color(COLOR_BG_2);
- int delta = G_Mixer.beats / G_Mixer.bars;
- for (int i=1; i<G_Mixer.bars; 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);
-}
-
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-void gDrawBox(int x, int y, int w, int h, Fl_Color c)
-{
- fl_color(c);
- fl_rectf(x, y, w, h);
- fl_color(COLOR_BD_0);
- fl_rect(x, y, w, h);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
gLiquidScroll::gLiquidScroll(int x, int y, int w, int h, const char *l)
: Fl_Scroll(x, y, w, h, l)
{
scrollbar.color(COLOR_BG_0);
scrollbar.selection_color(COLOR_BG_1);
scrollbar.labelcolor(COLOR_BD_1);
- scrollbar.slider(G_BOX);
+ scrollbar.slider(G_CUSTOM_BORDER_BOX);
}
align(FL_ALIGN_LEFT);
labelcolor(COLOR_TEXT_0);
- box(G_BOX);
+ box(G_CUSTOM_BORDER_BOX);
color(COLOR_BG_0);
selection_color(COLOR_BD_0);
}
}
-/* -------------------------------------------------------------------------- */
-
-
-gScroll::gScroll(int x, int y, int w, int h, int t)
- : Fl_Scroll(x, y, w, h)
-{
- type(t);
-
- scrollbar.color(COLOR_BG_0);
- scrollbar.selection_color(COLOR_BG_1);
- scrollbar.labelcolor(COLOR_BD_1);
- scrollbar.slider(G_BOX);
-
- hscrollbar.color(COLOR_BG_0);
- hscrollbar.selection_color(COLOR_BG_1);
- hscrollbar.labelcolor(COLOR_BD_1);
- hscrollbar.slider(G_BOX);
-}
-
-
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
-/* gDrawBox
- * custom boxes in FLTK. */
-
-#define G_BOX FL_FREE_BOXTYPE
-void gDrawBox(int x, int y, int w, int h, Fl_Color c);
-
-
-/* -------------------------------------------------------------------------- */
-
-
/* gLiquidScroll
* custom scroll that tells children to follow scroll's width when
* resized. Thanks to Greg Ercolano from FLTK dev team.
};
-/* -------------------------------------------------------------------------- */
-
-
-/* gScroll
- * custom scroll with nice scrollbars and something else. */
-
-class gScroll : public Fl_Scroll
-{
-public:
- gScroll(int x, int y, int w, int h, int type=Fl_Scroll::BOTH);
-};
-
-
/* -------------------------------------------------------------------------- */
/* gResizerBar
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_modeBox
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../utils/gui.h"
-#include "../../core/graphics.h"
-#include "../../core/sampleChannel.h"
-#include "../../core/const.h"
-#include "../dialogs/gd_mainWindow.h"
-#include "ge_modeBox.h"
-
-
-gModeBox::gModeBox(int x, int y, int w, int h, SampleChannel *ch, const char *L)
- : Fl_Menu_Button(x, y, w, h, L), ch(ch)
-{
- box(G_BOX);
- textsize(GUI_FONT_SIZE_BASE);
- textcolor(COLOR_TEXT_0);
- color(COLOR_BG_0);
-
- add("Loop . basic", 0, cb_changeMode, (void *)LOOP_BASIC);
- add("Loop . once", 0, cb_changeMode, (void *)LOOP_ONCE);
- add("Loop . once . bar", 0, cb_changeMode, (void *)LOOP_ONCE_BAR);
- add("Loop . repeat", 0, cb_changeMode, (void *)LOOP_REPEAT);
- add("Oneshot . basic", 0, cb_changeMode, (void *)SINGLE_BASIC);
- add("Oneshot . press", 0, cb_changeMode, (void *)SINGLE_PRESS);
- add("Oneshot . retrig", 0, cb_changeMode, (void *)SINGLE_RETRIG);
- add("Oneshot . endless", 0, cb_changeMode, (void *)SINGLE_ENDLESS);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gModeBox::draw() {
- fl_rect(x(), y(), w(), h(), COLOR_BD_0); // border
- switch (ch->mode) {
- case LOOP_BASIC:
- fl_draw_pixmap(loopBasic_xpm, x()+1, y()+1);
- break;
- case LOOP_ONCE:
- fl_draw_pixmap(loopOnce_xpm, x()+1, y()+1);
- break;
- case LOOP_ONCE_BAR:
- fl_draw_pixmap(loopOnceBar_xpm, x()+1, y()+1);
- break;
- case LOOP_REPEAT:
- fl_draw_pixmap(loopRepeat_xpm, x()+1, y()+1);
- break;
- case SINGLE_BASIC:
- fl_draw_pixmap(oneshotBasic_xpm, x()+1, y()+1);
- break;
- case SINGLE_PRESS:
- fl_draw_pixmap(oneshotPress_xpm, x()+1, y()+1);
- break;
- case SINGLE_RETRIG:
- fl_draw_pixmap(oneshotRetrig_xpm, x()+1, y()+1);
- break;
- case SINGLE_ENDLESS:
- fl_draw_pixmap(oneshotEndless_xpm, x()+1, y()+1);
- break;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gModeBox::cb_changeMode(Fl_Widget *v, void *p) { ((gModeBox*)v)->__cb_changeMode((intptr_t)p); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gModeBox::__cb_changeMode(int mode)
-{
- ch->mode = mode;
-
- /* what to do when the channel is playing and you change the mode?
- * Nothing, since v0.5.3. Just refresh the action editor window, in
- * case it's open */
-
- gu_refreshActionEditor();
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_modeBox
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_MODEBOX_H
-#define GE_MODEBOX_H
-
-
-#include <FL/Fl_Menu_Button.H>
-
-
-class gModeBox : public Fl_Menu_Button
-{
-private:
-
- static void cb_changeMode (Fl_Widget *v, void *p);
- inline void __cb_changeMode(int mode);
-
- class SampleChannel *ch;
-
-public:
-
- gModeBox(int x, int y, int w, int h, class SampleChannel *ch, const char *l=0);
- void draw();
-};
-
-
-#endif
#include "../../core/const.h"
#include "../../core/pluginHost.h"
#include "ge_mixed.h"
+#include "basics/boxtypes.h"
#include "ge_pluginBrowser.h"
gePluginBrowser::gePluginBrowser(int x, int y, int w, int h)
: Fl_Browser(x, y, w, h)
{
- box(G_BOX);
+ box(G_CUSTOM_BORDER_BOX);
textsize(GUI_FONT_SIZE_BASE);
textcolor(COLOR_TEXT_0);
selection_color(COLOR_BG_1);
this->scrollbar.color(COLOR_BG_0);
this->scrollbar.selection_color(COLOR_BG_1);
this->scrollbar.labelcolor(COLOR_BD_1);
- this->scrollbar.slider(G_BOX);
+ 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.slider(G_BOX);
+ this->hscrollbar.slider(G_CUSTOM_BORDER_BOX);
type(FL_HOLD_BROWSER);
void gePluginBrowser::refresh()
{
clear();
-
+
add("NAME\tMANUFACTURER\tCATEGORY\tFORMAT\tUID");
add("---\t---\t---\t---\t---");
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_status
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/mixer.h"
-#include "../../core/const.h"
-#include "ge_status.h"
-
-
-extern Mixer G_Mixer;
-extern Recorder G_Recorder;
-
-
-gStatus::gStatus(int x, int y, int w, int h, SampleChannel *ch, const char *L)
- : Fl_Box(x, y, w, h, L), ch(ch) {}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gStatus::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
-
- if (ch != NULL) {
- 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);
- }
- else
- if (ch->status == STATUS_PLAY)
- fl_rect(x(), y(), w(), h(), COLOR_BD_1);
- else
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_0); // status empty
-
-
- if (G_Mixer.recording && ch->armed)
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_3); // take in progress
- else
- if (G_Recorder.active && G_Recorder.canRec(ch))
- fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_4); // action record
-
- /* equation for the progress bar:
- * ((chanTracker - chanStart) * w()) / (chanEnd - chanStart). */
-
- int pos = ch->getPosition();
- if (pos == -1)
- pos = 0;
- else
- pos = (pos * (w()-1)) / (ch->end - ch->begin);
- fl_rectf(x()+1, y()+1, pos, h()-2, COLOR_BG_2);
- }
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_status
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_STATUS_H
-#define GE_STATUS_H
-
-
-#include <FL/Fl_Box.H>
-#include "../../core/sampleChannel.h"
-#include "ge_mixed.h"
-
-
-class gStatus : public Fl_Box
-{
-public:
- gStatus(int X, int Y, int W, int H, class SampleChannel *ch, const char *L=0);
- void draw();
- class SampleChannel *ch;
-};
-
-
-#endif
#include "../../core/const.h"
#include "../elems/ge_mixed.h"
#include "../elems/ge_waveform.h"
+#include "basics/boxtypes.h"
#include "ge_waveTools.h"
hscrollbar.color(COLOR_BG_0);
hscrollbar.selection_color(COLOR_BG_1);
hscrollbar.labelcolor(COLOR_BD_1);
- hscrollbar.slider(G_BOX);
+ hscrollbar.slider(G_CUSTOM_BORDER_BOX);
waveform = new gWaveform(x, y, w, h-24, ch);
#include "../dialogs/gd_editor.h"
#include "ge_waveTools.h"
#include "ge_mixed.h"
+#include "basics/boxtypes.h"
#include "ge_waveform.h"
}
Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_BOX);
+ b->box(G_CUSTOM_BORDER_BOX);
b->textsize(GUI_FONT_SIZE_BASE);
b->textcolor(COLOR_TEXT_0);
b->color(COLOR_BG_0);
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * beatMeter
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 <FL/fl_draw.H>
+#include "../../../core/const.h"
+#include "../../../core/mixer.h"
+#include "beatMeter.h"
+
+
+extern Mixer G_Mixer;
+
+
+geBeatMeter::geBeatMeter(int x, int y, int w, int h, const char *L)
+ : Fl_Box(x, y, w, h, L) {}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geBeatMeter::draw()
+{
+ int cursorW = w() / MAX_BEATS;
+ int greyX = G_Mixer.beats * cursorW;
+
+ fl_rect(x(), y(), w(), h(), COLOR_BD_0); // border
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, FL_BACKGROUND_COLOR); // bg
+ fl_rectf(x()+(G_Mixer.actualBeat*cursorW)+3, y()+3, cursorW-5, h()-6,
+ COLOR_BG_2); // cursor
+
+ /* beat cells */
+
+ fl_color(COLOR_BD_0);
+ for (int i=1; i<=G_Mixer.beats; i++)
+ fl_line(x()+cursorW*i, y()+1, x()+cursorW*i, y()+h()-2);
+
+ /* bar line */
+
+ fl_color(COLOR_BG_2);
+ int delta = G_Mixer.beats / G_Mixer.bars;
+ for (int i=1; i<G_Mixer.bars; 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);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * beatMeter
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_BEAT_METER_H
+#define GE_BEAT_METER_H
+
+
+#include <FL/Fl_Box.H>
+
+
+class geBeatMeter : public Fl_Box
+{
+public:
+
+ geBeatMeter(int X,int Y,int W,int H,const char *L=0);
+ void draw();
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_channel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../../core/const.h"
+#include "../../../../core/channel.h"
+#include "../../../../core/graphics.h"
+#include "../../../../core/pluginHost.h"
+#include "../../../../utils/gui.h"
+#include "../../../../glue/channel.h"
+#include "../../../dialogs/gd_mainWindow.h"
+#include "../../../dialogs/gd_pluginList.h"
+#include "column.h"
+#include "channelButton.h"
+#include "channel.h"
+
+
+extern gdMainWindow *G_MainWin;
+
+
+geChannel::geChannel(int X, int Y, int W, int H, int type, Channel *ch)
+ : Fl_Group(X, Y, W, H, NULL),
+ ch (ch),
+ type (type)
+{
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::cb_arm(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_arm(); }
+void geChannel::cb_mute(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_mute(); }
+void geChannel::cb_solo(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_solo(); }
+void geChannel::cb_changeVol(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_changeVol(); }
+#ifdef WITH_VST
+void geChannel::cb_openFxWindow(Fl_Widget *v, void *p) { ((geChannel*)p)->__cb_openFxWindow(); }
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::__cb_arm()
+{
+ glue_toggleArm(ch, true);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::__cb_mute()
+{
+ glue_setMute(ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::__cb_solo()
+{
+ solo->value() ? glue_setSoloOn(ch) : glue_setSoloOff(ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::__cb_changeVol()
+{
+ glue_setChanVol(ch, vol->value());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+void geChannel::__cb_openFxWindow()
+{
+ gu_openSubWindow(G_MainWin, new gdPluginList(PluginHost::CHANNEL, ch), WID_FX_LIST);
+}
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geChannel::keyPress(int e)
+{
+ return handleKey(e, ch->key);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+
+int geChannel::getColumnIndex()
+{
+ return ((geColumn*)parent())->getIndex();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::blink()
+{
+ if (gu_getBlinker() > 6)
+ mainButton->setPlayMode();
+ else
+ mainButton->setDefaultMode();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::setColorsByStatus(int playStatus, int recStatus)
+{
+ switch (playStatus) {
+ case STATUS_OFF:
+ case STATUS_EMPTY:
+ mainButton->setDefaultMode();
+ button->imgOn = channelPlay_xpm;
+ button->imgOff = channelStop_xpm;
+ button->redraw();
+ break;
+ case STATUS_PLAY:
+ mainButton->setPlayMode();
+ button->imgOn = channelStop_xpm;
+ button->imgOff = channelPlay_xpm;
+ button->redraw();
+ break;
+ case STATUS_WAIT:
+ blink();
+ break;
+ case STATUS_ENDING:
+ mainButton->setEndingMode();
+ break;
+ }
+
+ switch (recStatus) {
+ case REC_WAITING:
+ blink();
+ break;
+ case REC_ENDING:
+ mainButton->setEndingMode();
+ break;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannel::packWidgets()
+{
+ /* Count visible widgets and resize mainButton according to how many widgets
+ are visible. */
+
+ int visibles = 0;
+ for (int i=0; i<children(); i++) {
+ child(i)->size(20, 20); // also normalize widths
+ if (child(i)->visible())
+ visibles++;
+ }
+ mainButton->size(w() - ((visibles - 1) * (24)), 20); // -1: exclude itself
+
+ /* Reposition everything else */
+
+ for (int i=1, p=0; i<children(); i++) {
+ if (!child(i)->visible())
+ continue;
+ for (int k=i-1; k>=0; k--) // Get the first visible item prior to i
+ if (child(k)->visible()) {
+ p = k;
+ break;
+ }
+ child(i)->position(child(p)->x() + child(p)->w() + 4, y());
+ }
+
+ init_sizes(); // Resets the internal array of widget sizes and positions
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geChannel::handleKey(int e, int key)
+{
+ int ret;
+ if (e == FL_KEYDOWN && button->value()) // key already pressed! skip it
+ ret = 1;
+ else
+ if (Fl::event_key() == key && !button->value()) {
+ button->take_focus(); // move focus to this button
+ button->value((e == FL_KEYDOWN || e == FL_SHORTCUT) ? 1 : 0); // change the button's state
+ button->do_callback(); // invoke the button's callback
+ ret = 1;
+ }
+ else
+ ret = 0;
+
+ if (Fl::event_key() == key)
+ button->value((e == FL_KEYDOWN || e == FL_SHORTCUT) ? 1 : 0); // change the button's state
+
+ return ret;
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_channel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_CHANNEL_H
+#define GE_CHANNEL_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class geChannel : public Fl_Group
+{
+protected:
+
+ /* Define some breakpoints for dynamic resize. BREAK_DELTA: base amount of
+ pixels to shrink sampleButton. */
+
+#ifdef WITH_VST
+ static const int BREAK_READ_ACTIONS = 240;
+ static const int BREAK_MODE_BOX = 216;
+ static const int BREAK_FX = 192;
+ static const int BREAK_ARM = 168;
+#else
+ static const int BREAK_READ_ACTIONS = 216;
+ static const int BREAK_MODE_BOX = 192;
+ static const int BREAK_ARM = 168;
+#endif
+
+ static void cb_arm (Fl_Widget *v, void *p);
+ static void cb_mute (Fl_Widget *v, void *p);
+ static void cb_solo (Fl_Widget *v, void *p);
+ static void cb_changeVol (Fl_Widget *v, void *p);
+#ifdef WITH_VST
+ static void cb_openFxWindow(Fl_Widget *v, void *p);
+#endif
+
+ inline void __cb_mute();
+ inline void __cb_arm();
+ inline void __cb_solo();
+ inline void __cb_changeVol();
+#ifdef WITH_VST
+ inline void __cb_openFxWindow();
+#endif
+
+ /* blink
+ * blink button when channel is in wait/ending status. */
+
+ void blink();
+
+ /* setColorByStatus
+ * update colors depending on channel status. */
+
+ void setColorsByStatus(int playStatus, int recStatus);
+
+ /* handleKey
+ * method wrapped by virtual handle(int e). */
+
+ int handleKey(int e, int key);
+
+ /* packWidgets
+ Spread widgets across available space. */
+
+ void packWidgets();
+
+public:
+
+ geChannel(int x, int y, int w, int h, int type, class Channel *ch);
+
+ /* reset
+ * reset channel to initial status. */
+
+ virtual void reset() = 0;
+
+ /* update
+ * update the label of sample button and everything else such as 'R'
+ * button, key box and so on, according to global values. */
+
+ virtual void update() = 0;
+
+ /* refresh
+ * update graphics. */
+
+ virtual void refresh() = 0;
+
+ /* keypress
+ * what to do when the corresponding key is pressed. */
+
+ int keyPress(int event);
+
+ /* getColumnIndex
+ * return the numeric index of the column in which this channel is
+ * located. */
+
+ int getColumnIndex();
+
+ class Channel *ch;
+
+ class gButton *button;
+ class geChannelStatus *status;
+ class gClick *arm;
+ class geChannelButton *mainButton;
+ class gClick *mute;
+ class gClick *solo;
+ class gDial *vol;
+#ifdef WITH_VST
+ class gFxButton *fx;
+#endif
+
+ int type;
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_channelButton
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../../core/const.h"
+#include "channelButton.h"
+
+
+using std::string;
+
+
+geChannelButton::geChannelButton(int x, int y, int w, int h, const char *l)
+ : gClick(x, y, w, h, l), key("") {}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setKey(const string &k)
+{
+ key = k;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setKey(int k)
+{
+ if (k == 0)
+ key = "";
+ else {
+ // FIXME - this crap won't work with unicode/utf-8
+ char c = (char) k;
+ key = c;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::draw()
+{
+ gClick::draw();
+
+ if (key == "")
+ return;
+
+ /* draw background */
+
+ fl_rectf(x()+1, y()+1, 18, h()-2, bgColor0);
+
+ /* draw key */
+
+ fl_color(COLOR_TEXT_0);
+ fl_font(FL_HELVETICA, 11);
+ fl_draw(key.c_str(), x(), y(), 18, h(), FL_ALIGN_CENTER);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setInputRecordMode()
+{
+ bgColor0 = COLOR_BG_3;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setActionRecordMode()
+{
+ bgColor0 = COLOR_BG_4;
+ txtColor = COLOR_TEXT_0;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setDefaultMode(const char *l)
+{
+ bgColor0 = COLOR_BG_0;
+ bdColor = COLOR_BD_0;
+ txtColor = COLOR_TEXT_0;
+ if (l)
+ label(l);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setPlayMode()
+{
+ bgColor0 = COLOR_BG_2;
+ bdColor = COLOR_BD_1;
+ txtColor = COLOR_TEXT_1;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelButton::setEndingMode()
+{
+ bgColor0 = COLOR_BD_0;
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_channelButton
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_CHANNEL_BUTTON_H
+#define GE_CHANNEL_BUTTON_H
+
+
+#include "../../ge_mixed.h"
+
+
+class geChannelButton : public gClick
+{
+private:
+
+ std::string key;
+
+public:
+
+ geChannelButton(int x, int y, int w, int h, const char *l=0);
+
+ virtual int handle(int e) = 0;
+
+ void draw();
+ void setKey(const std::string &k);
+ void setKey(int k);
+ void setPlayMode();
+ void setEndingMode();
+ void setDefaultMode(const char *l=0);
+ void setInputRecordMode();
+ void setActionRecordMode();
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_modeBox
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 <FL/fl_draw.H>
+#include "../../../../utils/gui.h"
+#include "../../../../core/graphics.h"
+#include "../../../../core/sampleChannel.h"
+#include "../../../../core/const.h"
+#include "../../basics/boxtypes.h"
+#include "channelMode.h"
+
+
+geChannelMode::geChannelMode(int x, int y, int w, int h, SampleChannel *ch,
+ const char *L)
+ : 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);
+
+ add("Loop . basic", 0, cb_changeMode, (void *)LOOP_BASIC);
+ add("Loop . once", 0, cb_changeMode, (void *)LOOP_ONCE);
+ add("Loop . once . bar", 0, cb_changeMode, (void *)LOOP_ONCE_BAR);
+ add("Loop . repeat", 0, cb_changeMode, (void *)LOOP_REPEAT);
+ add("Oneshot . basic", 0, cb_changeMode, (void *)SINGLE_BASIC);
+ add("Oneshot . press", 0, cb_changeMode, (void *)SINGLE_PRESS);
+ add("Oneshot . retrig", 0, cb_changeMode, (void *)SINGLE_RETRIG);
+ add("Oneshot . endless", 0, cb_changeMode, (void *)SINGLE_ENDLESS);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelMode::draw() {
+ fl_rect(x(), y(), w(), h(), COLOR_BD_0); // border
+ switch (ch->mode) {
+ case LOOP_BASIC:
+ fl_draw_pixmap(loopBasic_xpm, x()+1, y()+1);
+ break;
+ case LOOP_ONCE:
+ fl_draw_pixmap(loopOnce_xpm, x()+1, y()+1);
+ break;
+ case LOOP_ONCE_BAR:
+ fl_draw_pixmap(loopOnceBar_xpm, x()+1, y()+1);
+ break;
+ case LOOP_REPEAT:
+ fl_draw_pixmap(loopRepeat_xpm, x()+1, y()+1);
+ break;
+ case SINGLE_BASIC:
+ fl_draw_pixmap(oneshotBasic_xpm, x()+1, y()+1);
+ break;
+ case SINGLE_PRESS:
+ fl_draw_pixmap(oneshotPress_xpm, x()+1, y()+1);
+ break;
+ case SINGLE_RETRIG:
+ fl_draw_pixmap(oneshotRetrig_xpm, x()+1, y()+1);
+ break;
+ case SINGLE_ENDLESS:
+ fl_draw_pixmap(oneshotEndless_xpm, x()+1, y()+1);
+ break;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelMode::cb_changeMode(Fl_Widget *v, void *p) { ((geChannelMode*)v)->__cb_changeMode((intptr_t)p); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geChannelMode::__cb_changeMode(int mode)
+{
+ ch->mode = mode;
+
+ /* what to do when the channel is playing and you change the mode?
+ * Nothing, since v0.5.3. Just refresh the action editor window, in
+ * case it's open */
+
+ gu_refreshActionEditor();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_modeBox
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_CHANNEL_MODE_H
+#define GE_CHANNEL_MODE_H
+
+
+#include <FL/Fl_Menu_Button.H>
+
+
+class geChannelMode : public Fl_Menu_Button
+{
+private:
+
+ static void cb_changeMode (Fl_Widget *v, void *p);
+ inline void __cb_changeMode(int mode);
+
+ class SampleChannel *ch;
+
+public:
+
+ geChannelMode(int x, int y, int w, int h, class SampleChannel *ch,
+ const char *l=0);
+ void draw();
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_status
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 <FL/fl_draw.H>
+#include "../../../../core/mixer.h"
+#include "../../../../core/sampleChannel.h"
+#include "../../../../core/recorder.h"
+#include "../../../../core/const.h"
+#include "channelStatus.h"
+
+
+extern Mixer G_Mixer;
+extern Recorder G_Recorder;
+
+
+geChannelStatus::geChannelStatus(int x, int y, int w, int h, SampleChannel *ch,
+ const char *L)
+ : Fl_Box(x, y, w, h, L), ch(ch) {}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+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
+
+ if (ch != NULL) {
+ 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);
+ }
+ else
+ if (ch->status == STATUS_PLAY)
+ fl_rect(x(), y(), w(), h(), COLOR_BD_1);
+ else
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_0); // status empty
+
+
+ if (G_Mixer.recording && ch->armed)
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_3); // take in progress
+ else
+ if (G_Recorder.active && G_Recorder.canRec(ch, &G_Mixer))
+ fl_rectf(x()+1, y()+1, w()-2, h()-2, COLOR_BG_4); // action record
+
+ /* equation for the progress bar:
+ * ((chanTracker - chanStart) * w()) / (chanEnd - chanStart). */
+
+ int pos = ch->getPosition();
+ if (pos == -1)
+ pos = 0;
+ else
+ pos = (pos * (w()-1)) / (ch->end - ch->begin);
+ fl_rectf(x()+1, y()+1, pos, h()-2, COLOR_BG_2);
+ }
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_status
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_CHANNEL_STATUS_H
+#define GE_CHANNEL_STATUS_H
+
+
+#include <FL/Fl_Box.H>
+
+
+class geChannelStatus : public Fl_Box
+{
+public:
+ geChannelStatus(int X, int Y, int W, int H, class SampleChannel *ch,
+ const char *L=0);
+ void draw();
+ class SampleChannel *ch;
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_column
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../../core/sampleChannel.h"
+#include "../../../../glue/channel.h"
+#include "../../../../utils/log.h"
+#include "../../../../utils/string.h"
+#include "../../../dialogs/gd_warnings.h"
+#include "../../../elems/basics/boxtypes.h"
+#include "keyboard.h"
+#include "sampleChannel.h"
+#include "midiChannel.h"
+#include "column.h"
+
+
+geColumn::geColumn(int X, int Y, int W, int H, int index, geKeyboard *parent)
+ : Fl_Group(X, Y, W, H), parent(parent), index(index)
+{
+ /* geColumn does a bit of a mess: we pass a pointer to its parent (geKeyboard) and
+ the geColumn itself deals with the creation of another widget, outside geColumn
+ and inside geKeyboard, which handles the vertical resize bar (gResizerBar).
+ The resizer cannot stay inside geColumn: it needs a broader view on the other
+ side widgets. The view can be obtained from geKeyboard only (the upper level).
+ Unfortunately, parent() can be NULL: at this point (i.e the constructor)
+ geColumn is still detached from any parent. We use a custom geKeyboard *parent
+ instead. */
+
+ begin();
+ addChannelBtn = new gClick(x(), y(), w(), 20, "Add new channel");
+ end();
+
+ resizer = new gResizerBar(x()+w(), y(), 16, h(), false);
+ resizer->setMinSize(MIN_COLUMN_WIDTH);
+ parent->add(resizer);
+
+ addChannelBtn->callback(cb_addChannel, (void*)this);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+geColumn::~geColumn()
+{
+ /* FIXME - this could actually cause a memory leak. resizer is
+ just removed, not deleted. But we cannot delete it right now. */
+
+ parent->remove(resizer);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+
+int geColumn::handle(int e)
+{
+ switch (e) {
+ case FL_RELEASE: {
+ if (Fl::event_button() == FL_RIGHT_MOUSE) {
+ __cb_addChannel();
+ return 1;
+ }
+ }
+ case FL_DND_ENTER: // return(1) for these events to 'accept' dnd
+ case FL_DND_DRAG:
+ case FL_DND_RELEASE: {
+ return 1;
+ }
+ case FL_PASTE: { // handle actual drop (paste) operation
+ vector<std::string> paths;
+ gu_split(Fl::event_text(), "\n", &paths);
+ bool fails = false;
+ int result = 0;
+ for (unsigned i=0; i<paths.size(); i++) {
+ gu_log("[geColumn::handle] loading %s...\n", paths.at(i).c_str());
+ SampleChannel *c = (SampleChannel*) glue_addChannel(index, CHANNEL_SAMPLE);
+ result = glue_loadChannel(c, gu_stripFileUrl(paths.at(i)).c_str());
+ if (result != SAMPLE_LOADED_OK) {
+ deleteChannel(c->guiChannel);
+ fails = true;
+ }
+ }
+ if (fails) {
+ if (paths.size() > 1)
+ gdAlert("Some files were not loaded successfully.");
+ else
+ parent->printChannelMessage(result);
+ }
+ return 1;
+ }
+ }
+
+ /* we return fl_Group::handle only if none of the cases above are fired. That
+ is because we don't want to propagate a dnd drop to all the sub widgets. */
+
+ return Fl_Group::handle(e);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::resize(int X, int Y, int W, int H)
+{
+ /* resize all children */
+
+ int ch = children();
+ for (int i=0; i<ch; i++) {
+ Fl_Widget *c = child(i);
+ c->resize(X, Y + (i * (c->h() + 4)), W, c->h());
+ }
+
+ /* resize group itself */
+
+ x(X); y(Y); w(W); h(H);
+
+ /* resize resizerBar */
+
+ resizer->size(16, H);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::refreshChannels()
+{
+ for (int i=1; i<children(); i++)
+ ((geChannel*) child(i))->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::draw()
+{
+ fl_color(fl_rgb_color(27, 27, 27));
+ fl_rectf(x(), y(), w(), h());
+
+ /* call draw and then redraw in order to avoid channel corruption when
+ scrolling horizontally */
+
+ for (int i=0; i<children(); i++) {
+ child(i)->draw();
+ child(i)->redraw();
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::cb_addChannel(Fl_Widget *v, void *p) { ((geColumn*)p)->__cb_addChannel(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+geChannel *geColumn::addChannel(Channel *ch)
+{
+ int currentY = y() + children() * 24;
+ geChannel *gch = NULL;
+ if (ch->type == CHANNEL_SAMPLE)
+ gch = (geSampleChannel*) new geSampleChannel(x(), currentY, w(), 20, (SampleChannel*) ch);
+ else
+ gch = (geMidiChannel*) new geMidiChannel(x(), currentY, w(), 20, (MidiChannel*) ch);
+
+ add(gch);
+ resize(x(), y(), w(), (children() * 24) + 66); // evil space for drag n drop
+ gch->redraw(); // avoid corruption
+ parent->redraw(); // redraw Keyboard
+ return gch;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::deleteChannel(geChannel *gch)
+{
+ gch->hide();
+ remove(gch);
+ delete gch;
+
+ /* reposition all other channels and resize this group */
+ /** TODO
+ * reposition is useless when called by geColumn::clear(). Add a new
+ * parameter to skip the operation */
+
+ for (int i=0; i<children(); i++) {
+ gch = (geChannel*) child(i);
+ gch->position(gch->x(), y()+(i*24));
+ }
+ size(w(), children() * 24 + 66); // evil space for drag n drop
+ redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::__cb_addChannel()
+{
+ gu_log("[geColumn::__cb_addChannel] index = %d\n", index);
+ int type = openTypeMenu();
+ if (type)
+ glue_addChannel(index, type);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geColumn::openTypeMenu()
+{
+ Fl_Menu_Item rclick_menu[] = {
+ {"Sample channel"},
+ {"MIDI channel"},
+ {0}
+ };
+
+ 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);
+
+ const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+ if (!m) return 0;
+
+ if (strcmp(m->label(), "Sample channel") == 0)
+ return CHANNEL_SAMPLE;
+ if (strcmp(m->label(), "MIDI channel") == 0)
+ return CHANNEL_MIDI;
+ return 0;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geColumn::clear(bool full)
+{
+ if (full)
+ Fl_Group::clear();
+ else {
+ while (children() >= 2) { // skip "add new channel" btn
+ int i = children()-1;
+ deleteChannel((geChannel*)child(i));
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+Channel *geColumn::getChannel(int i)
+{
+ geChannel *gch = (geChannel*) child(i);
+ if (gch->type == CHANNEL_SAMPLE)
+ return ((geSampleChannel*) child(i))->ch;
+ else
+ return ((geMidiChannel*) child(i))->ch;
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_column
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_COLUMN_H
+#define GE_COLUMN_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class geColumn : public Fl_Group
+{
+private:
+
+ static void cb_addChannel (Fl_Widget *v, void *p);
+ inline void __cb_addChannel();
+
+ int openTypeMenu();
+
+ class gClick *addChannelBtn;
+ class gResizerBar *resizer;
+ class geKeyboard *parent;
+
+ int index;
+
+public:
+
+ geColumn(int x, int y, int w, int h, int index, class geKeyboard *parent);
+ ~geColumn();
+
+ /* addChannel
+ * add a new channel in this column and set the internal pointer
+ * to channel to 'ch'. */
+
+ class geChannel *addChannel(class Channel *ch);
+
+ /* handle */
+
+ int handle(int e);
+
+ /* resize
+ * custom resize behavior. */
+
+ void resize(int x, int y, int w, int h);
+
+ /* deleteChannel
+ * remove the channel 'gch' from this column. */
+
+ void deleteChannel(geChannel *gch);
+
+ /* refreshChannels
+ * update channels' graphical statues. Called on each GUI cycle. */
+
+ void refreshChannels();
+
+ /* getChannel */
+
+ Channel *getChannel(int i);
+
+ /* clear
+ * remove all channels from the column. If full==true, delete also the
+ * "add new channel" button. This method ovverrides the inherited one
+ * from Fl_Group. */
+
+ void clear(bool full=false);
+
+ void draw();
+
+ inline int getIndex() { return index; }
+ inline void setIndex(int i) { index = i; }
+ inline bool isEmpty() { return children() == 1; }
+ inline int countChannels() { return children(); }
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * gg_keyboard
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../../core/sampleChannel.h"
+#include "../../../../glue/main.h"
+#include "../../../../glue/io.h"
+#include "../../../../utils/log.h"
+#include "../../../dialogs/gd_warnings.h"
+#include "../../basics/boxtypes.h"
+#include "column.h"
+#include "sampleChannel.h"
+#include "keyboard.h"
+
+
+int geKeyboard::indexColumn = 0;
+
+
+/* -------------------------------------------------------------------------- */
+
+
+geKeyboard::geKeyboard(int X, int Y, int W, int H)
+: Fl_Scroll (X, Y, W, H),
+ bckspcPressed(false),
+ endPressed (false),
+ spacePressed (false),
+ addColumnBtn (NULL)
+{
+ color(COLOR_BG_MAIN);
+ type(Fl_Scroll::BOTH_ALWAYS);
+ scrollbar.color(COLOR_BG_0);
+ scrollbar.selection_color(COLOR_BG_1);
+ scrollbar.labelcolor(COLOR_BD_1);
+ scrollbar.slider(G_CUSTOM_BORDER_BOX);
+ hscrollbar.color(COLOR_BG_0);
+ hscrollbar.selection_color(COLOR_BG_1);
+ hscrollbar.labelcolor(COLOR_BD_1);
+ hscrollbar.slider(G_CUSTOM_BORDER_BOX);
+
+ addColumnBtn = new gClick(8, y(), 200, 20, "Add new column");
+ addColumnBtn->callback(cb_addColumn, (void*) this);
+ add(addColumnBtn);
+
+ init();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::init()
+{
+ /* add 6 empty columns as init layout */
+
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+ __cb_addColumn();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::freeChannel(geChannel *gch)
+{
+ gch->reset();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::deleteChannel(geChannel *gch)
+{
+ for (unsigned i=0; i<columns.size(); i++) {
+ int k = columns.at(i)->find(gch);
+ if (k != columns.at(i)->children()) {
+ columns.at(i)->deleteChannel(gch);
+ return;
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::updateChannel(geChannel *gch)
+{
+ gch->update();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::organizeColumns()
+{
+ /* if only one column exists don't cleanup: the initial column must
+ * stay here. */
+
+ if (columns.size() == 1)
+ return;
+
+ /* otherwise delete all empty columns */
+ /** FIXME - this for loop might not work correctly! */
+
+ for (unsigned i=columns.size()-1; i>=1; i--) {
+ if (columns.at(i)->isEmpty()) {
+ //Fl::delete_widget(columns.at(i));
+ delete columns.at(i);
+ columns.erase(columns.begin() + i);
+ }
+ }
+
+ /* compact column, avoid empty spaces */
+
+ for (unsigned i=1; i<columns.size(); i++)
+ columns.at(i)->position(columns.at(i-1)->x() + columns.at(i-1)->w() + 16, y());
+
+ addColumnBtn->position(columns.back()->x() + columns.back()->w() + 16, y());
+
+ /* recompute col indexes */
+
+ refreshColIndexes();
+
+ redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::cb_addColumn(Fl_Widget *v, void *p)
+{
+ ((geKeyboard*)p)->__cb_addColumn(DEFAULT_COLUMN_WIDTH);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+geChannel *geKeyboard::addChannel(int colIndex, Channel *ch, bool build)
+{
+ geColumn *col = getColumnByIndex(colIndex);
+
+ /* no column with index 'colIndex' found? Just create it and set its index
+ to 'colIndex'. */
+
+ if (!col) {
+ __cb_addColumn();
+ col = columns.back();
+ col->setIndex(colIndex);
+ gu_log("[geKeyboard::addChannel] created new column with index=%d\n", colIndex);
+ }
+
+ gu_log("[geKeyboard::addChannel] add to column with index = %d\n", col->getIndex());
+ return col->addChannel(ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::refreshColumns()
+{
+ for (unsigned i=0; i<columns.size(); i++)
+ columns.at(i)->refreshChannels();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+geColumn *geKeyboard::getColumnByIndex(int index)
+{
+ for (unsigned i=0; i<columns.size(); i++)
+ if (columns.at(i)->getIndex() == index)
+ return columns.at(i);
+ return NULL;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+/* TODO - the following event handling for play, stop, rewind, start rec and
+so on should be moved to the proper widget: gdMainWindow or (better) geController. */
+
+int geKeyboard::handle(int e)
+{
+ int ret = Fl_Group::handle(e); // assume the buttons won't handle the Keyboard events
+ switch (e) {
+ case FL_FOCUS:
+ case FL_UNFOCUS: {
+ ret = 1; // enables receiving Keyboard events
+ break;
+ }
+ case FL_SHORTCUT: // in case widget that isn't ours has focus
+ case FL_KEYDOWN: // Keyboard key pushed
+ case FL_KEYUP: { // Keyboard key released
+
+ /* rewind session. Avoid retrigs */
+
+ if (e == FL_KEYDOWN) {
+ if (Fl::event_key() == FL_BackSpace && !bckspcPressed) {
+ bckspcPressed = true;
+ glue_rewindSeq();
+ ret = 1;
+ break;
+ }
+ else if (Fl::event_key() == FL_End && !endPressed) {
+ endPressed = true;
+ glue_startStopInputRec(false); // update gui
+ ret = 1;
+ break;
+ }
+ else if (Fl::event_key() == FL_Enter && !enterPressed) {
+ enterPressed = true;
+ glue_startStopActionRec(false); // update gui
+ ret = 1;
+ break;
+ }
+ else if (Fl::event_key() == ' ' && !spacePressed) {
+ spacePressed = true;
+ glue_startStopSeq(false); // update gui
+ ret = 1;
+ break;
+ }
+ }
+ else if (e == FL_KEYUP) {
+ if (Fl::event_key() == FL_BackSpace)
+ bckspcPressed = false;
+ else if (Fl::event_key() == FL_End)
+ endPressed = false;
+ else if (Fl::event_key() == ' ')
+ spacePressed = false;
+ else if (Fl::event_key() == FL_Enter)
+ enterPressed = false;
+ }
+
+ /* Walk button arrays, trying to match button's label with the Keyboard event.
+ * If found, set that button's value() based on up/down event,
+ * and invoke that button's callback() */
+
+ for (unsigned i=0; i<columns.size(); i++)
+ for (int k=1; k<columns.at(i)->children(); k++)
+ ret &= ((geChannel*)columns.at(i)->child(k))->keyPress(e);
+ break;
+ }
+ }
+ return ret;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::clear()
+{
+ for (unsigned i=0; i<columns.size(); i++)
+ delete columns.at(i);
+ columns.clear();
+ indexColumn = 0; // new columns will start from index=0
+ addColumnBtn->position(8, y());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::setChannelWithActions(geSampleChannel *gch)
+{
+ if (gch->ch->hasActions)
+ gch->showActionButton();
+ else
+ gch->hideActionButton();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::printChannelMessage(int res)
+{
+ if (res == SAMPLE_NOT_VALID)
+ gdAlert("This is not a valid WAVE file.");
+ else if (res == SAMPLE_MULTICHANNEL)
+ gdAlert("Multichannel samples not supported.");
+ else if (res == SAMPLE_WRONG_BIT)
+ gdAlert("This sample has an\nunsupported bit-depth (> 32 bit).");
+ else if (res == SAMPLE_WRONG_ENDIAN)
+ gdAlert("This sample has a wrong\nbyte order (not little-endian).");
+ else if (res == SAMPLE_WRONG_FORMAT)
+ gdAlert("This sample is encoded in\nan unsupported audio format.");
+ else if (res == SAMPLE_READ_ERROR)
+ gdAlert("Unable to read this sample.");
+ else if (res == SAMPLE_PATH_TOO_LONG)
+ gdAlert("File path too long.");
+ else
+ gdAlert("Unknown error.");
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::__cb_addColumn(int width)
+{
+ int colx;
+ int colxw;
+ int gap = 16;
+ if (columns.size() == 0) {
+ colx = x() - xposition(); // mind the offset with xposition()
+ colxw = colx + width;
+ }
+ else {
+ geColumn *prev = columns.back();
+ colx = prev->x()+prev->w() + gap;
+ colxw = colx + width;
+ }
+
+ /* add geColumn to geKeyboard and to columns vector */
+
+ geColumn *gc = new geColumn(colx, y(), width, 2000, indexColumn, this);
+ add(gc);
+ columns.push_back(gc);
+ indexColumn++;
+
+ /* move addColumn button */
+
+ addColumnBtn->position(colxw + gap, y());
+ redraw();
+
+ gu_log("[geKeyboard::__cb_addColumn] new column added (index=%d, w=%d), total count=%d, addColumn(x)=%d\n",
+ gc->getIndex(), width, columns.size(), addColumnBtn->x());
+
+ /* recompute col indexes */
+
+ refreshColIndexes();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::addColumn(int width)
+{
+ __cb_addColumn(width);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geKeyboard::refreshColIndexes()
+{
+ for (unsigned i=0; i<columns.size(); i++)
+ columns.at(i)->setIndex(i);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geKeyboard::getColumnWidth(int i)
+{
+ return getColumnByIndex(i)->w();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+geColumn *geKeyboard::getColumn(int i)
+{
+ return columns.at(i);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * gg_keyboard
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_KEYBOARD_H
+#define GE_KEYBOARD_H
+
+
+#include <vector>
+#include <FL/Fl_Scroll.H>
+#include "../../../../core/const.h"
+
+
+class geKeyboard : public Fl_Scroll
+{
+private:
+
+ /* refreshColIndexes
+ * Recompute all column indexes in order to avoid any gaps between them.
+ * Indexes must always be contiguous! */
+
+ void refreshColIndexes();
+
+ static void cb_addColumn (Fl_Widget *v, void *p);
+ inline void __cb_addColumn(int width=DEFAULT_COLUMN_WIDTH);
+
+ bool bckspcPressed;
+ bool endPressed;
+ bool spacePressed;
+ bool enterPressed;
+
+ /* indexColumn
+ * the last index used for column. */
+
+ static int indexColumn;
+
+ class gClick *addColumnBtn;
+
+ /* columns
+ * a vector of columns which in turn contain channels. */
+
+ std::vector<class geColumn*> columns;
+
+public:
+
+ geKeyboard(int X, int Y, int W, int H);
+
+ int handle(int e);
+
+ /* init
+ * build the initial setup of empty channels. */
+
+ void init();
+
+ /* addChannel
+ * add a new channel to geChannels. Used by callbacks and during
+ * patch loading. Requires Channel (and not geChannel). If build is
+ * set to true, also generate the corresponding column if column (index) does
+ * not exist yet. */
+
+ class geChannel *addChannel(int column, class Channel *ch, bool build=false);
+
+ /* addColumn
+ * add a new column to the top of the stack. */
+
+ void addColumn(int width=380);
+
+ /* deleteChannel
+ * delete a channel from geChannels<> where geChannel->ch == ch and remove
+ * it from the stack. */
+
+ void deleteChannel(geChannel *gch);
+
+ /* freeChannel
+ * free a channel from geChannels<> where geChannel->ch == ch. No channels
+ * are deleted */
+
+ void freeChannel(geChannel *gch);
+
+ /* updateChannel
+ * wrapper function to call gch->update(). */
+
+ void updateChannel(geChannel *gch);
+
+ /* organizeColumns
+ * reorganize columns layout by removing empty gaps. */
+
+ void organizeColumns();
+
+ /* refreshColumns
+ * refresh each column's channel, called on each GUI cycle. */
+
+ void refreshColumns();
+
+ /* getColumnByIndex
+ * return the column with index 'index', or NULL if not found. */
+
+ geColumn *getColumnByIndex(int index);
+
+ /* getColumn
+ * return the column with from columns->at(i). */
+
+ geColumn *getColumn(int i);
+
+ /* clear
+ * delete all channels and groups. */
+
+ void clear();
+
+ /* setChannelWithActions
+ * add 'R' button if channel has actions, and set recorder to active. */
+
+ void setChannelWithActions(class geSampleChannel *gch);
+
+ /* printChannelMessage
+ * given any output by glue_loadChannel, print the message on screen
+ * on a gdAlert subwindow. */
+
+ void printChannelMessage(int res);
+
+ /* getTotalColumns */
+
+ unsigned getTotalColumns() { return columns.size(); }
+
+ /* getColumnWidth
+ * return the width in pixel of i-th column. Warning: 'i' is the i-th column
+ * in the column array, NOT the index. */
+
+ int getColumnWidth(int i);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_midiChannel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../../core/const.h"
+#include "../../../../core/graphics.h"
+#include "../../../../core/midiChannel.h"
+#include "../../../../glue/channel.h"
+#include "../../../../glue/io.h"
+#include "../../../dialogs/gd_mainWindow.h"
+#include "../../../dialogs/gd_editor.h"
+#include "../../../dialogs/gd_actionEditor.h"
+#include "../../../dialogs/gd_warnings.h"
+#include "../../../dialogs/gd_browser.h"
+#include "../../../dialogs/gd_keyGrabber.h"
+#include "../../../dialogs/gd_pluginList.h"
+#include "../../../dialogs/midiIO/midiInputChannel.h"
+#include "../../../dialogs/midiIO/midiOutputMidiCh.h"
+#include "../../basics/boxtypes.h"
+#include "midiChannel.h"
+
+
+extern Recorder G_Recorder;
+extern gdMainWindow *G_MainWin;
+
+
+geMidiChannel::geMidiChannel(int X, int Y, int W, int H, MidiChannel *ch)
+ : geChannel(X, Y, W, H, CHANNEL_MIDI, ch)
+{
+ begin();
+
+#if defined(WITH_VST)
+ int delta = 144; // (6 widgets * 20) + (6 paddings * 4)
+#else
+ int delta = 120; // (5 widgets * 20) + (5 paddings * 4)
+#endif
+
+ button = new gButton(x(), y(), 20, 20, "", channelStop_xpm, channelPlay_xpm);
+ arm = new gClick(button->x()+button->w()+4, y(), 20, 20, "", armOff_xpm, armOn_xpm);
+ mainButton = new geMidiChannelButton(arm->x()+arm->w()+4, y(), w() - delta, 20, "-- MIDI --");
+ mute = new gClick(mainButton->x()+mainButton->w()+4, y(), 20, 20, "", muteOff_xpm, muteOn_xpm);
+ solo = new gClick(mute->x()+mute->w()+4, y(), 20, 20, "", soloOff_xpm, soloOn_xpm);
+#if defined(WITH_VST)
+ fx = new gFxButton(solo->x()+solo->w()+4, y(), 20, 20, fxOff_xpm, fxOn_xpm);
+ vol = new gDial(fx->x()+fx->w()+4, y(), 20, 20);
+#else
+ vol = new gDial(solo->x()+solo->w()+4, y(), 20, 20);
+#endif
+
+ end();
+
+ resizable(mainButton);
+
+ update();
+
+ button->callback(cb_button, (void*)this);
+ button->when(FL_WHEN_CHANGED); // do callback on keypress && on keyrelease
+
+ arm->type(FL_TOGGLE_BUTTON);
+ arm->callback(cb_arm, (void*)this);
+
+#ifdef WITH_VST
+ fx->callback(cb_openFxWindow, (void*)this);
+#endif
+
+ mute->type(FL_TOGGLE_BUTTON);
+ mute->callback(cb_mute, (void*)this);
+
+ solo->type(FL_TOGGLE_BUTTON);
+ solo->callback(cb_solo, (void*)this);
+
+ mainButton->callback(cb_openMenu, (void*)this);
+
+ vol->callback(cb_changeVol, (void*)this);
+
+ ch->guiChannel = this;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::cb_button (Fl_Widget *v, void *p) { ((geMidiChannel*)p)->__cb_button(); }
+void geMidiChannel::cb_openMenu (Fl_Widget *v, void *p) { ((geMidiChannel*)p)->__cb_openMenu(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::__cb_button()
+{
+ if (button->value())
+ glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::__cb_openMenu()
+{
+ Fl_Menu_Item rclick_menu[] = {
+ {"Edit actions..."}, // 0
+ {"Clear actions", 0, 0, 0, FL_SUBMENU}, // 1
+ {"All"}, // 2
+ {0}, // 3
+ {"Setup keyboard input..."}, // 5
+ {"Setup MIDI input..."}, // 6
+ {"Setup MIDI output..."}, // 7
+ {"Clone channel"}, // 8
+ {"Delete channel"}, // 9
+ {0}
+ };
+
+ /* no 'clear actions' if there are no actions */
+
+ if (!ch->hasActions)
+ rclick_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);
+
+ const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+ if (!m) return;
+
+ if (strcmp(m->label(), "Delete channel") == 0) {
+ if (!gdConfirmWin("Warning", "Delete channel: are you sure?"))
+ return;
+ glue_deleteChannel(ch);
+ return;
+ }
+
+ if (strcmp(m->label(), "Clone channel") == 0) {
+ glue_cloneChannel(ch);
+ return;
+ }
+
+ if (strcmp(m->label(), "Setup keyboard input...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdKeyGrabber(ch), 0);
+ //new gdKeyGrabber(ch);
+ return;
+ }
+
+ if (strcmp(m->label(), "All") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all actions: are you sure?"))
+ return;
+ G_Recorder.clearChan(ch->index);
+ ch->hasActions = false;
+ gu_refreshActionEditor(); // refresh a.editor window, it could be open
+ return;
+ }
+
+ if (strcmp(m->label(), "Edit actions...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdActionEditor(ch), WID_ACTION_EDITOR);
+ return;
+ }
+
+ if (strcmp(m->label(), "Setup MIDI input...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdMidiInputChannel(ch), 0);
+ return;
+ }
+
+ if (strcmp(m->label(), "Setup MIDI output...") == 0) {
+ //gu_openSubWindow(G_MainWin, new gdMidiGrabberChannel(ch, GrabForOutput), 0);
+ gu_openSubWindow(G_MainWin, new gdMidiOutputMidiCh((MidiChannel*) ch), 0);
+ return;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::refresh()
+{
+ setColorsByStatus(ch->status, ch->recStatus);
+ mainButton->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::reset()
+{
+ mainButton->setDefaultMode("-- MIDI --");
+ mainButton->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::update()
+{
+ if (((MidiChannel*) ch)->midiOut) {
+ char tmp[32];
+ sprintf(tmp, "-- MIDI (channel %d) --", ((MidiChannel*) ch)->midiOutChan+1);
+ mainButton->copy_label(tmp);
+ }
+ else
+ mainButton->label("-- MIDI --");
+
+ vol->value(ch->volume);
+ mute->value(ch->mute);
+ solo->value(ch->solo);
+
+ mainButton->setKey(ch->key);
+
+#ifdef WITH_VST
+ fx->full = ch->plugins.size() > 0;
+ fx->redraw();
+#endif
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiChannel::resize(int X, int Y, int W, int H)
+{
+ geChannel::resize(X, Y, W, H);
+
+ arm->hide();
+#ifdef WITH_VST
+ fx->hide();
+#endif
+
+ if (w() > BREAK_ARM)
+ arm->show();
+#ifdef WITH_VST
+ if (w() > BREAK_FX)
+ fx->show();
+#endif
+
+ packWidgets();
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+
+geMidiChannelButton::geMidiChannelButton(int x, int y, int w, int h, const char *l)
+ : geChannelButton(x, y, w, h, l) {}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geMidiChannelButton::handle(int e)
+{
+ // MIDI drag-n-drop does nothing so far.
+ return gClick::handle(e);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_midiChannel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_MIDI_CHANNEL_H
+#define GE_MIDI_CHANNEL_H
+
+
+#include "channel.h"
+#include "channelButton.h"
+
+
+class geMidiChannel : public geChannel
+{
+private:
+
+ static void cb_button (Fl_Widget *v, void *p);
+ static void cb_openMenu (Fl_Widget *v, void *p);
+
+ inline void __cb_button ();
+ inline void __cb_openMenu ();
+ inline void __cb_readActions ();
+
+public:
+
+ geMidiChannel(int x, int y, int w, int h, class MidiChannel *ch);
+
+ void reset ();
+ void update ();
+ void refresh ();
+ int keyPress(int event); // TODO - move to base class
+ void resize (int x, int y, int w, int h);
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+
+class geMidiChannelButton : public geChannelButton
+{
+public:
+ geMidiChannelButton(int x, int y, int w, int h, const char *l=0);
+ int handle(int e);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_sampleChannel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../../core/mixer.h"
+#include "../../../../core/conf.h"
+#include "../../../../core/recorder.h"
+#include "../../../../core/graphics.h"
+#include "../../../../core/wave.h"
+#include "../../../../core/sampleChannel.h"
+#include "../../../../glue/main.h"
+#include "../../../../glue/io.h"
+#include "../../../../glue/channel.h"
+#include "../../../../glue/storage.h"
+#include "../../../../utils/string.h"
+#include "../../../dialogs/gd_mainWindow.h"
+#include "../../../dialogs/gd_keyGrabber.h"
+#include "../../../dialogs/gd_editor.h"
+#include "../../../dialogs/gd_actionEditor.h"
+#include "../../../dialogs/gd_warnings.h"
+#include "../../../dialogs/gd_browser.h"
+#include "../../../dialogs/midiIO/midiOutputSampleCh.h"
+#include "../../../dialogs/midiIO/midiInputChannel.h"
+#include "../../basics/boxtypes.h"
+#include "channelStatus.h"
+#include "channelMode.h"
+#include "keyboard.h"
+#include "sampleChannel.h"
+
+
+extern Mixer G_Mixer;
+extern Conf G_Conf;
+extern Recorder G_Recorder;
+extern gdMainWindow *G_MainWin;
+
+
+geSampleChannel::geSampleChannel(int X, int Y, int W, int H, SampleChannel *ch)
+ : geChannel(X, Y, W, H, CHANNEL_SAMPLE, (Channel*) ch)
+{
+ begin();
+
+ button = new gButton(x(), y(), 20, 20, "", channelStop_xpm, channelPlay_xpm);
+ arm = new gClick(button->x()+button->w()+4, y(), 20, 20, "", armOff_xpm, armOn_xpm);
+ status = new geChannelStatus(arm->x()+arm->w()+4, y(), 20, 20, ch);
+ mainButton = new geSampleChannelButton(status->x()+status->w()+4, y(), 20, 20, "-- no sample --");
+ readActions = new gClick(mainButton->x()+mainButton->w()+4, y(), 20, 20, "", readActionOff_xpm, readActionOn_xpm);
+ modeBox = new geChannelMode(readActions->x()+readActions->w()+4, y(), 20, 20, ch);
+ mute = new gClick(modeBox->x()+modeBox->w()+4, y(), 20, 20, "", muteOff_xpm, muteOn_xpm);
+ solo = new gClick(mute->x()+mute->w()+4, y(), 20, 20, "", soloOff_xpm, soloOn_xpm);
+#ifdef WITH_VST
+ fx = new gFxButton(solo->x()+solo->w()+4, y(), 20, 20, fxOff_xpm, fxOn_xpm);
+ vol = new gDial(fx->x()+fx->w()+4, y(), 20, 20);
+#else
+ vol = new gDial(solo->x()+solo->w()+4, y(), 20, 20);
+#endif
+
+ end();
+
+ resizable(mainButton);
+
+ update();
+
+ button->callback(cb_button, (void*)this);
+ button->when(FL_WHEN_CHANGED); // do callback on keypress && on keyrelease
+
+ arm->type(FL_TOGGLE_BUTTON);
+ arm->callback(cb_arm, (void*)this);
+
+#ifdef WITH_VST
+ fx->callback(cb_openFxWindow, (void*)this);
+#endif
+
+ mute->type(FL_TOGGLE_BUTTON);
+ mute->callback(cb_mute, (void*)this);
+
+ solo->type(FL_TOGGLE_BUTTON);
+ solo->callback(cb_solo, (void*)this);
+
+ mainButton->callback(cb_openMenu, (void*)this);
+
+ readActions->type(FL_TOGGLE_BUTTON);
+ readActions->value(ch->readActions);
+ readActions->callback(cb_readActions, (void*)this);
+
+ vol->callback(cb_changeVol, (void*)this);
+
+ ch->guiChannel = this;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::cb_button (Fl_Widget *v, void *p) { ((geSampleChannel*)p)->__cb_button(); }
+void geSampleChannel::cb_openMenu (Fl_Widget *v, void *p) { ((geSampleChannel*)p)->__cb_openMenu(); }
+void geSampleChannel::cb_readActions (Fl_Widget *v, void *p) { ((geSampleChannel*)p)->__cb_readActions(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::__cb_button()
+{
+ if (button->value()) // pushed
+ glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
+ else // released
+ glue_keyRelease(ch, Fl::event_ctrl(), Fl::event_shift());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::__cb_openMenu()
+{
+ /* If you're recording (input or actions) no menu is allowed; you can't do
+ anything, especially deallocate the channel */
+
+ if (G_Mixer.recording || G_Recorder.active)
+ return;
+
+ /* the following is a trash workaround for a FLTK menu. We need a gMenu
+ * widget asap */
+
+ Fl_Menu_Item rclick_menu[] = {
+ {"Load new sample..."}, // 0
+ {"Export sample to file..."}, // 1
+ {"Setup keyboard input..."}, // 2
+ {"Setup MIDI input..."}, // 3
+ {"Setup MIDI output..."}, // 4
+ {"Edit sample..."}, // 5
+ {"Edit actions..."}, // 6
+ {"Clear actions", 0, 0, 0, FL_SUBMENU}, // 7
+ {"All"}, // 8
+ {"Mute"}, // 9
+ {"Volume"}, // 10
+ {"Start/Stop"}, // 11
+ {0}, // 12
+ {"Clone channel"}, // 13
+ {"Free channel"}, // 14
+ {"Delete channel"}, // 15
+ {0}
+ };
+
+ if (ch->status & (STATUS_EMPTY | STATUS_MISSING)) {
+ rclick_menu[1].deactivate();
+ rclick_menu[5].deactivate();
+ rclick_menu[14].deactivate();
+ }
+
+ /* no 'clear actions' if there are no actions */
+
+ if (!ch->hasActions)
+ rclick_menu[7].deactivate();
+
+ /* no 'clear start/stop actions' for those channels in loop mode:
+ * they cannot have start/stop actions. */
+
+ if (((SampleChannel*)ch)->mode & LOOP_ANY)
+ rclick_menu[11].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);
+
+ const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+ if (!m) return;
+
+ if (strcmp(m->label(), "Load new sample...") == 0) {
+ gWindow *w = new gdLoadBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Browse sample",
+ G_Conf.samplePath.c_str(), glue_loadSample, ch);
+ gu_openSubWindow(G_MainWin, w, WID_FILE_BROWSER);
+ return;
+ }
+
+ if (strcmp(m->label(), "Setup keyboard input...") == 0) {
+ new gdKeyGrabber(ch); /// FIXME - use gu_openSubWindow
+ return;
+ }
+
+ if (strcmp(m->label(), "Setup MIDI input...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdMidiInputChannel(ch), 0);
+ return;
+ }
+
+ if (strcmp(m->label(), "Setup MIDI output...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdMidiOutputSampleCh((SampleChannel*) ch), 0);
+ return;
+ }
+
+ if (strcmp(m->label(), "Edit sample...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdEditor((SampleChannel*) ch), WID_SAMPLE_EDITOR); /// FIXME title it's up to gdEditor
+ return;
+ }
+
+ if (strcmp(m->label(), "Export sample to file...") == 0) {
+ gWindow *w = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Save sample", \
+ G_Conf.samplePath.c_str(), "", glue_saveSample, ch);
+ gu_openSubWindow(G_MainWin, w, WID_FILE_BROWSER);
+ return;
+ }
+
+ if (strcmp(m->label(), "Delete channel") == 0) {
+ if (!gdConfirmWin("Warning", "Delete channel: are you sure?"))
+ return;
+ glue_deleteChannel(ch);
+ return;
+ }
+
+ if (strcmp(m->label(), "Free channel") == 0) {
+ if (ch->status == STATUS_PLAY) {
+ if (!gdConfirmWin("Warning", "This action will stop the channel: are you sure?"))
+ return;
+ }
+ else if (!gdConfirmWin("Warning", "Free channel: are you sure?"))
+ return;
+
+ glue_freeChannel(ch);
+
+ /* delete any related subwindow */
+
+ /** FIXME - use gu_closeAllSubwindows() */
+
+ G_MainWin->delSubWindow(WID_FILE_BROWSER);
+ G_MainWin->delSubWindow(WID_ACTION_EDITOR);
+ G_MainWin->delSubWindow(WID_SAMPLE_EDITOR);
+ G_MainWin->delSubWindow(WID_FX_LIST);
+
+ return;
+ }
+
+ if (strcmp(m->label(), "Clone channel") == 0) {
+ glue_cloneChannel(ch);
+ return;
+ }
+
+ if (strcmp(m->label(), "Mute") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all mute actions: are you sure?"))
+ return;
+ G_Recorder.clearAction(ch->index, ACTION_MUTEON | ACTION_MUTEOFF);
+ ch->hasActions = G_Recorder.hasActions(ch->index);
+
+ if (!ch->hasActions)
+ hideActionButton();
+
+ /* TODO - set mute=false */
+
+ gu_refreshActionEditor(); // refresh a.editor window, it could be open
+ return;
+ }
+
+ if (strcmp(m->label(), "Start/Stop") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all start/stop actions: are you sure?"))
+ return;
+ G_Recorder.clearAction(ch->index, ACTION_KEYPRESS | ACTION_KEYREL | ACTION_KILLCHAN);
+ ch->hasActions = G_Recorder.hasActions(ch->index);
+
+ if (!ch->hasActions)
+ hideActionButton();
+ gu_refreshActionEditor(); // refresh a.editor window, it could be open
+ return;
+ }
+
+ if (strcmp(m->label(), "Volume") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all volume actions: are you sure?"))
+ return;
+ G_Recorder.clearAction(ch->index, ACTION_VOLUME);
+ ch->hasActions = G_Recorder.hasActions(ch->index);
+ if (!ch->hasActions)
+ hideActionButton();
+ gu_refreshActionEditor(); // refresh a.editor window, it could be open
+ return;
+ }
+
+ if (strcmp(m->label(), "All") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all actions: are you sure?"))
+ return;
+ G_Recorder.clearChan(ch->index);
+ ch->hasActions = false;
+ hideActionButton();
+ gu_refreshActionEditor(); // refresh a.editor window, it could be open
+ return;
+ }
+
+ if (strcmp(m->label(), "Edit actions...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdActionEditor(ch), WID_ACTION_EDITOR);
+ return;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::__cb_readActions()
+{
+ glue_startStopReadingRecs((SampleChannel*) ch);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::refresh()
+{
+ if (!mainButton->visible()) // mainButton invisible? status too (see below)
+ return;
+
+ setColorsByStatus(ch->status, ch->recStatus);
+
+ if (((SampleChannel*) ch)->wave != NULL) {
+ if (G_Mixer.recording && ch->armed)
+ mainButton->setInputRecordMode();
+ if (G_Recorder.active) {
+ if (G_Recorder.canRec(ch, &G_Mixer))
+ mainButton->setActionRecordMode();
+ }
+ status->redraw(); // status invisible? sampleButton too (see below)
+ }
+ mainButton->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::reset()
+{
+ hideActionButton();
+ mainButton->setDefaultMode("-- no sample --");
+ mainButton->redraw();
+ status->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::update()
+{
+ /* update sample button's label */
+
+ switch (ch->status) {
+ case STATUS_EMPTY:
+ mainButton->label("-- no sample --");
+ break;
+ case STATUS_MISSING:
+ case STATUS_WRONG:
+ mainButton->label("* file not found! *");
+ break;
+ default:
+ mainButton->label(((SampleChannel*) ch)->wave->name.c_str());
+ break;
+ }
+
+ /* update channels. If you load a patch with recorded actions, the 'R'
+ * button must be shown. Moreover if the actions are active, the 'R'
+ * button must be activated accordingly. */
+
+ if (ch->hasActions)
+ showActionButton();
+ else
+ hideActionButton();
+
+ /* updates modebox */
+
+ modeBox->value(((SampleChannel*) ch)->mode);
+ modeBox->redraw();
+
+ /* update volumes+mute+solo */
+
+ vol->value(ch->volume);
+ mute->value(ch->mute);
+ solo->value(ch->solo);
+
+ mainButton->setKey(ch->key);
+
+#ifdef WITH_VST
+ fx->full = ch->plugins.size() > 0;
+ fx->redraw();
+#endif
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::showActionButton()
+{
+ readActions->value(((SampleChannel*) ch)->readActions);
+ readActions->show();
+ packWidgets();
+ redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::hideActionButton()
+{
+ readActions->hide();
+ packWidgets();
+ redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geSampleChannel::resize(int X, int Y, int W, int H)
+{
+ geChannel::resize(X, Y, W, H);
+
+ arm->hide();
+ modeBox->hide();
+ readActions->hide();
+#ifdef WITH_VST
+ fx->hide();
+#endif
+
+ if (w() > BREAK_ARM)
+ arm->show();
+#ifdef WITH_VST
+ if (w() > BREAK_FX)
+ fx->show();
+#endif
+ if (w() > BREAK_MODE_BOX)
+ modeBox->show();
+ if (w() > BREAK_READ_ACTIONS && ch->hasActions)
+ readActions->show();
+
+ packWidgets();
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+
+geSampleChannelButton::geSampleChannelButton(int x, int y, int w, int h, const char *l)
+ : geChannelButton(x, y, w, h, l) {}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geSampleChannelButton::handle(int e)
+{
+ int ret = gClick::handle(e);
+ switch (e) {
+ case FL_DND_ENTER:
+ case FL_DND_DRAG:
+ case FL_DND_RELEASE: {
+ ret = 1;
+ break;
+ }
+ case FL_PASTE: {
+ geSampleChannel *gch = (geSampleChannel*) parent(); // parent is geSampleChannel
+ SampleChannel *ch = (SampleChannel*) gch->ch;
+ int result = glue_loadChannel(ch, gu_trim(gu_stripFileUrl(Fl::event_text())).c_str());
+ if (result != SAMPLE_LOADED_OK)
+ G_MainWin->keyboard->printChannelMessage(result);
+ ret = 1;
+ break;
+ }
+ }
+ return ret;
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_sampleChannel
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_SAMPLE_CHANNEL_H
+#define GE_SAMPLE_CHANNEL_H
+
+
+#include "channel.h"
+#include "channelButton.h"
+
+
+class geSampleChannel : public geChannel
+{
+private:
+
+ static void cb_button (Fl_Widget *v, void *p);
+ static void cb_openMenu (Fl_Widget *v, void *p);
+ static void cb_readActions (Fl_Widget *v, void *p);
+
+ inline void __cb_button ();
+ inline void __cb_openMenu ();
+ inline void __cb_readActions ();
+
+public:
+
+ geSampleChannel(int x, int y, int w, int h, class SampleChannel *ch);
+
+ void reset ();
+ void update ();
+ void refresh ();
+ void resize (int x, int y, int w, int h);
+
+ /* show/hideActionButton
+ Adds or removes 'R' button when actions are available. */
+
+ void showActionButton();
+ void hideActionButton();
+
+ class geChannelMode *modeBox;
+ class gClick *readActions;
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+
+class geSampleChannelButton : public geChannelButton
+{
+public:
+ geSampleChannelButton(int x, int y, int w, int h, const char *l=0);
+ int handle(int e);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+*
+* Giada - Your Hardcore Loopmachine
+*
+* mainIO
+*
+* -----------------------------------------------------------------------------
+*
+* Copyright (C) 2010-2016 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 "../../../core/const.h"
+#include "../../../core/graphics.h"
+#include "../../../core/mixer.h"
+#include "../../../core/pluginHost.h"
+#include "../../../glue/main.h"
+#include "../../../utils/gui.h"
+#include "../../elems/ge_mixed.h"
+#include "../../dialogs/gd_mainWindow.h"
+#include "../../dialogs/gd_pluginList.h"
+#include "mainIO.h"
+
+
+extern Mixer G_Mixer;
+extern gdMainWindow *G_MainWin;
+
+
+geMainIO::geMainIO(int x, int y)
+ : Fl_Group(x, y, 396, 20)
+{
+ begin();
+
+#if defined(WITH_VST)
+ masterFxIn = new gFxButton (x, y, 20, 20, fxOff_xpm, fxOn_xpm);
+ inVol = new gDial (masterFxIn->x()+masterFxIn->w()+4, y, 20, 20);
+ inMeter = new gSoundMeter(inVol->x()+inVol->w()+4, y+4, 140, 12);
+ inToOut = new gClick (inMeter->x()+inMeter->w()+4, y+4, 12, 12, "", inputToOutputOff_xpm, inputToOutputOn_xpm);
+ outMeter = new gSoundMeter(inToOut->x()+inToOut->w()+4, y+4, 140, 12);
+ outVol = new gDial (outMeter->x()+outMeter->w()+4, y, 20, 20);
+ masterFxOut = new gFxButton (outVol->x()+outVol->w()+4, y, 20, 20, fxOff_xpm, fxOn_xpm);
+#else
+ inVol = new gDial (x+62, y, 20, 20);
+ inMeter = new gSoundMeter(inVol->x()+inVol->w()+4, y+5, 140, 12);
+ outMeter = new gSoundMeter(inMeter->x()+inMeter->w()+4, y+5, 140, 12);
+ outVol = new gDial (outMeter->x()+outMeter->w()+4, y, 20, 20);
+#endif
+
+ end();
+
+ resizable(NULL); // don't resize any widget
+
+ outVol->callback(cb_outVol, (void*)this);
+ outVol->value(G_Mixer.outVol);
+ inVol->callback(cb_inVol, (void*)this);
+ inVol->value(G_Mixer.inVol);
+
+#ifdef WITH_VST
+ masterFxOut->callback(cb_masterFxOut, (void*)this);
+ masterFxIn->callback(cb_masterFxIn, (void*)this);
+ inToOut->callback(cb_inToOut, (void*)this);
+ inToOut->type(FL_TOGGLE_BUTTON);
+#endif
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainIO::cb_outVol (Fl_Widget *v, void *p) { ((geMainIO*)p)->__cb_outVol(); }
+void geMainIO::cb_inVol (Fl_Widget *v, void *p) { ((geMainIO*)p)->__cb_inVol(); }
+#ifdef WITH_VST
+void geMainIO::cb_masterFxOut(Fl_Widget *v, void *p) { ((geMainIO*)p)->__cb_masterFxOut(); }
+void geMainIO::cb_masterFxIn (Fl_Widget *v, void *p) { ((geMainIO*)p)->__cb_masterFxIn(); }
+void geMainIO::cb_inToOut (Fl_Widget *v, void *p) { ((geMainIO*)p)->__cb_inToOut(); }
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainIO::__cb_outVol()
+{
+ glue_setOutVol(outVol->value());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainIO::__cb_inVol()
+{
+ glue_setInVol(inVol->value());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+void geMainIO::__cb_masterFxOut()
+{
+ gu_openSubWindow(G_MainWin, new gdPluginList(PluginHost::MASTER_OUT), WID_FX_LIST);
+}
+
+void geMainIO::__cb_masterFxIn()
+{
+ gu_openSubWindow(G_MainWin, new gdPluginList(PluginHost::MASTER_IN), WID_FX_LIST);
+}
+
+void geMainIO::__cb_inToOut()
+{
+ G_Mixer.inToOut = inToOut->value();
+}
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainIO::setOutVol(float v)
+{
+ outVol->value(v);
+}
+
+
+void geMainIO::setInVol(float v)
+{
+ inVol->value(v);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+void geMainIO::setMasterFxOutFull(bool v)
+{
+ masterFxOut->full = v;
+ masterFxOut->redraw();
+}
+
+
+void geMainIO::setMasterFxInFull(bool v)
+{
+ masterFxIn->full = v;
+ masterFxIn->redraw();
+}
+
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainIO::refresh()
+{
+ outMeter->mixerPeak = G_Mixer.peakOut;
+ inMeter->mixerPeak = G_Mixer.peakIn;
+ outMeter->redraw();
+ inMeter->redraw();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainIO
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_MAIN_IO_H
+#define GE_MAIN_IO_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class geMainIO : public Fl_Group
+{
+private:
+
+ class gSoundMeter *outMeter;
+ class gSoundMeter *inMeter;
+ class gDial *outVol;
+ class gDial *inVol;
+#ifdef WITH_VST
+ class gFxButton *masterFxOut;
+ class gFxButton *masterFxIn;
+ class gClick *inToOut;
+#endif
+
+ static void cb_outVol (Fl_Widget *v, void *p);
+ static void cb_inVol (Fl_Widget *v, void *p);
+#ifdef WITH_VST
+ static void cb_masterFxOut(Fl_Widget *v, void *p);
+ static void cb_masterFxIn (Fl_Widget *v, void *p);
+ static void cb_inToOut (Fl_Widget *v, void *p);
+#endif
+
+ inline void __cb_outVol ();
+ inline void __cb_inVol ();
+#ifdef WITH_VST
+ inline void __cb_masterFxOut();
+ inline void __cb_masterFxIn ();
+ inline void __cb_inToOut ();
+#endif
+
+public:
+
+ geMainIO(int x, int y);
+
+ void refresh();
+
+ void setOutVol(float v);
+ void setInVol (float v);
+#ifdef WITH_VST
+ void setMasterFxOutFull(bool v);
+ void setMasterFxInFull(bool v);
+#endif
+};
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainMenu
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/const.h"
+#include "../../../core/mixer.h"
+#include "../../../core/conf.h"
+#include "../../../core/patch.h"
+#include "../../../core/channel.h"
+#include "../../../core/sampleChannel.h"
+#include "../../../utils/gui.h"
+#include "../../../glue/storage.h"
+#include "../../../glue/main.h"
+#include "../../elems/ge_mixed.h"
+#include "../../elems/basics/boxtypes.h"
+#include "../../dialogs/gd_mainWindow.h"
+#include "../../dialogs/gd_about.h"
+#include "../../dialogs/gd_config.h"
+#include "../../dialogs/gd_browser.h"
+#include "../../dialogs/gd_warnings.h"
+#include "../../dialogs/midiIO/midiInputMaster.h"
+#include "keyboard/keyboard.h"
+#include "mainMenu.h"
+
+
+extern Mixer G_Mixer;
+extern Patch G_Patch;
+extern Conf G_Conf;
+extern gdMainWindow *G_MainWin;
+
+
+geMainMenu::geMainMenu(int x, int y)
+ : Fl_Group(x, y, 300, 20)
+{
+ begin();
+
+ file = new gClick(x, y, 70, 21, "file");
+ edit = new gClick(file->x()+file->w()+4, y, 70, 21, "edit");
+ config = new gClick(edit->x()+edit->w()+4, y, 70, 21, "config");
+ about = new gClick(config->x()+config->w()+4, y, 70, 21, "about");
+
+ end();
+
+ resizable(NULL); // don't resize any widget
+
+ about->callback(cb_about, (void*)this);
+ file->callback(cb_file, (void*)this);
+ edit->callback(cb_edit, (void*)this);
+ config->callback(cb_config, (void*)this);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainMenu::cb_about (Fl_Widget *v, void *p) { ((geMainMenu*)p)->__cb_about(); }
+void geMainMenu::cb_config(Fl_Widget *v, void *p) { ((geMainMenu*)p)->__cb_config(); }
+void geMainMenu::cb_file (Fl_Widget *v, void *p) { ((geMainMenu*)p)->__cb_file(); }
+void geMainMenu::cb_edit (Fl_Widget *v, void *p) { ((geMainMenu*)p)->__cb_edit(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainMenu::__cb_about()
+{
+ gu_openSubWindow(G_MainWin, new gdAbout(), WID_ABOUT);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainMenu::__cb_config()
+{
+ gu_openSubWindow(G_MainWin, new gdConfig(380, 370), WID_CONFIG);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainMenu::__cb_file()
+{
+ /* An Fl_Menu_Button is made of many Fl_Menu_Item */
+
+ Fl_Menu_Item menu[] = {
+ {"Open patch or project..."},
+ {"Save patch..."},
+ {"Save project..."},
+ {"Quit Giada"},
+ {0}
+ };
+
+ 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);
+
+ const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+ if (!m) return;
+
+ if (strcmp(m->label(), "Open patch or project...") == 0) {
+ gWindow *childWin = new gdLoadBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Load patch or project",
+ G_Conf.patchPath, glue_loadPatch, NULL);
+ gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
+ return;
+ }
+ if (strcmp(m->label(), "Save patch...") == 0) {
+ if (G_Mixer.hasLogicalSamples() || G_Mixer.hasEditedSamples())
+ if (!gdConfirmWin("Warning", "You should save a project in order to store\nyour takes and/or processed samples."))
+ return;
+ gWindow *childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Save patch",
+ G_Conf.patchPath, G_Patch.name, glue_savePatch, NULL);
+ gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
+ return;
+ }
+ if (strcmp(m->label(), "Save project...") == 0) {
+ gWindow *childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
+ G_Conf.browserW, G_Conf.browserH, "Save project",
+ G_Conf.patchPath, G_Patch.name, glue_saveProject, NULL);
+ gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
+ return;
+ }
+ if (strcmp(m->label(), "Quit Giada") == 0) {
+ G_MainWin->do_callback();
+ return;
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainMenu::__cb_edit()
+{
+ Fl_Menu_Item menu[] = {
+ {"Clear all samples"},
+ {"Clear all actions"},
+ {"Remove empty columns"},
+ {"Reset to init state"},
+ {"Setup global MIDI input..."},
+ {0}
+ };
+
+ /* clear all actions disabled if no recs, clear all samples disabled
+ * if no samples. */
+
+ menu[1].deactivate();
+
+ for (unsigned i=0; i<G_Mixer.channels.size(); i++)
+ if (G_Mixer.channels.at(i)->hasActions) {
+ menu[1].activate();
+ break;
+ }
+ for (unsigned i=0; i<G_Mixer.channels.size(); i++)
+ if (G_Mixer.channels.at(i)->type == CHANNEL_SAMPLE)
+ if (((SampleChannel*)G_Mixer.channels.at(i))->wave != NULL) {
+ menu[0].activate();
+ 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);
+
+ const Fl_Menu_Item *m = menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+ if (!m) return;
+
+ if (strcmp(m->label(), "Clear all samples") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all samples: are you sure?"))
+ return;
+ G_MainWin->delSubWindow(WID_SAMPLE_EDITOR);
+ glue_clearAllSamples();
+ return;
+ }
+ if (strcmp(m->label(), "Clear all actions") == 0) {
+ if (!gdConfirmWin("Warning", "Clear all actions: are you sure?"))
+ return;
+ G_MainWin->delSubWindow(WID_ACTION_EDITOR);
+ glue_clearAllRecs();
+ return;
+ }
+ if (strcmp(m->label(), "Reset to init state") == 0) {
+ if (!gdConfirmWin("Warning", "Reset to init state: are you sure?"))
+ return;
+ gu_closeAllSubwindows();
+ glue_resetToInitState();
+ return;
+ }
+ if (strcmp(m->label(), "Remove empty columns") == 0) {
+ G_MainWin->keyboard->organizeColumns();
+ return;
+ }
+ if (strcmp(m->label(), "Setup global MIDI input...") == 0) {
+ gu_openSubWindow(G_MainWin, new gdMidiInputMaster(), 0);
+ return;
+ }
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainMenu
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_MAIN_MENU_H
+#define GE_MAIN_MENU_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class geMainMenu : public Fl_Group
+{
+private:
+
+ class gClick *file;
+ class gClick *edit;
+ class gClick *config;
+ class gClick *about;
+
+ static void cb_about (Fl_Widget *v, void *p);
+ static void cb_config(Fl_Widget *v, void *p);
+ static void cb_file (Fl_Widget *v, void *p);
+ static void cb_edit (Fl_Widget *v, void *p);
+
+ inline void __cb_about ();
+ inline void __cb_config();
+ inline void __cb_file ();
+ inline void __cb_edit ();
+
+public:
+
+ geMainMenu(int x, int y);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainTimer
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/const.h"
+#include "../../../core/mixer.h"
+#include "../../../core/graphics.h"
+#include "../../../glue/main.h"
+#include "../../../utils/gui.h"
+#include "../../elems/ge_mixed.h"
+#include "../../dialogs/gd_mainWindow.h"
+#include "../../dialogs/gd_bpmInput.h"
+#include "../../dialogs/gd_beatsInput.h"
+#include "mainTimer.h"
+
+
+extern Mixer G_Mixer;
+extern gdMainWindow *G_MainWin;
+
+
+geMainTimer::geMainTimer(int x, int y)
+ : Fl_Group(x, y, 180, 20)
+{
+ begin();
+
+ quantizer = new gChoice(x, y, 40, 20, "", false);
+ bpm = new gClick (quantizer->x()+quantizer->w()+4, y, 40, 20);
+ meter = new gClick (bpm->x()+bpm->w()+8, y, 40, 20, "4/1");
+ multiplier = new gClick (meter->x()+meter->w()+4, y, 20, 20, "", multiplyOff_xpm, multiplyOn_xpm);
+ divider = new gClick (multiplier->x()+multiplier->w()+4, y, 20, 20, "", divideOff_xpm, divideOn_xpm);
+
+ end();
+
+ resizable(NULL); // don't resize any widget
+
+ char buf[6]; snprintf(buf, 6, "%f", G_Mixer.bpm);
+ bpm->copy_label(buf);
+
+ bpm->callback(cb_bpm, (void*)this);
+ meter->callback(cb_meter, (void*)this);
+ multiplier->callback(cb_multiplier, (void*)this);
+ divider->callback(cb_divider, (void*)this);
+
+ quantizer->add("off", 0, cb_quantizer, (void*)this);
+ quantizer->add("1b", 0, cb_quantizer, (void*)this);
+ quantizer->add("2b", 0, cb_quantizer, (void*)this);
+ quantizer->add("3b", 0, cb_quantizer, (void*)this);
+ quantizer->add("4b", 0, cb_quantizer, (void*)this);
+ quantizer->add("6b", 0, cb_quantizer, (void*)this);
+ quantizer->add("8b", 0, cb_quantizer, (void*)this);
+ quantizer->value(0); // "off" by default
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::cb_bpm (Fl_Widget *v, void *p) { ((geMainTimer*)p)->__cb_bpm(); }
+void geMainTimer::cb_meter (Fl_Widget *v, void *p) { ((geMainTimer*)p)->__cb_meter(); }
+void geMainTimer::cb_quantizer (Fl_Widget *v, void *p) { ((geMainTimer*)p)->__cb_quantizer(); }
+void geMainTimer::cb_multiplier(Fl_Widget *v, void *p) { ((geMainTimer*)p)->__cb_multiplier(); }
+void geMainTimer::cb_divider (Fl_Widget *v, void *p) { ((geMainTimer*)p)->__cb_divider(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::__cb_bpm()
+{
+ gu_openSubWindow(G_MainWin, new gdBpmInput(bpm->label()), WID_BPM);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::__cb_meter()
+{
+ gu_openSubWindow(G_MainWin, new gdBeatsInput(), WID_BEATS);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::__cb_quantizer()
+{
+ glue_quantize(quantizer->value());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::__cb_multiplier()
+{
+ glue_beatsMultiply();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::__cb_divider()
+{
+ glue_beatsDivide();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::setBpm(const char *v)
+{
+ bpm->copy_label(v);
+}
+
+
+void geMainTimer::setBpm(float v)
+{
+ char buf[6];
+ sprintf(buf, "%.01f", v); // only 1 decimal place (e.g. 120.0)
+ bpm->copy_label(buf);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::setLock(bool v)
+{
+ if (v) {
+ bpm->deactivate();
+ meter->deactivate();
+ multiplier->deactivate();
+ divider->deactivate();
+ }
+ else {
+ bpm->activate();
+ meter->activate();
+ multiplier->activate();
+ divider->activate();
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTimer::setMeter(int beats, int bars)
+{
+ char buf[8];
+ sprintf(buf, "%d/%d", beats, bars);
+ meter->copy_label(buf);
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainTimer
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_MAIN_TIMER_H
+#define GE_MAIN_TIMER_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class geMainTimer : public Fl_Group
+{
+private:
+
+ class gClick *bpm;
+ class gClick *meter;
+ class gChoice *quantizer;
+ class gClick *multiplier;
+ class gClick *divider;
+
+ static void cb_bpm (Fl_Widget *v, void *p);
+ static void cb_meter (Fl_Widget *v, void *p);
+ static void cb_quantizer (Fl_Widget *v, void *p);
+ static void cb_multiplier(Fl_Widget *v, void *p);
+ static void cb_divider (Fl_Widget *v, void *p);
+
+ inline void __cb_bpm();
+ inline void __cb_meter();
+ inline void __cb_quantizer();
+ inline void __cb_multiplier();
+ inline void __cb_divider();
+
+public:
+
+ geMainTimer(int x, int y);
+
+ void setBpm(const char *v);
+ void setBpm(float v);
+ void setMeter(int beats, int bars);
+
+ /* setLock
+ Locks bpm, beter and multipliers. Used during audio recordings. */
+
+ void setLock(bool v);
+};
+
+
+#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainTransport
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "../../../core/graphics.h"
+#include "../../../glue/main.h"
+#include "../../../glue/io.h"
+#include "../ge_mixed.h"
+#include "mainTransport.h"
+
+
+geMainTransport::geMainTransport(int x, int y)
+ : Fl_Group(x, y, 131, 25)
+{
+ begin();
+
+ rewind = new gClick(x, y, 25, 25, "", rewindOff_xpm, rewindOn_xpm);
+ play = new gClick(rewind->x()+rewind->w()+4, y, 25, 25, "", play_xpm, pause_xpm);
+ recAction = new gClick(play->x()+play->w()+4, y, 25, 25, "", recOff_xpm, recOn_xpm);
+ recInput = new gClick(recAction->x()+recAction->w()+4, y, 25, 25, "", inputRecOff_xpm, inputRecOn_xpm);
+ metronome = new gClick(recInput->x()+recInput->w()+4, y+10, 15, 15, "", metronomeOff_xpm, metronomeOn_xpm);
+
+ end();
+
+ resizable(NULL); // don't resize any widget
+
+ rewind->callback(cb_rewind, (void*)this);
+
+ play->callback(cb_play);
+ play->type(FL_TOGGLE_BUTTON);
+
+ recAction->callback(cb_recAction, (void*)this);
+ recAction->type(FL_TOGGLE_BUTTON);
+
+ recInput->callback(cb_recInput, (void*)this);
+ recInput->type(FL_TOGGLE_BUTTON);
+
+ metronome->callback(cb_metronome);
+ metronome->type(FL_TOGGLE_BUTTON);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::cb_rewind (Fl_Widget *v, void *p) { ((geMainTransport*)p)->__cb_rewind(); }
+void geMainTransport::cb_play (Fl_Widget *v, void *p) { ((geMainTransport*)p)->__cb_play(); }
+void geMainTransport::cb_recAction(Fl_Widget *v, void *p) { ((geMainTransport*)p)->__cb_recAction(); }
+void geMainTransport::cb_recInput (Fl_Widget *v, void *p) { ((geMainTransport*)p)->__cb_recInput(); }
+void geMainTransport::cb_metronome(Fl_Widget *v, void *p) { ((geMainTransport*)p)->__cb_metronome(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::__cb_rewind()
+{
+ glue_rewindSeq();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::__cb_play()
+{
+ glue_startStopSeq(true);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::__cb_recAction()
+{
+ glue_startStopActionRec(true);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::__cb_recInput()
+{
+ glue_startStopInputRec(true);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::__cb_metronome()
+{
+ glue_startStopMetronome(true);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::updatePlay(int v)
+{
+ play->value(v);
+ play->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::updateMetronome(int v)
+{
+ metronome->value(v);
+ metronome->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::updateRecInput(int v)
+{
+ recInput->value(v);
+ recInput->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMainTransport::updateRecAction(int v)
+{
+ recAction->value(v);
+ recAction->redraw();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * mainTransport
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_MAIN_TRANSPORT_H
+#define GE_MAIN_TRANSPORT_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class geMainTransport : public Fl_Group
+{
+private:
+
+ class gClick *rewind;
+ class gClick *play;
+ class gClick *recAction;
+ class gClick *recInput;
+ class gClick *metronome;
+
+ static void cb_rewind (Fl_Widget *v, void *p);
+ static void cb_play (Fl_Widget *v, void *p);
+ static void cb_recAction(Fl_Widget *v, void *p);
+ static void cb_recInput (Fl_Widget *v, void *p);
+ static void cb_metronome(Fl_Widget *v, void *p);
+
+ inline void __cb_rewind ();
+ inline void __cb_play ();
+ inline void __cb_recAction();
+ inline void __cb_recInput ();
+ inline void __cb_metronome();
+
+public:
+
+ geMainTransport(int x, int y);
+
+ void updatePlay (int v);
+ void updateMetronome(int v);
+ void updateRecInput (int v);
+ void updateRecAction(int v);
+};
+
+#endif
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_midiChannel
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/mixer.h"
-#include "../../core/conf.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/graphics.h"
-#include "../../core/channel.h"
-#include "../../core/midiChannel.h"
-#include "../../glue/channel.h"
-#include "../../glue/main.h"
-#include "../../glue/io.h"
-#include "../../utils/gui.h"
-#include "../dialogs/gd_mainWindow.h"
-#include "../dialogs/gd_keyGrabber.h"
-#include "../dialogs/gd_midiInput.h"
-#include "../dialogs/gd_editor.h"
-#include "../dialogs/gd_actionEditor.h"
-#include "../dialogs/gd_warnings.h"
-#include "../dialogs/gd_browser.h"
-#include "../dialogs/gd_keyGrabber.h"
-#include "../dialogs/gd_midiOutput.h"
-#include "../dialogs/gd_pluginList.h"
-#include "midiChannel.h"
-
-
-extern Mixer G_Mixer;
-extern Conf G_Conf;
-extern Recorder G_Recorder;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern gdMainWindow *G_MainWin;
-
-
-geMidiChannel::geMidiChannel(int X, int Y, int W, int H, MidiChannel *ch)
- : geChannel(X, Y, W, H, CHANNEL_MIDI, ch)
-{
- begin();
-
-#if defined(WITH_VST)
- int delta = 144; // (6 widgets * 20) + (6 paddings * 4)
-#else
- int delta = 120; // (5 widgets * 20) + (5 paddings * 4)
-#endif
-
- button = new gButton(x(), y(), 20, 20, "", channelStop_xpm, channelPlay_xpm);
- arm = new gClick(button->x()+button->w()+4, y(), 20, 20, "", armOff_xpm, armOn_xpm);
- mainButton = new geMidiChannelButton(arm->x()+arm->w()+4, y(), w() - delta, 20, "-- MIDI --");
- mute = new gClick(mainButton->x()+mainButton->w()+4, y(), 20, 20, "", muteOff_xpm, muteOn_xpm);
- solo = new gClick(mute->x()+mute->w()+4, y(), 20, 20, "", soloOff_xpm, soloOn_xpm);
-#if defined(WITH_VST)
- fx = new gFxButton(solo->x()+solo->w()+4, y(), 20, 20, fxOff_xpm, fxOn_xpm);
- vol = new gDial(fx->x()+fx->w()+4, y(), 20, 20);
-#else
- vol = new gDial(solo->x()+solo->w()+4, y(), 20, 20);
-#endif
-
- end();
-
- resizable(mainButton);
-
- update();
-
- button->callback(cb_button, (void*)this);
- button->when(FL_WHEN_CHANGED); // do callback on keypress && on keyrelease
-
- arm->type(FL_TOGGLE_BUTTON);
- arm->callback(cb_arm, (void*)this);
-
-#ifdef WITH_VST
- fx->callback(cb_openFxWindow, (void*)this);
-#endif
-
- mute->type(FL_TOGGLE_BUTTON);
- mute->callback(cb_mute, (void*)this);
-
- solo->type(FL_TOGGLE_BUTTON);
- solo->callback(cb_solo, (void*)this);
-
- mainButton->callback(cb_openMenu, (void*)this);
-
- vol->callback(cb_changeVol, (void*)this);
-
- ch->guiChannel = this;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::cb_button (Fl_Widget *v, void *p) { ((geMidiChannel*)p)->__cb_button(); }
-void geMidiChannel::cb_openMenu (Fl_Widget *v, void *p) { ((geMidiChannel*)p)->__cb_openMenu(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::__cb_button()
-{
- if (button->value())
- glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::__cb_openMenu()
-{
- Fl_Menu_Item rclick_menu[] = {
- {"Edit actions..."}, // 0
- {"Clear actions", 0, 0, 0, FL_SUBMENU}, // 1
- {"All"}, // 2
- {0}, // 3
- {"Setup keyboard input..."}, // 5
- {"Setup MIDI input..."}, // 6
- {"Setup MIDI output..."}, // 7
- {"Clone channel"}, // 8
- {"Delete channel"}, // 9
- {0}
- };
-
- /* no 'clear actions' if there are no actions */
-
- if (!ch->hasActions)
- rclick_menu[1].deactivate();
-
- Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
-
- const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
- if (!m) return;
-
- if (strcmp(m->label(), "Delete channel") == 0) {
- if (!gdConfirmWin("Warning", "Delete channel: are you sure?"))
- return;
- glue_deleteChannel(ch);
- return;
- }
-
- if (strcmp(m->label(), "Clone channel") == 0) {
- glue_cloneChannel(ch);
- return;
- }
-
- if (strcmp(m->label(), "Setup keyboard input...") == 0) {
- gu_openSubWindow(G_MainWin, new gdKeyGrabber(ch), 0);
- //new gdKeyGrabber(ch);
- return;
- }
-
- if (strcmp(m->label(), "All") == 0) {
- if (!gdConfirmWin("Warning", "Clear all actions: are you sure?"))
- return;
- G_Recorder.clearChan(ch->index);
- gu_refreshActionEditor(); // refresh a.editor window, it could be open
- return;
- }
-
- if (strcmp(m->label(), "Edit actions...") == 0) {
- gu_openSubWindow(G_MainWin, new gdActionEditor(ch), WID_ACTION_EDITOR);
- return;
- }
-
- if (strcmp(m->label(), "Setup MIDI input...") == 0) {
- gu_openSubWindow(G_MainWin, new gdMidiInputChannel(ch), 0);
- return;
- }
-
- if (strcmp(m->label(), "Setup MIDI output...") == 0) {
- //gu_openSubWindow(G_MainWin, new gdMidiGrabberChannel(ch, GrabForOutput), 0);
- gu_openSubWindow(G_MainWin, new gdMidiOutputMidiCh((MidiChannel*) ch), 0);
- return;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::refresh()
-{
- setColorsByStatus(ch->status, ch->recStatus);
- mainButton->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::reset()
-{
- mainButton->setDefaultMode("-- MIDI --");
- mainButton->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::update()
-{
- if (((MidiChannel*) ch)->midiOut) {
- char tmp[32];
- sprintf(tmp, "-- MIDI (channel %d) --", ((MidiChannel*) ch)->midiOutChan+1);
- mainButton->copy_label(tmp);
- }
- else
- mainButton->label("-- MIDI --");
-
- vol->value(ch->volume);
- mute->value(ch->mute);
- solo->value(ch->solo);
-
- mainButton->setKey(ch->key);
-
-#ifdef WITH_VST
- fx->full = ch->plugins.size() > 0;
- fx->redraw();
-#endif
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geMidiChannel::resize(int X, int Y, int W, int H)
-{
- geChannel::resize(X, Y, W, H);
-
- arm->hide();
-#ifdef WITH_VST
- fx->hide();
-#endif
-
- if (w() > BREAK_ARM)
- arm->show();
-#ifdef WITH_VST
- if (w() > BREAK_FX)
- fx->show();
-#endif
-
- packWidgets();
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-geMidiChannelButton::geMidiChannelButton(int x, int y, int w, int h, const char *l)
- : geChannelButton(x, y, w, h, l) {}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-int geMidiChannelButton::handle(int e)
-{
- // MIDI drag-n-drop does nothing so far.
- return gClick::handle(e);
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_midiChannel
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_MIDI_CHANNEL_H
-#define GE_MIDI_CHANNEL_H
-
-
-#include "channel.h"
-#include "channelButton.h"
-
-
-class geMidiChannel : public geChannel
-{
-private:
-
- static void cb_button (Fl_Widget *v, void *p);
- static void cb_openMenu (Fl_Widget *v, void *p);
-
- inline void __cb_button ();
- inline void __cb_openMenu ();
- inline void __cb_readActions ();
-
-public:
-
- geMidiChannel(int x, int y, int w, int h, class MidiChannel *ch);
-
- void reset ();
- void update ();
- void refresh ();
- int keyPress(int event); // TODO - move to base class
- void resize (int x, int y, int w, int h);
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class geMidiChannelButton : public geChannelButton
-{
-public:
- geMidiChannelButton(int x, int y, int w, int h, const char *l=0);
- int handle(int e);
-};
-
-
-#endif
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiLearner
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 "ge_mixed.h"
+#include "basics/boxtypes.h"
+#include "midiLearner.h"
+
+
+extern KernelMidi G_KernelMidi;
+
+
+geMidiLearner::geMidiLearner(int X, int Y, int W, const char *l,
+ KernelMidi::cb_midiLearn *cb, uint32_t *param)
+ : Fl_Group(X, Y, W, 20),
+ callback(cb),
+ param (param)
+{
+ begin();
+ text = new gBox(x(), y(), 156, 20, l);
+ value = new gClick(text->x()+text->w()+4, y(), 80, 20);
+ button = new gButton(value->x()+value->w()+4, y(), 40, 20, "learn");
+ end();
+
+ text->box(G_CUSTOM_BORDER_BOX);
+ text->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
+
+ value->box(G_CUSTOM_BORDER_BOX);
+ value->callback(cb_value, (void*)this);
+ value->when(FL_WHEN_RELEASE);
+ updateValue();
+
+ button->type(FL_TOGGLE_BUTTON);
+ button->callback(cb_button, (void*)this);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiLearner::updateValue()
+{
+ char buf[16];
+ if (*param != 0x0)
+ snprintf(buf, 9, "0x%X", *param);
+ else
+ snprintf(buf, 16, "(not set)");
+ value->copy_label(buf);
+ button->value(0);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiLearner::cb_button(Fl_Widget *v, void *p) { ((geMidiLearner*)p)->__cb_button(); }
+void geMidiLearner::cb_value(Fl_Widget *v, void *p) { ((geMidiLearner*)p)->__cb_value(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiLearner::__cb_value()
+{
+ if (Fl::event_button() == FL_RIGHT_MOUSE) {
+ *param = 0x0;
+ updateValue();
+ }
+ /// TODO - elif (LEFT_MOUSE) : insert values by hand
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geMidiLearner::__cb_button()
+{
+ if (button->value() == 1) {
+ cbData.window = (gdMidiInput*) parent(); // parent = gdMidiInput
+ cbData.learner = this;
+ G_KernelMidi.startMidiLearn(callback, (void*)&cbData);
+ }
+ else
+ G_KernelMidi.stopMidiLearn();
+}
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * midiLearner
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2016 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 GE_LEARNER_H
+#define GE_LEARNER_H
+
+
+#include <FL/Fl_Group.H>
+#include "../../core/kernelMidi.h"
+
+
+extern KernelMidi G_KernelMidi;
+
+
+class geMidiLearner : public Fl_Group
+{
+private:
+
+ /* callback
+ * cb to pass to kernelMidi. Requires two parameters:
+ * uint32_t msg - MIDI message
+ * void *data - extra data */
+
+ KernelMidi::cb_midiLearn *callback;
+
+ class gBox *text;
+ class gClick *value;
+ class gButton *button;
+
+ static void cb_button(Fl_Widget *v, void *p);
+ static void cb_value (Fl_Widget *v, void *p);
+ inline void __cb_button();
+ inline void __cb_value();
+
+public:
+
+ /* cbData_t
+ * struct we pass to kernelMidi as extra parameter. */
+
+ struct cbData_t
+ {
+ class gdMidiInput *window;
+ class geMidiLearner *learner;
+ } cbData;
+
+ /* param
+ * pointer to ch->midiIn[value] */
+
+ uint32_t *param;
+
+ geMidiLearner(int x, int y, int w, const char *l, KernelMidi::cb_midiLearn *cb,
+ uint32_t *param);
+
+ void updateValue();
+};
+
+
+#endif
#include "../../utils/log.h"
#include "../dialogs/gd_actionEditor.h"
#include "../dialogs/gd_mainWindow.h"
-#include "ge_keyboard.h"
+#include "mainWindow/keyboard/keyboard.h"
#include "muteEditor.h"
G_Recorder.rec(pParent->chan->index, ACTION_MUTEON, frame_a);
G_Recorder.rec(pParent->chan->index, ACTION_MUTEOFF, frame_b);
}
+ pParent->chan->hasActions = true;
G_Recorder.sortActions();
G_MainWin->keyboard->setChannelWithActions((geSampleChannel*)pParent->chan->guiChannel); // update mainWindow
//gu_log("selected: a=%d, b=%d >>> frame_a=%d, frame_b=%d\n",
// a, b, points.at(a).frame, points.at(b).frame);
- G_Recorder.deleteAction(pParent->chan->index, points.at(a).frame, points.at(a).type, false); // false = don't check vals
- G_Recorder.deleteAction(pParent->chan->index, points.at(b).frame, points.at(b).type, false); // false = don't check vals
- G_Recorder.sortActions();
+ G_Recorder.deleteAction(pParent->chan->index, points.at(a).frame,
+ points.at(a).type, false, &G_Mixer.mutex_recs); // false = don't check vals
+ G_Recorder.deleteAction(pParent->chan->index, points.at(b).frame,
+ points.at(b).type, false, &G_Mixer.mutex_recs); // false = don't check vals
+ pParent->chan->hasActions = G_Recorder.hasActions(pParent->chan->index);
+
+ G_Recorder.sortActions();
G_MainWin->keyboard->setChannelWithActions((geSampleChannel*)pParent->chan->guiChannel); // update mainWindow
extractPoints();
int newFrame = points.at(draggedPoint).x * pParent->zoom;
- G_Recorder.deleteAction(
- pParent->chan->index,
- points.at(draggedPoint).frame,
- points.at(draggedPoint).type,
- false); // don't check values
+ G_Recorder.deleteAction(pParent->chan->index,
+ points.at(draggedPoint).frame, points.at(draggedPoint).type, false,
+ &G_Mixer.mutex_recs); // don't check values
+ pParent->chan->hasActions = G_Recorder.hasActions(pParent->chan->index);
G_Recorder.rec(
pParent->chan->index,
points.at(draggedPoint).type,
newFrame);
+ pParent->chan->hasActions = true;
G_Recorder.sortActions();
points.at(draggedPoint).frame = newFrame;
G_Recorder.rec(pParent->chan->index, ACTION_MIDI, frame_a, event_a);
G_Recorder.rec(pParent->chan->index, ACTION_MIDI, frame_b, event_b);
+ pParent->chan->hasActions = true;
}
void gePianoItem::remove()
{
- G_Recorder.deleteAction(pParent->chan->index, frame_a, ACTION_MIDI, true, event_a, 0.0);
- G_Recorder.deleteAction(pParent->chan->index, frame_b, ACTION_MIDI, true, event_b, 0.0);
+ G_Recorder.deleteAction(pParent->chan->index, frame_a, ACTION_MIDI, true,
+ &G_Mixer.mutex_recs, event_a, 0.0);
+ G_Recorder.deleteAction(pParent->chan->index, frame_b, ACTION_MIDI, true,
+ &G_Mixer.mutex_recs, event_b, 0.0);
/* send a note-off in case we are deleting it in a middle of a key_on
* key_off sequence. */
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_sampleChannel
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 "../../core/pluginHost.h"
-#include "../../core/mixer.h"
-#include "../../core/conf.h"
-#include "../../core/patch_DEPR_.h"
-#include "../../core/recorder.h"
-#include "../../core/graphics.h"
-#include "../../core/wave.h"
-#include "../../glue/main.h"
-#include "../../glue/io.h"
-#include "../../glue/channel.h"
-#include "../../glue/storage.h"
-#include "../../utils/gui.h"
-#include "../../utils/string.h"
-#include "../dialogs/gd_mainWindow.h"
-#include "../dialogs/gd_keyGrabber.h"
-#include "../dialogs/gd_midiOutput.h"
-#include "../dialogs/gd_midiInput.h"
-#include "../dialogs/gd_editor.h"
-#include "../dialogs/gd_actionEditor.h"
-#include "../dialogs/gd_warnings.h"
-#include "../dialogs/gd_browser.h"
-#include "ge_status.h"
-#include "ge_modeBox.h"
-#include "ge_keyboard.h"
-#include "sampleChannel.h"
-
-
-extern Mixer G_Mixer;
-extern Conf G_Conf;
-extern Recorder G_Recorder;
-extern Patch_DEPR_ G_Patch_DEPR_;
-extern gdMainWindow *G_MainWin;
-
-
-geSampleChannel::geSampleChannel(int X, int Y, int W, int H, SampleChannel *ch)
- : geChannel(X, Y, W, H, CHANNEL_SAMPLE, ch)
-{
- begin();
-
- button = new gButton(x(), y(), 20, 20, "", channelStop_xpm, channelPlay_xpm);
- arm = new gClick(button->x()+button->w()+4, y(), 20, 20, "", armOff_xpm, armOn_xpm);
- status = new gStatus(arm->x()+arm->w()+4, y(), 20, 20, ch);
- mainButton = new geSampleChannelButton(status->x()+status->w()+4, y(), 20, 20, "-- no sample --");
- readActions = new gClick(mainButton->x()+mainButton->w()+4, y(), 20, 20, "", readActionOff_xpm, readActionOn_xpm);
- modeBox = new gModeBox(readActions->x()+readActions->w()+4, y(), 20, 20, ch);
- mute = new gClick(modeBox->x()+modeBox->w()+4, y(), 20, 20, "", muteOff_xpm, muteOn_xpm);
- solo = new gClick(mute->x()+mute->w()+4, y(), 20, 20, "", soloOff_xpm, soloOn_xpm);
-#ifdef WITH_VST
- fx = new gFxButton(solo->x()+solo->w()+4, y(), 20, 20, fxOff_xpm, fxOn_xpm);
- vol = new gDial(fx->x()+fx->w()+4, y(), 20, 20);
-#else
- vol = new gDial(solo->x()+solo->w()+4, y(), 20, 20);
-#endif
-
- end();
-
- resizable(mainButton);
-
- update();
-
- button->callback(cb_button, (void*)this);
- button->when(FL_WHEN_CHANGED); // do callback on keypress && on keyrelease
-
- arm->type(FL_TOGGLE_BUTTON);
- arm->callback(cb_arm, (void*)this);
-
-#ifdef WITH_VST
- fx->callback(cb_openFxWindow, (void*)this);
-#endif
-
- mute->type(FL_TOGGLE_BUTTON);
- mute->callback(cb_mute, (void*)this);
-
- solo->type(FL_TOGGLE_BUTTON);
- solo->callback(cb_solo, (void*)this);
-
- mainButton->callback(cb_openMenu, (void*)this);
-
- readActions->type(FL_TOGGLE_BUTTON);
- readActions->value(ch->readActions);
- readActions->callback(cb_readActions, (void*)this);
-
- vol->callback(cb_changeVol, (void*)this);
-
- ch->guiChannel = this;
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::cb_button (Fl_Widget *v, void *p) { ((geSampleChannel*)p)->__cb_button(); }
-void geSampleChannel::cb_openMenu (Fl_Widget *v, void *p) { ((geSampleChannel*)p)->__cb_openMenu(); }
-void geSampleChannel::cb_readActions (Fl_Widget *v, void *p) { ((geSampleChannel*)p)->__cb_readActions(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::__cb_button()
-{
- if (button->value()) // pushed
- glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
- else // released
- glue_keyRelease(ch, Fl::event_ctrl(), Fl::event_shift());
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::__cb_openMenu()
-{
- /* If you're recording (input or actions) no menu is allowed; you can't do
- anything, especially deallocate the channel */
-
- if (G_Mixer.recording || G_Recorder.active)
- return;
-
- /* the following is a trash workaround for a FLTK menu. We need a gMenu
- * widget asap */
-
- Fl_Menu_Item rclick_menu[] = {
- {"Load new sample..."}, // 0
- {"Export sample to file..."}, // 1
- {"Setup keyboard input..."}, // 2
- {"Setup MIDI input..."}, // 3
- {"Setup MIDI output..."}, // 4
- {"Edit sample..."}, // 5
- {"Edit actions..."}, // 6
- {"Clear actions", 0, 0, 0, FL_SUBMENU}, // 7
- {"All"}, // 8
- {"Mute"}, // 9
- {"Volume"}, // 10
- {"Start/Stop"}, // 11
- {0}, // 12
- {"Clone channel"}, // 13
- {"Free channel"}, // 14
- {"Delete channel"}, // 15
- {0}
- };
-
- if (ch->status & (STATUS_EMPTY | STATUS_MISSING)) {
- rclick_menu[1].deactivate();
- rclick_menu[5].deactivate();
- rclick_menu[14].deactivate();
- }
-
- /* no 'clear actions' if there are no actions */
-
- if (!ch->hasActions)
- rclick_menu[7].deactivate();
-
- /* no 'clear start/stop actions' for those channels in loop mode:
- * they cannot have start/stop actions. */
-
- if (((SampleChannel*)ch)->mode & LOOP_ANY)
- rclick_menu[11].deactivate();
-
- Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
- b->box(G_BOX);
- b->textsize(GUI_FONT_SIZE_BASE);
- b->textcolor(COLOR_TEXT_0);
- b->color(COLOR_BG_0);
-
- const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
- if (!m) return;
-
- if (strcmp(m->label(), "Load new sample...") == 0) {
- openBrowser(BROWSER_LOAD_SAMPLE);
- return;
- }
-
- if (strcmp(m->label(), "Setup keyboard input...") == 0) {
- new gdKeyGrabber(ch); /// FIXME - use gu_openSubWindow
- return;
- }
-
- if (strcmp(m->label(), "Setup MIDI input...") == 0) {
- gu_openSubWindow(G_MainWin, new gdMidiInputChannel(ch), 0);
- return;
- }
-
- if (strcmp(m->label(), "Setup MIDI output...") == 0) {
- gu_openSubWindow(G_MainWin, new gdMidiOutputSampleCh((SampleChannel*) ch), 0);
- return;
- }
-
- if (strcmp(m->label(), "Edit sample...") == 0) {
- gu_openSubWindow(G_MainWin, new gdEditor((SampleChannel*) ch), WID_SAMPLE_EDITOR); /// FIXME title it's up to gdEditor
- return;
- }
-
- if (strcmp(m->label(), "Export sample to file...") == 0) {
- openBrowser(BROWSER_SAVE_SAMPLE);
- return;
- }
-
- if (strcmp(m->label(), "Delete channel") == 0) {
- if (!gdConfirmWin("Warning", "Delete channel: are you sure?"))
- return;
- glue_deleteChannel(ch);
- return;
- }
-
- if (strcmp(m->label(), "Free channel") == 0) {
- if (ch->status == STATUS_PLAY) {
- if (!gdConfirmWin("Warning", "This action will stop the channel: are you sure?"))
- return;
- }
- else if (!gdConfirmWin("Warning", "Free channel: are you sure?"))
- return;
-
- glue_freeChannel(ch);
-
- /* delete any related subwindow */
-
- /** FIXME - use gu_closeAllSubwindows() */
-
- G_MainWin->delSubWindow(WID_FILE_BROWSER);
- G_MainWin->delSubWindow(WID_ACTION_EDITOR);
- G_MainWin->delSubWindow(WID_SAMPLE_EDITOR);
- G_MainWin->delSubWindow(WID_FX_LIST);
-
- return;
- }
-
- if (strcmp(m->label(), "Clone channel") == 0) {
- glue_cloneChannel(ch);
- return;
- }
-
- if (strcmp(m->label(), "Mute") == 0) {
- if (!gdConfirmWin("Warning", "Clear all mute actions: are you sure?"))
- return;
- G_Recorder.clearAction(ch->index, ACTION_MUTEON | ACTION_MUTEOFF);
- if (!ch->hasActions)
- hideActionButton();
-
- /* TODO - set mute=false */
-
- gu_refreshActionEditor(); // refresh a.editor window, it could be open
- return;
- }
-
- if (strcmp(m->label(), "Start/Stop") == 0) {
- if (!gdConfirmWin("Warning", "Clear all start/stop actions: are you sure?"))
- return;
- G_Recorder.clearAction(ch->index, ACTION_KEYPRESS | ACTION_KEYREL | ACTION_KILLCHAN);
- if (!ch->hasActions)
- hideActionButton();
- gu_refreshActionEditor(); // refresh a.editor window, it could be open
- return;
- }
-
- if (strcmp(m->label(), "Volume") == 0) {
- if (!gdConfirmWin("Warning", "Clear all volume actions: are you sure?"))
- return;
- G_Recorder.clearAction(ch->index, ACTION_VOLUME);
- if (!ch->hasActions)
- hideActionButton();
- gu_refreshActionEditor(); // refresh a.editor window, it could be open
- return;
- }
-
- if (strcmp(m->label(), "All") == 0) {
- if (!gdConfirmWin("Warning", "Clear all actions: are you sure?"))
- return;
- G_Recorder.clearChan(ch->index);
- hideActionButton();
- gu_refreshActionEditor(); // refresh a.editor window, it could be open
- return;
- }
-
- if (strcmp(m->label(), "Edit actions...") == 0) {
- gu_openSubWindow(G_MainWin, new gdActionEditor(ch), WID_ACTION_EDITOR);
- return;
- }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::__cb_readActions()
-{
- glue_startStopReadingRecs((SampleChannel*) ch);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::openBrowser(int type)
-{
- gWindow *childWin = NULL;
- switch (type) {
- case BROWSER_LOAD_SAMPLE:
- childWin = new gdLoadBrowser(G_Conf.browserX, G_Conf.browserY,
- G_Conf.browserW, G_Conf.browserH, "Browse sample",
- G_Conf.samplePath.c_str(), glue_loadSample, ch);
- break;
- case BROWSER_SAVE_SAMPLE:
- childWin = new gdSaveBrowser(G_Conf.browserX, G_Conf.browserY,
- G_Conf.browserW, G_Conf.browserH, "Save sample", \
- G_Conf.samplePath.c_str(), "", glue_saveSample, ch);
- break;
- }
- if (childWin)
- gu_openSubWindow(G_MainWin, childWin, WID_FILE_BROWSER);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::refresh()
-{
- if (!mainButton->visible()) // mainButton invisible? status too (see below)
- return;
-
- setColorsByStatus(ch->status, ch->recStatus);
-
- if (((SampleChannel*) ch)->wave != NULL) {
- if (G_Mixer.recording && ch->armed)
- mainButton->setInputRecordMode();
- if (G_Recorder.active) {
- if (G_Recorder.canRec(ch))
- mainButton->setActionRecordMode();
- }
- status->redraw(); // status invisible? sampleButton too (see below)
- }
- mainButton->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::reset()
-{
- hideActionButton();
- mainButton->setDefaultMode("-- no sample --");
- mainButton->redraw();
- status->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::update()
-{
- /* update sample button's label */
-
- switch (ch->status) {
- case STATUS_EMPTY:
- mainButton->label("-- no sample --");
- break;
- case STATUS_MISSING:
- case STATUS_WRONG:
- mainButton->label("* file not found! *");
- break;
- default:
- mainButton->label(((SampleChannel*) ch)->wave->name.c_str());
- break;
- }
-
- /* update channels. If you load a patch with recorded actions, the 'R'
- * button must be shown. Moreover if the actions are active, the 'R'
- * button must be activated accordingly. */
-
- if (ch->hasActions)
- showActionButton();
- else
- hideActionButton();
-
- /* updates modebox */
-
- modeBox->value(((SampleChannel*) ch)->mode);
- modeBox->redraw();
-
- /* update volumes+mute+solo */
-
- vol->value(ch->volume);
- mute->value(ch->mute);
- solo->value(ch->solo);
-
- mainButton->setKey(ch->key);
-
-#ifdef WITH_VST
- fx->full = ch->plugins.size() > 0;
- fx->redraw();
-#endif
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::showActionButton()
-{
- readActions->value(((SampleChannel*) ch)->readActions);
- readActions->show();
- packWidgets();
- redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::hideActionButton()
-{
- readActions->hide();
- packWidgets();
- redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void geSampleChannel::resize(int X, int Y, int W, int H)
-{
- geChannel::resize(X, Y, W, H);
-
- arm->hide();
- modeBox->hide();
- readActions->hide();
-#ifdef WITH_VST
- fx->hide();
-#endif
-
- if (w() > BREAK_ARM)
- arm->show();
-#ifdef WITH_VST
- if (w() > BREAK_FX)
- fx->show();
-#endif
- if (w() > BREAK_MODE_BOX)
- modeBox->show();
- if (w() > BREAK_READ_ACTIONS && ch->hasActions)
- readActions->show();
-
- packWidgets();
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-geSampleChannelButton::geSampleChannelButton(int x, int y, int w, int h, const char *l)
- : geChannelButton(x, y, w, h, l) {}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-int geSampleChannelButton::handle(int e)
-{
- int ret = gClick::handle(e);
- switch (e) {
- case FL_DND_ENTER:
- case FL_DND_DRAG:
- case FL_DND_RELEASE: {
- ret = 1;
- break;
- }
- case FL_PASTE: {
- geSampleChannel *gch = (geSampleChannel*) parent(); // parent is geSampleChannel
- SampleChannel *ch = (SampleChannel*) gch->ch;
- int result = glue_loadChannel(ch, gu_trim(gu_stripFileUrl(Fl::event_text())).c_str());
- if (result != SAMPLE_LOADED_OK)
- G_MainWin->keyboard->printChannelMessage(result);
- ret = 1;
- break;
- }
- }
- return ret;
-}
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_sampleChannel
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2016 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 GE_SAMPLE_CHANNEL_H
-#define GE_SAMPLE_CHANNEL_H
-
-
-#include "channel.h"
-#include "channelButton.h"
-
-
-class geSampleChannel : public geChannel
-{
-private:
-
- static void cb_button (Fl_Widget *v, void *p);
- static void cb_openMenu (Fl_Widget *v, void *p);
- static void cb_readActions (Fl_Widget *v, void *p);
-
- inline void __cb_button ();
- inline void __cb_openMenu ();
- inline void __cb_readActions ();
-
- void openBrowser(int type);
-
-public:
-
- geSampleChannel(int x, int y, int w, int h, class SampleChannel *ch);
-
- void reset ();
- void update ();
- void refresh ();
- void resize (int x, int y, int w, int h);
-
- /* show/hideActionButton
- Adds or removes 'R' button when actions are available. */
-
- void showActionButton();
- void hideActionButton();
-
- class gModeBox *modeBox;
- class gClick *readActions;
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class geSampleChannelButton : public geChannelButton
-{
-public:
- geSampleChannelButton(int x, int y, int w, int h, const char *l=0);
- int handle(int e);
-};
-
-
-#endif
#include "../gui/dialogs/gd_warnings.h"
#include "../gui/dialogs/gd_mainWindow.h"
#include "../gui/dialogs/gd_actionEditor.h"
-#include "../gui/elems/ge_keyboard.h"
#include "../gui/elems/ge_window.h"
-#include "../gui/elems/channel.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 "log.h"
#include "string.h"
#include "gui.h"
/* update dynamic elements: in and out meters, beat meter and
* each channel */
- G_MainWin->inOut->refresh();
+ G_MainWin->mainIO->refresh();
G_MainWin->beatMeter->redraw();
G_MainWin->keyboard->refreshColumns();
for (unsigned i=0; i<G_Mixer.channels.size(); i++)
G_Mixer.channels.at(i)->guiChannel->update();
- G_MainWin->inOut->setOutVol(G_Mixer.outVol);
- G_MainWin->inOut->setInVol(G_Mixer.inVol);
+ G_MainWin->mainIO->setOutVol(G_Mixer.outVol);
+ G_MainWin->mainIO->setInVol(G_Mixer.inVol);
#ifdef WITH_VST
- G_MainWin->inOut->setMasterFxOutFull(G_PluginHost.getStack(PluginHost::MASTER_OUT)->size() > 0);
- G_MainWin->inOut->setMasterFxInFull(G_PluginHost.getStack(PluginHost::MASTER_IN)->size() > 0);
+ G_MainWin->mainIO->setMasterFxOutFull(G_PluginHost.getStack(PluginHost::MASTER_OUT)->size() > 0);
+ G_MainWin->mainIO->setMasterFxInFull(G_PluginHost.getStack(PluginHost::MASTER_IN)->size() > 0);
#endif
- G_MainWin->timing->setMeter(G_Mixer.beats, G_Mixer.bars);
- G_MainWin->timing->setBpm(G_Mixer.bpm);
+ G_MainWin->mainTimer->setMeter(G_Mixer.beats, G_Mixer.bars);
+ G_MainWin->mainTimer->setBpm(G_Mixer.bpm);
- G_MainWin->controller->updatePlay(G_Mixer.running);
- G_MainWin->controller->updateMetronome(G_Mixer.metronome);
+ G_MainWin->mainTransport->updatePlay(G_Mixer.running);
+ G_MainWin->mainTransport->updateMetronome(G_Mixer.metronome);
}