New upstream version 0.13.2~dfsg1
authorJaromír Mikeš <mira.mikes@seznam.cz>
Sun, 15 Jan 2017 17:50:59 +0000 (18:50 +0100)
committerJaromír Mikeš <mira.mikes@seznam.cz>
Sun, 15 Jan 2017 17:50:59 +0000 (18:50 +0100)
132 files changed:
.travis.yml [deleted file]
ChangeLog
Makefile.am
src/core/channel.cpp
src/core/channel.h
src/core/conf.cpp
src/core/conf.h
src/core/const.h
src/core/init.cpp
src/core/kernelMidi.cpp
src/core/kernelMidi.h
src/core/midiChannel.cpp
src/core/midiChannel.h
src/core/mixer.cpp
src/core/mixer.h
src/core/mixerHandler.cpp
src/core/patch.cpp
src/core/patch.h
src/core/patch_DEPR_.cpp
src/core/plugin.cpp
src/core/plugin.h
src/core/pluginHost.cpp
src/core/pluginHost.h
src/core/recorder.cpp
src/core/recorder.h
src/core/sampleChannel.cpp
src/core/sampleChannel.h
src/deps/juce-config.h [new file with mode: 0644]
src/glue/channel.cpp
src/glue/channel.h
src/glue/io.cpp
src/glue/main.cpp
src/glue/plugin.cpp [new file with mode: 0644]
src/glue/plugin.h [new file with mode: 0644]
src/glue/storage.cpp
src/gui/dialogs/gd_about.cpp
src/gui/dialogs/gd_actionEditor.cpp
src/gui/dialogs/gd_actionEditor.h
src/gui/dialogs/gd_beatsInput.cpp
src/gui/dialogs/gd_browser.cpp
src/gui/dialogs/gd_browser.h
src/gui/dialogs/gd_config.cpp
src/gui/dialogs/gd_editor.cpp
src/gui/dialogs/gd_keyGrabber.cpp
src/gui/dialogs/gd_mainWindow.cpp
src/gui/dialogs/gd_mainWindow.h
src/gui/dialogs/gd_midiInput.cpp [deleted file]
src/gui/dialogs/gd_midiInput.h [deleted file]
src/gui/dialogs/gd_midiOutput.cpp [deleted file]
src/gui/dialogs/gd_midiOutput.h [deleted file]
src/gui/dialogs/gd_pluginChooser.cpp
src/gui/dialogs/gd_pluginList.cpp
src/gui/dialogs/gd_pluginWindow.cpp
src/gui/dialogs/gd_pluginWindowGUI.cpp
src/gui/dialogs/midiIO/midiInputBase.cpp [new file with mode: 0644]
src/gui/dialogs/midiIO/midiInputBase.h [new file with mode: 0644]
src/gui/dialogs/midiIO/midiInputChannel.cpp [new file with mode: 0644]
src/gui/dialogs/midiIO/midiInputChannel.h [new file with mode: 0644]
src/gui/dialogs/midiIO/midiInputMaster.cpp [new file with mode: 0644]
src/gui/dialogs/midiIO/midiInputMaster.h [new file with mode: 0644]
src/gui/dialogs/midiIO/midiOutputBase.cpp [new file with mode: 0644]
src/gui/dialogs/midiIO/midiOutputBase.h [new file with mode: 0644]
src/gui/dialogs/midiIO/midiOutputMidiCh.cpp [new file with mode: 0644]
src/gui/dialogs/midiIO/midiOutputMidiCh.h [new file with mode: 0644]
src/gui/dialogs/midiIO/midiOutputSampleCh.cpp [new file with mode: 0644]
src/gui/dialogs/midiIO/midiOutputSampleCh.h [new file with mode: 0644]
src/gui/elems/actionEditor.cpp
src/gui/elems/basics/boxtypes.cpp [new file with mode: 0644]
src/gui/elems/basics/boxtypes.h [new file with mode: 0644]
src/gui/elems/basics/scroll.cpp [new file with mode: 0644]
src/gui/elems/basics/scroll.h [new file with mode: 0644]
src/gui/elems/browser.cpp [new file with mode: 0644]
src/gui/elems/browser.h [new file with mode: 0644]
src/gui/elems/channel.cpp [deleted file]
src/gui/elems/channel.h [deleted file]
src/gui/elems/channelButton.cpp [deleted file]
src/gui/elems/channelButton.h [deleted file]
src/gui/elems/envelopeEditor.cpp
src/gui/elems/ge_browser.cpp [deleted file]
src/gui/elems/ge_browser.h [deleted file]
src/gui/elems/ge_column.cpp [deleted file]
src/gui/elems/ge_column.h [deleted file]
src/gui/elems/ge_controller.cpp [deleted file]
src/gui/elems/ge_controller.h [deleted file]
src/gui/elems/ge_keyboard.cpp [deleted file]
src/gui/elems/ge_keyboard.h [deleted file]
src/gui/elems/ge_midiIoTools.cpp [deleted file]
src/gui/elems/ge_midiIoTools.h [deleted file]
src/gui/elems/ge_mixed.cpp
src/gui/elems/ge_mixed.h
src/gui/elems/ge_modeBox.cpp [deleted file]
src/gui/elems/ge_modeBox.h [deleted file]
src/gui/elems/ge_pluginBrowser.cpp
src/gui/elems/ge_status.cpp [deleted file]
src/gui/elems/ge_status.h [deleted file]
src/gui/elems/ge_waveTools.cpp
src/gui/elems/ge_waveform.cpp
src/gui/elems/mainWindow/beatMeter.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/beatMeter.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channel.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channel.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channelButton.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channelButton.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channelMode.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channelMode.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channelStatus.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/channelStatus.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/column.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/column.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/keyboard.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/keyboard.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/midiChannel.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/midiChannel.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/sampleChannel.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/sampleChannel.h [new file with mode: 0644]
src/gui/elems/mainWindow/mainIO.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/mainIO.h [new file with mode: 0644]
src/gui/elems/mainWindow/mainMenu.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/mainMenu.h [new file with mode: 0644]
src/gui/elems/mainWindow/mainTimer.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/mainTimer.h [new file with mode: 0644]
src/gui/elems/mainWindow/mainTransport.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/mainTransport.h [new file with mode: 0644]
src/gui/elems/midiChannel.cpp [deleted file]
src/gui/elems/midiChannel.h [deleted file]
src/gui/elems/midiLearner.cpp [new file with mode: 0644]
src/gui/elems/midiLearner.h [new file with mode: 0644]
src/gui/elems/muteEditor.cpp
src/gui/elems/pianoItem.cpp
src/gui/elems/sampleChannel.cpp [deleted file]
src/gui/elems/sampleChannel.h [deleted file]
src/utils/gui.cpp

diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644 (file)
index 5c770bc..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-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
index 22878ce9131430c01c1ced5ea71a5543464490d4..65e29a57c530123e36374c5137b3b5bd7df2b67f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 --------------------------------------------------------------------------------
 
 
+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
index 7990158a465d0abdd6c899e01c83f81e99f15587..edb15a427c06b2b7651f94da28ac350aec2addb5 100644 (file)
@@ -55,6 +55,8 @@ src/glue/storage.h                     \
 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             \
@@ -81,28 +83,30 @@ src/gui/dialogs/gd_editor.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         \
@@ -113,28 +117,46 @@ src/gui/elems/noteEditor.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                        \
@@ -147,14 +169,14 @@ src/utils/string.cpp
 
 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
@@ -173,7 +195,7 @@ giada_CPPFLAGS =
 
 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                 \
@@ -270,14 +292,14 @@ src/utils/log.cpp
 
 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 \
@@ -288,7 +310,7 @@ giada_tests_CXXFLAGS = -std=c++11
 
 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                 \
index bcbafeb716a5d811a962c73179d485dc0500f205..95ad99a1df993ce9f80ff6f548880117dfcefebb 100644 (file)
@@ -28,7 +28,7 @@
 
 
 #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"
@@ -69,6 +69,7 @@ Channel::Channel(int type, int status, int bufferSize, MidiMapConf *midiMapConf)
   mute           (false),
   solo           (false),
   hasActions     (false),
+       readActions    (false),
   armed          (false),
   recStatus      (REC_STOPPED),
   vChan          (nullptr),
@@ -147,8 +148,10 @@ void Channel::copy(const Channel *src, pthread_mutex_t *pluginMutex)
   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;
+      }
     }
   }
 }
@@ -255,14 +258,14 @@ int Channel::writePatch(int i, bool isProject, Patch *patch)
        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
@@ -305,6 +308,7 @@ int Channel::readPatch(const string &path, int i, Patch *patch,
        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
@@ -313,14 +317,17 @@ int Channel::readPatch(const string &path, int i, Patch *patch,
                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
index df9fe64694f11d9f0f12707331844c8d98aa8c12..2df3d14804367fc5940ef9e4749b5589451f5038 100644 (file)
@@ -37,7 +37,7 @@
 #include "recorder.h"
 
 #ifdef WITH_VST
-       #include "../deps/juce/config.h"
+       #include "../deps/juce-config.h"
 #endif
 
 
@@ -143,10 +143,10 @@ public:
 
        /* 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. */
@@ -213,6 +213,7 @@ public:
        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
index 021549b99c3f08fa82654b95ee6766eefe89a944..1a690ace4700b82dbd1d6cbc8f1b4a2dca024857 100644 (file)
@@ -154,6 +154,11 @@ void Conf::init()
        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;
 
@@ -260,6 +265,10 @@ int Conf::read()
        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
 
@@ -361,6 +370,10 @@ int Conf::write()
        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
 
@@ -413,11 +426,19 @@ void Conf::sanitize()
        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;
index f96265d883fb63d6c610f40df2f1e13efd319ba1..81901bc642d617d248c41f9aa2016440914cb4c5 100644 (file)
@@ -80,14 +80,14 @@ public:
        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;
@@ -108,25 +108,27 @@ public:
        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
 
index 9571b2db9d8e266af6875cbdec80fc98f0d98560..99fa701ae396add4c9f5e938103c7cee1a2561c6 100644 (file)
 
 
 /* -- 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
@@ -384,6 +375,7 @@ const int MIDI_CHANS[16] = {
 #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"
@@ -466,6 +458,10 @@ const int MIDI_CHANS[16] = {
 #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 */
index e280d462de2978645e20b90d0785f3043b63fad5..41105a622b1b126cd49272fa60879d827d651a67 100644 (file)
@@ -37,6 +37,7 @@
 #include "mixer.h"
 #include "wave.h"
 #include "const.h"
+#include "channel.h"
 #include "mixerHandler.h"
 #include "patch_DEPR_.h"
 #include "patch.h"
@@ -207,6 +208,12 @@ void init_shutdown()
        }
 
        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
index 9676143aff5411d91e4a613baf6bb2fa5a3589db..f8c519be33314c844848b977c7a1dd38b5871fae 100644 (file)
 #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"
 
 
@@ -48,8 +51,9 @@ extern Conf        G_Conf;
 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;
@@ -415,7 +419,15 @@ void KernelMidi::processChannels(uint32_t pure, uint32_t value)
                        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);
        }
@@ -425,6 +437,37 @@ void KernelMidi::processChannels(uint32_t pure, uint32_t 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();
index 834e0de43ccdb20c0eade05db176a8deaaa6be15..e8cb0f4d259f2086c47e17dfcc4b4d48a7c9a045 100644 (file)
@@ -96,7 +96,7 @@ public:
 
 private:
 
-       int      api;
+       int api;
        class RtMidiOut *midiOut;
        class RtMidiIn  *midiIn;
 
@@ -119,6 +119,9 @@ private:
 
        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
index cf1f88ac76c51f265d2e83376ff443684e2812a6..ad531d6700d8265a0e7ea9fc3d60a145cf5b672d 100644 (file)
 #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),
@@ -108,7 +111,7 @@ void MidiChannel::empty() {}
 /* -------------------------------------------------------------------------- */
 
 
-void MidiChannel::quantize(int index, int localFrame, int globalFrame) {}
+void MidiChannel::quantize(int index, int localFrame, Mixer *m) {}
 
 
 /* -------------------------------------------------------------------------- */
@@ -335,19 +338,24 @@ void MidiChannel::receiveMidi(uint32_t msg)
 {
   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;
+  }
 }
 
 
index dcaaa27e8d98265c910aa35727af1ee0295d75e2..94336b8d3c9aed966423b7d61aa400bc4a5571ad 100644 (file)
@@ -32,7 +32,7 @@
 
 
 #ifdef WITH_VST
-       #include "../deps/juce/config.h"
+       #include "../deps/juce-config.h"
 #endif
 
 #include "channel.h"
@@ -65,7 +65,7 @@ public:
        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,
@@ -81,7 +81,6 @@ public:
        void sendMidi(Recorder::action *a, int localFrame);
        void sendMidi(uint32_t data);
 
-
 #ifdef WITH_VST
 
        /* addVstMidiEvent
index 7321f1b97609025138514fa7eaff6e19b45c9ef5..efe2532c85f0a40b48f3cc0d59f75e01786f8495 100644 (file)
@@ -99,7 +99,7 @@ void Mixer::init()
        recording   = false;
        ready       = true;
        waitRec     = 0;
-       actualFrame = 0;
+       currentFrame = 0;
        bpm                 = DEFAULT_BPM;
        bars                = DEFAULT_BARS;
        beats               = DEFAULT_BEATS;
@@ -246,7 +246,7 @@ Channel *Mixer::getChannelByIndex(int index)
 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
@@ -257,7 +257,7 @@ void Mixer::sendMIDIsync()
                 * 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
@@ -363,7 +363,7 @@ int Mixer::__masterPlay(void *_outBuf, void *_inBuf, unsigned bufferSize)
                        testBar(j);
                        testFirstBeat(j);
                        readActions(j);
-                       actualFrame += 2;
+                       currentFrame += 2;
                        testLastBeat();  // this test must be the last one
                        sendMIDIsync();
                }
@@ -463,7 +463,7 @@ bool Mixer::isSilent()
 
 void Mixer::rewind()
 {
-       actualFrame = 0;
+       currentFrame = 0;
        actualBeat  = 0;
 
        if (running)
@@ -586,11 +586,11 @@ void Mixer::readActions(unsigned frame)
 {
        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;
                }
@@ -606,7 +606,7 @@ void Mixer::doQuantize(unsigned frame)
 {
        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) {
@@ -615,7 +615,7 @@ void Mixer::doQuantize(unsigned frame)
        }
        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);
 }
 
@@ -625,7 +625,7 @@ void Mixer::doQuantize(unsigned frame)
 
 void Mixer::testBar(unsigned frame)
 {
-       if (actualFrame % framesPerBar != 0 || actualFrame == 0)
+       if (currentFrame % framesPerBar != 0 || currentFrame == 0)
                return;
 
        if (metronome)
@@ -643,7 +643,7 @@ void Mixer::testBar(unsigned frame)
 
 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++)
@@ -657,15 +657,15 @@ void Mixer::testFirstBeat(unsigned frame)
 
 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
index f8afb461c481f44fff9549254735be8c175b7e85..66d08235603b906393df667aedca3b573330e51b 100644 (file)
@@ -150,7 +150,7 @@ public:
        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
index e3d19458ad18c74a2aee233a72993c1ed411b78d..5bb2bd4dfd2ccc4c7b7cdccf2ed4408c75fb21b0 100644 (file)
@@ -76,6 +76,7 @@ static int __mh_readPatchPlugins__(vector<Patch::plugin_t> *list, int type)
        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) {
@@ -238,9 +239,9 @@ bool mh_startInputRec()
 
        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;
index dbc1aa78e7c4ef14731aa0985ed567316bf1c05a..b622537b059b6e65d856e517e61801fce0d0ac0f 100644 (file)
@@ -119,17 +119,23 @@ void Patch::writePlugins(json_t *jContainer, vector<plugin_t> *plugins, const ch
   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);
 }
@@ -413,8 +419,8 @@ bool Patch::readPlugins(json_t *jContainer, vector<plugin_t> *container, const c
       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 */
 
@@ -426,6 +432,16 @@ bool Patch::readPlugins(json_t *jContainer, vector<plugin_t> *container, const c
     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;
@@ -459,7 +475,7 @@ void Patch::sanitize()
     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;
   }
 }
 
index 99ef6a15eeae4031df5c026ccff09d9a3afe23ec..ba17077fec825ca322992f94e09ddf1347f96e41 100644 (file)
@@ -56,9 +56,10 @@ public:
 #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
 
index 99010a02a13f9b639f3e97eaa666ddf392a68fed..5ded87df7cd5abd585026c07ef10301696b0e28c 100644 (file)
@@ -31,7 +31,7 @@
 #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"
@@ -514,6 +514,7 @@ int Patch_DEPR_::readRecs()
                                                G_Recorder.rec(ch->index, type, frame, iValue_fix, fValue);
                                        else
                                                G_Recorder.rec(ch->index, type, frame, iValue, fValue);
+          ch->hasActions = true;
                                }
                }
        }
index bf4a1c40743e053615da54423010d61ddae84249..1ef79b2afea5e5725f088d5558c8df4f437ee9e4 100644 (file)
@@ -41,24 +41,44 @@ int Plugin::idGenerator = 1;
 /* -------------------------------------------------------------------------- */
 
 
-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();
 }
 
 
@@ -90,7 +110,142 @@ bool Plugin::isEditorOpen()
 
 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();
 }
 
 
index 38e411c436e7afd7a32a0c93a167eb673c1ac3f0..d295e507e1e7e181ea969f3b6f2954f558950a38 100644 (file)
  *
  * -------------------------------------------------------------------------- */
 
+
 #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);
 
@@ -67,16 +67,36 @@ public:
   /* 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
index f95a96694d261cd359e646c702678e1aa78c5c29..a23f2669ca90235f871b39b1a7e9a0eb2855f5f4 100644 (file)
@@ -144,35 +144,28 @@ Plugin *PluginHost::addPlugin(const string &fid, int stackType,
     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;
 }
@@ -286,22 +279,14 @@ void PluginHost::freeStack(int stackType, pthread_mutex_t *mutex, Channel *ch)
        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);
 }
@@ -337,17 +322,17 @@ void PluginHost::processStack(float *buffer, int stackType, Channel *ch)
 
        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);
     }
   }
 
@@ -395,17 +380,13 @@ void PluginHost::swapPlugin(unsigned indexA, unsigned indexB, int stackType,
   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;
        }
 }
 
@@ -413,35 +394,26 @@ void PluginHost::swapPlugin(unsigned indexA, unsigned indexB, int stackType,
 /* -------------------------------------------------------------------------- */
 
 
-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;
 }
 
 
@@ -475,15 +447,15 @@ void PluginHost::freeAllStacks(vector <Channel*> *channels, pthread_mutex_t *mut
 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;
 }
 
index c1f0a515d4f91f41b6d982fc80fb0ad22ca4c96e..2ddc7a582b547712642e6be81d611e16a74400f6 100644 (file)
@@ -33,7 +33,7 @@
 
 
 #include <pthread.h>
-#include "../deps/juce/config.h"
+#include "../deps/juce-config.h"
 
 
 using std::string;
@@ -186,19 +186,19 @@ public:
   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);
 
index 57958c73d007b1c94f7de24d41e2cdd2b1824a47..992a98e265d8c81a8b511d4fb932f5c9342ce87b 100644 (file)
 
 #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)
@@ -66,7 +55,7 @@ void Recorder::init()
 /* -------------------------------------------------------------------------- */
 
 
-bool Recorder::canRec(Channel *ch)
+bool Recorder::canRec(Channel *ch, Mixer *mixer)
 {
        /* NO recording if:
         * recorder is inactive
@@ -74,9 +63,9 @@ bool Recorder::canRec(Channel *ch)
         * 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;
@@ -142,11 +131,6 @@ void Recorder::rec(int index, int type, int frame, uint32_t iValue, float fValue
                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",
@@ -175,9 +159,6 @@ void Recorder::clearChan(int index)
                                j++;
                }
        }
-
-       Channel *ch = G_Mixer.getChannelByIndex(index);
-       ch->hasActions = false;
        optimize();
        //print();
 }
@@ -203,10 +184,7 @@ void Recorder::clearAction(int index, char act)
                                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();
 }
 
@@ -215,7 +193,7 @@ void Recorder::clearAction(int index, char act)
 
 
 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 */
 
@@ -226,41 +204,39 @@ void Recorder::deleteAction(int chan, int frame, char type, bool checkValues,
 
        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);
        }
@@ -273,7 +249,8 @@ void Recorder::deleteAction(int chan, int frame, char type, bool checkValues,
 /* -------------------------------------------------------------------------- */
 
 
-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;
@@ -283,7 +260,7 @@ void Recorder::deleteActions(int chan, int frame_a, int frame_b, char type)
                        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
 }
 
 
@@ -300,13 +277,6 @@ void Recorder::clearAll()
                        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();
 }
@@ -494,22 +464,17 @@ void Recorder::shrink(int new_fpb)
 /* -------------------------------------------------------------------------- */
 
 
-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;
 }
 
 
@@ -564,7 +529,8 @@ int Recorder::getAction(int chan, char action, int frame, struct action **out)
 /* -------------------------------------------------------------------------- */
 
 
-void Recorder::startOverdub(int index, char actionMask, int frame)
+void Recorder::startOverdub(int index, char actionMask, int frame,
+  unsigned bufferSize)
 {
        /* prepare the composite struct */
 
@@ -590,25 +556,22 @@ void Recorder::startOverdub(int index, char actionMask, int frame)
        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;
 
@@ -618,23 +581,20 @@ void Recorder::stopOverdub(int frame)
        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) {
@@ -645,11 +605,9 @@ void Recorder::stopOverdub(int frame)
 
                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
                }
        }
 }
@@ -664,7 +622,8 @@ void Recorder::print()
        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);
                }
        }
 }
index 307b408367a44d1abff1d859a18aaf8fee599f23..a4f021067f7a7b89f0b11761a7903568c850d618 100644 (file)
@@ -37,6 +37,7 @@
        #include <cstdint>
 #endif
 #include <vector>
+#include <pthread.h>
 
 
 using std::vector;
@@ -79,16 +80,16 @@ public:
 
        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. */
@@ -110,13 +111,14 @@ public:
         * 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. */
@@ -164,8 +166,8 @@ public:
 
        /* 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:
 
index 4489801700cba2fbb762298b54ce335edb5426bb..650d36f63e7a8371f83155574bc6f34b434bad0c 100644 (file)
@@ -34,6 +34,7 @@
 #include "patch_DEPR_.h"
 #include "patch.h"
 #include "conf.h"
+#include "mixer.h"
 #include "wave.h"
 #include "pluginHost.h"
 #include "waveFx.h"
@@ -56,7 +57,7 @@ SampleChannel::SampleChannel(int bufferSize, MidiMapConf *midiMapConf)
                tracker          (0),
                begin            (0),
                end              (0),
-               pitch            (gDEFAULT_PITCH),
+               pitch            (G_DEFAULT_PITCH),
                boost            (1.0f),
                mode             (DEFAULT_CHANMODE),
                qWait              (false),
@@ -66,7 +67,6 @@ SampleChannel::SampleChannel(int bufferSize, MidiMapConf *midiMapConf)
                fadeoutVol       (1.0f),
                fadeoutTracker   (0),
                fadeoutStep      (DEFAULT_FADEOUT_STEP),
-         readActions      (false),
          midiInReadActions(0x0),
          midiInPitch      (0x0)
 {
@@ -477,7 +477,7 @@ void SampleChannel::onZero(int frame, bool recsStopOnChanHalt)
 /* -------------------------------------------------------------------------- */
 
 
-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 */
 
@@ -500,11 +500,15 @@ void SampleChannel::quantize(int index, int localFrame, int globalFrame)
        /* 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;
        }
 }
 
index 751b99959d8f9815fd279ba38092ca0438b8bd2c..2eeb574603475231124964e84677a7103aef9e9a 100644 (file)
@@ -106,7 +106,7 @@ public:
   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,
@@ -193,10 +193,6 @@ public:
   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;
diff --git a/src/deps/juce-config.h b/src/deps/juce-config.h
new file mode 100644 (file)
index 0000000..ea20a6c
--- /dev/null
@@ -0,0 +1,21 @@
+#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
index c1fa9ba88b1cf88b06ce70a602417d87550800a4..0af1044731100071d2eb979a074eeef7d25a7abb 100644 (file)
 
 #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
 
 
@@ -101,6 +104,7 @@ Channel *glue_addChannel(int column, int type)
 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
@@ -125,6 +129,7 @@ void glue_freeChannel(Channel *ch)
 #endif
        G_MainWin->keyboard->freeChannel(ch->guiChannel);
        G_Recorder.clearChan(ch->index);
+  ch->hasActions = false;
        ch->empty();
 }
 
@@ -243,11 +248,14 @@ void glue_setPanning(gdEditor *win, SampleChannel *ch, float val)
 
 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);
@@ -434,8 +442,7 @@ void glue_setBoost(gdEditor *win, SampleChannel *ch, float val, bool numeric)
 /* -------------------------------------------------------------------------- */
 
 
-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)
index 25523e09630e2f70ebda3e2ab0c6d5e4c2b145ff..3534addfbda54bc52d36dd6b77a7b8ed3d0ed5ee 100644 (file)
@@ -94,4 +94,5 @@ void glue_setBoost(class gdEditor *win, class SampleChannel *ch, float val,
 void glue_setVolEditor(class gdEditor *win, class SampleChannel *ch, float val,
   bool numeric);
 
+
 #endif
index bdc932ee52095e0fa71740a383c87119bb522f65..4dc9acfd83490d551191959a2fcc838481feb890 100644 (file)
 #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"
@@ -53,6 +55,7 @@
 
 
 extern Recorder                         G_Recorder;
+extern KernelAudio   G_KernelAudio;
 extern bool                             G_audio_status;
 extern Mixer                    G_Mixer;
 extern gdMainWindow *G_MainWin;
@@ -117,8 +120,10 @@ void glue_keyPress(SampleChannel *ch, bool ctrl, bool shift)
                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 {
@@ -138,14 +143,18 @@ void glue_keyPress(SampleChannel *ch, bool ctrl, bool shift)
                 * 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
@@ -182,8 +191,8 @@ void glue_keyRelease(SampleChannel *ch, bool ctrl, bool shift)
        /* 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() */
 
@@ -214,7 +223,7 @@ void glue_startActionRec(bool gui)
 
        if (!gui) {
                Fl::lock();
-               G_MainWin->controller->updateRecAction(1);
+               G_MainWin->mainTransport->updateRecAction(1);
                Fl::unlock();
        }
 }
@@ -242,7 +251,7 @@ void glue_stopActionRec(bool gui)
 
        if (!gui) {
                Fl::lock();
-               G_MainWin->controller->updateRecAction(0);
+               G_MainWin->mainTransport->updateRecAction(0);
                Fl::unlock();
        }
 
@@ -273,7 +282,7 @@ int glue_startInputRec(bool gui)
 
        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;
        }
@@ -281,11 +290,11 @@ int glue_startInputRec(bool gui)
        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. */
@@ -314,14 +323,14 @@ int glue_stopInputRec(bool gui)
                        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;
 }
index 4c3638fe26ddf0c374c87286f28301ab2c0601a3..d9033d05f263e43566e22270ca464ca08a899d47 100644 (file)
 #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"
@@ -74,6 +77,11 @@ extern PluginHost    G_PluginHost;
 
 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)      {
@@ -96,7 +104,7 @@ void glue_setBpm(const char *v1, const char *v2)
        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);
 }
 
@@ -106,7 +114,12 @@ void glue_setBpm(const char *v1, const char *v2)
 
 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;
@@ -145,7 +158,7 @@ void glue_setBeats(int beats, int bars, bool expand)
                //      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
 }
 
@@ -179,7 +192,7 @@ void glue_startSeq(bool gui)
 
        if (!gui) {
     Fl::lock();
-    G_MainWin->controller->updatePlay(1);
+    G_MainWin->mainTransport->updatePlay(1);
     Fl::unlock();
   }
 }
@@ -206,7 +219,7 @@ void glue_stopSeq(bool gui)
        if (G_Recorder.active) {
                G_Recorder.active = false;
     Fl::lock();
-         G_MainWin->controller->updateRecAction(0);
+         G_MainWin->mainTransport->updateRecAction(0);
          Fl::unlock();
        }
 
@@ -216,13 +229,13 @@ void glue_stopSeq(bool gui)
        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();
   }
 }
@@ -321,7 +334,7 @@ void glue_setOutVol(float v, bool gui)
        G_Mixer.outVol = v;
        if (!gui) {
                Fl::lock();
-               G_MainWin->inOut->setOutVol(v);
+               G_MainWin->mainIO->setOutVol(v);
                Fl::unlock();
        }
 }
@@ -335,7 +348,7 @@ void glue_setInVol(float v, bool gui)
        G_Mixer.inVol = v;
        if (!gui) {
                Fl::lock();
-               G_MainWin->inOut->setInVol(v);
+               G_MainWin->mainIO->setInVol(v);
                Fl::unlock();
        }
 }
@@ -398,7 +411,7 @@ void glue_startStopMetronome(bool gui)
        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();
        }
 }
diff --git a/src/glue/plugin.cpp b/src/glue/plugin.cpp
new file mode 100644 (file)
index 0000000..8c4ee23
--- /dev/null
@@ -0,0 +1,73 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/glue/plugin.h b/src/glue/plugin.h
new file mode 100644 (file)
index 0000000..02e8278
--- /dev/null
@@ -0,0 +1,46 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
index 41924d914d4094d00edbff63e2e59835954bb574..997389a5bd5585e0426cc7e63cb1ea6010788bd4 100644 (file)
  * -------------------------------------------------------------------------- */
 
 
-#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"
@@ -91,7 +91,7 @@ static void __glue_fillPatchGlobalsPlugins__(vector <Plugin *> *host, vector<Pat
 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();
index 5c42d261d7073b48e984c7ad4cca1c571cc2eafc..e47076d80d8c680c0d04b088d383bad5d948750b 100644 (file)
@@ -33,7 +33,9 @@
 #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"
index 9d705066dd6a0b32f97972185fa5de81d035588d..cf860be98e600ee75090c5d95d6282447187cd22 100644 (file)
@@ -40,6 +40,7 @@
 #include "../elems/muteEditor.h"
 #include "../elems/noteEditor.h"
 #include "../elems/ge_mixed.h"
+#include "../elems/basics/scroll.h"
 #include "gd_actionEditor.h"
 
 
@@ -94,7 +95,7 @@ gdActionEditor::gdActionEditor(Channel *chan)
 
        /* 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) {
 
index 435619d7f3530de36d71e6f70c4577c9196a9cba..c7f60f25067031b399da93dce9ace41940aa7a22 100644 (file)
@@ -72,7 +72,7 @@ public:
        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;
index e77e83999111ba47f5336b17451ca29c9d2800e6..35ca62e4855e03cf0f5df0617adde3bad0c7b52b 100644 (file)
@@ -32,6 +32,7 @@
 #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"
 
index 0c45a1824209cb7bd8f811985651aa516c244a7e..cbb7e464571b8efa18f755719a7c98bc878316b1 100644 (file)
 
 
 #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"
 
 
@@ -54,19 +48,22 @@ gdBaseBrowser::gdBaseBrowser(int x, int y, int w, int h, const string &title,
 {
        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);
@@ -113,12 +110,14 @@ gdBaseBrowser::~gdBaseBrowser()
 
 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);
@@ -129,7 +128,8 @@ void gdBaseBrowser::__cb_up() {
 /* -------------------------------------------------------------------------- */
 
 
-void gdBaseBrowser::__cb_close() {
+void gdBaseBrowser::__cb_close()
+{
        do_callback();
 }
 
@@ -137,6 +137,15 @@ void gdBaseBrowser::__cb_close() {
 /* -------------------------------------------------------------------------- */
 
 
+void gdBaseBrowser::__cb_toggleHiddenFiles()
+{
+       browser->toggleHiddenFiles();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 void gdBaseBrowser::setStatusBar(float v)
 {
        status->value(status->value() + v);
@@ -147,6 +156,33 @@ void gdBaseBrowser::setStatusBar(float v)
 /* -------------------------------------------------------------------------- */
 
 
+void gdBaseBrowser::showStatusBar()
+{
+  status->show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdBaseBrowser::hideStatusBar()
+{
+  status->hide();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+string gdBaseBrowser::getCurrentPath()
+{
+  return where->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 string gdBaseBrowser::getSelectedItem()
 {
        return browser->getSelectedItem();
@@ -166,7 +202,7 @@ gdSaveBrowser::gdSaveBrowser(int x, int y, int w, int h, const string &title,
 
        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);
 
@@ -210,6 +246,15 @@ void gdSaveBrowser::__cb_down()
 /* -------------------------------------------------------------------------- */
 
 
+string gdSaveBrowser::getName()
+{
+  return name->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 void gdSaveBrowser::__cb_save()
 {
        callback((void*) this);
index bf797ec6d7d515f48e94865ed17bdf4330e22151..5606b52f1960951ae2344ec8e1ef2884adc651cb 100644 (file)
@@ -31,9 +31,6 @@
 #define GD_BROWSER_H
 
 
-#include <FL/Fl.H>
-#include <FL/Fl_Double_Window.H>
-#include "../elems/ge_mixed.h"
 #include "../elems/ge_window.h"
 
 
@@ -42,18 +39,21 @@ class gdBaseBrowser : public gWindow
 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. */
@@ -79,12 +79,13 @@ public:
 
        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); }
 };
 
 
@@ -109,7 +110,7 @@ public:
                        const string &path,     const string &name, void (*callback)(void*),
                        class Channel *ch);
 
-       string getName() { return name->value(); }
+       string getName();
 };
 
 
index 832b75a5448211736e55eb367e01d736a449539e..10c49ad23beb1ee2fcd322dba3be64830ef8c944 100644 (file)
@@ -39,6 +39,7 @@
 #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"
@@ -954,6 +955,10 @@ gdConfig::gdConfig(int w, int h) : gWindow(w, h, "Configuration")
                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);
@@ -969,10 +974,6 @@ gdConfig::gdConfig(int w, int h) : gWindow(w, h, "Configuration")
 
        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);
 
index af5d55b19d6b6baa89b516b005b5da42f0c74c49..881b4abc0a447304fa8c6fdc7810888fe039a560 100644 (file)
 #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"
 
@@ -407,7 +407,7 @@ void gdEditor::__cb_reload()
   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
index 508867b5c9feabe4af265dc24478ab9c8b60aa58..d76e41f412ace521c756f998414496340f278ef9 100644 (file)
 #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"
index dba57641aa4bc9be0974b2238b57e3968cdb3116..0220f7a8fb0564804a03a20641333dc3261335c6 100644 (file)
  * -------------------------------------------------------------------------- */
 
 
-#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)
@@ -72,30 +52,37 @@ gdMainWindow::gdMainWindow(int W, int H, const char *title, int argc, char **arg
        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 */
 
@@ -135,414 +122,3 @@ void gdMainWindow::__cb_endprogram()
        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);
-}
index a0a048904b4f8f802c0ad91ddc7ca162d08042f0..6b079171b945772e71a6dcb2f2d9e83eefe8e527 100644 (file)
 #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
diff --git a/src/gui/dialogs/gd_midiInput.cpp b/src/gui/dialogs/gd_midiInput.cpp
deleted file mode 100644 (file)
index e713416..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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();
-}
diff --git a/src/gui/dialogs/gd_midiInput.h b/src/gui/dialogs/gd_midiInput.h
deleted file mode 100644 (file)
index eb236e7..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/dialogs/gd_midiOutput.cpp b/src/gui/dialogs/gd_midiOutput.cpp
deleted file mode 100644 (file)
index 5b2be1f..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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();
-}
diff --git a/src/gui/dialogs/gd_midiOutput.h b/src/gui/dialogs/gd_midiOutput.h
deleted file mode 100644 (file)
index 03cc32a..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/* ----------------------------------------------------------------------
- *
- * 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
index d86810867856a969932f2634a1aa29c25cba91af..0e20dc1155f889d7d6e6dec508d5296039b54101 100644 (file)
@@ -30,9 +30,9 @@
 #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"
@@ -41,7 +41,6 @@
 
 
 extern PluginHost G_PluginHost;
-extern Mixer      G_Mixer;
 extern Conf       G_Conf;
 
 
@@ -108,7 +107,8 @@ void gdPluginChooser::cb_sort(Fl_Widget *v, void *p)  { ((gdPluginChooser*)p)->_
 /* -------------------------------------------------------------------------- */
 
 
-void gdPluginChooser::__cb_close() {
+void gdPluginChooser::__cb_close()
+{
        do_callback();
 }
 
@@ -116,7 +116,8 @@ void gdPluginChooser::__cb_close() {
 /* -------------------------------------------------------------------------- */
 
 
-void gdPluginChooser::__cb_sort() {
+void gdPluginChooser::__cb_sort()
+{
        G_PluginHost.sortPlugins(sortMethod->value());
   browser->refresh();
 }
@@ -125,12 +126,13 @@ void gdPluginChooser::__cb_sort() {
 /* -------------------------------------------------------------------------- */
 
 
-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
index 003ca630674f47ab2e9a568da5a59e99fa7f6462..65d8e6d1c0942870356a7e1e1802025c4a43f7b7 100644 (file)
 #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"
@@ -71,7 +74,7 @@ gdPluginList::gdPluginList(int stackType, Channel *ch)
        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();
@@ -101,7 +104,8 @@ gdPluginList::gdPluginList(int stackType, Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-gdPluginList::~gdPluginList() {
+gdPluginList::~gdPluginList()
+{
        G_Conf.pluginListX = x();
        G_Conf.pluginListY = y();
 }
@@ -116,8 +120,8 @@ void gdPluginList::cb_addPlugin(Fl_Widget *v, void *p)   { ((gdPluginList*)p)->_
 /* -------------------------------------------------------------------------- */
 
 
-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). */
@@ -138,8 +142,8 @@ void gdPluginList::cb_refreshList(Fl_Widget *v, void *p) {
 /* -------------------------------------------------------------------------- */
 
 
-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
@@ -156,8 +160,8 @@ void gdPluginList::__cb_addPlugin() {
 /* -------------------------------------------------------------------------- */
 
 
-void gdPluginList::refreshList() {
-
+void gdPluginList::refreshList()
+{
        /* delete the previous list */
 
        list->clear();
@@ -198,12 +202,12 @@ void gdPluginList::refreshList() {
   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 {
@@ -230,32 +234,24 @@ gdPlugin::gdPlugin(gdPluginList *gdp, Plugin *p, int X, int Y, int W)
        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);
@@ -277,20 +273,20 @@ void gdPlugin::cb_setProgram      (Fl_Widget *v, void *p)    { ((gdPlugin*)p)->_
 /* -------------------------------------------------------------------------- */
 
 
-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();
 }
 
@@ -298,8 +294,8 @@ void gdPlugin::__cb_shiftUp() {
 /* -------------------------------------------------------------------------- */
 
 
-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)
@@ -311,8 +307,7 @@ void gdPlugin::__cb_shiftDown() {
        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();
 }
 
@@ -320,14 +315,12 @@ void gdPlugin::__cb_shiftDown() {
 /* -------------------------------------------------------------------------- */
 
 
-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();
 }
 
@@ -366,7 +359,8 @@ void gdPlugin::__cb_openPluginWindow()
 /* -------------------------------------------------------------------------- */
 
 
-void gdPlugin::__cb_setBypass() {
+void gdPlugin::__cb_setBypass()
+{
        pPlugin->toggleBypass();
 }
 
@@ -374,7 +368,8 @@ void gdPlugin::__cb_setBypass() {
 /* -------------------------------------------------------------------------- */
 
 
-void gdPlugin::__cb_setProgram() {
+void gdPlugin::__cb_setProgram()
+{
        pPlugin->setCurrentProgram(program->value());
 }
 
index 0c0be5f3b8996e7a24ef66485fc8cb80f5c891c3..d3b7136ca76d83ee4e535ef42fe716a37e0b715b 100644 (file)
@@ -34,6 +34,7 @@
 #include "../../utils/gui.h"
 #include "../../core/plugin.h"
 #include "../elems/ge_mixed.h"
+#include "../elems/basics/boxtypes.h"
 #include "gd_pluginWindow.h"
 
 
@@ -46,7 +47,7 @@ Parameter::Parameter(int paramIndex, Plugin *p, int X, int Y, int W)
        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);
@@ -55,7 +56,7 @@ Parameter::Parameter(int paramIndex, Plugin *p, int X, int Y, int W)
 
                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);
@@ -86,8 +87,8 @@ void Parameter::__cb_setValue()
 
 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());
 }
 
@@ -113,7 +114,7 @@ gdPluginWindow::gdPluginWindow(Plugin *p)
 
        end();
 
-       label(pPlugin->getName().toRawUTF8());
+       label(pPlugin->getName().c_str());
 
        size_range(400, (24*1)+12);
        resizable(list);
index e8ba698345b42649b0b62ec2281e5b211edf9562..7a5c772698b56b459170641b0067084e2aee0afc 100644 (file)
@@ -79,7 +79,7 @@ gdPluginWindowGUI::gdPluginWindowGUI(Plugin *pPlugin)
 
   Fl::add_timeout(GUI_PLUGIN_RATE, cb_refresh, (void*) this);
 
-  copy_label(pPlugin->getName().toRawUTF8());
+  copy_label(pPlugin->getName().c_str());
 
 }
 
diff --git a/src/gui/dialogs/midiIO/midiInputBase.cpp b/src/gui/dialogs/midiIO/midiInputBase.cpp
new file mode 100644 (file)
index 0000000..256c9d5
--- /dev/null
@@ -0,0 +1,103 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/dialogs/midiIO/midiInputBase.h b/src/gui/dialogs/midiIO/midiInputBase.h
new file mode 100644 (file)
index 0000000..48f213b
--- /dev/null
@@ -0,0 +1,61 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/dialogs/midiIO/midiInputChannel.cpp b/src/gui/dialogs/midiIO/midiInputChannel.cpp
new file mode 100644 (file)
index 0000000..6bb75e3
--- /dev/null
@@ -0,0 +1,172 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/dialogs/midiIO/midiInputChannel.h b/src/gui/dialogs/midiIO/midiInputChannel.h
new file mode 100644 (file)
index 0000000..462a158
--- /dev/null
@@ -0,0 +1,68 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/dialogs/midiIO/midiInputMaster.cpp b/src/gui/dialogs/midiIO/midiInputMaster.cpp
new file mode 100644 (file)
index 0000000..e7a8def
--- /dev/null
@@ -0,0 +1,60 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/dialogs/midiIO/midiInputMaster.h b/src/gui/dialogs/midiIO/midiInputMaster.h
new file mode 100644 (file)
index 0000000..55a4cd5
--- /dev/null
@@ -0,0 +1,45 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/dialogs/midiIO/midiOutputBase.cpp b/src/gui/dialogs/midiIO/midiOutputBase.cpp
new file mode 100644 (file)
index 0000000..d8afd77
--- /dev/null
@@ -0,0 +1,116 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/dialogs/midiIO/midiOutputBase.h b/src/gui/dialogs/midiIO/midiOutputBase.h
new file mode 100644 (file)
index 0000000..fd639d4
--- /dev/null
@@ -0,0 +1,86 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/dialogs/midiIO/midiOutputMidiCh.cpp b/src/gui/dialogs/midiIO/midiOutputMidiCh.cpp
new file mode 100644 (file)
index 0000000..08954dd
--- /dev/null
@@ -0,0 +1,119 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/dialogs/midiIO/midiOutputMidiCh.h b/src/gui/dialogs/midiIO/midiOutputMidiCh.h
new file mode 100644 (file)
index 0000000..a0deb21
--- /dev/null
@@ -0,0 +1,61 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/dialogs/midiIO/midiOutputSampleCh.cpp b/src/gui/dialogs/midiIO/midiOutputSampleCh.cpp
new file mode 100644 (file)
index 0000000..4cbe682
--- /dev/null
@@ -0,0 +1,72 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/dialogs/midiIO/midiOutputSampleCh.h b/src/gui/dialogs/midiIO/midiOutputSampleCh.h
new file mode 100644 (file)
index 0000000..b229ca8
--- /dev/null
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
index 4a88413919bcde1d29ccc83005a406c1b52d822c..065860d2da325f5d490a6535b155cc42a48a3b8a 100644 (file)
@@ -35,7 +35,7 @@
 #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"
 
 
@@ -591,6 +591,8 @@ void gAction::addAction()
                //gu_log("action added, [%d]\n", frame_a);
        }
 
+  parent->chan->hasActions = true;
+
        G_Recorder.sortActions();
 
        index++; // important!
@@ -606,11 +608,17 @@ void gAction::delAction()
         * 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 */
@@ -648,6 +656,8 @@ void gAction::moveAction(int frame_a)
                G_Recorder.rec(parent->chan->index, ACTION_KEYREL, frame_b);
        }
 
+  parent->chan->hasActions = true;
+
        G_Recorder.sortActions();
 }
 
diff --git a/src/gui/elems/basics/boxtypes.cpp b/src/gui/elems/basics/boxtypes.cpp
new file mode 100644 (file)
index 0000000..547d1aa
--- /dev/null
@@ -0,0 +1,59 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/elems/basics/boxtypes.h b/src/gui/elems/basics/boxtypes.h
new file mode 100644 (file)
index 0000000..d717c86
--- /dev/null
@@ -0,0 +1,47 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/basics/scroll.cpp b/src/gui/elems/basics/scroll.cpp
new file mode 100644 (file)
index 0000000..9cee240
--- /dev/null
@@ -0,0 +1,50 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/elems/basics/scroll.h b/src/gui/elems/basics/scroll.h
new file mode 100644 (file)
index 0000000..b122d44
--- /dev/null
@@ -0,0 +1,46 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/browser.cpp b/src/gui/elems/browser.cpp
new file mode 100644 (file)
index 0000000..812aaba
--- /dev/null
@@ -0,0 +1,188 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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;
+}
diff --git a/src/gui/elems/browser.h b/src/gui/elems/browser.h
new file mode 100644 (file)
index 0000000..4515dbf
--- /dev/null
@@ -0,0 +1,77 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/channel.cpp b/src/gui/elems/channel.cpp
deleted file mode 100644 (file)
index a33f121..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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;
-}
diff --git a/src/gui/elems/channel.h b/src/gui/elems/channel.h
deleted file mode 100644 (file)
index 33dc00d..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/elems/channelButton.cpp b/src/gui/elems/channelButton.cpp
deleted file mode 100644 (file)
index 69d262d..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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;
-}
diff --git a/src/gui/elems/channelButton.h b/src/gui/elems/channelButton.h
deleted file mode 100644 (file)
index da08cd8..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
index 7ade20919bfc6568023c899b45e8eee30af5f016..796a3fe8e28610fac46520cc7a17ea6ae7bddf3f 100644 (file)
@@ -36,7 +36,7 @@
 #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"
 
 
@@ -194,6 +194,7 @@ int geEnvelopeEditor::handle(int e) {
                                                        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 */
@@ -202,6 +203,7 @@ int geEnvelopeEditor::handle(int e) {
                                                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();
                                        }
@@ -219,11 +221,14 @@ int geEnvelopeEditor::handle(int e) {
                                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
@@ -259,11 +264,14 @@ int geEnvelopeEditor::handle(int e) {
 
                                        /*  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
diff --git a/src/gui/elems/ge_browser.cpp b/src/gui/elems/ge_browser.cpp
deleted file mode 100644 (file)
index 9ae3235..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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;
-}
diff --git a/src/gui/elems/ge_browser.h b/src/gui/elems/ge_browser.h
deleted file mode 100644 (file)
index e338143..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/elems/ge_column.cpp b/src/gui/elems/ge_column.cpp
deleted file mode 100644 (file)
index 7f8a046..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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;
-}
diff --git a/src/gui/elems/ge_column.h b/src/gui/elems/ge_column.h
deleted file mode 100644 (file)
index bcaa2ca..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/elems/ge_controller.cpp b/src/gui/elems/ge_controller.cpp
deleted file mode 100644 (file)
index 9ff5f25..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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();
-}
diff --git a/src/gui/elems/ge_controller.h b/src/gui/elems/ge_controller.h
deleted file mode 100644 (file)
index 4c4aa6c..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/elems/ge_keyboard.cpp b/src/gui/elems/ge_keyboard.cpp
deleted file mode 100644 (file)
index 68a8228..0000000
+++ /dev/null
@@ -1,400 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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);
-}
diff --git a/src/gui/elems/ge_keyboard.h b/src/gui/elems/ge_keyboard.h
deleted file mode 100644 (file)
index c5558b9..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/elems/ge_midiIoTools.cpp b/src/gui/elems/ge_midiIoTools.cpp
deleted file mode 100644 (file)
index 8c20101..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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();
-}
diff --git a/src/gui/elems/ge_midiIoTools.h b/src/gui/elems/ge_midiIoTools.h
deleted file mode 100644 (file)
index 0712937..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
index 0969a8a1b5bc441c4447b6ef7f9b4e10af43fef2..913f023f4fb8222cb101e53cea16a47bd9ea8771 100644 (file)
@@ -36,6 +36,7 @@
 #include "../../core/sampleChannel.h"
 #include "../../utils/gui.h"
 #include "../dialogs/gd_mainWindow.h"
+#include "basics/boxtypes.h"
 #include "ge_mixed.h"
 
 
@@ -130,8 +131,8 @@ void gClickRepeat::draw()
 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);
@@ -173,8 +174,9 @@ void gDial::draw()
 
 
 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);
@@ -241,7 +243,7 @@ void gRadio::draw()
 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);
 
 }
 
@@ -294,38 +296,6 @@ void gSoundMeter::draw()
   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);
-}
-
 
 /* -------------------------------------------------------------------------- */
 
@@ -375,18 +345,6 @@ void gChoice::draw()
 /* -------------------------------------------------------------------------- */
 
 
-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)
 {
@@ -394,7 +352,7 @@ gLiquidScroll::gLiquidScroll(int x, int y, int w, int h, const char *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);
 }
 
 
@@ -422,7 +380,7 @@ gSlider::gSlider(int x, int y, int w, int h, const char *l)
   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);
 }
@@ -563,26 +521,6 @@ void gResizerBar::resize(int X,int Y,int W,int H)
 }
 
 
-/* -------------------------------------------------------------------------- */
-
-
-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);
-}
-
-
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
 /* -------------------------------------------------------------------------- */
index d454497e29da87affc386f3757913abf44028d9e..4b1090e48425da8ebd1087fedba9d500b47e0cbf 100644 (file)
@@ -242,16 +242,6 @@ public:
 /* -------------------------------------------------------------------------- */
 
 
-/* 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.
@@ -265,19 +255,6 @@ public:
 };
 
 
-/* -------------------------------------------------------------------------- */
-
-
-/* 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
diff --git a/src/gui/elems/ge_modeBox.cpp b/src/gui/elems/ge_modeBox.cpp
deleted file mode 100644 (file)
index 4a6915b..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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();
-}
diff --git a/src/gui/elems/ge_modeBox.h b/src/gui/elems/ge_modeBox.h
deleted file mode 100644 (file)
index 2e82cd3..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
index 21baf738e8756076646a74b42c60fca3e6aa0f7d..2754feac844457fbbb2452e404cb7b0c54039754 100644 (file)
@@ -34,6 +34,7 @@
 #include "../../core/const.h"
 #include "../../core/pluginHost.h"
 #include "ge_mixed.h"
+#include "basics/boxtypes.h"
 #include "ge_pluginBrowser.h"
 
 
@@ -46,7 +47,7 @@ using std::vector;
 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);
@@ -55,12 +56,12 @@ gePluginBrowser::gePluginBrowser(int x, int y, int w, int h)
        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);
 
@@ -81,7 +82,7 @@ gePluginBrowser::gePluginBrowser(int x, int y, int w, int h)
 void gePluginBrowser::refresh()
 {
        clear();
-       
+
        add("NAME\tMANUFACTURER\tCATEGORY\tFORMAT\tUID");
        add("---\t---\t---\t---\t---");
 
diff --git a/src/gui/elems/ge_status.cpp b/src/gui/elems/ge_status.cpp
deleted file mode 100644 (file)
index 80cbac7..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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);
-  }
-}
diff --git a/src/gui/elems/ge_status.h b/src/gui/elems/ge_status.h
deleted file mode 100644 (file)
index e75d919..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
index 7e7b1979f6998e8e470cca1c248a454312c8450d..e2ec4b7076cf09585446cc27bfbace67347fd0cc 100644 (file)
@@ -32,6 +32,7 @@
 #include "../../core/const.h"
 #include "../elems/ge_mixed.h"
 #include "../elems/ge_waveform.h"
+#include "basics/boxtypes.h"
 #include "ge_waveTools.h"
 
 
@@ -42,7 +43,7 @@ gWaveTools::gWaveTools(int x, int y, int w, int h, SampleChannel *ch, const char
        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);
 
index dd893ce200fbabd11b3cdf390177e1702f7811d8..022257f49b9c7ce1e623ab121383794fb4685825 100644 (file)
@@ -42,6 +42,7 @@
 #include "../dialogs/gd_editor.h"
 #include "ge_waveTools.h"
 #include "ge_mixed.h"
+#include "basics/boxtypes.h"
 #include "ge_waveform.h"
 
 
@@ -621,7 +622,7 @@ void gWaveform::openEditMenu()
   }
 
   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);
diff --git a/src/gui/elems/mainWindow/beatMeter.cpp b/src/gui/elems/mainWindow/beatMeter.cpp
new file mode 100644 (file)
index 0000000..d0bb077
--- /dev/null
@@ -0,0 +1,72 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/elems/mainWindow/beatMeter.h b/src/gui/elems/mainWindow/beatMeter.h
new file mode 100644 (file)
index 0000000..5ca7b32
--- /dev/null
@@ -0,0 +1,46 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/channel.cpp b/src/gui/elems/mainWindow/keyboard/channel.cpp
new file mode 100644 (file)
index 0000000..1114d7c
--- /dev/null
@@ -0,0 +1,237 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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;
+}
diff --git a/src/gui/elems/mainWindow/keyboard/channel.h b/src/gui/elems/mainWindow/keyboard/channel.h
new file mode 100644 (file)
index 0000000..f76378f
--- /dev/null
@@ -0,0 +1,139 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/channelButton.cpp b/src/gui/elems/mainWindow/keyboard/channelButton.cpp
new file mode 100644 (file)
index 0000000..9a17eb4
--- /dev/null
@@ -0,0 +1,136 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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;
+}
diff --git a/src/gui/elems/mainWindow/keyboard/channelButton.h b/src/gui/elems/mainWindow/keyboard/channelButton.h
new file mode 100644 (file)
index 0000000..5163983
--- /dev/null
@@ -0,0 +1,60 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/channelMode.cpp b/src/gui/elems/mainWindow/keyboard/channelMode.cpp
new file mode 100644 (file)
index 0000000..5babd63
--- /dev/null
@@ -0,0 +1,111 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/elems/mainWindow/keyboard/channelMode.h b/src/gui/elems/mainWindow/keyboard/channelMode.h
new file mode 100644 (file)
index 0000000..0829be9
--- /dev/null
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/channelStatus.cpp b/src/gui/elems/mainWindow/keyboard/channelStatus.cpp
new file mode 100644 (file)
index 0000000..bc89239
--- /dev/null
@@ -0,0 +1,84 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+  }
+}
diff --git a/src/gui/elems/mainWindow/keyboard/channelStatus.h b/src/gui/elems/mainWindow/keyboard/channelStatus.h
new file mode 100644 (file)
index 0000000..6e911cb
--- /dev/null
@@ -0,0 +1,47 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/column.cpp b/src/gui/elems/mainWindow/keyboard/column.cpp
new file mode 100644 (file)
index 0000000..6518aed
--- /dev/null
@@ -0,0 +1,293 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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;
+}
diff --git a/src/gui/elems/mainWindow/keyboard/column.h b/src/gui/elems/mainWindow/keyboard/column.h
new file mode 100644 (file)
index 0000000..1d78540
--- /dev/null
@@ -0,0 +1,102 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/keyboard.cpp b/src/gui/elems/mainWindow/keyboard/keyboard.cpp
new file mode 100644 (file)
index 0000000..00d2bef
--- /dev/null
@@ -0,0 +1,405 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/elems/mainWindow/keyboard/keyboard.h b/src/gui/elems/mainWindow/keyboard/keyboard.h
new file mode 100644 (file)
index 0000000..8778c2a
--- /dev/null
@@ -0,0 +1,158 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/midiChannel.cpp b/src/gui/elems/mainWindow/keyboard/midiChannel.cpp
new file mode 100644 (file)
index 0000000..183bc71
--- /dev/null
@@ -0,0 +1,284 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/elems/mainWindow/keyboard/midiChannel.h b/src/gui/elems/mainWindow/keyboard/midiChannel.h
new file mode 100644 (file)
index 0000000..cd06ddc
--- /dev/null
@@ -0,0 +1,72 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/keyboard/sampleChannel.cpp b/src/gui/elems/mainWindow/keyboard/sampleChannel.cpp
new file mode 100644 (file)
index 0000000..fa3289c
--- /dev/null
@@ -0,0 +1,499 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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;
+}
diff --git a/src/gui/elems/mainWindow/keyboard/sampleChannel.h b/src/gui/elems/mainWindow/keyboard/sampleChannel.h
new file mode 100644 (file)
index 0000000..5c52151
--- /dev/null
@@ -0,0 +1,81 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/mainIO.cpp b/src/gui/elems/mainWindow/mainIO.cpp
new file mode 100644 (file)
index 0000000..7e61889
--- /dev/null
@@ -0,0 +1,180 @@
+/* -----------------------------------------------------------------------------
+*
+* 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();
+}
diff --git a/src/gui/elems/mainWindow/mainIO.h b/src/gui/elems/mainWindow/mainIO.h
new file mode 100644 (file)
index 0000000..f275211
--- /dev/null
@@ -0,0 +1,81 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/mainMenu.cpp b/src/gui/elems/mainWindow/mainMenu.cpp
new file mode 100644 (file)
index 0000000..5c9a0f4
--- /dev/null
@@ -0,0 +1,229 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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;
+       }
+}
diff --git a/src/gui/elems/mainWindow/mainMenu.h b/src/gui/elems/mainWindow/mainMenu.h
new file mode 100644 (file)
index 0000000..a8e6f4f
--- /dev/null
@@ -0,0 +1,62 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/mainTimer.cpp b/src/gui/elems/mainWindow/mainTimer.cpp
new file mode 100644 (file)
index 0000000..e1c0d94
--- /dev/null
@@ -0,0 +1,180 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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);
+}
diff --git a/src/gui/elems/mainWindow/mainTimer.h b/src/gui/elems/mainWindow/mainTimer.h
new file mode 100644 (file)
index 0000000..8be1d82
--- /dev/null
@@ -0,0 +1,74 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/mainWindow/mainTransport.cpp b/src/gui/elems/mainWindow/mainTransport.cpp
new file mode 100644 (file)
index 0000000..9b54c22
--- /dev/null
@@ -0,0 +1,160 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/elems/mainWindow/mainTransport.h b/src/gui/elems/mainWindow/mainTransport.h
new file mode 100644 (file)
index 0000000..57b83e3
--- /dev/null
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
diff --git a/src/gui/elems/midiChannel.cpp b/src/gui/elems/midiChannel.cpp
deleted file mode 100644 (file)
index bfdbea5..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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);
-}
diff --git a/src/gui/elems/midiChannel.h b/src/gui/elems/midiChannel.h
deleted file mode 100644 (file)
index cd06ddc..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
diff --git a/src/gui/elems/midiLearner.cpp b/src/gui/elems/midiLearner.cpp
new file mode 100644 (file)
index 0000000..f63b208
--- /dev/null
@@ -0,0 +1,110 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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();
+}
diff --git a/src/gui/elems/midiLearner.h b/src/gui/elems/midiLearner.h
new file mode 100644 (file)
index 0000000..9d5b0a0
--- /dev/null
@@ -0,0 +1,84 @@
+/* -----------------------------------------------------------------------------
+ *
+ * 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
index e2861b2b24fdf0d1e2d415d1c3c88f96cda4cfc5..1c9ae3bb639921a79b87bfca07edb19396f69c92 100644 (file)
@@ -32,7 +32,7 @@
 #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"
 
 
@@ -253,6 +253,7 @@ int geMuteEditor::handle(int e) {
                                                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
@@ -281,9 +282,13 @@ int geMuteEditor::handle(int e) {
                                        //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();
@@ -305,17 +310,17 @@ int geMuteEditor::handle(int e) {
 
                                        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;
index 870b61a75fae69a579384e99a30b1f7760f8d2a0..c6449cb4de24ac79f65dd86180c214603d7dade0 100644 (file)
@@ -143,6 +143,7 @@ void gePianoItem::record()
 
        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;
 }
 
 
@@ -151,8 +152,10 @@ void gePianoItem::record()
 
 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. */
diff --git a/src/gui/elems/sampleChannel.cpp b/src/gui/elems/sampleChannel.cpp
deleted file mode 100644 (file)
index 5b7e4c9..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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;
-}
diff --git a/src/gui/elems/sampleChannel.h b/src/gui/elems/sampleChannel.h
deleted file mode 100644 (file)
index efde2a6..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * 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
index 5daf5d5f345299d78a157fe7b01270056304c722..715126d524d6f9f6d50f057abe290278c67b1e15 100644 (file)
 #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"
@@ -68,7 +72,7 @@ void gu_refreshUI()
        /* 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();
 
@@ -102,18 +106,18 @@ void gu_updateControls()
        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);
 }