New upstream version 0.14.4~dfsg1
authorJaromír Mikeš <mira.mikes@seznam.cz>
Sat, 25 Nov 2017 14:57:44 +0000 (15:57 +0100)
committerJaromír Mikeš <mira.mikes@seznam.cz>
Sat, 25 Nov 2017 14:57:44 +0000 (15:57 +0100)
106 files changed:
ChangeLog
Makefile.am
README.md
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/midiChannel.h
src/core/mixer.cpp
src/core/mixerHandler.cpp
src/core/mixerHandler.h
src/core/patch.cpp
src/core/patch.h
src/core/plugin.cpp
src/core/plugin.h
src/core/pluginHost.cpp
src/core/pluginHost.h
src/core/sampleChannel.cpp
src/core/sampleChannel.h
src/core/storager.cpp
src/core/wave.cpp
src/core/wave.h
src/core/waveFx.cpp
src/core/waveFx.h
src/core/waveManager.cpp
src/deps/juce-config.h
src/glue/channel.cpp
src/glue/channel.h
src/glue/io.cpp
src/glue/plugin.cpp
src/glue/plugin.h
src/glue/sampleEditor.cpp
src/glue/sampleEditor.h
src/glue/storage.cpp
src/gui/dialogs/beatsInput.cpp [new file with mode: 0644]
src/gui/dialogs/beatsInput.h [new file with mode: 0644]
src/gui/dialogs/bpmInput.cpp [new file with mode: 0644]
src/gui/dialogs/bpmInput.h [new file with mode: 0644]
src/gui/dialogs/browser/browserBase.cpp
src/gui/dialogs/browser/browserBase.h
src/gui/dialogs/browser/browserLoad.cpp
src/gui/dialogs/browser/browserLoad.h
src/gui/dialogs/browser/browserSave.cpp
src/gui/dialogs/browser/browserSave.h
src/gui/dialogs/channelNameInput.cpp [new file with mode: 0644]
src/gui/dialogs/channelNameInput.h [new file with mode: 0644]
src/gui/dialogs/gd_beatsInput.cpp [deleted file]
src/gui/dialogs/gd_beatsInput.h [deleted file]
src/gui/dialogs/gd_bpmInput.cpp [deleted file]
src/gui/dialogs/gd_bpmInput.h [deleted file]
src/gui/dialogs/gd_pluginChooser.cpp [deleted file]
src/gui/dialogs/gd_pluginChooser.h [deleted file]
src/gui/dialogs/gd_pluginList.cpp [deleted file]
src/gui/dialogs/gd_pluginList.h [deleted file]
src/gui/dialogs/gd_pluginWindow.cpp [deleted file]
src/gui/dialogs/gd_pluginWindow.h [deleted file]
src/gui/dialogs/gd_pluginWindowGUI.cpp [deleted file]
src/gui/dialogs/gd_pluginWindowGUI.h [deleted file]
src/gui/dialogs/pluginChooser.cpp [new file with mode: 0644]
src/gui/dialogs/pluginChooser.h [new file with mode: 0644]
src/gui/dialogs/pluginList.cpp [new file with mode: 0644]
src/gui/dialogs/pluginList.h [new file with mode: 0644]
src/gui/dialogs/pluginWindow.cpp [new file with mode: 0644]
src/gui/dialogs/pluginWindow.h [new file with mode: 0644]
src/gui/dialogs/pluginWindowGUI.cpp [new file with mode: 0644]
src/gui/dialogs/pluginWindowGUI.h [new file with mode: 0644]
src/gui/dialogs/sampleEditor.cpp
src/gui/dialogs/sampleEditor.h
src/gui/dialogs/window.h
src/gui/elems/basics/liquidScroll.cpp
src/gui/elems/config/tabAudio.cpp
src/gui/elems/config/tabMidi.cpp
src/gui/elems/config/tabMisc.cpp
src/gui/elems/mainWindow/keyboard/channel.cpp
src/gui/elems/mainWindow/keyboard/channel.h
src/gui/elems/mainWindow/keyboard/channelButton.cpp
src/gui/elems/mainWindow/keyboard/channelButton.h
src/gui/elems/mainWindow/keyboard/channelStatus.cpp
src/gui/elems/mainWindow/keyboard/midiChannel.cpp
src/gui/elems/mainWindow/keyboard/midiChannel.h
src/gui/elems/mainWindow/keyboard/midiChannelButton.cpp [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/midiChannelButton.h [new file with mode: 0644]
src/gui/elems/mainWindow/keyboard/sampleChannel.cpp
src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp
src/gui/elems/mainWindow/keyboard/sampleChannelButton.h
src/gui/elems/mainWindow/mainIO.cpp
src/gui/elems/mainWindow/mainMenu.cpp
src/gui/elems/mainWindow/mainTimer.cpp
src/gui/elems/plugin/pluginBrowser.cpp [new file with mode: 0644]
src/gui/elems/plugin/pluginBrowser.h [new file with mode: 0644]
src/gui/elems/plugin/pluginParameter.cpp [new file with mode: 0644]
src/gui/elems/plugin/pluginParameter.h [new file with mode: 0644]
src/gui/elems/pluginBrowser.cpp [deleted file]
src/gui/elems/pluginBrowser.h [deleted file]
src/gui/elems/sampleEditor/rangeTool.cpp
src/gui/elems/sampleEditor/shiftTool.cpp [new file with mode: 0644]
src/gui/elems/sampleEditor/shiftTool.h [new file with mode: 0644]
src/gui/elems/sampleEditor/waveform.cpp
src/utils/fs.h
src/utils/string.cpp
src/utils/string.h
src/utils/time.cpp
tests/wave.cpp

index 01102c86982ddda9cdb3ebc7b25e13af680efc9f..cf11e2be3df9e436b89057961a7c29102bc1f11a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 --------------------------------------------------------------------------------
 
 
+0.14.4 --- 2017 . 10 . 28
+- Renameable channels
+- Portable VST path
+- [Sample Editor] Sample shift tool
+- [Linux/Mac] Don't skip '/' path when navigating to upper folders
+- Ability to process more than one plug-in instrument at once
+- Beautify Configuration Window
+- Bring VST window to front when opening UI
+- Save 'arm' status to patch/project file
+- Revamped Beats and Bpm input windows
+- Simplified audio samples' storage in project folders
+- Update JUCE to version 5.1.2
+- UI-less plug-in window refinements
+- Update UI-less plug-in window on MIDI parameter's change
+- Strip .gptc/.gprj extention from patch name
+- [Sample Editor] Fix non-working 'cut' operation
+- Fix missed MIDI events with more than 1 plug-in in the stack
+- Fix File Browser path widget drawn incorrectly in OS X
+- Fix missing MIDI learn for 'Arm channel' and 'Kill channel'
+
+
 0.14.3 --- 2017 . 09 . 18
 - [Sample Editor] New "reverse selection" function
 - [Sample Editor] New "normalize hard" function
 - [Sample Editor] New "copy to channel" function
+- [Sample Editor] New "copy & paste" function
 - [Sample Editor] Double click on waveform selects all
 - [Sample Editor] Fix garbled characters in window's title
 - [Sample Editor] Fix wrong result on "set pitch to song/bar"
index 2e2a260c841b490f4af41c6b2aea9f6ed2a954b0..e008f6201671cb22ebc21a6090bb2592faccc71d 100644 (file)
@@ -71,28 +71,30 @@ src/gui/dialogs/gd_about.h             \
 src/gui/dialogs/gd_about.cpp           \
 src/gui/dialogs/gd_mainWindow.h        \
 src/gui/dialogs/gd_mainWindow.cpp      \
-src/gui/dialogs/gd_beatsInput.h        \
-src/gui/dialogs/gd_beatsInput.cpp      \
+src/gui/dialogs/beatsInput.h           \
+src/gui/dialogs/beatsInput.cpp         \
 src/gui/dialogs/gd_warnings.h          \
 src/gui/dialogs/gd_warnings.cpp        \
-src/gui/dialogs/gd_bpmInput.h          \
-src/gui/dialogs/gd_bpmInput.cpp        \
+src/gui/dialogs/bpmInput.h             \
+src/gui/dialogs/bpmInput.cpp           \
+src/gui/dialogs/channelNameInput.h     \
+src/gui/dialogs/channelNameInput.cpp   \
 src/gui/dialogs/gd_config.h                             \
 src/gui/dialogs/gd_config.cpp          \
 src/gui/dialogs/gd_devInfo.h           \
 src/gui/dialogs/gd_devInfo.cpp              \
-src/gui/dialogs/gd_pluginList.h               \
-src/gui/dialogs/gd_pluginList.cpp      \
-src/gui/dialogs/gd_pluginWindow.h           \
-src/gui/dialogs/gd_pluginWindow.cpp    \
+src/gui/dialogs/pluginList.h            \
+src/gui/dialogs/pluginList.cpp         \
+src/gui/dialogs/pluginWindow.h        \
+src/gui/dialogs/pluginWindow.cpp       \
 src/gui/dialogs/sampleEditor.h         \
 src/gui/dialogs/sampleEditor.cpp       \
-src/gui/dialogs/gd_pluginWindowGUI.h   \
-src/gui/dialogs/gd_pluginWindowGUI.cpp \
+src/gui/dialogs/pluginWindowGUI.h      \
+src/gui/dialogs/pluginWindowGUI.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/dialogs/pluginChooser.h        \
+src/gui/dialogs/pluginChooser.cpp      \
 src/gui/dialogs/browser/browserBase.h           \
 src/gui/dialogs/browser/browserBase.cpp         \
 src/gui/dialogs/browser/browserLoad.h           \
@@ -117,8 +119,10 @@ src/gui/elems/browser.h                     \
 src/gui/elems/browser.cpp          \
 src/gui/elems/soundMeter.h                  \
 src/gui/elems/soundMeter.cpp       \
-src/gui/elems/pluginBrowser.h      \
-src/gui/elems/pluginBrowser.cpp    \
+src/gui/elems/plugin/pluginBrowser.h                \
+src/gui/elems/plugin/pluginBrowser.cpp              \
+src/gui/elems/plugin/pluginParameter.h              \
+src/gui/elems/plugin/pluginParameter.cpp            \
 src/gui/elems/sampleEditor/waveform.h               \
 src/gui/elems/sampleEditor/waveform.cpp             \
 src/gui/elems/sampleEditor/waveTools.h              \
@@ -133,6 +137,8 @@ src/gui/elems/sampleEditor/pitchTool.h              \
 src/gui/elems/sampleEditor/pitchTool.cpp            \
 src/gui/elems/sampleEditor/rangeTool.h              \
 src/gui/elems/sampleEditor/rangeTool.cpp            \
+src/gui/elems/sampleEditor/shiftTool.h              \
+src/gui/elems/sampleEditor/shiftTool.cpp            \
 src/gui/elems/actionEditor/baseActionEditor.h       \
 src/gui/elems/actionEditor/baseActionEditor.cpp     \
 src/gui/elems/actionEditor/envelopeEditor.h         \
@@ -165,24 +171,26 @@ 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/mainWindow/keyboard/sampleChannelButton.h    \
-src/gui/elems/mainWindow/keyboard/sampleChannelButton.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/mainWindow/keyboard/sampleChannelButton.h   \
+src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp \
+src/gui/elems/mainWindow/keyboard/midiChannelButton.h     \
+src/gui/elems/mainWindow/keyboard/midiChannelButton.cpp   \
 src/gui/elems/config/tabMisc.h         \
 src/gui/elems/config/tabMisc.cpp       \
 src/gui/elems/config/tabMidi.h         \
@@ -359,6 +367,7 @@ src/core/storager.cpp        \
 src/core/recorder.cpp        \
 src/utils/fs.cpp             \
 src/utils/string.cpp         \
+src/utils/time.cpp           \
 src/utils/log.cpp
 
 if WITH_VST
index 4b36cda7ce6f1fdd3333d9f41b471d6241af867c..9da5e2a5b32e917e75cca92d4067206f24d6ec0c 100644 (file)
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Giada is a free, minimal, hardcore audio tool for DJs, live performers and elect
 * unlimited number of channels (controllable via computer keyboard);
 * several playback modes and combinations;
 * BPM and beat sync with sample-accurate loop engine;
-* VST and VSTi (instrument) plugin support;
+* VST and VSTi (instrument) plug-in support;
 * MIDI input and output support, featuring custom [MIDI lightning messages](https://github.com/monocasual/giada-midimaps);
 * super-sleek, built-in wave editor;
 * live sampler from external inputs;
@@ -49,6 +49,8 @@ Found a typo or a terrible mistake? Feel free to clone the [website repository](
 
 We do our best to make the compilation process as simple as possible. You can find all the information in the [official docs page](http://giadamusic.com/documentation/show/compiling-from-source).
 
+Something went wrong? Try our new [Docker image](https://github.com/monocasual/giada-docker) for building and running Giada without hurdles. 
+
 ## Bugs, requests and questions for non-developers
 
 Feel free to ask anything on our end-user forum:
index d4bded3cb8b0c9e0e5b29d4da94dc9679c493e1b..95aa43ef61773df7d46a9f04398c84f7797ae709 100644 (file)
@@ -52,8 +52,9 @@ using namespace giada::m;
 Channel::Channel(int type, int status, int bufferSize)
 : bufferSize     (bufferSize),
        midiFilter     (-1),
-       pan            (0.5f),
        previewMode    (G_PREVIEW_NONE),
+       pan            (0.5f),
+       armed          (false),
        type           (type),
        status         (status),
        key            (0),
@@ -66,7 +67,6 @@ Channel::Channel(int type, int status, int bufferSize)
        solo           (false),
        hasActions     (false),
        readActions    (false),
-       armed          (false),
        recStatus      (REC_STOPPED),
        vChan          (nullptr),
        guiChannel     (nullptr),
@@ -187,7 +187,7 @@ void Channel::sendMidiLmessage(uint32_t learn, const midimap::message_t &msg)
 /* -------------------------------------------------------------------------- */
 
 
-bool Channel::isPlaying()
+bool Channel::isPlaying() const
 {
        return status & (STATUS_PLAY | STATUS_ENDING);
 }
@@ -202,7 +202,9 @@ int Channel::writePatch(int i, bool isProject)
        pch.type            = type;
        pch.index           = index;
        pch.size            = guiChannel->getSize();
+       pch.name            = name;
        pch.key             = key;
+       pch.armed           = armed;
        pch.column          = guiChannel->getColumnIndex();
        pch.mute            = mute;
        pch.mute_s          = mute_s;
@@ -224,7 +226,7 @@ int Channel::writePatch(int i, bool isProject)
 
        for (unsigned i=0; i<recorder::global.size(); i++) {
                for (unsigned k=0; k<recorder::global.at(i).size(); k++) {
-                       recorder::action *action = recorder::global.at(i).at(k);
+                       recorder::actionaction = recorder::global.at(i).at(k);
                        if (action->chan == index) {
                                patch::action_t pac;
                                pac.type   = action->type;
@@ -240,7 +242,7 @@ int Channel::writePatch(int i, bool isProject)
 
        unsigned numPlugs = pluginHost::countPlugins(pluginHost::CHANNEL, this);
        for (unsigned i=0; i<numPlugs; i++) {
-               Plugin *pPlugin = pluginHost::getPluginByIndex(i, pluginHost::CHANNEL, this);
+               PluginpPlugin = pluginHost::getPluginByIndex(i, pluginHost::CHANNEL, this);
                patch::plugin_t pp;
                pp.path   = pPlugin->getUniqueId();
                pp.bypass = pPlugin->isBypassed();
@@ -262,13 +264,15 @@ int Channel::writePatch(int i, bool isProject)
 /* -------------------------------------------------------------------------- */
 
 
-int Channel::readPatch(const string &path, int i, pthread_mutex_t *pluginMutex,
+int Channel::readPatch(const string& path, int i, pthread_mutex_t* pluginMutex,
        int samplerate, int rsmpQuality)
 {
        int ret = 1;
-       patch::channel_t *pch = &patch::channels.at(i);
+       patch::channel_tpch = &patch::channels.at(i);
        key             = pch->key;
+       armed           = pch->armed;
        type            = pch->type;
+       name            = pch->name;
        index           = pch->index;
        mute            = pch->mute;
        mute_s          = pch->mute_s;
@@ -287,28 +291,26 @@ int Channel::readPatch(const string &path, int i, pthread_mutex_t *pluginMutex,
        midiOutLmute    = pch->midiOutLmute;
        midiOutLsolo    = pch->midiOutLsolo;
 
-       for (unsigned k=0; k<pch->actions.size(); k++) {
-               patch::action_t *ac = &pch->actions.at(k);
-               recorder::rec(index, ac->type, ac->frame, ac->iValue, ac->fValue);
+       for (const patch::action_t& ac : pch->actions) {
+               recorder::rec(index, ac.type, ac.frame, ac.iValue, ac.fValue);
                hasActions = true;
        }
 
 #ifdef WITH_VST
 
-       for (unsigned k=0; k<pch->plugins.size(); k++) {
-               patch::plugin_t *ppl = &pch->plugins.at(k);
-               Plugin *plugin = pluginHost::addPlugin(ppl->path, pluginHost::CHANNEL,
+       for (const patch::plugin_t& ppl : pch->plugins) {
+               Plugin* plugin = pluginHost::addPlugin(ppl.path, pluginHost::CHANNEL,
                        pluginMutex, this);
                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->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));
+               for (uint32_t midiInParam : ppl.midiInParams)
+                       plugin->midiInParams.push_back(midiInParam);
                ret &= 1;
        }
 
@@ -391,7 +393,7 @@ void Channel::setPan(float v)
 }
 
 
-float Channel::getPan()
+float Channel::getPan() const
 {
        return pan;
 }
@@ -420,7 +422,7 @@ void Channel::setPreviewMode(int m)
 }
 
 
-bool Channel::isPreview()
+bool Channel::isPreview() const
 {
        return previewMode != G_PREVIEW_NONE;
 }
@@ -429,6 +431,36 @@ bool Channel::isPreview()
 /* -------------------------------------------------------------------------- */
 
 
+void Channel::setArmed(bool b)
+{
+       armed = b;
+}
+
+
+bool Channel::isArmed() const
+{
+       return armed;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+std::string Channel::getName() const
+{
+       return name;
+}
+
+
+void Channel::setName(const std::string& s)
+{
+       name = s;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 #ifdef WITH_VST
 
 juce::MidiBuffer &Channel::getPluginMidiEvents()
index 6f96257d07f03a73c3dbdd47b5eafc7fb2a02790..72e6f2d6b8072d66211504f3dde85b788e77be95 100644 (file)
@@ -49,18 +49,29 @@ class Channel
 {
 protected:
 
+       /* sendMidiLMessage
+       Composes a MIDI message by merging bytes from MidiMap conf class, and sends it 
+       to KernelMidi. */
+
+       void sendMidiLmessage(uint32_t learn, const giada::m::midimap::message_t& msg);
+
+       /* calcPanning
+       Given an audio channel (stereo: 0 or 1) computes the current panning value. */
+
+       float calcPanning(int ch);
+
 #ifdef WITH_VST
 
-       /* MidiBuffer contains MIDI events. When ready, events are sent to
-        * each plugin in the channel. This is available for any kind of
-        * channel, but it makes sense only for MIDI channels. */
+       /* MidiBuffer contains MIDI events. When ready, events are sent to each plugin 
+       in the channel. This is available for any kind of channel, but it makes sense 
+       only for MIDI channels. */
 
        juce::MidiBuffer midiBuffer;
 
 #endif
 
        /* bufferSize
-        * size of every buffer in this channel (vChan, pChan) */
+       Size of every buffer in this channel (vChan, pChan) */
 
        int bufferSize;
 
@@ -70,23 +81,14 @@ protected:
 
   int midiFilter;
 
-       float pan;
-
        /* previewMode
        Whether the channel is in audio preview mode or not. */
 
        int previewMode;
 
-       /* sendMidiLMessage
-       Composes a MIDI message by merging bytes from MidiMap conf class, and sends it 
-       to KernelMidi. */
-
-       void sendMidiLmessage(uint32_t learn, const giada::m::midimap::message_t& msg);
-
-       /* calcPanning
-       Given an audio channel (stereo: 0 or 1) computes the current panning value. */
-
-       float calcPanning(int ch);
+       float pan;
+       bool armed;
+       std::string name;
 
 public:
 
@@ -95,12 +97,12 @@ public:
        virtual ~Channel();
 
        /* copy
-        * Make a shallow copy (no vChan/pChan allocation) of another channel. */
+       Makes a shallow copy (no vChan/pChan allocation) of another channel. */
 
        virtual void copy(const Channel* src, pthread_mutex_t* pluginMutex) = 0;
 
        /* readPatch
-        * Fill channel with data from patch. */
+       Fills channel with data from patch. */
 
        virtual int readPatch(const std::string& basePath, int i,
     pthread_mutex_t* pluginMutex, int samplerate, int rsmpQuality);
@@ -127,54 +129,53 @@ public:
                        bool mixerIsRunning, bool forceStart, bool isUserGenerated) = 0;
 
        /* stop
-        * action to do when channel is stopped normally (via key or MIDI). */
+       What to do when channel is stopped normally (via key or MIDI). */
 
        virtual void stop() = 0;
 
        /* kill
-        * action to do when channel stops abruptly. */
+       What to do when channel stops abruptly. */
 
        virtual void kill(int frame) = 0;
 
        /* mute
-        * action to do when channel is muted. If internal == true, set
-        * internal mute without altering main mute. */
+       What to do when channel is muted. If internal == true, set internal mute 
+       without altering main mute. */
 
        virtual void setMute  (bool internal) = 0;
        virtual void unsetMute(bool internal) = 0;
 
        /* empty
-        * free any associated resources (e.g. waveform for SAMPLE). */
+       Frees any associated resources (e.g. waveform for SAMPLE). */
 
        virtual void empty() = 0;
 
        /* stopBySeq
-        * action to do when channel is stopped by sequencer. */
+       What to do when channel is stopped by sequencer. */
 
        virtual void stopBySeq(bool chansStopOnSeqHalt) = 0;
 
        /* quantize
-        * start channel according to quantizer. Index = array index of
-        * mixer::channels, used by recorder. LocalFrame = frame within the current
-   * buffer.  */
+       Starts channel according to quantizer. Index = array index of mixer::channels, 
+       used by recorder. LocalFrame = frame within the current buffer.  */
 
        virtual void quantize(int index, int localFrame) = 0;
 
        /* onZero
-        * action to do when frame goes to zero, i.e. sequencer restart. */
+       What to do when frame goes to zero, i.e. sequencer restart. */
 
        virtual void onZero(int frame, bool recsStopOnChanHalt) = 0;
 
        /* onBar
-        * action to do when a bar has passed. */
+       What to do when a bar has passed. */
 
        virtual void onBar(int frame) = 0;
 
        /* parseAction
-        * do something on a recorded action. Parameters:
-        * action *a   - action to parse
-        * localFrame  - frame number of the processed buffer
-        * globalFrame - actual frame in Mixer */
+       Does something on a recorded action. Parameters:
+               - action *a   - action to parse
+         - localFrame  - frame number of the processed buffer
+         - globalFrame - actual frame in Mixer */
 
         // TODO - quantize is useless!
 
@@ -182,7 +183,7 @@ public:
     int globalFrame, int quantize, bool mixerIsRunning) = 0;
 
        /* rewind
-        * rewind channel when rewind button is pressed. */
+       Rewinds channel when rewind button is pressed. */
 
        virtual void rewind() = 0;
 
@@ -199,13 +200,13 @@ public:
        virtual bool canInputRec() = 0;
 
        /* writePatch
-        * Fill a patch with channel values. Returns the index of the last
-        * Patch::channel_t added. */
+       Fills a patch with channel values. Returns the index of the last 
+       Patch::channel_t added. */
 
        virtual int writePatch(int i, bool isProject);
 
        /* receiveMidi
-        * Receives and processes midi messages from external devices. */
+       Receives and processes midi messages from external devices. */
 
        virtual void receiveMidi(uint32_t msg);
 
@@ -215,7 +216,41 @@ public:
 
        virtual bool allocBuffers();
 
-       /* ------------------------------------------------------------------------ */
+       /* isPlaying
+        * tell wether the channel is playing or is stopped. */
+
+       bool isPlaying() const;
+
+       /* sendMidiL*
+        * send MIDI lightning events to a physical device. */
+
+       void sendMidiLmute();
+       void sendMidiLsolo();
+       void sendMidiLplay();
+
+       void setPan(float v);
+       float getPan() const;
+
+       void setArmed(bool b);
+       bool isArmed() const;
+
+       std::string getName() const;
+       void setName(const std::string& s);
+
+       void setPreviewMode(int m);
+       bool isPreview() const;
+
+#ifdef WITH_VST
+
+       /* getPluginMidiEvents
+        * Return a reference to midiBuffer stack. This is available for any kind of
+        * channel, but it makes sense only for MIDI channels. */
+
+       juce::MidiBuffer& getPluginMidiEvents();
+
+       void clearMidiBuffer();
+
+#endif
 
        int    index;                 // unique id
        int    type;                  // midi or sample
@@ -230,7 +265,6 @@ public:
        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
   geChannel* guiChannel;        // pointer to a gChannel object, part of the GUI
@@ -260,38 +294,6 @@ public:
   std::vector <Plugin*> plugins;
 #endif
 
-
-       /* ------------------------------------------------------------------------ */
-
-       /* isPlaying
-        * tell wether the channel is playing or is stopped. */
-
-       bool isPlaying();
-
-       /* sendMidiL*
-        * send MIDI lightning events to a physical device. */
-
-       void sendMidiLmute();
-       void sendMidiLsolo();
-       void sendMidiLplay();
-
-       void setPan(float v);
-       float getPan();
-
-       void setPreviewMode(int m);
-       bool isPreview();
-
-#ifdef WITH_VST
-
-       /* getPluginMidiEvents
-        * Return a reference to midiBuffer stack. This is available for any kind of
-        * channel, but it makes sense only for MIDI channels. */
-
-       juce::MidiBuffer& getPluginMidiEvents();
-
-       void clearMidiBuffer();
-
-#endif
 };
 
 
index 39bc9ec3ebc5f4061976c7a31e9b20d40b7348ae..e32c28951bb9d317d6cb99aff75cd6a329df6331 100644 (file)
@@ -238,6 +238,9 @@ int beatsY = 0;
 int aboutX = 0;
 int aboutY = 0;
 
+int nameX = 0;
+int nameY = 0;
+
 #ifdef WITH_VST
 
 int pluginChooserX   = 0;
@@ -365,6 +368,8 @@ int read()
        if (!storager::setInt(jRoot, CONF_KEY_BEATS_Y, beatsY)) return 0;
        if (!storager::setInt(jRoot, CONF_KEY_ABOUT_X, aboutX)) return 0;
        if (!storager::setInt(jRoot, CONF_KEY_ABOUT_Y, aboutY)) return 0;
+  if (!storager::setInt(jRoot, CONF_KEY_NAME_X, nameX)) return 0;
+  if (!storager::setInt(jRoot, CONF_KEY_NAME_Y, nameY)) return 0;
   if (!storager::setInt(jRoot, CONF_KEY_MIDI_INPUT_X, midiInputX)) return 0;
   if (!storager::setInt(jRoot, CONF_KEY_MIDI_INPUT_Y, midiInputY)) return 0;
   if (!storager::setInt(jRoot, CONF_KEY_MIDI_INPUT_W, midiInputW)) return 0;
@@ -470,7 +475,9 @@ int write()
        json_object_set_new(jRoot, CONF_KEY_BEATS_X,                   json_integer(beatsX));
        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_ABOUT_Y,                   json_integer(aboutY));   
+       json_object_set_new(jRoot, CONF_KEY_NAME_X,                    json_integer(nameX));
+       json_object_set_new(jRoot, CONF_KEY_NAME_Y,                    json_integer(nameY));
        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));
index 138579d11330b5dfd1368e24205b75261f1298c5..024c734d45882b02151d178c18c061cff0e42a79 100644 (file)
@@ -104,6 +104,7 @@ extern int configX, configY;
 extern int bpmX, bpmY;
 extern int beatsX, beatsY;
 extern int aboutX, aboutY;
+extern int nameX, nameY;
 
 #ifdef WITH_VST
 
index 3d3c223b2780b8e3a858543533175afbce56560b..7e48358f4d56fc28d507a64f960ae399a6b83575 100644 (file)
 
 /* -- version --------------------------------------------------------------- */
 #define G_APP_NAME      "Giada"
-#define G_VERSION_STR   "0.14.3"
+#define G_VERSION_STR   "0.14.4"
 #define G_VERSION_MAJOR 0
 #define G_VERSION_MINOR 14
-#define G_VERSION_PATCH 3
+#define G_VERSION_PATCH 4
 
 #define CONF_FILENAME "giada.conf"
 
 #define WID_SAMPLE_EDITOR -8
 #define WID_FX            -9
 #define WID_KEY_GRABBER   -10
+#define WID_SAMPLE_NAME   -11
 
 
 
@@ -359,6 +360,7 @@ const int MIDI_CHANS[16] = {
 #define PATCH_KEY_CHANNEL_TYPE                 "type"
 #define PATCH_KEY_CHANNEL_INDEX                "index"
 #define PATCH_KEY_CHANNEL_SIZE                 "size"
+#define PATCH_KEY_CHANNEL_NAME                 "name"
 #define PATCH_KEY_CHANNEL_COLUMN               "column"
 #define PATCH_KEY_CHANNEL_MUTE                 "mute"
 #define PATCH_KEY_CHANNEL_MUTE_S               "mute_s"
@@ -392,6 +394,7 @@ const int MIDI_CHANS[16] = {
 #define PATCH_KEY_CHANNEL_MIDI_OUT_CHAN        "midi_out_chan"
 #define PATCH_KEY_CHANNEL_PLUGINS              "plugins"
 #define PATCH_KEY_CHANNEL_ACTIONS              "actions"
+#define PATCH_KEY_CHANNEL_ARMED                "armed"
 #define PATCH_KEY_ACTION_TYPE                  "type"
 #define PATCH_KEY_ACTION_FRAME                 "frame"
 #define PATCH_KEY_ACTION_F_VALUE               "f_value"
@@ -479,6 +482,8 @@ const int MIDI_CHANS[16] = {
 #define CONF_KEY_BEATS_Y                  "beats_y"
 #define CONF_KEY_ABOUT_X                  "about_x"
 #define CONF_KEY_ABOUT_Y                  "about_y"
+#define CONF_KEY_NAME_X                   "name_x"
+#define CONF_KEY_NAME_Y                   "name_y"
 #define CONF_KEY_PLUGIN_CHOOSER_X         "plugin_chooser_x"
 #define CONF_KEY_PLUGIN_CHOOSER_Y         "plugin_chooser_y"
 #define CONF_KEY_PLUGIN_CHOOSER_W         "plugin_chooser_w"
index db18cbcaa9223aaad69afebe72e9eafe94e347e3..610487492a34dbaa66132f2c116d99f6d2b35fd2 100644 (file)
@@ -189,6 +189,7 @@ void init_shutdown()
 
        if (kernelAudio::getStatus()) {
                kernelAudio::closeDevice();
+               gu_log("[init] KernelAudio closed\n");
                mixer::close();
                gu_log("[init] Mixer closed\n");
        }
index 41d57ad0779316d0ac095a201f07687bc7729e95..8a19181fef830cf29a1c7fcae16422c34d898352 100644 (file)
@@ -28,6 +28,7 @@
 #include <rtmidi/RtMidi.h>
 #include "../utils/log.h"
 #include "../glue/channel.h"
+#include "../glue/plugin.h"
 #include "../glue/main.h"
 #include "../glue/transport.h"
 #include "../glue/io.h"
@@ -57,8 +58,8 @@ namespace
 {
 bool status = false;
 int api = 0;
-RtMidiOut *midiOut = nullptr;
-RtMidiIn  *midiIn  = nullptr;
+RtMidiOutmidiOut = nullptr;
+RtMidiIn*  midiIn  = nullptr;
 unsigned numOutPorts = 0;
 unsigned numInPorts  = 0;
 
@@ -67,8 +68,8 @@ unsigned numInPorts  = 0;
  * kernelMidi. It contains things to do once the midi message has been
  * stored. */
 
-cb_midiLearn *cb_learn = nullptr;
-void         *cb_data  = nullptr;
+cb_midiLearncb_learn = nullptr;
+void* cb_data = nullptr;
 
 
 /* -------------------------------------------------------------------------- */
@@ -76,25 +77,24 @@ void         *cb_data  = nullptr;
 
 #ifdef WITH_VST
 
-void processPlugins(Channel *ch, uint32_t pure, uint32_t value)
+void processPlugins(Channelch, 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. */
+  /* Plugins' parameters layout reflects the structure of the matrix
+  Channel::midiInPlugins. It is safe to assume then that i (i.e. Plugin*) and k 
+  indexes match both the structure of Channel::midiInPlugins and 
+  vector<Plugin*>* plugins. */
 
-  vector <Plugin *> *plugins = pluginHost::getStack(pluginHost::CHANNEL, ch);
+  vector<Plugin*>* plugins = pluginHost::getStack(pluginHost::CHANNEL, ch);
 
-  for (unsigned i=0; i<plugins->size(); i++)
-  {
-    Plugin *plugin = plugins->at(i);
+  for (Plugin* plugin : *plugins) {
     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);
+      float vf = (value >> 8) / 127.0f;
+      c::plugin::setParameter(plugin, k, vf, false); // false: not from GUI
       gu_log("  >>> [plugin %d parameter %d] ch=%d (pure=0x%X, value=%d, float=%f)\n",
-        i, k, ch->index, pure, value >> 8, vf);
+        plugin->getId(), k, ch->index, pure, value >> 8, vf);
     }
   }
 }
@@ -107,9 +107,7 @@ void processPlugins(Channel *ch, uint32_t pure, uint32_t value)
 
 void processChannels(uint32_t pure, uint32_t value)
 {
-       for (unsigned i=0; i<mixer::channels.size(); i++) {
-
-               Channel *ch = static_cast<SampleChannel*>(mixer::channels.at(i));
+       for (Channel* ch : mixer::channels) {
 
                if (!ch->midiIn)
                        continue;
@@ -124,11 +122,19 @@ void processChannels(uint32_t pure, uint32_t value)
                }
                else if (pure == ch->midiInMute) {
                        gu_log("  >>> mute ch=%d (pure=0x%X)\n", ch->index, pure);
-                       glue_setMute(ch, false);
+                       glue_toggleMute(ch, false);
+               }               
+               else if (pure == ch->midiInKill) {
+                       gu_log("  >>> kill ch=%d (pure=0x%X)\n", ch->index, pure);
+                       glue_kill(ch);
+               }               
+               else if (pure == ch->midiInArm) {
+                       gu_log("  >>> arm ch=%d (pure=0x%X)\n", ch->index, pure);
+                       glue_toggleArm(ch, false);
                }
                else if (pure == ch->midiInSolo) {
                        gu_log("  >>> solo ch=%d (pure=0x%X)\n", ch->index, pure);
-                       ch->solo ? glue_setSoloOn(ch, false) : glue_setSoloOff(ch, false);
+                       glue_toggleSolo(ch, false);
                }
                else if (pure == ch->midiInVolume) {
                        float vf = (value >> 8)/127.0f;
@@ -136,22 +142,27 @@ void processChannels(uint32_t pure, uint32_t value)
                                ch->index, pure, value >> 8, vf);
                        glue_setVolume(ch, vf, false);
                }
-               else if (pure == ((SampleChannel*)ch)->midiInPitch) {
-                       float vf = (value >> 8)/(127/4.0f); // [0-127] ~> [0.0 4.0]
-                       gu_log("  >>> pitch ch=%d (pure=0x%X, value=%d, float=%f)\n",
-                               ch->index, pure, value >> 8, vf);
-                       glue_setPitch(static_cast<SampleChannel*>(ch), vf);
-               }
-               else if (pure == ((SampleChannel*)ch)->midiInReadActions) {
-                       gu_log("  >>> start/stop read actions ch=%d (pure=0x%X)\n", ch->index, pure);
-                       glue_startStopReadingRecs(static_cast<SampleChannel*>(ch), false);
+               else {
+                       SampleChannel* sch = static_cast<SampleChannel*>(ch);
+                       if (pure == sch->midiInPitch) {
+                               float vf = (value >> 8)/(127/4.0f); // [0-127] ~> [0.0-4.0]
+                               gu_log("  >>> pitch ch=%d (pure=0x%X, value=%d, float=%f)\n",
+                                       sch->index, pure, value >> 8, vf);
+                               glue_setPitch(sch, vf);
+                       }
+                       else 
+                       if (pure == sch->midiInReadActions) {
+                               gu_log("  >>> toggle read actions ch=%d (pure=0x%X)\n", sch->index, pure);
+                               glue_toggleReadingRecs(sch, false);
+                       }
                }
 
 #ifdef WITH_VST
     processPlugins(ch, pure, value); // Process plugins' parameters
 #endif
 
-               /* Redirect full midi message (pure + value) to plugins */
+               /* Redirect full midi message (pure + value) to plugins. */
+
                ch->receiveMidi(pure | value);
        }
 }
@@ -208,38 +219,37 @@ void processMaster(uint32_t pure, uint32_t value)
 /* -------------------------------------------------------------------------- */
 
 
-static void callback(double t, std::vector<unsigned char> *msg, void *data)
+static void callback(double t, std::vector<unsigned char>* msg, void* data)
 {
-  /* 0.8.0 - for now we handle other midi signals (common and real-time
-        * messages) as unknown, for debugging purposes */
+  /* 0.8.0 - for now we handle other MIDI signals (common and real-time 
+  messages) as unknown, for debugging purposes. */
 
        if (msg->size() < 3) {
-               gu_log("[KM] MIDI received - unknown signal - size=%d, value=0x", (int) msg->size());
-               for (unsigned i=0; i<msg->size(); i++)
-                       gu_log("%X", (int) msg->at(i));
-               gu_log("\n");
+               //gu_log("[KM] MIDI received - unknown signal - size=%d, value=0x", (int) msg->size());
+               //for (unsigned i=0; i<msg->size(); i++)
+               //      gu_log("%X", (int) msg->at(i));
+               //gu_log("\n");
                return;
        }
 
-       /* in this place we want to catch two things: a) note on/note off
-        * from a keyboard and b) knob/wheel/slider movements from a
-        * controller */
+       /* Here we want to catch two things: a) note on/note off from a keyboard and 
+       b) knob/wheel/slider movements from a controller. */
 
        uint32_t input = getIValue(msg->at(0), msg->at(1), msg->at(2));
        uint32_t chan  = input & 0x0F000000;
        uint32_t value = input & 0x0000FF00;
        uint32_t pure  = 0x00;
        if (!conf::noNoteOff)
-               pure = input & 0xFFFF0000;   // input without 'value' byte
+               pure = input & 0xFFFF0000;   // input without 'value' (i.e. velocity) byte
        else
-               pure = input & 0xFFFFFF00;   // input with 'value' byte
+               pure = input & 0xFFFFFF00;   // input with 'value' (i.e. velocity) byte
 
        gu_log("[KM] MIDI received - 0x%X (chan %d)\n", input, chan >> 24);
 
-       /* start dispatcher. If midi learn is on don't parse channels, just
-        * learn incoming midi signal. Otherwise process master events first,
-        * then each channel in the stack. This way incoming signals don't
-        * get processed by glue_* when midi learning is on. */
+       /* Start dispatcher. If midi learn is on don't parse channels, just learn 
+       incoming MIDI signal. Otherwise process master events first, then each channel 
+       in the stack. This way incoming signals don't get processed by glue_* when 
+       MIDI learning is on. */
 
        if (cb_learn)
                cb_learn(pure, cb_data);
index feec2b1a55b292208142cbae54b4fc99e3e00cac..8b2cd56b73ac5353177109dab65944c3c2f58a8e 100644 (file)
@@ -49,12 +49,12 @@ public:
   bool    midiOut;           // enable midi output
   uint8_t midiOutChan;       // midi output channel
 
-       void copy(const Channel *src, pthread_mutex_t *pluginMutex) override;
+       void copy(const Channel* src, pthread_mutex_t* pluginMutex) override;
        void clear() override;
-       void process(float *outBuffer, float *inBuffer) override;
-       void preview(float *outBuffer) override;
+       void process(floatoutBuffer, float *inBuffer) override;
+       void preview(floatoutBuffer) override;
        void start(int frame, bool doQuantize, int quantize, bool mixerIsRunning,
-                 bool forceStart, bool isUserGenerated) override;
+               bool forceStart, bool isUserGenerated) override;
        void kill(int frame) override;
        void empty() override;
        void stopBySeq(bool chansStopOnSeqHalt) override;
@@ -62,23 +62,21 @@ public:
        void rewind() override;
        void setMute(bool internal) override;
        void unsetMute(bool internal) override;
-       int readPatch(const std::string &basePath, int i, pthread_mutex_t *pluginMutex,
+       int readPatch(const std::string& basePath, int i, pthread_mutex_t* pluginMutex,
     int samplerate, int rsmpQuality) override;
        int writePatch(int i, bool isProject) override;
        void quantize(int index, int localFrame) override;
        void onZero(int frame, bool recsStopOnChanHalt) override;
        void onBar(int frame) override;
-       void parseAction(giada::m::recorder::action *a, int localFrame, int globalFrame,
-                       int quantize, bool mixerIsRunning) override;
+       void parseAction(giada::m::recorder::actiona, int localFrame, int globalFrame,
+               int quantize, bool mixerIsRunning) override;
        void receiveMidi(uint32_t msg) override;
        bool canInputRec() override;
 
-       /* ------------------------------------------------------------------------ */
-
        /* sendMidi
         * send Midi event to the outside world. */
 
-       void sendMidi(giada::m::recorder::action *a, int localFrame);
+       void sendMidi(giada::m::recorder::actiona, int localFrame);
        void sendMidi(uint32_t data);
 
 #ifdef WITH_VST
index e86595ddbae2d30e56aec77c7de9cbcc4925d8f2..350769a758e3a8b575c543ea14299f27f2deb337 100644 (file)
@@ -542,7 +542,7 @@ void mergeVirtualInput()
                if (channels.at(i)->type == CHANNEL_MIDI)
                        continue;
                SampleChannel *ch = static_cast<SampleChannel*>(channels.at(i));
-               if (ch->armed)
+               if (ch->isArmed())
                        memcpy(ch->wave->getData(), vChanInput, clock::getTotalFrames() * sizeof(float));
        }
        memset(vChanInput, 0, clock::getTotalFrames() * sizeof(float)); // clear vchan
index 623ed27f64f0cd3d7b582ff00d590198623de527..40220a733f8541f609ffc75eadba25cdd82c5467 100644 (file)
@@ -64,7 +64,7 @@ namespace
 {
 #ifdef WITH_VST
 
-int readPatchPlugins(vector<patch::plugin_t> *list, int type)
+int readPatchPlugins(vector<patch::plugin_t>list, int type)
 {
        int ret = 1;
        for (unsigned i=0; i<list->size(); i++) {
@@ -115,15 +115,13 @@ int getNewChanIndex()
 /* -------------------------------------------------------------------------- */
 
 
-bool uniqueSampleName(SampleChannel* ch, const string& name)
+bool uniqueSamplePath(const SampleChannel* skip, const string& path)
 {
-       for (unsigned i=0; i<mixer::channels.size(); i++) {
-               if (ch == mixer::channels.at(i))  // skip itself
-                       continue;
-               if (mixer::channels.at(i)->type != CHANNEL_SAMPLE)
+       for (const Channel* ch : mixer::channels) {
+               if (skip == ch || ch->type != CHANNEL_SAMPLE) // skip itself and MIDI channels
                        continue;
-               SampleChannel* other = (SampleChannel*) mixer::channels.at(i);
-               if (other->wave != nullptr && name == other->wave->getName())
+               const SampleChannel* sch = static_cast<const SampleChannel*>(ch);
+               if (sch->wave != nullptr && path == sch->wave->getPath())
                        return false;
        }
        return true;
@@ -330,19 +328,12 @@ bool startInputRec()
                        continue;
                }
 
-               ch->pushWave(wave, false);  // false: don't generate name, we provide it
-
-               /* Increase lastTakeId until the sample name TAKE-[n] is unique. */
-
-               while (!uniqueSampleName(ch, ch->wave->getName())) {
-                       patch::lastTakeId++;
-                       ch->wave->setName("TAKE-" + gu_toString(patch::lastTakeId));
-               }
+               ch->pushWave(wave);
+               ch->setName("TAKE-" + gu_toString(patch::lastTakeId++)); // Increase lastTakeId 
+               channelsReady++;
 
                gu_log("[startInputRec] start input recs using chan %d with size %d "
                        "frame=%d\n", ch->index, clock::getTotalFrames(), mixer::inputTracker);
-
-               channelsReady++;
        }
 
        if (channelsReady > 0) {
@@ -375,7 +366,7 @@ bool hasArmedSampleChannels()
 {
        for (unsigned i=0; i<mixer::channels.size(); i++) {
                Channel *ch = mixer::channels.at(i);
-               if (ch->type == CHANNEL_SAMPLE && ch->armed)
+               if (ch->type == CHANNEL_SAMPLE && ch->isArmed())
                        return true;
        }
        return false;
index 362c346634a3fc06eec7c0063828b27f18188e5e..18b02831a6a7c758fadb73844c3f5325ce760aa0 100644 (file)
@@ -43,17 +43,17 @@ namespace mh
 /* addChannel
 Adds a new channel of type 'type' into mixer's stack. */
 
-Channel *addChannel(int type);
+ChanneladdChannel(int type);
 
 /* deleteChannel
 Completely removes a channel from the stack. */
 
-int deleteChannel(Channel *ch);
+int deleteChannel(Channelch);
 
 /* getChannelByIndex
 Returns channel with given index 'i'. */
 
-Channel *getChannelByIndex(int i);
+ChannelgetChannelByIndex(int i);
 
 /* hasLogicalSamples
 True if 1 or more samples are logical (memory only, such as takes) */
@@ -66,8 +66,7 @@ True if 1 or more samples was edited via gEditor */
 bool hasEditedSamples();
 
 /* stopSequencer
- * stop the sequencer, with special case if samplesStopOnSeqHalt is
- * true. */
+Stops the sequencer, with special case if samplesStopOnSeqHalt is true. */
 
 void stopSequencer();
 
@@ -76,28 +75,27 @@ void rewindSequencer();
 /* uniqueSolo
  * true if ch is the only solo'd channel in mixer. */
 
-bool uniqueSolo(Channel *ch);
+bool uniqueSolo(Channelch);
 
 /* loadPatch
- * load a path or a project (if isProject) into Mixer. If isProject, path
- * must contain the address of the project folder. */
+Loads a path or a project (if isProject) into Mixer. If isProject, path must 
+contain the address of the project folder. */
 
 void readPatch();
 
 /* startInputRec - record from line in
- * creates a new empty wave in the first available channels and returns
- * the chan number chosen, otherwise -1 if there are no more empty
- * channels available. */
+Creates a new empty wave in the first available channels. Returns false if
+something went wrong. */
 
 bool startInputRec();
 
 void stopInputRec();
 
-/* uniqueSamplename
- * return true if samplename 'n' is unique. Requires SampleChannel *ch
- * in order to skip check against itself. */
+/* uniqueSamplePath
+Returns true if path 'p' is unique. Requires SampleChannel 'skip' in order
+to skip check against itself. */
 
-bool uniqueSampleName(SampleChannel *ch, const std::string &s);
+bool uniqueSamplePath(const SampleChannel* skip, const std::string& p);
 
 /* hasArmedSampleChannels
 Tells whether Mixer has one or more sample channels armed for input
index 495134df5289d2c4eff9def28d88021207e22950..b70ea9e3877b99850f213373b57e1bcac2786bd4 100644 (file)
@@ -208,6 +208,7 @@ bool readChannels(json_t* jContainer)
     if (!storager::setInt   (jChannel, PATCH_KEY_CHANNEL_TYPE,                 channel.type)) return 0;
     if (!storager::setInt   (jChannel, PATCH_KEY_CHANNEL_INDEX,                channel.index)) return 0;
     if (!storager::setInt   (jChannel, PATCH_KEY_CHANNEL_SIZE,                 channel.size)) return 0;
+    if (!storager::setString(jChannel, PATCH_KEY_CHANNEL_NAME,                 channel.name)) return 0;
     if (!storager::setInt   (jChannel, PATCH_KEY_CHANNEL_COLUMN,               channel.column)) return 0;
     if (!storager::setInt   (jChannel, PATCH_KEY_CHANNEL_MUTE,                 channel.mute)) return 0;
     if (!storager::setInt   (jChannel, PATCH_KEY_CHANNEL_MUTE_S,               channel.mute_s)) return 0;
@@ -239,6 +240,7 @@ bool readChannels(json_t* jContainer)
     if (!storager::setUint32(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_PITCH,        channel.midiInPitch)) return 0;
     if (!storager::setUint32(jChannel, PATCH_KEY_CHANNEL_MIDI_OUT,             channel.midiOut)) return 0;
     if (!storager::setUint32(jChannel, PATCH_KEY_CHANNEL_MIDI_OUT_CHAN,        channel.midiOutChan)) return 0;
+    if (!storager::setBool  (jChannel, PATCH_KEY_CHANNEL_ARMED,                channel.armed)) return 0;
 
     readActions(jChannel, &channel);
 
@@ -383,6 +385,7 @@ void writeChannels(json_t* jContainer, vector<channel_t>* channels)
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_TYPE,                 json_integer(channel.type));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_INDEX,                json_integer(channel.index));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_SIZE,                 json_integer(channel.size));
+    json_object_set_new(jChannel, PATCH_KEY_CHANNEL_NAME,                 json_string(channel.name.c_str()));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_COLUMN,               json_integer(channel.column));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MUTE,                 json_integer(channel.mute));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MUTE_S,               json_integer(channel.mute_s));
@@ -414,6 +417,7 @@ void writeChannels(json_t* jContainer, vector<channel_t>* channels)
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_IN_PITCH,        json_integer(channel.midiInPitch));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_OUT,             json_integer(channel.midiOut));
     json_object_set_new(jChannel, PATCH_KEY_CHANNEL_MIDI_OUT_CHAN,        json_integer(channel.midiOutChan));
+    json_object_set_new(jChannel, PATCH_KEY_CHANNEL_ARMED,                json_boolean(channel.armed));
     json_array_append_new(jChannels, jChannel);
 
     writeActions(jChannel, &channel.actions);
index 7018dbaeeca07c01ea1e212e1af75bb1abed2824..bfc757eded016d0e7d67ef88abaf66e941fa652b 100644 (file)
@@ -65,6 +65,7 @@ struct channel_t
        int         type;
        int         index;
        int         size;
+       std::string name;
        int         column;
        int         mute;
        int         mute_s;
@@ -83,6 +84,7 @@ struct channel_t
        uint32_t    midiOutLplaying;
        uint32_t    midiOutLmute;
        uint32_t    midiOutLsolo;
+       bool        armed;
        // sample channel
        std::string samplePath;
        int         key;
index 83361f9fe8d24a89c3d6f61e46418d951d9de0b3..ce2b58e9936b37a236c525fb4a99fdb19fac37ea 100644 (file)
@@ -46,21 +46,21 @@ int Plugin::idGenerator = 1;
 
 
 Plugin::Plugin(juce::AudioPluginInstance *plugin, double samplerate,
-  int buffersize)
-  : ui    (nullptr),
-    plugin(plugin),
-    id    (idGenerator++),
-    bypass(false)
+       int buffersize)
+       : ui    (nullptr),
+               plugin(plugin),
+               id    (idGenerator++),
+               bypass(false)
 {
-  /* Init midiInParams. All values are empty (0x0): they will be filled during
-  midi learning process. */
+       /* Init midiInParams. All values are empty (0x0): they will be filled during
+       midi learning process. */
 
-  for (int i=0; i<plugin->getNumParameters(); i++)
-    midiInParams.push_back(0x0);
-  
-  plugin->prepareToPlay(samplerate, buffersize);
+       for (int i=0; i<plugin->getNumParameters(); i++)
+               midiInParams.push_back(0x0);
+       
+       plugin->prepareToPlay(samplerate, buffersize);
 
-  gu_log("[Plugin] plugin initialized and ready\n");
+       gu_log("[Plugin] plugin initialized and ready\n");
 }
 
 
@@ -70,8 +70,8 @@ Plugin::Plugin(juce::AudioPluginInstance *plugin, double samplerate,
 Plugin::~Plugin()
 {
        closeEditor();
-  plugin->suspendProcessing(true);
-  plugin->releaseResources();
+       plugin->suspendProcessing(true);
+       plugin->releaseResources();
 }
 
 
@@ -80,174 +80,205 @@ Plugin::~Plugin()
 
 void Plugin::showEditor(void* parent)
 {
-  ui = plugin->createEditorIfNeeded();
-  if (ui == nullptr) {
-    gu_log("[Plugin::showEditor] unable to create editor!\n");
-    return;
-  }
+       ui = plugin->createEditorIfNeeded();
+       if (ui == nullptr) {
+               gu_log("[Plugin::showEditor] unable to create editor!\n");
+               return;
+       }
 
-  /* A silly workaround on X: it seems that calling addToDesktop too fast, i.e.
-  before the X Window is fully ready screws up the plugin's event dispatcher. */
+       /* A silly workaround on X: it seems that calling addToDesktop too fast, i.e.
+       before the X Window is fully ready screws up the plugin's event dispatcher. */
 
 #ifdef G_OS_LINUX
-  time::sleep(500);
+       time::sleep(500);
 #endif
 
-  ui->setOpaque(true);
-  ui->addToDesktop(0, parent);
+       ui->setOpaque(true);
+       ui->addToDesktop(0, parent);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool Plugin::isEditorOpen()
+bool Plugin::isEditorOpen() const
 {
-  return ui != nullptr && ui->isVisible() && ui->isOnDesktop();
+       return ui != nullptr && ui->isVisible() && ui->isOnDesktop();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-string Plugin::getUniqueId()
+string Plugin::getUniqueId() const
 {
-  return plugin->getPluginDescription().fileOrIdentifier.toStdString();
+       //return plugin->getPluginDescription().fileOrIdentifier.toStdString();
+       return plugin->getPluginDescription().createIdentifierString().toStdString();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int Plugin::getNumParameters()
+int Plugin::getNumParameters() const
 {
-  return plugin->getNumParameters();
+       return plugin->getNumParameters();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-float Plugin::getParameter(int paramIndex)
+float Plugin::getParameter(int paramIndex) const
 {
-  return plugin->getParameter(paramIndex);
+       return plugin->getParameter(paramIndex);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void Plugin::setParameter(int paramIndex, float value)
+void Plugin::setParameter(int paramIndex, float value) const
 {
-  return plugin->setParameter(paramIndex, value);
+       return plugin->setParameter(paramIndex, value);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void Plugin::prepareToPlay(double samplerate, int buffersize)
+void Plugin::prepareToPlay(double samplerate, int buffersize) const
 {
-  plugin->prepareToPlay(samplerate, buffersize);
+       plugin->prepareToPlay(samplerate, buffersize);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-string Plugin::getName()
+string Plugin::getName() const
 {
-  return plugin->getName().toStdString();
+       return plugin->getName().toStdString();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool Plugin::isSuspended()
+bool Plugin::isSuspended() const
 {
-  return plugin->isSuspended();
+       return plugin->isSuspended();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void Plugin::process(juce::AudioBuffer<float> &b, juce::MidiBuffer &m)
+bool Plugin::acceptsMidi() const
 {
-  plugin->processBlock(b, m);
+       return plugin->acceptsMidi();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int Plugin::getNumPrograms()
+bool Plugin::isBypassed() const { return bypass; }
+void Plugin::toggleBypass() { bypass = !bypass; }
+void Plugin::setBypass(bool b) { bypass = b; }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int Plugin::getId() const { return id; }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int Plugin::getEditorW() const { return ui->getWidth(); }
+int Plugin::getEditorH() const { return ui->getHeight(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void Plugin::process(juce::AudioBuffer<float>& b, juce::MidiBuffer m) const
+{
+       plugin->processBlock(b, m);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int Plugin::getNumPrograms() const
 {
-  return plugin->getNumPrograms();
+       return plugin->getNumPrograms();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int Plugin::getCurrentProgram()
+int Plugin::getCurrentProgram() const
 {
-  return plugin->getCurrentProgram();
+       return plugin->getCurrentProgram();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void Plugin::setCurrentProgram(int index)
+void Plugin::setCurrentProgram(int index) const
 {
-  plugin->setCurrentProgram(index);
+       plugin->setCurrentProgram(index);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool Plugin::hasEditor()
+bool Plugin::hasEditor() const
 {
-  return plugin->hasEditor();
+       return plugin->hasEditor();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-string Plugin::getProgramName(int index)
+string Plugin::getProgramName(int index) const
 {
-  return plugin->getProgramName(index).toStdString();
+       return plugin->getProgramName(index).toStdString();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-string Plugin::getParameterName(int index)
+string Plugin::getParameterName(int index) const
 {
-  return plugin->getParameterName(index).toStdString();
+       return plugin->getParameterName(index).toStdString();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-string Plugin::getParameterText(int index)
+string Plugin::getParameterText(int index) const
 {
-  return plugin->getParameterText(index).toStdString();
+       return plugin->getParameterText(index).toStdString();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-string Plugin::getParameterLabel(int index)
+string Plugin::getParameterLabel(int index) const
 {
-  return plugin->getParameterLabel(index).toStdString();
+       return plugin->getParameterLabel(index).toStdString();
 }
 
 
@@ -256,10 +287,10 @@ string Plugin::getParameterLabel(int index)
 
 void Plugin::closeEditor()
 {
-  if (ui == nullptr)
-    return;
-  delete ui;
-  ui = nullptr;
+       if (ui == nullptr)
+               return;
+       delete ui;
+       ui = nullptr;
 }
 
 #endif
index 9a524738eba269ee7aaca854b6add66436a261ef..8091d8ea11ab4a42ac66afb42b3ca2a26d215c2c 100644 (file)
@@ -40,63 +40,68 @@ class Plugin
 {
 private:
 
-  static int idGenerator;
+       static int idGenerator;
 
-  juce::AudioProcessorEditor *ui;     // gui
-  juce::AudioPluginInstance  *plugin; // core
+       juce::AudioProcessorEditor* ui;    // gui
+       juce::AudioPluginInstance* plugin; // core
 
-  int  id;
-  bool bypass;
+       int id;
+       bool bypass;
 
 public:
 
-  Plugin(juce::AudioPluginInstance *p, double samplerate, int buffersize);
-  ~Plugin();
-
-  void showEditor(void *parent);
-
-  /* closeEditor
-   * Shut down plugin GUI. */
-
-  void closeEditor();
-
-  /* isEditorOpen */
-
-  bool isEditorOpen();
-
-  /* getUniqueId
-   * Return a string-based UID. */
-
-  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 isBypassed()      { return bypass; }
-  int  getEditorW()      { return ui->getWidth(); }
-  int  getEditorH()      { return ui->getHeight(); }
-  void toggleBypass()    { bypass = !bypass; }
-  void setBypass(bool b) { bypass = b; }
-
-  /* midiInParams
-  A list of midiIn hex values for parameter automation. */
-
-  std::vector<uint32_t> midiInParams;
+       Plugin(juce::AudioPluginInstance* p, double samplerate, int buffersize);
+       ~Plugin();
+
+       /* getUniqueId
+       Returns a string-based UID. */
+
+       std::string getUniqueId() const;
+
+       /* process
+       Process the plug-in with audio and MIDI data. The audio buffer is a reference:
+       it has to be altered by the plug-in itself. Conversely, the MIDI buffer must
+       be passed by copy: each plug-in must receive its own copy of the event set, so
+       that any attempt to change/clear the MIDI buffer will only modify the local 
+       copy. */
+
+       void process(juce::AudioBuffer<float>& b, juce::MidiBuffer m) const;
+
+       std::string getName() const;
+       bool isEditorOpen() const;
+       bool hasEditor() const;
+       int getNumParameters() const;
+       float getParameter(int index) const;
+       std::string getParameterName(int index) const;
+       std::string getParameterText(int index) const;
+       std::string getParameterLabel(int index) const;
+       bool isSuspended() const;
+       bool isBypassed() const;
+       int getNumPrograms() const;
+       int getCurrentProgram() const;
+       std::string getProgramName(int index) const;
+       int getId() const;
+       int getEditorW() const;
+       int getEditorH() const;
+       void setParameter(int index, float value) const;
+       void prepareToPlay(double samplerate, int buffersize) const;
+       void setCurrentProgram(int index) const;
+       bool acceptsMidi() const;
+
+       void showEditor(void* parent);
+
+       /* closeEditor
+       Shuts down plugin GUI. */
+
+       void closeEditor();
+
+       void toggleBypass();
+       void setBypass(bool b);
+
+       /* midiInParams
+       A list of midiIn hex values for parameter automation. */
+
+       std::vector<uint32_t> midiInParams;
 };
 
 #endif
index 188d41a303f19fd298c1089ce7f627ce3dfc2700..6ca000676b13ef9c869c74933c9a50c0b7ae3e32 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "../utils/log.h"
 #include "../utils/fs.h"
+#include "../utils/string.h"
 #include "const.h"
 #include "channel.h"
 #include "plugin.h"
@@ -46,7 +47,7 @@ namespace pluginHost
 {
 namespace
 {
-juce::MessageManager *messageManager;
+juce::MessageManagermessageManager;
 
 /* pluginFormat
  * Plugin format manager. */
@@ -61,10 +62,10 @@ juce::KnownPluginList knownPluginList;
 /* unknownPluginList
  * List of unrecognized plugins found in a patch. */
 
-std::vector<std::string> unknownPluginList;
+vector<string> unknownPluginList;
 
-std::vector<Plugin*> masterOut;
-std::vector<Plugin*> masterIn;
+vector<Plugin*> masterOut;
+vector<Plugin*> masterIn;
 
 /* Audio|MidiBuffer
  * Dynamic buffers. */
@@ -79,6 +80,49 @@ int buffersize;
 
 bool missingPlugins;
 
+void splitPluginDescription(const string& descr, vector<string>& out)
+{
+       // input:  VST-mda-Ambience-18fae2d2-6d646141  string
+       // output: [2-------------] [1-----] [0-----]  vector.size() == 3
+       
+       string chunk = "";
+       int count = 2;
+       for (int i=descr.length()-1; i >= 0; i--) {
+               if (descr[i] == '-' && count != 0) {
+                       out.push_back(chunk);
+                       count--;
+                       chunk = "";
+               }
+               else
+                       chunk += descr[i];
+       }
+       out.push_back(chunk);
+}
+
+
+/* findPluginDescription
+Browses the list of known plug-ins until plug-in with id == 'id' is found.
+Unfortunately knownPluginList.getTypeForIdentifierString(id) doesn't work for
+VSTs: their ID is based on the plug-in file location. E.g.:
+
+       /home/vst/mdaAmbience.so      -> VST-mdaAmbience-18fae2d2-6d646141
+       /home/vst-test/mdaAmbience.so -> VST-mdaAmbience-b328b2f6-6d646141
+
+The following function simply drops the first hash code during comparison. */
+
+const juce::PluginDescription* findPluginDescription(const string& id)
+{
+       vector<string> idParts;
+       splitPluginDescription(id, idParts);
+
+       for (const juce::PluginDescription* pd : knownPluginList) {
+               vector<string> tmpIdParts;
+               splitPluginDescription(pd->createIdentifierString().toStdString(), tmpIdParts);
+               if (idParts[0] == tmpIdParts[0] && idParts[2] == tmpIdParts[2])
+                       return pd;
+       }
+       return nullptr;
+}
 }; // {anonymous}
 
 
@@ -95,7 +139,7 @@ pthread_mutex_t mutex_midi;
 
 void close()
 {
-  messageManager->deleteInstance();
+       messageManager->deleteInstance();
 }
 
 
@@ -104,149 +148,150 @@ void close()
 
 void init(int _buffersize, int _samplerate)
 {
-  gu_log("[pluginHost::init] initialize with buffersize=%d, samplerate=%d\n",
-    _buffersize, _samplerate);
-
-  messageManager = juce::MessageManager::getInstance();
-  audioBuffer.setSize(2, _buffersize);
-  samplerate = _samplerate;
-  buffersize = _buffersize;
-  missingPlugins = false;
-  //unknownPluginList.empty();
-  loadList(gu_getHomePath() + G_SLASH + "plugins.xml");
-
-  pthread_mutex_init(&mutex_midi, nullptr);
+       gu_log("[pluginHost::init] initialize with buffersize=%d, samplerate=%d\n",
+               _buffersize, _samplerate);
+
+       messageManager = juce::MessageManager::getInstance();
+       audioBuffer.setSize(2, _buffersize);
+       samplerate = _samplerate;
+       buffersize = _buffersize;
+       missingPlugins = false;
+       //unknownPluginList.empty();
+       loadList(gu_getHomePath() + G_SLASH + "plugins.xml");
+
+       pthread_mutex_init(&mutex_midi, nullptr);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int scanDir(const string &dirpath, void (*callback)(float progress, void *p),
-    void *p)
+int scanDir(const string& dirpath, void (*callback)(float progress, void* p),
+               void* p)
 {
-  gu_log("[pluginHost::scanDir] requested directory: '%s'\n", dirpath.c_str());
-  gu_log("[pluginHost::scanDir] current plugins: %d\n", knownPluginList.getNumTypes());
-
-  knownPluginList.clear();   // clear up previous plugins
-
-  juce::VSTPluginFormat format;
-  juce::FileSearchPath path(dirpath);
-  juce::PluginDirectoryScanner scanner(knownPluginList, format, path,
-      true, juce::File::nonexistent); // true: recursive
-
-  bool cont = true;
-  juce::String name;
-  while (cont) {
-    gu_log("[pluginHost::scanDir]   scanning '%s'\n", name.toRawUTF8());
-    cont = scanner.scanNextFile(false, name);
-    if (callback)
-      callback(scanner.getProgress(), p);
-  }
-
-  gu_log("[pluginHost::scanDir] %d plugin(s) found\n", knownPluginList.getNumTypes());
-  return knownPluginList.getNumTypes();
+       gu_log("[pluginHost::scanDir] requested directory: '%s'\n", dirpath.c_str());
+       gu_log("[pluginHost::scanDir] current plugins: %d\n", knownPluginList.getNumTypes());
+
+       knownPluginList.clear();   // clear up previous plugins
+
+       juce::VSTPluginFormat format;
+       juce::FileSearchPath path(dirpath);
+       juce::PluginDirectoryScanner scanner(knownPluginList, format, path,
+                       true, juce::File::nonexistent); // true: recursive
+
+       bool cont = true;
+       juce::String name;
+       while (cont) {
+               gu_log("[pluginHost::scanDir]   scanning '%s'\n", name.toRawUTF8());
+               cont = scanner.scanNextFile(false, name);
+               if (callback)
+                       callback(scanner.getProgress(), p);
+       }
+
+       gu_log("[pluginHost::scanDir] %d plugin(s) found\n", knownPluginList.getNumTypes());
+       return knownPluginList.getNumTypes();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int saveList(const string &filepath)
+int saveList(const stringfilepath)
 {
-  int out = knownPluginList.createXml()->writeToFile(juce::File(filepath), "");
-  if (!out)
-    gu_log("[pluginHost::saveList] unable to save plugin list to %s\n", filepath.c_str());
-  return out;
+       int out = knownPluginList.createXml()->writeToFile(juce::File(filepath), "");
+       if (!out)
+               gu_log("[pluginHost::saveList] unable to save plugin list to %s\n", filepath.c_str());
+       return out;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int loadList(const string &filepath)
+int loadList(const stringfilepath)
 {
-  juce::XmlElement *elem = juce::XmlDocument::parse(juce::File(filepath));
-  if (elem) {
-    knownPluginList.recreateFromXml(*elem);
-    delete elem;
-    return 1;
-  }
-  return 0;
+       juce::XmlElement* elem = juce::XmlDocument::parse(juce::File(filepath));
+       if (elem) {
+               knownPluginList.recreateFromXml(*elem);
+               delete elem;
+               return 1;
+       }
+       return 0;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-Plugin *addPlugin(const string &fid, int stackType,
-  pthread_mutex_t *mutex, Channel *ch)
+Plugin* addPlugin(const string& fid, int stackType, pthread_mutex_t* mutex, 
+       Channel* ch)
 {
-  /* Get the proper stack to add the plugin to */
-
-  vector <Plugin *> *pStack;
-       pStack = getStack(stackType, ch);
-
-  /* Initialize plugin */
-
-  juce::PluginDescription *pd = knownPluginList.getTypeForFile(fid);
-  if (!pd) {
-    gu_log("[pluginHost::addPlugin] no plugin found with fid=%s!\n", fid.c_str());
-    missingPlugins = true;
-    unknownPluginList.push_back(fid);
-    return nullptr;
-  }
+       vector<Plugin*>* pStack = getStack(stackType, ch);
+
+       /* Initialize plugin. The default mode uses getTypeForIdentifierString, 
+       falling back to  getTypeForFile (deprecated) for old patches (< 0.14.4). */
+
+       const juce::PluginDescription* pd = findPluginDescription(fid);
+       if (pd == nullptr) {
+               gu_log("[pluginHost::addPlugin] no plugin found with fid=%s! Trying with "
+                       "deprecated mode...\n", fid.c_str());
+               pd = knownPluginList.getTypeForFile(fid);
+               if (pd == nullptr) {
+                       gu_log("[pluginHost::addPlugin] still nothing to do, returning unknown plugin\n");
+                       missingPlugins = true;
+                       unknownPluginList.push_back(fid);
+                       return nullptr;
+               }
+       }
 
-  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 nullptr;
-  }
-  gu_log("[pluginHost::addPlugin] plugin instance with fid=%s created\n", fid.c_str());
+       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 nullptr;
+       }
+       gu_log("[pluginHost::addPlugin] plugin instance with fid=%s created\n", fid.c_str());
 
-  Plugin *p = new Plugin(pi, samplerate, buffersize);
+       Plugin* p = new Plugin(pi, samplerate, buffersize);
 
-  /* Try to inject the plugin as soon as possible. */
+       /* Try to inject the plugin as soon as possible. */
 
-  while (true) {
-    if (pthread_mutex_trylock(mutex) != 0)
-      continue;
-    pStack->push_back(p);
-    pthread_mutex_unlock(mutex);
-    break;
-  }
+       while (true) {
+               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().c_str(), stackType, pStack->size());
+       gu_log("[pluginHost::addPlugin] plugin id=%s loaded (%s), stack type=%d, stack size=%d\n",
+               fid.c_str(), p->getName().c_str(), stackType, pStack->size());
 
-  return p;
+       return p;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-Plugin *addPlugin(int index, int stackType, pthread_mutex_t *mutex,
-  Channel *ch)
+Plugin* addPlugin(int index, int stackType, pthread_mutex_t* mutex,
+       Channel* ch)
 {
-  juce::PluginDescription *pd = knownPluginList.getType(index);
-  if (pd) {
-    gu_log("[pluginHost::addPlugin] plugin found, uid=%s, name=%s...\n",
-      pd->fileOrIdentifier.toStdString().c_str(), pd->name.toStdString().c_str());
-    return addPlugin(pd->fileOrIdentifier.toStdString(), stackType, mutex, ch);
-  }
-  else {
-    gu_log("[pluginHost::addPlugin] no plugins found at index=%d!\n", index);
-    return nullptr;
-  }
+       juce::PluginDescription* pd = knownPluginList.getType(index);
+       if (pd) {
+               gu_log("[pluginHost::addPlugin] plugin found, uid=%s, name=%s...\n",
+                       pd->createIdentifierString().toRawUTF8(), pd->name.toRawUTF8());
+               return addPlugin(pd->createIdentifierString().toStdString(), stackType, mutex, ch);
+       }
+       gu_log("[pluginHost::addPlugin] no plugins found at index=%d!\n", index);
+       return nullptr;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-vector <Plugin *> *getStack(int stackType, Channel *ch)
+vector<Plugin*>* getStack(int stackType, Channel* ch)
 {
        switch(stackType) {
                case MASTER_OUT:
@@ -264,9 +309,9 @@ vector <Plugin *> *getStack(int stackType, Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-unsigned countPlugins(int stackType, Channel *ch)
+unsigned countPlugins(int stackType, Channelch)
 {
-       vector <Plugin *> *pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
        return pStack->size();
 }
 
@@ -276,7 +321,7 @@ unsigned countPlugins(int stackType, Channel *ch)
 
 int countAvailablePlugins()
 {
-  return knownPluginList.getNumTypes();
+       return knownPluginList.getNumTypes();
 }
 
 
@@ -285,7 +330,7 @@ int countAvailablePlugins()
 
 unsigned countUnknownPlugins()
 {
-  return unknownPluginList.size();
+       return unknownPluginList.size();
 }
 
 
@@ -294,15 +339,15 @@ unsigned countUnknownPlugins()
 
 pluginHost::PluginInfo getAvailablePluginInfo(int i)
 {
-  juce::PluginDescription *pd = knownPluginList.getType(i);
-  PluginInfo pi;
-  pi.uid = pd->fileOrIdentifier.toStdString();
-  pi.name = pd->name.toStdString();
-  pi.category = pd->category.toStdString();
-  pi.manufacturerName = pd->manufacturerName.toStdString();
-  pi.format = pd->pluginFormatName.toStdString();
-  pi.isInstrument = pd->isInstrument;
-  return pi;
+       juce::PluginDescription* pd = knownPluginList.getType(i);
+       PluginInfo pi;
+       pi.uid = pd->fileOrIdentifier.toStdString();
+       pi.name = pd->name.toStdString();
+       pi.category = pd->category.toStdString();
+       pi.manufacturerName = pd->manufacturerName.toStdString();
+       pi.format = pd->pluginFormatName.toStdString();
+       pi.isInstrument = pd->isInstrument;
+       return pi;
 }
 
 
@@ -311,7 +356,7 @@ pluginHost::PluginInfo getAvailablePluginInfo(int i)
 
 bool hasMissingPlugins()
 {
-  return missingPlugins;
+       return missingPlugins;
 };
 
 
@@ -320,80 +365,100 @@ bool hasMissingPlugins()
 
 string getUnknownPluginInfo(int i)
 {
-  return unknownPluginList.at(i);
+       return unknownPluginList.at(i);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void freeStack(int stackType, pthread_mutex_t *mutex, Channel *ch)
+void freeStack(int stackType, pthread_mutex_t* mutex, Channel* ch)
 {
-       vector <Plugin *> *pStack;
-       pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
 
        if (pStack->size() == 0)
                return;
 
        while (true) {
                if (pthread_mutex_trylock(mutex) != 0)
-      continue;
+                       continue;
                for (unsigned i=0; i<pStack->size(); i++)
-      delete pStack->at(i);
+                       delete pStack->at(i);
                pStack->clear();
                pthread_mutex_unlock(mutex);
                break;
        }
-  gu_log("[pluginHost::freeStack] stack type=%d freed\n", stackType);
+       gu_log("[pluginHost::freeStack] stack type=%d freed\n", stackType);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void processStack(float *buffer, int stackType, Channel *ch)
+void processStack(float* buffer, int stackType, Channel* ch)
 {
-       vector <Plugin *> *pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
 
-       /* empty stack, stack not found or mixer not ready: do nothing */
+       /* Empty stack, stack not found or mixer not ready: do nothing. */
 
        if (pStack == nullptr || pStack->size() == 0)
                return;
 
-       /* converting buffer from Giada to Juce */
+       /* MIDI channels must not process the current buffer: give them an empty one. 
+       Sample channels and Master in/out want audio data instead: let's convert the 
+       internal buffer from Giada to Juce. */
 
-       for (int i=0; i<buffersize; i++) {
-    audioBuffer.setSample(0, i, buffer[i*2]);
-    audioBuffer.setSample(1, i, buffer[(i*2)+1]);
-       }
+       if (ch != nullptr && ch->type == CHANNEL_MIDI) 
+               audioBuffer.clear();
+       else
+               for (int i=0; i<buffersize; i++) {
+                       audioBuffer.setSample(0, i, buffer[i*2]);
+                       audioBuffer.setSample(1, i, buffer[(i*2)+1]);
+               }
 
        /* Hardcore processing. At the end we swap input and output, so that he N-th
-  plugin will process the result of the plugin N-1. Part of this loop must be
-  guarded by mutexes, i.e. the MIDI process part. You definitely don't want
-  a situation like the following one:
-    processBlock(...)
-    [a new midi event from kernelMidi thread]
-    clearMidiBuffer()
-  The midi event in between would be surely lost, deleted by clearMidiBuffer! */
-
-       for (unsigned i=0; i<pStack->size(); i++) {
-    Plugin *plugin = pStack->at(i);
+       plugin will process the result of the plugin N-1. Part of this loop must be
+       guarded by mutexes, i.e. the MIDI process part. You definitely don't want
+       a situation like the following one:
+               this::processStack()
+               [a new midi event comes in from kernelMidi thread]
+               channel::clearMidiBuffer()
+       The midi event in between would be surely lost, deleted by the last call to
+       channel::clearMidiBuffer()! */
+
+       if (ch != nullptr)
+               pthread_mutex_lock(&mutex_midi);
+
+       for (const Plugin* plugin : *pStack) {
                if (plugin->isSuspended() || plugin->isBypassed())
                        continue;
-    if (ch) { // ch might be null if stackType is MASTER_IN/OUT
-      pthread_mutex_lock(&mutex_midi);
-      plugin->process(audioBuffer, ch->getPluginMidiEvents());
-      ch->clearMidiBuffer();
-      pthread_mutex_unlock(&mutex_midi);
-    }
-    else {
-      juce::MidiBuffer midiBuffer;  // empty buffer
-      plugin->process(audioBuffer, midiBuffer);
-    }
-  }
-
-       /* converting buffer from Juce to Giada. A note for the future: if we
-        * overwrite (=) (as we do now) it's SEND, if we add (+) it's INSERT. */
+
+               /* If this is a Channel (ch != nullptr) and the current plugin is an 
+               instrument (i.e. accepts MIDI), don't let it fill the current audio buffer: 
+               create a new temporary one instead and then merge the result into the main
+               one when done. This way each plug-in generates its own audio data and we can
+               play more than one plug-in instrument in the same stack, driven by the same
+               set of MIDI events. */
+
+               if (ch != nullptr && plugin->acceptsMidi()) {
+                       juce::AudioBuffer<float> tmp(2, buffersize);
+                       plugin->process(tmp, ch->getPluginMidiEvents());
+                       for (int i=0; i<buffersize; i++) {
+                               audioBuffer.addSample(0, i, tmp.getSample(0, i));
+                               audioBuffer.addSample(1, i, tmp.getSample(1, i));
+                       }
+               }
+               else
+                       plugin->process(audioBuffer, juce::MidiBuffer()); // Empty MIDI buffer
+       }
+
+       if (ch != nullptr) {
+               ch->clearMidiBuffer();
+               pthread_mutex_unlock(&mutex_midi);
+       }
+
+       /* Converting buffer from Juce to Giada. A note for the future: if we 
+       overwrite (=) (as we do now) it's SEND, if we add (+) it's INSERT. */
 
        for (int i=0; i<buffersize; i++) {
                buffer[i*2]     = audioBuffer.getSample(0, i);
@@ -405,9 +470,9 @@ void processStack(float *buffer, int stackType, Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-Plugin *getPluginByIndex(int index, int stackType, Channel *ch)
+Plugin* getPluginByIndex(int index, int stackType, Channel* ch)
 {
-       vector <Plugin *> *pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
        if (pStack->size() == 0)
                return nullptr;
        if ((unsigned) index >= pStack->size())
@@ -419,9 +484,9 @@ Plugin *getPluginByIndex(int index, int stackType, Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-int getPluginIndex(int id, int stackType, Channel *ch)
+int getPluginIndex(int id, int stackType, Channelch)
 {
-       vector <Plugin *> *pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
        for (unsigned i=0; i<pStack->size(); i++)
                if (pStack->at(i)->getId() == id)
                        return i;
@@ -433,12 +498,12 @@ int getPluginIndex(int id, int stackType, Channel *ch)
 
 
 void swapPlugin(unsigned indexA, unsigned indexB, int stackType,
-  pthread_mutex_t *mutex, Channel *ch)
+       pthread_mutex_t* mutex, Channel* ch)
 {
-       vector <Plugin *> *pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
        while (true) {
                if (pthread_mutex_trylock(mutex) != 0)
-      continue;
+                       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);
@@ -450,26 +515,25 @@ void swapPlugin(unsigned indexA, unsigned indexB, int stackType,
 /* -------------------------------------------------------------------------- */
 
 
-int freePlugin(int id, int stackType, pthread_mutex_t *mutex,
-  Channel *ch)
+int freePlugin(int id, int stackType, pthread_mutex_t* mutex, Channel* ch)
 {
-       vector <Plugin *> *pStack = getStack(stackType, ch);
+       vector<Plugin*>* pStack = getStack(stackType, ch);
        for (unsigned i=0; i<pStack->size(); i++) {
-    Plugin *pPlugin = pStack->at(i);
+               Plugin *pPlugin = pStack->at(i);
                if (pPlugin->getId() != id)
-      continue;
+                       continue;
                while (true) {
                        if (pthread_mutex_trylock(mutex) != 0)
-        continue;
+                               continue;
                        delete pPlugin;
                        pStack->erase(pStack->begin() + i);
                        pthread_mutex_unlock(mutex);
                        gu_log("[pluginHost::freePlugin] plugin id=%d removed\n", id);
                        return i;
                }
-  }
+       }
        gu_log("[pluginHost::freePlugin] plugin id=%d not found\n", id);
-  return -1;
+       return -1;
 }
 
 
@@ -478,32 +542,32 @@ int freePlugin(int id, int stackType, pthread_mutex_t *mutex,
 
 void runDispatchLoop()
 {
-  messageManager->runDispatchLoopUntil(10);
-  //gu_log("[pluginHost::runDispatchLoop] %d, hasStopMessageBeenSent=%d\n", r, messageManager->hasStopMessageBeenSent());
+       messageManager->runDispatchLoopUntil(10);
+       //gu_log("[pluginHost::runDispatchLoop] %d, hasStopMessageBeenSent=%d\n", r, messageManager->hasStopMessageBeenSent());
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void freeAllStacks(vector <Channel*> *channels, pthread_mutex_t *mutex)
+void freeAllStacks(vector<Channel*>* channels, pthread_mutex_t* mutex)
 {
        freeStack(pluginHost::MASTER_OUT, mutex);
        freeStack(pluginHost::MASTER_IN, mutex);
        for (unsigned i=0; i<channels->size(); i++)
                freeStack(pluginHost::CHANNEL, mutex, channels->at(i));
-  missingPlugins = false;
-  unknownPluginList.clear();
+       missingPlugins = false;
+       unknownPluginList.clear();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-int clonePlugin(Plugin *src, int stackType, pthread_mutex_t *mutex,
-  Channel *ch)
+int clonePlugin(Plugin* src, int stackType, pthread_mutex_t* mutex,
+       Channel* ch)
 {
-       Plugin *p = addPlugin(src->getUniqueId(), stackType, mutex, ch);
+       Pluginp = addPlugin(src->getUniqueId(), stackType, mutex, ch);
        if (!p) {
                gu_log("[pluginHost::clonePlugin] unable to add new plugin to stack!\n");
                return 0;
@@ -519,9 +583,9 @@ int clonePlugin(Plugin *src, int stackType, pthread_mutex_t *mutex,
 /* -------------------------------------------------------------------------- */
 
 
-bool doesPluginExist(const string &fid)
+bool doesPluginExist(const stringfid)
 {
-  return pluginFormat.doesPluginStillExist(*knownPluginList.getTypeForFile(fid));
+       return pluginFormat.doesPluginStillExist(*knownPluginList.getTypeForFile(fid));
 }
 
 
@@ -530,20 +594,20 @@ bool doesPluginExist(const string &fid)
 
 void sortPlugins(int method)
 {
-  switch (method) {
-    case sortMethod::NAME:
-      knownPluginList.sort(juce::KnownPluginList::SortMethod::sortAlphabetically, true);
-      break;
-    case sortMethod::CATEGORY:
-      knownPluginList.sort(juce::KnownPluginList::SortMethod::sortByCategory, true);
-      break;
-    case sortMethod::MANUFACTURER:
-      knownPluginList.sort(juce::KnownPluginList::SortMethod::sortByManufacturer, true);
-      break;
-    case sortMethod::FORMAT:
-      knownPluginList.sort(juce::KnownPluginList::SortMethod::sortByFormat, true);
-      break;
-  }
+       switch (method) {
+               case sortMethod::NAME:
+                       knownPluginList.sort(juce::KnownPluginList::SortMethod::sortAlphabetically, true);
+                       break;
+               case sortMethod::CATEGORY:
+                       knownPluginList.sort(juce::KnownPluginList::SortMethod::sortByCategory, true);
+                       break;
+               case sortMethod::MANUFACTURER:
+                       knownPluginList.sort(juce::KnownPluginList::SortMethod::sortByManufacturer, true);
+                       break;
+               case sortMethod::FORMAT:
+                       knownPluginList.sort(juce::KnownPluginList::SortMethod::sortByFormat, true);
+                       break;
+       }
 }
 
 }}}; // giada::m::pluginHost::
index 13ee170a6ef762bc5c8b4d5d0af33b96afa51be7..f36bf41715e2ca518f74783c88ed2f8ddcd6435b 100644 (file)
@@ -76,14 +76,14 @@ void close();
  * called on each plugin found. Used to update the main window from the GUI
  * thread. */
 
-int scanDir(const std::string &path, void (*callback)(float progress, void *p)=nullptr,
-    void *p=nullptr);
+int scanDir(const std::string& path, void (*callback)(float progress, void* p)=nullptr,
+    voidp=nullptr);
 
 /* (save|load)List
  * (Save|Load) knownPluginList (in|from) an XML file. */
 
-int saveList(const std::string &path);
-int loadList(const std::string &path);
+int saveList(const std::stringpath);
+int loadList(const std::stringpath);
 
 /* addPlugin
  * Add a new plugin to 'stackType' by unique id or by index in knownPluginList
@@ -95,15 +95,15 @@ int loadList(const std::string &path);
  * bufSize - buffer size
  * ch - if stackType == CHANNEL. */
 
-Plugin *addPlugin(const std::string &fid, int stackType, pthread_mutex_t *mutex,
-  Channel *ch=nullptr);
-Plugin *addPlugin(int index, int stackType, pthread_mutex_t *mutex,
-  Channel *ch=nullptr);
+Plugin* addPlugin(const std::string& fid, int stackType, pthread_mutex_t* mutex,
+  Channelch=nullptr);
+Plugin *addPlugin(int index, int stackType, pthread_mutex_tmutex,
+  Channelch=nullptr);
 
 /* countPlugins
  * Return size of 'stackType'. */
 
-unsigned countPlugins(int stackType, Channel *ch=nullptr);
+unsigned countPlugins(int stackType, Channelch=nullptr);
 
 /* countAvailablePlugins
  * Return size of knownPluginList. */
@@ -126,37 +126,37 @@ std::string getUnknownPluginInfo(int index);
 /* freeStack
  * free plugin stack of type 'stackType'. */
 
-void freeStack(int stackType, pthread_mutex_t *mutex, Channel *ch=nullptr);
+void freeStack(int stackType, pthread_mutex_t* mutex, Channel* ch=nullptr);
 
 /* processStack
  * apply the fx list to the buffer. */
 
-void processStack(float *buffer, int stackType, Channel *ch=nullptr);
+void processStack(float* buffer, int stackType, Channel* ch=nullptr);
 
 /* getStack
 * Return a std::vector <Plugin *> given the stackType. If stackType == CHANNEL
 * a pointer to Channel is also required. */
 
-std::vector <Plugin *> *getStack(int stackType, Channel *ch=nullptr);
+std::vector<Plugin*>* getStack(int stackType, Channel* ch=nullptr);
 
 /* getPluginByIndex */
 
-Plugin *getPluginByIndex(int index, int stackType, Channel *ch=nullptr);
+Plugin* getPluginByIndex(int index, int stackType, Channel* ch=nullptr);
 
 /* getPluginIndex */
 
-int getPluginIndex(int id, int stackType, Channel *ch=nullptr);
+int getPluginIndex(int id, int stackType, Channelch=nullptr);
 
 /* swapPlugin */
 
 void swapPlugin(unsigned indexA, unsigned indexB, int stackType,
-  pthread_mutex_t *mutex, Channel *ch=nullptr);
+  pthread_mutex_t* mutex, Channel* ch=nullptr);
 
 /* freePlugin.
 Returns the internal stack index of the deleted plugin. */
 
 int freePlugin(int id, int stackType, pthread_mutex_t *mutex,
-  Channel *ch=nullptr);
+  Channelch=nullptr);
 
 /* runDispatchLoop
  * Wakes up plugins' GUI manager for N milliseconds. */
@@ -166,16 +166,15 @@ void runDispatchLoop();
 /* freeAllStacks
  * Frees everything. */
 
-void freeAllStacks(std::vector <Channel*> *channels, pthread_mutex_t *mutex);
+void freeAllStacks(std::vector<Channel*>* channels, pthread_mutex_t* mutex);
 
 /* clonePlugin */
 
-int clonePlugin(Plugin *src, int stackType, pthread_mutex_t *mutex,
-  Channel *ch);
-
+int clonePlugin(Plugin* src, int stackType, pthread_mutex_t* mutex, Channel* ch);
 /* doesPluginExist */
 
-bool doesPluginExist(const std::string &fid);
+bool doesPluginExist(const std::stringfid);
 
 bool hasMissingPlugins();
 
index 6ffdd805a2f4627b6d279123f22c3b77f46ba050..38dad90975272a3850cb37340e113165d3a4e9bb 100644 (file)
@@ -61,6 +61,7 @@ SampleChannel::SampleChannel(int bufferSize, bool inputMonitor)
                boost            (G_DEFAULT_BOOST),
                pitch            (G_DEFAULT_PITCH),
                trackerPreview   (0),
+               shift            (0),
                wave             (nullptr),
                tracker          (0),
                mode             (G_DEFAULT_CHANMODE),
@@ -155,23 +156,9 @@ void SampleChannel::copy(const Channel* _src, pthread_mutex_t* pluginMutex)
 /* -------------------------------------------------------------------------- */
 
 
-void SampleChannel::generateUniqueSampleName()
-{
-       string oldName = wave->getName();
-       int k = 0;
-       while (!mh::uniqueSampleName(this, wave->getName())) {
-               wave->setName(oldName + "-" + gu_toString(k));
-               k++;
-       }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
 void SampleChannel::clear()
 {
-       /** TODO - these memsets can be done only if status PLAY (if below),
+       /** TODO - these memsets may be done only if status PLAY (if below),
         * but it would require extra clearPChan calls when samples stop */
 
        std::memset(vChan, 0, sizeof(float) * bufferSize);
@@ -261,15 +248,6 @@ void SampleChannel::onBar(int frame)
 /* -------------------------------------------------------------------------- */
 
 
-int SampleChannel::save(const char* path)
-{
-       return waveManager::save(wave, path);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
 void SampleChannel::setBegin(int f)
 {
        /* TODO - Opaque channel's count - everything in SampleChannel should be
@@ -357,6 +335,13 @@ int SampleChannel::getTrackerPreview() const
 /* -------------------------------------------------------------------------- */
 
 
+int SampleChannel::getShift() const { return shift; }
+void SampleChannel::setShift(int s) { shift = s; }
+
+
+/* -------------------------------------------------------------------------- */
+
+
 void SampleChannel::setPitch(float v)
 {
        if (v > G_MAX_PITCH)
@@ -852,15 +837,14 @@ void SampleChannel::empty()
 /* -------------------------------------------------------------------------- */
 
 
-void SampleChannel::pushWave(Wave* w, bool generateName)
+void SampleChannel::pushWave(Wave* w)
 {
        sendMidiLplay();     // FIXME - why here?!?!
        wave   = w;
        status = STATUS_OFF;
        begin  = 0;
        end    = (wave->getSize() - 1) * wave->getChannels(); // TODO - Opaque channels' count
-       if (generateName)
-               generateUniqueSampleName();
+       name   = wave->getBasename();
 }
 
 
@@ -990,15 +974,15 @@ void SampleChannel::stop()
 /* -------------------------------------------------------------------------- */
 
 
-int SampleChannel::readPatch(const string &basePath, int i,
-               pthread_mutex_t *pluginMutex, int samplerate, int rsmpQuality)
+int SampleChannel::readPatch(const stringbasePath, int i,
+               pthread_mutex_tpluginMutex, int samplerate, int rsmpQuality)
 {
        /* load channel's data first: if the sample is missing or wrong, the channel
         * is not completely blank. */
 
        Channel::readPatch("", i, pluginMutex, samplerate, rsmpQuality);
 
-       patch::channel_t *pch = &patch::channels.at(i);
+       const patch::channel_t* pch = &patch::channels.at(i);
 
        mode              = pch->mode;
        boost             = pch->boost;
@@ -1008,13 +992,14 @@ int SampleChannel::readPatch(const string &basePath, int i,
        midiInPitch       = pch->midiInPitch;
   inputMonitor      = pch->inputMonitor;
 
-  Wave *w = nullptr;
+  Wavew = nullptr;
   int res = waveManager::create(basePath + pch->samplePath, &w); 
 
        if (res == G_RES_OK) {
                pushWave(w);
+               setName(pch->name);
                setBegin(pch->begin);
-               setEnd  (pch->end);
+               setEnd(pch->end);
                setPitch(pch->pitch);
        }
        else {
index 8435dfe8ec9ef3c3d0edc0ab08c082829a9de586..783c9aea1c1bbb243b565445e5a5fecae7ac23bb 100644 (file)
@@ -42,6 +42,29 @@ class SampleChannel : public Channel
 {
 private:
 
+       /* fillChan
+       Fills 'dest' buffer at point 'offset' with wave data taken from 'start'. If 
+       rewind=false don't rewind internal tracker. Returns new sample position, 
+       in frames. It resamples data if pitch != 1.0f. */
+
+       int fillChan(float* dest, int start, int offset, bool rewind=true);
+
+       /* clearChan
+        * set data to zero from start to bufferSize-1. */
+
+       void clearChan(float* dest, int start);
+
+       /* calcFadeoutStep
+        * how many frames are left before the end of the sample? Is there
+        * enough room for a complete fadeout? Should we shorten it? */
+
+       void calcFadeoutStep();
+
+       /* calcVolumeEnv
+        * compute any changes in volume done via envelope tool */
+
+       void calcVolumeEnv(int frame);
+
        /* rsmp_state, rsmp_data
         * structs from libsamplerate */
 
@@ -68,41 +91,13 @@ private:
        float boost;
        float pitch;
        int   trackerPreview;  // chan position for audio preview
+       int   shift;
 
        /* onPreviewEnd
        A callback fired when audio preview ends. */
 
        std::function<void()> onPreviewEnd;
 
-       /* fillChan
-       Fills 'dest' buffer at point 'offset' with wave data taken from 'start'. If 
-       rewind=false don't rewind internal tracker. Returns new sample position, 
-       in frames. It resamples data if pitch != 1.0f. */
-
-       int fillChan(float* dest, int start, int offset, bool rewind=true);
-
-       /* clearChan
-        * set data to zero from start to bufferSize-1. */
-
-       void clearChan(float* dest, int start);
-
-       /* calcFadeoutStep
-        * how many frames are left before the end of the sample? Is there
-        * enough room for a complete fadeout? Should we shorten it? */
-
-       void calcFadeoutStep();
-
-       /* calcVolumeEnv
-        * compute any changes in volume done via envelope tool */
-
-       void calcVolumeEnv(int frame);
-
-       /* generateUniqueSampleName
-        * Sample name must be unique. Generate a new samplename with the "-[n]"
-        * suffix. */
-
-       void generateUniqueSampleName();
-
 public:
 
        SampleChannel(int bufferSize, bool inputMonitor);
@@ -132,6 +127,10 @@ public:
        bool canInputRec() override;
        bool allocBuffers() override;
 
+       int getTrackerPreview() const;
+       int getShift() const;
+       void setShift(int s);
+
        void reset(int frame);
 
        /* fade methods
@@ -143,10 +142,9 @@ public:
        void setXFade(int frame);
 
        /* pushWave
-       Adds a new wave to an existing channel. It also generates a unique name
-       on request. */
+       Adds a new wave to an existing channel. */
 
-       void pushWave(Wave* w, bool generateName=true);
+       void pushWave(Wave* w);
 
        /* getPosition
         * returns the position of an active sample. If EMPTY o MISSING
@@ -168,12 +166,6 @@ public:
        void setEnd(int f);
        int getEnd();
        void setTrackerPreview(int f);
-       int getTrackerPreview() const;
-
-       /* save
-        * save sample to file. */
-
-       int save(const char* path);
 
        /* hardStop
         * stop the channel immediately, no further checks. */
@@ -191,8 +183,6 @@ public:
 
        void setOnEndPreviewCb(std::function<void()> f);
 
-       /* ------------------------------------------------------------------------ */
-
        Wave* wave;
        int   tracker;         // chan position
        int   mode;            // mode: see const.h
index 191d4858a78a6bdff168f7cb42e186599c411974..6c72e6b91dd8522557cd33b6a5f6d0256de6cff4 100644 (file)
@@ -37,116 +37,121 @@ namespace giada {
 namespace m {
 namespace storager
 {
-bool setString(json_t *jRoot, const char *key, string &output)
+bool setString(json_t* jRoot, const char* key, string& output)
 {
-  json_t *jObject = json_object_get(jRoot, key);
-  if (!json_is_string(jObject)) {
-    gu_log("[storager::setString] key '%s' is not a string!\n", key);
-    json_decref(jRoot);
-    return false;
-  }
-  output = json_string_value(jObject);
-  return true;
+       json_t* jObject = json_object_get(jRoot, key);
+       if (!jObject) {
+               gu_log("[storager::setString] key '%s' not found, using default value\n", key);
+               output = "";
+               return true;
+       }
+       if (!json_is_string(jObject)) {
+               gu_log("[storager::setString] key '%s' is not a string!\n", key);
+               json_decref(jRoot);
+               return false;
+       }
+       output = json_string_value(jObject);
+       return true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool setFloat(json_t *jRoot, const char *key, float &output)
+bool setFloat(json_t* jRoot, const char* key, float& output)
 {
-  json_t *jObject = json_object_get(jRoot, key);
-  if (!jObject) {
-    gu_log("[storager::setFloat] key '%s' not found, using default value\n", key);
-    output = 0.0f;
-    return true;
-  }
-  if (!json_is_real(jObject)) {
-    gu_log("[storager::setFloat] key '%s' is not a float!\n", key);
-    json_decref(jRoot);
-    return false;
-  }
-  output = json_real_value(jObject);
-  return true;
+       json_t* jObject = json_object_get(jRoot, key);
+       if (!jObject) {
+               gu_log("[storager::setFloat] key '%s' not found, using default value\n", key);
+               output = 0.0f;
+               return true;
+       }
+       if (!json_is_real(jObject)) {
+               gu_log("[storager::setFloat] key '%s' is not a float!\n", key);
+               json_decref(jRoot);
+               return false;
+       }
+       output = json_real_value(jObject);
+       return true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool setUint32(json_t *jRoot, const char *key, uint32_t &output)
+bool setUint32(json_t* jRoot, const char* key, uint32_t &output)
 {
-  json_t *jObject = json_object_get(jRoot, key);
-  if (!jObject) {
-    gu_log("[storager::setUint32] key '%s' not found, using default value\n", key);
-    output = 0;
-    return true;
-  }
-  if (!json_is_integer(jObject)) {
-    gu_log("[storager::setUint32] key '%s' is not an integer!\n", key);
-    json_decref(jRoot);
-    return false;
-  }
-  output = json_integer_value(jObject);
-  return true;
+       json_t* jObject = json_object_get(jRoot, key);
+       if (!jObject) {
+               gu_log("[storager::setUint32] key '%s' not found, using default value\n", key);
+               output = 0;
+               return true;
+       }
+       if (!json_is_integer(jObject)) {
+               gu_log("[storager::setUint32] key '%s' is not an integer!\n", key);
+               json_decref(jRoot);
+               return false;
+       }
+       output = json_integer_value(jObject);
+       return true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool setBool(json_t *jRoot, const char *key, bool &output)
+bool setBool(json_t* jRoot, const char* key, bool& output)
 {
-  json_t *jObject = json_object_get(jRoot, key);
-  if (!jObject) {
-    gu_log("[storager::setBool] key '%s' not found, using default value\n", key);
-    output = false;
-    return true;
-  }
-  if (!json_is_boolean(jObject)) {
-    gu_log("[storager::setBool] key '%s' is not a boolean!\n", key);
-    json_decref(jRoot);
-    return false;
-  }
-  output = json_boolean_value(jObject);
-  return true;
+       json_t* jObject = json_object_get(jRoot, key);
+       if (!jObject) {
+               gu_log("[storager::setBool] key '%s' not found, using default value\n", key);
+               output = false;
+               return true;
+       }
+       if (!json_is_boolean(jObject)) {
+               gu_log("[storager::setBool] key '%s' is not a boolean!\n", key);
+               json_decref(jRoot);
+               return false;
+       }
+       output = json_boolean_value(jObject);
+       return true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool setInt(json_t *jRoot, const char *key, int &output)
+bool setInt(json_t* jRoot, const char* key, int& output)
 {
-  return setUint32(jRoot, key, (uint32_t&) output);
+       return setUint32(jRoot, key, (uint32_t&) output);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool checkObject(json_t *jRoot, const char *key)
+bool checkObject(json_t* jRoot, const char* key)
 {
-  if (!json_is_object(jRoot)) {
-    gu_log("[DataStorageJson::checkObject] malformed json: %s is not an object!\n", key);
-    json_decref(jRoot);
-    return false;
-  }
-  return true;
+       if (!json_is_object(jRoot)) {
+               gu_log("[DataStorageJson::checkObject] malformed json: %s is not an object!\n", key);
+               json_decref(jRoot);
+               return false;
+       }
+       return true;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-bool checkArray(json_t *jRoot, const char *key)
+bool checkArray(json_t* jRoot, const char* key)
 {
-  if (!json_is_array(jRoot)) {
-    gu_log("[DataStorageJson::checkObject] malformed json: %s is not an array!\n", key);
-    json_decref(jRoot);
-    return false;
-  }
-  return true;
+       if (!json_is_array(jRoot)) {
+               gu_log("[DataStorageJson::checkObject] malformed json: %s is not an array!\n", key);
+               json_decref(jRoot);
+               return false;
+       }
+       return true;
 }
 
 }}}; // giada::m::storager::
index 28edd18630eb8bda376d79ea0ed6fc0c18f876bc..f1a6c42e0ff398a51078f2d941fc9080668744aa 100644 (file)
@@ -31,6 +31,7 @@
 #include <cstring>  // memcpy
 #include "../utils/fs.h"
 #include "../utils/log.h"
+#include "../utils/string.h"
 #include "const.h"
 #include "wave.h"
 
@@ -57,8 +58,7 @@ Wave::Wave(float* data, int size, int channels, int rate, int bits,
   m_bits    (bits),
   m_logical (false),
   m_edited  (false),
-  m_path    (path),
-  m_name    (gu_stripExt(gu_basename(path)))
+  m_path    (path)
 {
 }      
 
@@ -83,8 +83,7 @@ Wave::Wave(const Wave& other)
   m_bits    (other.m_bits),    
        m_logical (true),   // a cloned wave does not exist on disk
        m_edited  (false),
-       m_path    (other.m_path),
-       m_name    (other.m_name)
+       m_path    (other.m_path)
 {
        m_data = new float[m_size];
        memcpy(m_data, other.m_data, m_size * sizeof(float));
@@ -126,25 +125,9 @@ string Wave::getBasename(bool ext) const
 /* -------------------------------------------------------------------------- */
 
 
-void Wave::setName(const string& n)
-{
-       string ext = gu_getExt(m_path);
-       m_name = gu_stripExt(gu_basename(n));
-       m_path = gu_dirname(m_path) + G_SLASH + m_name + "." + ext;
-       m_logical  = true;
-
-       /* A wave with updated m_name must become logical, since the underlying file
-       does not exist yet. */
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
 int Wave::getRate() const { return m_rate; }
 int Wave::getChannels() const { return m_channels; }
 std::string Wave::getPath() const { return m_path; }
-std::string Wave::getName() const { return m_name; }
 float* Wave::getData() const { return m_data; }
 int Wave::getSize() const { return m_size / m_channels; }
 int Wave::getBits() const { return m_bits; }
@@ -164,6 +147,15 @@ int Wave::getDuration() const
 /* -------------------------------------------------------------------------- */
 
 
+std::string Wave::getExtension() const
+{
+       return gu_getExt(m_path);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 float* Wave::getFrame(int f) const
 {
        assert(f >= 0);
@@ -179,7 +171,6 @@ float* Wave::getFrame(int f) const
 
 void Wave::setRate(int v) { m_rate = v; }
 void Wave::setChannels(int v) { m_channels = v; }
-void Wave::setPath(const string& p) { m_path = p; }
 void Wave::setLogical(bool l) { m_logical = l; }
 void Wave::setEdited(bool e) { m_edited = e; }
 
@@ -187,6 +178,20 @@ void Wave::setEdited(bool e) { m_edited = e; }
 /* -------------------------------------------------------------------------- */
 
 
+void Wave::setPath(const string& p, int id) 
+{ 
+       if (id == -1)
+               m_path = p; 
+       else 
+               m_path = gu_stripExt(p) + "-" + gu_toString(id) + "." + gu_getExt(p);
+
+
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 void Wave::setData(float* d, int size) 
 { 
        m_data = d; 
index 7c9f56b9031451bec9e71a4caf339ca0fef41f87..19f7ea83e7264d0d19b931e688bb8c4ce05ffa94 100644 (file)
@@ -49,7 +49,6 @@ private:
        bool m_edited;    // edited via editor
        
        std::string m_path; // E.g. /path/to/my/sample.wav
-       std::string m_name; // Sample name (can be changed)
 
 public:
 
@@ -60,17 +59,21 @@ public:
 
        void setRate(int v);
        void setChannels(int v);
-       void setPath(const std::string& p);
-       void setName(const std::string& p);
        void setData(float* data, int size);
        void setLogical(bool l);
        void setEdited(bool e);
 
+       /* setPath
+       Sets new path 'p'. If 'id' != -1 inserts a numeric id next to the file 
+       extension, e.g. : /path/to/sample-[id].wav */
+        
+       void setPath(const std::string& p, int id=-1);
+
        std::string getBasename(bool ext=false) const;
+       std::string getExtension() const;
        int getRate() const;
        int getChannels() const;
        std::string getPath() const;    
-       std::string getName() const;
        int getBits() const;
        float* getData() const;
        int getSize() const;        // with channels count
index a215a7c9d6e2523e0eb88d4f3f1d5dcf76fb68ef..7f278adbd38c66f39157ff451725736d12aaad93 100644 (file)
@@ -302,12 +302,28 @@ void smooth(Wave* w, int a, int b)
 /* -------------------------------------------------------------------------- */
 
 
+void shift(Wave* w, int offset)
+{
+       if (offset < 0)
+               offset = (w->getSize() + w->getChannels()) + offset;
+
+       float* begin = w->getData();
+       float* end   = w->getData() + (w->getSize() * w->getChannels());
+
+       std::rotate(begin, end - (offset * w->getChannels()), end);
+       w->setEdited(true);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
 void reverse(Wave* w, int a, int b)
 {
        /* https://stackoverflow.com/questions/33201528/reversing-an-array-of-structures-in-c */
 
-       float* begin = (w->getData() + (a * w->getChannels()));
-       float* end   = (w->getData() + (b * w->getChannels()));
+       float* begin = w->getData() + (a * w->getChannels());
+       float* end   = w->getData() + (b * w->getChannels());
 
        std::reverse(begin, end);
 
index 438c7b6e1a8ed20181ef9c690d30291797faf2fe..918795c25a8adcbdf76feb7c8262735abdc13a99 100644 (file)
@@ -71,6 +71,8 @@ Flips Wave's data. */
 
 void reverse(Wave* w, int a, int b);
 
+void shift(Wave* w, int offset);
+
 }}}; // giada::m::wfx::
 
 #endif
index 3e430e45605591671b3b4ffa921914e1ef452787..becf115927ce25e2306733fbd331af29e17ae8ea 100644 (file)
@@ -142,8 +142,6 @@ int createEmpty(int size, int samplerate, const string& name, Wave** out)
        Wave* wave = new Wave(data, size, G_DEFAULT_AUDIO_CHANS, samplerate, 
                G_DEFAULT_BIT_DEPTH, "");
        wave->setLogical(true);
-       wave->setName(name);
-       wave->setPath(gu_getCurrentPath() + G_SLASH + wave->getName());
 
        *out = wave;
 
@@ -171,7 +169,6 @@ int createFromWave(const Wave* src, int a, int b, Wave** out)
        Wave* wave = new Wave(data, size, numChans, src->getRate(),
                src->getBits(), src->getPath());
        wave->setLogical(true);
-       wave->setName(src->getName() + " part");
 
        *out = wave;
 
index ea20a6c716b9ee34acc717edb328720c11d83813..4039c869b4ec794f7a198a253d7c2f1456ebd66e 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __JUCE_APPCONFIG_H__
-#define __JUCE_APPCONFIG_H__
+#ifndef JUCE_APPCONFIG_H
+#define JUCE_APPCONFIG_H
 
 
 #ifdef _WIN32
index 12f7582bff5c8169fc890c5be40d5361a985512f..edebcf5ddfbb91458103c9adc116fe123928f7c5 100644 (file)
@@ -113,9 +113,9 @@ int glue_loadChannel(SampleChannel* ch, const string& fname)
 
 Channel* glue_addChannel(int column, int type, int size)
 {
-       Channel* ch     = mh::addChannel(type);
-       geChannel* gch  = G_MainWin->keyboard->addChannel(column, ch, size);
-       ch->guiChannel  = gch;
+       Channel* ch    = mh::addChannel(type);
+       geChannel* gch = G_MainWin->keyboard->addChannel(column, ch, size);
+       ch->guiChannel = gch;
        return ch;
 }
 
@@ -143,7 +143,7 @@ void glue_deleteChannel(Channel* ch)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_freeChannel(Channel *ch)
+void glue_freeChannel(Channelch)
 {
        if (ch->status == STATUS_PLAY) {
                if (!gdConfirmWin("Warning", "This action will stop the channel: are you sure?"))
@@ -170,20 +170,20 @@ void glue_freeChannel(Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_toggleArm(Channel *ch, bool gui)
+void glue_toggleArm(Channelch, bool gui)
 {
-       ch->armed = !ch->armed;
+       ch->setArmed(!ch->isArmed());
        if (!gui)
-               ch->guiChannel->arm->value(ch->armed);
+               ch->guiChannel->arm->value(ch->isArmed());
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void glue_toggleInputMonitor(Channel *ch)
+void glue_toggleInputMonitor(Channelch)
 {
-       SampleChannel *sch = static_cast<SampleChannel*>(ch);
+       SampleChannelsch = static_cast<SampleChannel*>(ch);
        sch->inputMonitor = !sch->inputMonitor;
 }
 
@@ -191,10 +191,10 @@ void glue_toggleInputMonitor(Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-int glue_cloneChannel(Channel *src)
+int glue_cloneChannel(Channelsrc)
 {
-       Channel *ch    = mh::addChannel(src->type);
-       geChannel *gch = G_MainWin->keyboard->addChannel(src->guiChannel->getColumnIndex(), 
+       Channelch    = mh::addChannel(src->type);
+       geChannelgch = G_MainWin->keyboard->addChannel(src->guiChannel->getColumnIndex(), 
                ch, src->guiChannel->getSize());
 
        ch->guiChannel = gch;
@@ -208,7 +208,7 @@ int glue_cloneChannel(Channel *src)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_setVolume(Channel *ch, float v, bool gui, bool editor)
+void glue_setVolume(Channelch, float v, bool gui, bool editor)
 {
        ch->volume = v;
 
@@ -264,7 +264,7 @@ void glue_setPanning(SampleChannel* ch, float val)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_setMute(Channel *ch, bool gui)
+void glue_toggleMute(Channel* ch, bool gui)
 {
        if (recorder::active && recorder::canRec(ch, clock::isRunning(), mixer::recording)) {
                if (!ch->mute) {
@@ -290,7 +290,25 @@ void glue_setMute(Channel *ch, bool gui)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_setSoloOn(Channel *ch, bool gui)
+void glue_toggleSolo(Channel* ch, bool gui)
+{
+       ch->solo ? glue_setSoloOn(ch, gui) : glue_setSoloOff(ch, gui);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_kill(Channel* ch)
+{
+       ch->kill(0); // on frame 0: it's a user-generated event
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_setSoloOn(Channel* ch, bool gui)
 {
        /* if there's no solo session, store mute configuration of all chans
         * and start the session */
@@ -336,7 +354,7 @@ void glue_setSoloOn(Channel *ch, bool gui)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_setSoloOff(Channel *ch, bool gui)
+void glue_setSoloOff(Channelch, bool gui)
 {
        /* if this is uniqueSolo, stop solo session and restore mute status,
         * else mute this */
@@ -381,7 +399,7 @@ void glue_setSoloOff(Channel *ch, bool gui)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_setBoost(SampleChannel *ch, float val)
+void glue_setBoost(SampleChannelch, float val)
 {
        ch->setBoost(val);
        gdSampleEditor *gdEditor = static_cast<gdSampleEditor*>(gu_getSubwindow(G_MainWin, WID_SAMPLE_EDITOR));
@@ -396,7 +414,17 @@ void glue_setBoost(SampleChannel *ch, float val)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_startStopReadingRecs(SampleChannel *ch, bool gui)
+void glue_setName(Channel* ch, const string& name)
+{
+       ch->setName(name);
+       ch->guiChannel->update();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_toggleReadingRecs(SampleChannel* ch, bool gui)
 {
        /* When you call glue_startReadingRecs with conf::treatRecsAsLoops, the
        member value ch->readActions actually is not set to true immediately, because
@@ -416,7 +444,7 @@ void glue_startStopReadingRecs(SampleChannel *ch, bool gui)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_startReadingRecs(SampleChannel *ch, bool gui)
+void glue_startReadingRecs(SampleChannelch, bool gui)
 {
        if (conf::treatRecsAsLoops)
                ch->recStatus = REC_WAITING;
@@ -433,7 +461,7 @@ void glue_startReadingRecs(SampleChannel *ch, bool gui)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_stopReadingRecs(SampleChannel *ch, bool gui)
+void glue_stopReadingRecs(SampleChannelch, bool gui)
 {
        /* First of all, if the mixer is not running just stop and disable everything.
        Then if "treatRecsAsLoop" wait until the sequencer reaches beat 0, so put the
index 65cd77e8998079150e994f5e1ba5660abe9b285c..e3b9468588bec0a6850ccc4b942c143c8746d3fc 100644 (file)
@@ -40,55 +40,51 @@ class gdSampleEditor;
 /* addChannel
  * add an empty new channel to the stack. Returns the new channel. */
 
-Channel *glue_addChannel(int column, int type, int size);
+Channelglue_addChannel(int column, int type, int size);
 
 /* loadChannel
  * fill an existing channel with a wave. */
 
-int glue_loadChannel(SampleChannel *ch, const std::string &fname);
+int glue_loadChannel(SampleChannel* ch, const std::string& fname);
 
 /* deleteChannel
  * Remove a channel from Mixer. */
 
-void glue_deleteChannel(Channel *ch);
+void glue_deleteChannel(Channelch);
 
 /* freeChannel
  * Unload the sample from a sample channel. */
 
-void glue_freeChannel(Channel *ch);
+void glue_freeChannel(Channelch);
 
 /* cloneChannel
  * Make an exact copy of Channel *ch. */
 
-int glue_cloneChannel(Channel *ch);
+int glue_cloneChannel(Channelch);
 
 /* toggle/set*
- * Toggle or set several channel properties. If gui == true the signal comes
- * from a manual interaction on the GUI, otherwise it's a MIDI/Jack/external
- * signal. */
-
-void glue_toggleArm(Channel *ch, bool gui=true);
-void glue_toggleInputMonitor(Channel *ch);
-void glue_setMute(Channel *ch, bool gui=true);
-void glue_setSoloOn (Channel *ch, bool gui=true);
-void glue_setSoloOff(Channel *ch, bool gui=true);
-void glue_setVolume(Channel *ch, float v, bool gui=true, bool editor=false);
-
-/* TODO move to glue_sampleEditor */
-void glue_setPitch(SampleChannel *ch, float val);
-
-/* TODO move to glue_sampleEditor */
-void glue_setPanning(SampleChannel *ch, float val);
-
-/* TODO move to glue_sampleEditor */
-void glue_setBoost(SampleChannel *ch, float val);
-
-/* start/stopReadingRecs
+Toggles or set several channel properties. If gui == true the signal comes from 
+a manual interaction on the GUI, otherwise it's a MIDI/Jack/external signal. */
+
+void glue_toggleArm(Channel* ch, bool gui=true);
+void glue_toggleInputMonitor(Channel* ch);
+void glue_kill(Channel* ch);
+void glue_toggleMute(Channel* ch, bool gui=true);
+void glue_setSoloOn(Channel* ch, bool gui=true);
+void glue_setSoloOff(Channel* ch, bool gui=true);
+void glue_toggleSolo(Channel* ch, bool gui=true);
+void glue_setVolume(Channel* ch, float v, bool gui=true, bool editor=false);
+void glue_setName(Channel* ch, const std::string& name);
+void glue_setPitch(SampleChannel* ch, float val);
+void glue_setPanning(SampleChannel* ch, float val);
+void glue_setBoost(SampleChannel* ch, float val);
+
+/* toggleReadingRecs
 Handles the 'R' button. If gui == true the signal comes from an user interaction
 on the GUI, otherwise it's a MIDI/Jack/external signal. */
 
-void glue_startStopReadingRecs(SampleChannel *ch, bool gui=true);
-void glue_startReadingRecs    (SampleChannel *ch, bool gui=true);
-void glue_stopReadingRecs     (SampleChannel *ch, bool gui=true);
+void glue_toggleReadingRecs(SampleChannel* ch, bool gui=true);
+void glue_startReadingRecs(SampleChannel* ch, bool gui=true);
+void glue_stopReadingRecs(SampleChannel* ch, bool gui=true);
 
 #endif
index 31d678121175d3618f2b10ed169913194d5580b6..0171457d6d2a4f75d29be2622b348a669dfe05da 100644 (file)
@@ -81,7 +81,7 @@ void glue_keyRelease(Channel *ch, bool ctrl, bool shift)
 void glue_keyPress(MidiChannel *ch, bool ctrl, bool shift)
 {
        if (ctrl)
-               glue_setMute(ch);
+               glue_toggleMute(ch);
        else
        if (shift)
                ch->kill(0);        // on frame 0: user-generated event
@@ -98,7 +98,7 @@ void glue_keyPress(SampleChannel *ch, bool ctrl, bool shift)
        /* case CTRL */
 
        if (ctrl)
-               glue_setMute(ch);
+               glue_toggleMute(ch);
 
        /* case SHIFT
         *
@@ -320,7 +320,7 @@ int glue_stopInputRec(bool gui)
                if (mixer::channels.at(i)->type == CHANNEL_MIDI)
                        continue;
                SampleChannel *ch = (SampleChannel*) mixer::channels.at(i);
-               if (ch->mode & (LOOP_ANY) && ch->status == STATUS_OFF && ch->armed)
+               if (ch->mode & (LOOP_ANY) && ch->status == STATUS_OFF && ch->isArmed())
                        ch->start(clock::getCurrentFrame(), true, clock::getQuantize(),
         clock::isRunning(), true, true);
        }
index d8320c6a856e5f52e12cd2c23e9db92ce0afb2bc..c7928d614cfd824edf574d2298e6618cf6e7821f 100644 (file)
 #include "../core/mixer.h"
 #include "../core/plugin.h"
 #include "../core/channel.h"
+#include "../core/const.h"
+#include "../utils/gui.h"
+#include "../gui/dialogs/gd_mainWindow.h"
+#include "../gui/dialogs/pluginWindow.h"
+#include "../gui/dialogs/pluginList.h"
 #include "plugin.h"
 
 
+extern gdMainWindow* G_MainWin;
+
+
 using namespace giada::m;
 
 
-Plugin *glue_addPlugin(Channel *ch, int index, int stackType)
+namespace giada {
+namespace c     {
+namespace plugin 
+{
+Plugin* addPlugin(Channel* ch, int index, int stackType)
 {
   if (index >= pluginHost::countAvailablePlugins())
     return nullptr;
-
-  return pluginHost::addPlugin(index, stackType,  &mixer::mutex_plugins, ch);
+  return pluginHost::addPlugin(index, stackType, &mixer::mutex_plugins, ch);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void glue_swapPlugins(Channel *ch, int index1, int index2, int stackType)
+void swapPlugins(Channel* ch, int index1, int index2, int stackType)
 {
   pluginHost::swapPlugin(index1, index2, stackType, &mixer::mutex_plugins,
     ch);
@@ -60,10 +71,36 @@ void glue_swapPlugins(Channel *ch, int index1, int index2, int stackType)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_freePlugin(Channel *ch, int index, int stackType)
+void freePlugin(Channel* ch, int index, int stackType)
 {
   pluginHost::freePlugin(index, stackType, &mixer::mutex_plugins, ch);
 }
 
 
+/* -------------------------------------------------------------------------- */
+
+
+void setParameter(Plugin* p, int index, float value, bool gui)
+{
+       p->setParameter(index, value);
+
+       /* No need to update plug-in editor if it has one: the plug-in's editor takes
+       care of it on its own. Conversely, update the specific parameter for UI-less 
+       plug-ins. */
+
+       if (p->hasEditor())
+               return;
+
+       gdPluginList* parent = static_cast<gdPluginList*>(gu_getSubwindow(G_MainWin, WID_FX_LIST));
+       gdPluginWindow* child = static_cast<gdPluginWindow*>(gu_getSubwindow(parent, p->getId() + 1));
+       if (child != nullptr) {
+               Fl::lock();
+               child->updateParameter(index, !gui);
+               Fl::unlock();
+       }
+}
+
+}}}; // giada::c::plugin::
+
+
 #endif
index 9f95d0c91e3400b305c51e373283fd6f78e964e3..72041ff039d61f666b8d2576fbed4d05453f7502 100644 (file)
 
 #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);
+class Plugin;
+class Channel;
+
+
+namespace giada {
+namespace c     {
+namespace plugin 
+{
+Plugin* addPlugin(Channel* ch, int index, int stackType);
+void swapPlugins(Channel* ch, int indexP1, int indexP2, int stackType);
+void freePlugin(Channel* ch, int index, int stackType);
+void setParameter(Plugin* p, int index, float value, bool gui=true); 
+}}}; // giada::c::plugin::
 
-void glue_freePlugin(class Channel *ch, int index, int stackType);
 
 #endif
 
index 0c20347f301eb001f62f43eb2f4318b4324354ed..f5b037e1017d49e529a58cfd89a8cee8c6868e1f 100644 (file)
@@ -37,6 +37,7 @@
 #include "../gui/elems/sampleEditor/panTool.h"
 #include "../gui/elems/sampleEditor/pitchTool.h"
 #include "../gui/elems/sampleEditor/rangeTool.h"
+#include "../gui/elems/sampleEditor/shiftTool.h"
 #include "../gui/elems/sampleEditor/waveform.h"
 #include "../gui/elems/mainWindow/keyboard/channel.h"
 #include "../core/sampleChannel.h"
@@ -103,6 +104,7 @@ void setBeginEnd(SampleChannel* ch, int b, int e)
 
 void cut(SampleChannel* ch, int a, int b)
 {
+       copy(ch, a, b);
        if (!wfx::cut(ch->wave, a, b)) {
                gdAlert("Unable to cut the sample!");
                return;
@@ -136,8 +138,10 @@ void copy(SampleChannel* ch, int a, int b)
 
 void paste(SampleChannel* ch, int a)
 {
-       if (!isWaveBufferFull())
+       if (!isWaveBufferFull()) {
+               gu_log("[sampleEditor::paste] Buffer is empty, nothing to paste\n");
                return;
+       }
        
        wfx::paste(m_waveBuffer, ch->wave, a);
 
@@ -278,8 +282,7 @@ void toNewChannel(SampleChannel* ch, int a, int b)
                return;
        }
 
-       newCh->pushWave(wave, true);
-
+       newCh->pushWave(wave);
        newCh->guiChannel->update();
 }
 
@@ -292,4 +295,18 @@ bool isWaveBufferFull()
        return m_waveBuffer != nullptr;
 }
 
+
+/* -------------------------------------------------------------------------- */
+
+
+void shift(SampleChannel* ch, int offset)
+{
+       wfx::shift(ch->wave, offset - ch->getShift());
+       ch->setShift(offset);
+       gdSampleEditor* gdEditor = getSampleEditorWindow();
+       gdEditor->shiftTool->refresh();
+       gdEditor->waveTools->waveform->refresh();       
+}
+
+
 }}}; // giada::c::sampleEditor::
index 3846f9ff83b16d48f8d2676b3a09ad9c6b1e25e5..e6d1221dba5ea45b2a92825a09cad607a87259e0 100644 (file)
@@ -59,6 +59,7 @@ void normalizeHard(SampleChannel* ch, int a, int b);
 void silence(SampleChannel* ch, int a, int b);
 void fade(SampleChannel* ch, int a, int b, int type);
 void smoothEdges(SampleChannel* ch, int a, int b);
+void shift(SampleChannel* ch, int offset);
 
 bool isWaveBufferFull();
 
index da1a80fee1708044cf255774d22207286c350e43..c9db5eeeb08958c63e8be87af6e034e8fdd5b66e 100644 (file)
 #include "../core/patch.h"
 #include "../core/sampleChannel.h"
 #include "../core/midiChannel.h"
+#include "../core/waveManager.h"
 #include "../core/clock.h"
 #include "../core/wave.h"
 #include "../utils/gui.h"
 #include "../utils/log.h"
+#include "../utils/string.h"
 #include "../utils/fs.h"
 #include "../gui/elems/basics/progress.h"
 #include "../gui/elems/mainWindow/keyboard/column.h"
@@ -61,7 +63,7 @@ using namespace giada::m;
 
 #ifdef WITH_VST
 
-static void __glue_fillPatchGlobalsPlugins__(vector <Plugin *> *host, vector<patch::plugin_t> *patch)
+static void glue_fillPatchGlobalsPlugins__(vector <Plugin *> *host, vector<patch::plugin_t> *patch)
 {
        for (unsigned i=0; i<host->size(); i++) {
                Plugin *pl = host->at(i);
@@ -81,7 +83,7 @@ static void __glue_fillPatchGlobalsPlugins__(vector <Plugin *> *host, vector<pat
 /* -------------------------------------------------------------------------- */
 
 
-static void __glue_fillPatchColumns__()
+static void glue_fillPatchColumns__()
 {
        for (unsigned i=0; i<G_MainWin->keyboard->getTotalColumns(); i++) {
                geColumn *gCol = G_MainWin->keyboard->getColumn(i);
@@ -106,7 +108,7 @@ static void __glue_fillPatchColumns__()
 /* -------------------------------------------------------------------------- */
 
 
-static void __glue_fillPatchChannels__(bool isProject)
+static void glue_fillPatchChannels__(bool isProject)
 {
        for (unsigned i=0; i<mixer::channels.size(); i++) {
                mixer::channels.at(i)->writePatch(i, isProject);
@@ -117,7 +119,7 @@ static void __glue_fillPatchChannels__(bool isProject)
 /* -------------------------------------------------------------------------- */
 
 
-static void __glue_fillPatchGlobals__(const string &name)
+static void glue_fillPatchGlobals__(const string &name)
 {
        patch::version      = G_VERSION_STR;
        patch::versionMajor = G_VERSION_MAJOR;
@@ -134,9 +136,9 @@ static void __glue_fillPatchGlobals__(const string &name)
 
 #ifdef WITH_VST
 
-       __glue_fillPatchGlobalsPlugins__(pluginHost::getStack(pluginHost::MASTER_IN),
+       glue_fillPatchGlobalsPlugins__(pluginHost::getStack(pluginHost::MASTER_IN),
                        &patch::masterInPlugins);
-       __glue_fillPatchGlobalsPlugins__(pluginHost::getStack(pluginHost::MASTER_OUT),
+       glue_fillPatchGlobalsPlugins__(pluginHost::getStack(pluginHost::MASTER_OUT),
                        &patch::masterOutPlugins);
 
 #endif
@@ -146,14 +148,14 @@ static void __glue_fillPatchGlobals__(const string &name)
 /* -------------------------------------------------------------------------- */
 
 
-static bool __glue_savePatch__(const string &fullPath, const string &name,
+static bool glue_savePatch__(const string &fullPath, const string &name,
                bool isProject)
 {
        patch::init();
 
-       __glue_fillPatchGlobals__(name);
-       __glue_fillPatchChannels__(isProject);
-       __glue_fillPatchColumns__();
+       glue_fillPatchGlobals__(name);
+       glue_fillPatchChannels__(isProject);
+       glue_fillPatchColumns__();
 
        if (patch::write(fullPath)) {
                gu_updateMainWinLabel(name);
@@ -167,11 +169,34 @@ static bool __glue_savePatch__(const string &fullPath, const string &name,
 /* -------------------------------------------------------------------------- */
 
 
-void glue_savePatch(void *data)
+static string glue_makeSamplePath__(const string& base, const Wave* w, int k)
 {
-       gdBrowserSave *browser = (gdBrowserSave*) data;
-       string name            = browser->getName();
-       string fullPath        = browser->getCurrentPath() + G_SLASH + gu_stripExt(name) + ".gptc";
+       return base + G_SLASH + w->getBasename(false) + "-" + gu_toString(k) + "." +  w->getExtension();
+} 
+
+
+static string glue_makeUniqueSamplePath__(const string& base, const SampleChannel* ch)
+{
+       string path = base + G_SLASH + ch->wave->getBasename(true);
+       if (mh::uniqueSamplePath(ch, path))
+               return path;
+
+       int k = 0;
+       path = glue_makeSamplePath__(base, ch->wave, k);
+       while (!mh::uniqueSamplePath(ch, path))
+               path = glue_makeSamplePath__(base, ch->wave, k++);
+       return path;
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void glue_savePatch(void* data)
+{
+       gdBrowserSave* browser = (gdBrowserSave*) data;
+       string name            = gu_stripExt(browser->getName());
+       string fullPath        = browser->getCurrentPath() + G_SLASH + name + ".gptc";
 
        if (name == "") {
                gdAlert("Please choose a file name.");
@@ -182,7 +207,7 @@ void glue_savePatch(void *data)
                if (!gdConfirmWin("Warning", "File exists: overwrite?"))
                        return;
 
-       if (__glue_savePatch__(fullPath, name, false)) {  // false == not a project
+       if (glue_savePatch__(fullPath, name, false)) {  // false == not a project
                conf::patchPath = gu_dirname(fullPath);
                browser->do_callback();
        }
@@ -222,58 +247,57 @@ void glue_loadPatch(void* data)
                return;
        }
 
-       /* close all other windows. This prevents segfault if plugin
-        * windows GUIs are on. */
+       /* Close all other windows. This prevents segfault if plugin windows GUIs are 
+       open. */
 
        gu_closeAllSubwindows();
 
-       /* reset the system. False(1): don't update the gui right now. False(2): do
-        * not create empty columns. */
+       /* Reset the system. False(1): don't update the gui right now. False(2): do 
+       not create empty columns. */
 
        glue_resetToInitState(false, false);
 
        browser->setStatusBar(0.1f);
-       //__glue_setProgressBar__(status, 0.1f);
 
-       /* Add common stuff, columns and channels. Also increment the progress bar
-        * by 0.8 / total_channels steps.  */
+       /* Add common stuff, columns and channels. Also increment the progress bar by 
+       0.8 / total_channels steps.  */
 
        float steps = 0.8 / patch::channels.size();
        
        for (const patch::column_t& col : patch::columns) {
                G_MainWin->keyboard->addColumn(col.width);
-               for (unsigned k=0; k<patch::channels.size(); k++) {
-                       if (patch::channels.at(k).column == col.index) {
-                               Channel* ch = glue_addChannel(patch::channels.at(k).column,
-                                       patch::channels.at(k).type, patch::channels.at(k).size);
+               unsigned k = 0;
+               for (const patch::channel_t& pch : patch::channels) {
+                       if (pch.column == col.index) {
+                               Channel* ch = glue_addChannel(pch.column, pch.type, pch.size);
                                ch->readPatch(basePath, k, &mixer::mutex_plugins, conf::samplerate,
                                        conf::rsmpQuality);
                        }
                        browser->setStatusBar(steps);
+                       k++;
                }
        }
 
-       /* fill Mixer */
+       /* Fill Mixer. */
 
        mh::readPatch();
 
-       /* let recorder recompute the actions' positions if the current
-        * samplerate != patch samplerate */
+       /* Let recorder recompute the actions' positions if the current 
+       samplerate != patch samplerate. */
 
        recorder::updateSamplerate(conf::samplerate, patch::samplerate);
 
-       /* save patchPath by taking the last dir of the broswer, in order to
-        * reuse it the next time */
+       /* Save patchPath by taking the last dir of the broswer, in order to reuse it 
+       the next time. */
 
        conf::patchPath = gu_dirname(fullPath);
 
-       /* refresh GUI */
+       /* Refresh GUI. */
 
        gu_updateControls();
        gu_updateMainWinLabel(patch::name);
 
        browser->setStatusBar(0.1f);
-       //__glue_setProgressBar__(status, 1.0f);
 
        gu_log("[glue] patch loaded successfully\n");
 
@@ -291,12 +315,12 @@ void glue_loadPatch(void* data)
 /* -------------------------------------------------------------------------- */
 
 
-void glue_saveProject(void *data)
+void glue_saveProject(voiddata)
 {
-       gdBrowserSave *browser = (gdBrowserSave*) data;
-       string name            = browser->getName();
-       string folderPath      = browser->getCurrentPath(); //browser->getSelectedItem();
-       string fullPath        = folderPath + G_SLASH + gu_stripExt(name) + ".gprj";
+       gdBrowserSavebrowser = (gdBrowserSave*) data;
+       string name            = gu_stripExt(browser->getName());
+       string folderPath      = browser->getCurrentPath();
+       string fullPath        = folderPath + G_SLASH + name + ".gprj";
 
        if (name == "") {
                gdAlert("Please choose a project name.");
@@ -307,38 +331,36 @@ void glue_saveProject(void *data)
                return;
 
        if (!gu_dirExists(fullPath) && !gu_mkdir(fullPath)) {
-               gu_log("[glue_saveProject] unable to make project directory!\n");
+               gu_log("[glue_saveProject] Unable to make project directory!\n");
                return;
        }
 
-       gu_log("[glue_saveProject] project dir created: %s\n", fullPath.c_str());
+       gu_log("[glue_saveProject] Project dir created: %s\n", fullPath.c_str());
 
-       /* copy all samples inside the folder. Takes and logical ones are saved
-        * via glue_saveSample() */
+       /* Copy all samples inside the folder. Takes and logical ones are saved via 
+       glue_saveSample(). Update the new sample path: everything now comes from the 
+       project folder (folderPath). Also make sure the file path is unique inside the 
+       project folder.*/
 
-       for (unsigned i=0; i<mixer::channels.size(); i++) {
+       for (const Channel* ch : mixer::channels) {
 
-               if (mixer::channels.at(i)->type == CHANNEL_MIDI)
+               if (ch->type == CHANNEL_MIDI)
                        continue;
 
-               SampleChannel *ch = (SampleChannel*) mixer::channels.at(i);
+               const SampleChannel* sch = static_cast<const SampleChannel*>(ch);
 
-               if (ch->wave == nullptr)
+               if (sch->wave == nullptr)
                        continue;
 
-               /* update the new samplePath: everything now comes from the project
-                * folder (folderPath). Also remove any existing file. */
+               sch->wave->setPath(glue_makeUniqueSamplePath__(fullPath, sch));
 
-               string samplePath = fullPath + G_SLASH + ch->wave->getBasename(true);
+               gu_log("[glue_saveProject] Save file to %s\n", sch->wave->getPath().c_str());
 
-               if (gu_fileExists(samplePath))
-                       remove(samplePath.c_str());
-               if (ch->save(samplePath.c_str()))
-                       ch->wave->setPath(samplePath);
+               waveManager::save(sch->wave, sch->wave->getPath()); // TODO - error checking    
        }
 
-       string gptcPath = fullPath + G_SLASH + gu_stripExt(name) + ".gptc";
-       if (__glue_savePatch__(gptcPath, name, true)) // true == it's a project
+       string gptcPath = fullPath + G_SLASH + name + ".gptc";
+       if (glue_savePatch__(gptcPath, name, true)) // true == it's a project
                browser->do_callback();
        else
                gdAlert("Unable to save the project!");
@@ -374,7 +396,7 @@ void glue_loadSample(void* data)
 
 void glue_saveSample(void *data)
 {
-       gdBrowserSave *browser = (gdBrowserSave*) data;
+       gdBrowserSavebrowser = (gdBrowserSave*) data;
        string name            = browser->getName();
        string folderPath      = browser->getCurrentPath();
 
@@ -391,7 +413,9 @@ void glue_saveSample(void *data)
                if (!gdConfirmWin("Warning", "File exists: overwrite?"))
                        return;
 
-       if (static_cast<SampleChannel*>(browser->getChannel())->save(filePath.c_str())) {
+       SampleChannel* ch = static_cast<SampleChannel*>(browser->getChannel());
+
+       if (waveManager::save(ch->wave, filePath)) {
                gu_log("[glue_saveSample] sample saved to %s\n", filePath.c_str());
                conf::samplePath = gu_dirname(filePath);
                browser->do_callback();
diff --git a/src/gui/dialogs/beatsInput.cpp b/src/gui/dialogs/beatsInput.cpp
new file mode 100644 (file)
index 0000000..3d77b6f
--- /dev/null
@@ -0,0 +1,108 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include <cstring>
+#include "../../utils/gui.h"
+#include "../../utils/string.h"
+#include "../../core/mixer.h"
+#include "../../core/clock.h"
+#include "../../core/conf.h"
+#include "../../core/const.h"
+#include "../../glue/main.h"
+#include "../elems/basics/input.h"
+#include "../elems/basics/button.h"
+#include "../elems/basics/check.h"
+#include "beatsInput.h"
+#include "gd_mainWindow.h"
+
+
+extern gdMainWindow* mainWin;
+
+
+using namespace giada::m;
+
+
+gdBeatsInput::gdBeatsInput()
+       : gdWindow(180, 60, "Beats")
+{
+       if (conf::beatsX)
+               resize(conf::beatsX, conf::beatsY, w(), h());
+
+       set_modal();
+
+       beats     = new geInput(8,  8,  43, G_GUI_UNIT);
+       bars      = new geInput(beats->x()+beats->w()+4, 8,  43, G_GUI_UNIT);
+       ok                  = new geButton(bars->x()+bars->w()+4, 8,  70, G_GUI_UNIT, "Ok");
+       resizeRec = new geCheck(8,  40, 12, 12, "resize recorded actions");
+       end();
+
+       beats->maximum_size(2);
+       beats->value(gu_toString(clock::getBeats()).c_str());
+       beats->type(FL_INT_INPUT);
+       
+       bars->maximum_size(2);
+       bars->value(gu_toString(clock::getBars()).c_str());
+       bars->type(FL_INT_INPUT);
+       
+       ok->shortcut(FL_Enter);
+       ok->callback(cb_update, (void*)this);
+       
+       resizeRec->value(conf::resizeRecordings);
+
+       gu_setFavicon(this);
+       setId(WID_BEATS);
+       show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdBeatsInput::~gdBeatsInput()
+{
+       conf::beatsX = x();
+       conf::beatsY = y();
+       conf::resizeRecordings = resizeRec->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdBeatsInput::cb_update(Fl_Widget* w, void* p) { ((gdBeatsInput*)p)->cb_update(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdBeatsInput::cb_update()
+{
+       if (!strcmp(beats->value(), "") || !strcmp(bars->value(), ""))
+               return;
+       glue_setBeats(atoi(beats->value()), atoi(bars->value()), resizeRec->value());
+       do_callback();
+}
diff --git a/src/gui/dialogs/beatsInput.h b/src/gui/dialogs/beatsInput.h
new file mode 100644 (file)
index 0000000..b1d0bb8
--- /dev/null
@@ -0,0 +1,59 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef GD_BEATSINPUT_H
+#define GD_BEATSINPUT_H
+
+
+#include "window.h"
+
+
+class geInput;
+class geButton;
+class geCheck;
+
+
+class gdBeatsInput : public gdWindow
+{
+private:
+
+       static void cb_update(Fl_Widget* w, void* p);
+       void cb_update();
+
+       geInput* beats;
+       geInput* bars;
+       geButton* ok;
+       geCheck* resizeRec;
+
+public:
+
+       gdBeatsInput();
+       ~gdBeatsInput();
+};
+
+
+#endif
diff --git a/src/gui/dialogs/bpmInput.cpp b/src/gui/dialogs/bpmInput.cpp
new file mode 100644 (file)
index 0000000..f76c629
--- /dev/null
@@ -0,0 +1,109 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include <cstring>
+#include "../../core/conf.h"
+#include "../../core/const.h"
+#include "../../core/mixer.h"
+#include "../../core/clock.h"
+#include "../../glue/main.h"
+#include "../../utils/gui.h"
+#include "../../utils/string.h"
+#include "../elems/basics/button.h"
+#include "../elems/basics/input.h"
+#include "bpmInput.h"
+#include "gd_mainWindow.h"
+
+
+extern gdMainWindow *mainWin;
+
+
+using std::vector;
+using std::string;
+using namespace giada::m;
+
+
+gdBpmInput::gdBpmInput(const char* label)
+: gdWindow(144, 36, "Bpm")
+{
+       if (conf::bpmX)
+               resize(conf::bpmX, conf::bpmY, w(), h());
+
+       set_modal();
+
+       input_a = new geInput(8,  8, 30, G_GUI_UNIT);
+       input_b = new geInput(42, 8, 20, G_GUI_UNIT);
+       ok                = new geButton(66, 8, 70, G_GUI_UNIT, "Ok");
+       end();
+
+       input_a->maximum_size(3);
+       input_a->type(FL_INT_INPUT);
+       input_a->value(gu_toString(clock::getBpm()).c_str());
+
+       /* Use the decimal value from the string label. */
+
+       vector<string> tokens;
+       gu_split(label, ".", &tokens);
+       input_b->maximum_size(1);
+       input_b->type(FL_INT_INPUT);
+       input_b->value(tokens[1].c_str());
+
+       ok->shortcut(FL_Enter);
+       ok->callback(cb_update, (void*)this);
+
+       gu_setFavicon(this);
+       setId(WID_BPM);
+       show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdBpmInput::~gdBpmInput()
+{
+       conf::bpmX = x();
+       conf::bpmY = y();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdBpmInput::cb_update(Fl_Widget* w, void* p) { ((gdBpmInput*)p)->cb_update(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdBpmInput::cb_update()
+{
+       if (strcmp(input_a->value(), "") == 0)
+               return;
+       glue_setBpm(input_a->value(), input_b->value());
+       do_callback();
+}
diff --git a/src/gui/dialogs/bpmInput.h b/src/gui/dialogs/bpmInput.h
new file mode 100644 (file)
index 0000000..3a994ef
--- /dev/null
@@ -0,0 +1,56 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef GD_BPMINPUT_H
+#define GD_BPMINPUT_H
+
+
+#include "window.h"
+
+
+class geInput;
+class geButton;
+
+
+class gdBpmInput : public gdWindow
+{
+private:
+
+       static void cb_update(Fl_Widget* w, void* p);
+       void cb_update();
+
+       geInput* input_a;
+       geInput* input_b;
+       geButton* ok;
+
+public:
+
+       gdBpmInput(const char* label); // pointer to mainWin->timing->bpm->label()
+       ~gdBpmInput();
+};
+
+#endif
index a1435d4cb63eebf6c1c088a8c6d3ec6e184ff859..5903962866b5c39eb7810d5ce76a35906f1c444a 100644 (file)
@@ -42,15 +42,15 @@ using std::string;
 using namespace giada::m;
 
 
-gdBrowserBase::gdBrowserBase(int x, int y, int w, int h, const string &title,
-               const string &path, void (*callback)(void*))
+gdBrowserBase::gdBrowserBase(int x, int y, int w, int h, const stringtitle,
+               const stringpath, void (*callback)(void*))
        :       gdWindow(x, y, w, h, title.c_str()), callback(callback)
 {
        set_non_modal();
 
        groupTop = new Fl_Group(8, 8, w-16, 40);
     hiddenFiles = new geCheck(groupTop->x(), groupTop->y(), 400, 20, "Show hidden files");
-               where = new geInput(groupTop->x(), hiddenFiles->y()+hiddenFiles->h(), 152, 20);
+               where = new geInput(groupTop->x(), hiddenFiles->y()+hiddenFiles->h(), 20, 20);
                updir   = new geButton(groupTop->x()+groupTop->w()-20, where->y(), 20, 20, "", updirOff_xpm, updirOn_xpm);
        groupTop->end();
        groupTop->resizable(where);
@@ -108,18 +108,31 @@ gdBrowserBase::~gdBrowserBase()
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserBase::cb_up   (Fl_Widget *v, void *p) { ((gdBrowserBase*)p)->__cb_up(); }
-void gdBrowserBase::cb_close(Fl_Widget *v, void *p) { ((gdBrowserBase*)p)->__cb_close(); }
-void gdBrowserBase::cb_toggleHiddenFiles(Fl_Widget *v, void *p) { ((gdBrowserBase*)p)->__cb_toggleHiddenFiles(); }
+void gdBrowserBase::cb_up   (Fl_Widget* v, void* p) { ((gdBrowserBase*)p)->cb_up(); }
+void gdBrowserBase::cb_close(Fl_Widget* v, void* p) { ((gdBrowserBase*)p)->cb_close(); }
+void gdBrowserBase::cb_toggleHiddenFiles(Fl_Widget *v, void *p) { ((gdBrowserBase*)p)->cb_toggleHiddenFiles(); }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserBase::__cb_up()
+void gdBrowserBase::cb_up()
 {
        string dir = browser->getCurrentDir();
-       dir = dir.substr(0, dir.find_last_of(G_SLASH_STR));  // remove up to the next slash
+
+       /* Take 'dir' path and remove all chars up to the next slash, e.g.:
+               /path/to/my/dir -> /path/to/my
+       Make sure not to remove the leading '/' (OS X/Linux only). */
+
+       dir = dir.substr(0, dir.find_last_of(G_SLASH_STR));
+
+#if defined(G_OS_MAC) || defined(G_OS_LINUX)
+
+       if (dir.empty())
+               dir = G_SLASH_STR;
+
+#endif
+
        browser->loadDir(dir);
        where->value(browser->getCurrentDir().c_str());
 }
@@ -128,7 +141,7 @@ void gdBrowserBase::__cb_up()
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserBase::__cb_close()
+void gdBrowserBase::cb_close()
 {
        do_callback();
 }
@@ -137,7 +150,7 @@ void gdBrowserBase::__cb_close()
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserBase::__cb_toggleHiddenFiles()
+void gdBrowserBase::cb_toggleHiddenFiles()
 {
        browser->toggleHiddenFiles();
 }
index f96dab10eea82ce2d3d39345d2de8a07131d94f4..9ca486a735cbd0ff67bfc7f173c411006bdb3440 100644 (file)
@@ -45,32 +45,31 @@ class gdBrowserBase : public gdWindow
 {
 protected:
 
-  Channel *channel;
-
-       Fl_Group   *groupTop;
-  geCheck    *hiddenFiles;
-       geBrowser  *browser;
-       geButton   *ok;
-       geButton   *cancel;
-       geInput    *where;
-       geButton   *updir;
-       geProgress *status;
-
-       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_toggleHiddenFiles();
+       Channel* channel;
+
+       Fl_Group* groupTop;
+       geCheck* hiddenFiles;
+       geBrowser* browser;
+       geButton* ok;
+       geButton* cancel;
+       geInput* where;
+       geButton* updir;
+       geProgress* status;
+
+       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);
+       void cb_up();
+       void cb_close();
+       void cb_toggleHiddenFiles();
 
        /* Callback
         * Fired when the save/load button is pressed. */
 
        void (*callback)(void*);
 
-  gdBrowserBase(int x, int y, int w, int h, const std::string &title,
-               const std::string &path,        void (*callback)(void*));
+       gdBrowserBase(int x, int y, int w, int h, const std::string& title,
+                       const std::string& path, void (*callback)(void*));
 
 public:
 
@@ -88,9 +87,9 @@ public:
 
        void showStatusBar();
        void hideStatusBar();
-  std::string getCurrentPath();
+       std::string getCurrentPath();
 
-       Channel *getChannel() { return channel; }
+       ChannelgetChannel() { return channel; }
        void fireCallback()   { callback((void*) this); }
 };
 
index 4717fdd800697a276c168cdcb7d797b8b3ab263b..d8e9dd13a3d23cdc742c97718ca6356295204848 100644 (file)
@@ -35,8 +35,8 @@
 using std::string;
 
 
-gdBrowserLoad::gdBrowserLoad(int x, int y, int w, int h, const string &title,
-               const string &path, void (*cb)(void*), Channel *ch)
+gdBrowserLoad::gdBrowserLoad(int x, int y, int w, int h, const stringtitle,
+               const string& path, void (*cb)(void*), Channel* ch)
        :       gdBrowserBase(x, y, w, h, title, path, cb)
 {
        channel = ch;
@@ -48,20 +48,25 @@ gdBrowserLoad::gdBrowserLoad(int x, int y, int w, int h, const string &title,
        ok->label("Load");
        ok->callback(cb_load, (void*) this);
        ok->shortcut(FL_ENTER);
+
+       /* On OS X the 'where' input doesn't get resized properly on startup. Let's 
+       force it. */
+       
+       where->redraw();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserLoad::cb_load(Fl_Widget *v, void *p) { ((gdBrowserLoad*)p)->__cb_load(); }
-void gdBrowserLoad::cb_down(Fl_Widget *v, void *p) { ((gdBrowserLoad*)p)->__cb_down(); }
+void gdBrowserLoad::cb_load(Fl_Widget* v, void* p) { ((gdBrowserLoad*)p)->cb_load(); }
+void gdBrowserLoad::cb_down(Fl_Widget* v, void* p) { ((gdBrowserLoad*)p)->cb_down(); }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserLoad::__cb_load()
+void gdBrowserLoad::cb_load()
 {
        callback((void*) this);
 }
@@ -70,7 +75,7 @@ void gdBrowserLoad::__cb_load()
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserLoad::__cb_down()
+void gdBrowserLoad::cb_down()
 {
        string path = browser->getSelectedItem();
 
index b1ad7629cdf43327a4ce5662373b5c27167ab5f3..e361484a6b0eeb49d6a6f3860242f17a1a74b476 100644 (file)
@@ -46,16 +46,15 @@ class gdBrowserLoad : public gdBrowserBase
 {
 private:
 
-       static void cb_load(Fl_Widget *w, void *p);
-       static void cb_down(Fl_Widget *v, void *p);
-
-       inline void __cb_load();
-       inline void __cb_down();
+       static void cb_load(Fl_Widget* w, void* p);
+       static void cb_down(Fl_Widget* v, void* p);
+       void cb_load();
+       void cb_down();
 
 public:
 
-       gdBrowserLoad(int x, int y, int w, int h, const std::string &title,
-                       const std::string &path,        void (*callback)(void*), Channel *ch);
+       gdBrowserLoad(int x, int y, int w, int h, const std::stringtitle,
+                       const std::string& path, void (*callback)(void*), Channel* ch);
 };
 
 
index 7011bc1b3da0e27694ad717c1e807e74ea657cb2..ad765b9912554386b3d1638827eb60ccf38ee58e 100644 (file)
@@ -35,8 +35,8 @@
 using std::string;
 
 
-gdBrowserSave::gdBrowserSave(int x, int y, int w, int h, const string &title,
-               const string &path, const string &_name, void (*cb)(void*), Channel *ch)
+gdBrowserSave::gdBrowserSave(int x, int y, int w, int h, const stringtitle,
+               const string& path, const string& _name, void (*cb)(void*), Channel* ch)
        :       gdBrowserBase(x, y, w, h, title, path, cb)
 {
        channel = ch;
@@ -52,20 +52,26 @@ gdBrowserSave::gdBrowserSave(int x, int y, int w, int h, const string &title,
        ok->label("Save");
        ok->callback(cb_save, (void*) this);
        ok->shortcut(FL_ENTER);
+
+       /* On OS X the 'where' and 'name' inputs don't get resized properly on startup. 
+       Let's force them. */
+
+       where->redraw();
+       name->redraw();
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserSave::cb_save(Fl_Widget *v, void *p) { ((gdBrowserSave*)p)->__cb_save(); }
-void gdBrowserSave::cb_down(Fl_Widget *v, void *p) { ((gdBrowserSave*)p)->__cb_down(); }
+void gdBrowserSave::cb_save(Fl_Widget* v, void* p) { ((gdBrowserSave*)p)->cb_save(); }
+void gdBrowserSave::cb_down(Fl_Widget* v, void* p) { ((gdBrowserSave*)p)->cb_down(); }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserSave::__cb_down()
+void gdBrowserSave::cb_down()
 {
        string path = browser->getSelectedItem();
 
@@ -96,7 +102,7 @@ string gdBrowserSave::getName()
 /* -------------------------------------------------------------------------- */
 
 
-void gdBrowserSave::__cb_save()
+void gdBrowserSave::cb_save()
 {
        callback((void*) this);
 }
index 3b7f8189e00d7f68e34858e7ca29c190bcf30ebd..53cb61b0e31a77087448cb32e25c681738e03465 100644 (file)
@@ -46,19 +46,18 @@ class gdBrowserSave : public gdBrowserBase
 {
 private:
 
-       geInput *name;
+       geInputname;
 
-       static void cb_down(Fl_Widget *v, void *p);
-       static void cb_save(Fl_Widget *w, void *p);
-
-       inline void __cb_down();
-       inline void __cb_save();
+       static void cb_down(Fl_Widget* v, void* p);
+       static void cb_save(Fl_Widget* w, void* p);
+       void cb_down();
+       void cb_save();
 
 public:
 
-       gdBrowserSave(int x, int y, int w, int h, const std::string &title,
-                       const std::string &path,        const std::string &name, void (*callback)(void*),
-                       Channel *ch);
+       gdBrowserSave(int x, int y, int w, int h, const std::stringtitle,
+                       const std::string& path, const std::string& name, void (*callback)(void*),
+                       Channelch);
 
        std::string getName();
 };
diff --git a/src/gui/dialogs/channelNameInput.cpp b/src/gui/dialogs/channelNameInput.cpp
new file mode 100644 (file)
index 0000000..a0bd3bc
--- /dev/null
@@ -0,0 +1,101 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include "../../glue/channel.h"
+#include "../../utils/gui.h"
+#include "../../core/const.h"
+#include "../../core/conf.h"
+#include "../../core/channel.h"
+#include "../elems/basics/button.h"
+#include "../elems/basics/input.h"
+#include "channelNameInput.h"
+
+
+using namespace giada::m;
+
+
+gdChannelNameInput::gdChannelNameInput(Channel* ch)
+: gdWindow(400, 64, "New channel name"),
+  m_ch    (ch)
+{
+       if (conf::nameX)
+               resize(conf::nameX, conf::nameY, w(), h());
+
+       set_modal();
+
+       m_name = new geInput(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, w() - (G_GUI_OUTER_MARGIN * 2), G_GUI_UNIT);
+       m_ok = new geButton(w() - 70 - G_GUI_OUTER_MARGIN, m_name->y()+m_name->h() + G_GUI_OUTER_MARGIN, 70, G_GUI_UNIT, "Ok");
+       m_cancel = new geButton(m_ok->x() - 70 - G_GUI_OUTER_MARGIN, m_ok->y(), 70, G_GUI_UNIT, "Cancel");
+       end();
+
+       m_name->value(m_ch->getName().c_str());
+
+       m_ok->shortcut(FL_Enter);
+       m_ok->callback(cb_update, (void*)this);
+
+       m_cancel->callback(cb_cancel, (void*)this);
+
+       gu_setFavicon(this);
+       setId(WID_SAMPLE_NAME);
+       show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdChannelNameInput::~gdChannelNameInput()
+{
+       conf::nameX = x();
+       conf::nameY = y();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdChannelNameInput::cb_update(Fl_Widget* w, void* p) { ((gdChannelNameInput*)p)->cb_update(); }
+void gdChannelNameInput::cb_cancel(Fl_Widget* w, void* p) { ((gdChannelNameInput*)p)->cb_cancel(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdChannelNameInput::cb_cancel()
+{
+       do_callback();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdChannelNameInput::cb_update()
+{
+       glue_setName(m_ch, m_name->value());
+       do_callback();
+}
diff --git a/src/gui/dialogs/channelNameInput.h b/src/gui/dialogs/channelNameInput.h
new file mode 100644 (file)
index 0000000..86f03d5
--- /dev/null
@@ -0,0 +1,61 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef GD_CHANNEL_NAME_INPUT_H
+#define GD_CHANNEL_NAME_INPUT_H
+
+
+#include "window.h"
+
+
+class Channel;
+class geInput;
+class geButton;
+
+
+class gdChannelNameInput : public gdWindow
+{
+private:
+
+       static void cb_update(Fl_Widget* w, void* p);
+       static void cb_cancel(Fl_Widget* w, void* p);
+       void cb_update();
+       void cb_cancel();
+
+       Channel* m_ch;
+
+       geInput* m_name;
+       geButton* m_ok;
+       geButton* m_cancel;
+
+public:
+
+       gdChannelNameInput(Channel* ch);
+       ~gdChannelNameInput();
+};
+
+#endif
diff --git a/src/gui/dialogs/gd_beatsInput.cpp b/src/gui/dialogs/gd_beatsInput.cpp
deleted file mode 100644 (file)
index a00c2d7..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#include "../../utils/gui.h"
-#include "../../core/mixer.h"
-#include "../../core/clock.h"
-#include "../../core/conf.h"
-#include "../../core/const.h"
-#include "../../glue/main.h"
-#include "../elems/basics/input.h"
-#include "../elems/basics/button.h"
-#include "../elems/basics/check.h"
-#include "gd_beatsInput.h"
-#include "gd_mainWindow.h"
-
-
-extern gdMainWindow *mainWin;
-
-
-using namespace giada::m;
-
-
-gdBeatsInput::gdBeatsInput()
-       : gdWindow(164, 60, "Beats")
-{
-       if (conf::beatsX)
-               resize(conf::beatsX, conf::beatsY, w(), h());
-
-       set_modal();
-
-       beats     = new geInput(8,  8,  35, 20);
-       bars      = new geInput(47, 8,  35, 20);
-       ok                  = new geButton(86, 8,  70, 20, "Ok");
-       resizeRec = new geCheck(8,  40, 12, 12, "resize recorded actions");
-       end();
-
-       char buf_bars[3]; sprintf(buf_bars, "%d", clock::getBars());
-       char buf_beats[3]; sprintf(buf_beats, "%d", clock::getBeats());
-       beats->maximum_size(2);
-       beats->value(buf_beats);
-       beats->type(FL_INT_INPUT);
-       bars->maximum_size(2);
-       bars->value(buf_bars);
-       bars->type(FL_INT_INPUT);
-       ok->shortcut(FL_Enter);
-       ok->callback(cb_update_batt, (void*)this);
-       resizeRec->value(conf::resizeRecordings);
-
-       gu_setFavicon(this);
-       setId(WID_BEATS);
-       show();
-}
-
-
-/* ------------------------------------------------------------------ */
-
-
-gdBeatsInput::~gdBeatsInput()
-{
-       conf::beatsX = x();
-       conf::beatsY = y();
-       conf::resizeRecordings =        resizeRec->value();
-}
-
-
-/* ------------------------------------------------------------------ */
-
-
-void gdBeatsInput::cb_update_batt(Fl_Widget *w, void *p) { ((gdBeatsInput*)p)->__cb_update_batt(); }
-
-
-/* ------------------------------------------------------------------ */
-
-
-void gdBeatsInput::__cb_update_batt()
-{
-       if (!strcmp(beats->value(), "") || !strcmp(bars->value(), ""))
-               return;
-       glue_setBeats(atoi(beats->value()), atoi(bars->value()), resizeRec->value());
-       do_callback();
-}
diff --git a/src/gui/dialogs/gd_beatsInput.h b/src/gui/dialogs/gd_beatsInput.h
deleted file mode 100644 (file)
index 90150ea..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* ---------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ---------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * ------------------------------------------------------------------ */
-
-#ifndef GD_BEATSINPUT_H
-#define GD_BEATSINPUT_H
-
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include "window.h"
-
-
-class geInput;
-class geButton;
-class geCheck;
-
-
-class gdBeatsInput : public gdWindow
-{
-private:
-
-       static void cb_update_batt(Fl_Widget *w, void *p);
-       inline void __cb_update_batt();
-
-       geInput  *beats;
-       geInput  *bars;
-       geButton *ok;
-       geCheck   *resizeRec;
-
-public:
-
-       gdBeatsInput();
-       ~gdBeatsInput();
-};
-
-
-#endif
diff --git a/src/gui/dialogs/gd_bpmInput.cpp b/src/gui/dialogs/gd_bpmInput.cpp
deleted file mode 100644 (file)
index c3fbe0a..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#include <cstring>
-#include "../../core/conf.h"
-#include "../../core/const.h"
-#include "../../core/mixer.h"
-#include "../../core/clock.h"
-#include "../../glue/main.h"
-#include "../../utils/gui.h"
-#include "../elems/basics/button.h"
-#include "../elems/basics/input.h"
-#include "gd_bpmInput.h"
-#include "gd_mainWindow.h"
-
-
-extern gdMainWindow *mainWin;
-
-
-using namespace giada::m;
-
-
-gdBpmInput::gdBpmInput(const char *label)
-: gdWindow(144, 36, "Bpm")
-{
-       if (conf::bpmX)
-               resize(conf::bpmX, conf::bpmY, w(), h());
-
-       set_modal();
-
-       input_a = new geInput(8,  8, 30, 20);
-       input_b = new geInput(42, 8, 20, 20);
-       ok                = new geButton(66, 8, 70, 20, "Ok");
-       end();
-
-       char   a[4];
-       snprintf(a, 4, "%d", (int) clock::getBpm());
-       char   b[2];
-       for (unsigned i=0; i<strlen(label); i++)        // looking for the dot
-               if (label[i] == '.') {
-                       snprintf(b, 2, "%c", label[i+1]);
-                       break;
-               }
-
-       input_a->maximum_size(3);
-       input_a->type(FL_INT_INPUT);
-       input_a->value(a);
-       input_b->maximum_size(1);
-       input_b->type(FL_INT_INPUT);
-       input_b->value(b);
-
-       ok->shortcut(FL_Enter);
-       ok->callback(cb_update_bpm, (void*)this);
-
-       gu_setFavicon(this);
-       setId(WID_BPM);
-       show();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gdBpmInput::~gdBpmInput()
-{
-       conf::bpmX = x();
-       conf::bpmY = y();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdBpmInput::cb_update_bpm(Fl_Widget *w, void *p) { ((gdBpmInput*)p)->__cb_update_bpm(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdBpmInput::__cb_update_bpm()
-{
-       if (strcmp(input_a->value(), "") == 0)
-               return;
-       glue_setBpm(input_a->value(), input_b->value());
-       do_callback();
-}
diff --git a/src/gui/dialogs/gd_bpmInput.h b/src/gui/dialogs/gd_bpmInput.h
deleted file mode 100644 (file)
index 0f7a166..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifndef GD_BPMINPUT_H
-#define GD_BPMINPUT_H
-
-
-#include "window.h"
-
-
-class geInput;
-class geButton;
-
-
-class gdBpmInput : public gdWindow
-{
-private:
-
-       static void cb_update_bpm(Fl_Widget *w, void *p);
-       inline void __cb_update_bpm();
-
-  geInput  *input_a;
-  geInput  *input_b;
-  geButton *ok;
-
-public:
-
-       gdBpmInput(const char *label); // pointer to mainWin->timing->bpm->label()
-       ~gdBpmInput();
-};
-
-#endif
diff --git a/src/gui/dialogs/gd_pluginChooser.cpp b/src/gui/dialogs/gd_pluginChooser.cpp
deleted file mode 100644 (file)
index 8c62705..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-
-#include "../../glue/plugin.h"
-#include "../../utils/gui.h"
-#include "../../core/channel.h"
-#include "../../core/conf.h"
-#include "../../core/pluginHost.h"
-#include "../elems/pluginBrowser.h"
-#include "../elems/basics/button.h"
-#include "../elems/basics/choice.h"
-#include "../elems/basics/box.h"
-#include "gd_pluginChooser.h"
-
-
-using namespace giada::m;
-
-
-gdPluginChooser::gdPluginChooser(int X, int Y, int W, int H, int stackType, Channel *ch)
-  : gdWindow(X, Y, W, H, "Available plugins"), ch(ch), stackType(stackType)
-{
-  /* top area */
-  Fl_Group *group_top = new Fl_Group(8, 8, w()-16, 20);
-  sortMethod = new geChoice(group_top->x() + 45, group_top->y(), 100, 20, "Sort by");
-    geBox *b1 = new geBox(sortMethod->x()+sortMethod->w(), group_top->y(), 100, 20);   // spacer window border <-> menu
-  group_top->resizable(b1);
-  group_top->end();
-
-  /* center browser */
-  browser = new gePluginBrowser(8, 36, w()-16, h()-70);
-
-  /* ok/cancel buttons */
-  Fl_Group *group_btn = new Fl_Group(8, browser->y()+browser->h()+8, w()-16, h()-browser->h()-16);
-    geBox *b2 = new geBox(8, browser->y()+browser->h(), 100, 20);      // spacer window border <-> buttons
-    addBtn = new geButton(w()-88, group_btn->y(), 80, 20, "Add");
-    cancelBtn = new geButton(addBtn->x()-88, group_btn->y(), 80, 20, "Cancel");
-  group_btn->resizable(b2);
-  group_btn->end();
-
-  end();
-
-  sortMethod->add("Name");
-  sortMethod->add("Category");
-  sortMethod->add("Manufacturer");
-  sortMethod->callback(cb_sort, (void*) this);
-  sortMethod->value(conf::pluginSortMethod);
-
-  addBtn->callback(cb_add, (void*) this);
-  addBtn->shortcut(FL_Enter);
-  cancelBtn->callback(cb_close, (void*) this);
-
-  resizable(browser);
-       gu_setFavicon(this);
-  show();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gdPluginChooser::~gdPluginChooser()
-{
-  conf::pluginChooserX = x();
-  conf::pluginChooserY = y();
-  conf::pluginChooserW = w();
-  conf::pluginChooserH = h();
-  conf::pluginSortMethod = sortMethod->value();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginChooser::cb_close(Fl_Widget *v, void *p) { ((gdPluginChooser*)p)->__cb_close(); }
-void gdPluginChooser::cb_add(Fl_Widget *v, void *p)   { ((gdPluginChooser*)p)->__cb_add(); }
-void gdPluginChooser::cb_sort(Fl_Widget *v, void *p)  { ((gdPluginChooser*)p)->__cb_sort(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginChooser::__cb_close()
-{
-       do_callback();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginChooser::__cb_sort()
-{
-       pluginHost::sortPlugins(sortMethod->value());
-  browser->refresh();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginChooser::__cb_add()
-{
-  int index = browser->value() - 3; // subtract header lines
-  if (index < 0)
-    return;
-  glue_addPlugin(ch, index, stackType);
-  do_callback();
-}
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginChooser.h b/src/gui/dialogs/gd_pluginChooser.h
deleted file mode 100644 (file)
index f74c374..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-#ifndef GD_PLUGIN_CHOOSER_H
-#define GD_PLUGIN_CHOOSER_H
-
-
-#include <FL/Fl.H>
-#include <FL/Fl_Scroll.H>
-#include "window.h"
-
-
-class Channel;
-class geChoice;
-class geButton;
-class geButton;
-class gePluginBrowser;
-
-
-class gdPluginChooser : public gdWindow
-{
-private:
-
-  Channel *ch;      // ch == nullptr ? masterOut
-       int stackType;
-
-  geChoice         *sortMethod;
-  geButton        *addBtn;
-  geButton        *cancelBtn;
-  gePluginBrowser *browser;
-
-       static void cb_close(Fl_Widget *w, void *p);
-       static void cb_add  (Fl_Widget *w, void *p);
-       static void cb_sort (Fl_Widget *w, void *p);
-  inline void __cb_close();
-  inline void __cb_add  ();
-  inline void __cb_sort ();
-
-public:
-
-       gdPluginChooser(int x, int y, int w, int h, int stackType, Channel *ch=nullptr);
-  ~gdPluginChooser();
-};
-
-
-#endif
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginList.cpp b/src/gui/dialogs/gd_pluginList.cpp
deleted file mode 100644 (file)
index edb8de7..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-
-#include "../../utils/gui.h"
-#include "../../utils/fs.h"
-#include "../../core/conf.h"
-#include "../../core/const.h"
-#include "../../core/graphics.h"
-#include "../../core/pluginHost.h"
-#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/basics/boxtypes.h"
-#include "../elems/basics/idButton.h"
-#include "../elems/basics/statusButton.h"
-#include "../elems/basics/choice.h"
-#include "../elems/mainWindow/mainIO.h"
-#include "../elems/mainWindow/keyboard/channel.h"
-#include "gd_pluginList.h"
-#include "gd_pluginChooser.h"
-#include "gd_pluginWindow.h"
-#include "gd_pluginWindowGUI.h"
-#include "gd_mainWindow.h"
-
-
-extern gdMainWindow *G_MainWin;
-
-
-using std::string;
-using namespace giada::m;
-
-
-gdPluginList::gdPluginList(int stackType, Channel *ch)
-  : gdWindow(468, 204), ch(ch), stackType(stackType)
-{
-       if (conf::pluginListX)
-               resize(conf::pluginListX, conf::pluginListY, w(), h());
-
-       list = new Fl_Scroll(8, 8, 476, 188);
-       list->type(Fl_Scroll::VERTICAL);
-       list->scrollbar.color(G_COLOR_GREY_2);
-       list->scrollbar.selection_color(G_COLOR_GREY_4);
-       list->scrollbar.labelcolor(G_COLOR_LIGHT_1);
-       list->scrollbar.slider(G_CUSTOM_BORDER_BOX);
-
-       list->begin();
-               refreshList();
-       list->end();
-
-       end();
-       set_non_modal();
-
-  /* TODO - awful stuff... we should subclass into gdPluginListChannel and
-  gdPluginListMaster */
-
-       if (stackType == pluginHost::MASTER_OUT)
-               label("Master Out Plugins");
-       else
-       if (stackType == pluginHost::MASTER_IN)
-               label("Master In Plugins");
-       else {
-    string l = "Channel " + gu_toString(ch->index+1) + " Plugins";
-    copy_label(l.c_str());
-       }
-
-       gu_setFavicon(this);
-       show();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gdPluginList::~gdPluginList()
-{
-       conf::pluginListX = x();
-       conf::pluginListY = y();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginList::cb_addPlugin(Fl_Widget *v, void *p)   { ((gdPluginList*)p)->__cb_addPlugin(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-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). */
-
-       gdWindow *child = (gdWindow*) v;
-       if (child->getParent() != nullptr)
-               (child->getParent())->delSubWindow(child);
-
-       /* finally refresh plugin list: void *p is a pointer to gdPluginList.
-        * This callback works even when you click 'x' to close the window...
-        * well, who cares */
-
-       ((gdPluginList*)p)->refreshList();
-       ((gdPluginList*)p)->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginList::__cb_addPlugin()
-{
-       /* the usual callback that gdWindow 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
-        * we add to gdPluginChooser. It does exactly what we need. */
-
-  gdPluginChooser *pc = new gdPluginChooser(conf::pluginChooserX,
-      conf::pluginChooserY, conf::pluginChooserW, conf::pluginChooserH,
-      stackType, ch);
-  addSubWindow(pc);
-  pc->callback(cb_refreshList, (void*)this);   // 'this' refers to gdPluginList
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginList::refreshList()
-{
-       /* delete the previous list */
-
-       list->clear();
-       list->scroll_to(0, 0);
-
-       /* add new buttons, as many as the plugin in pluginHost::stack + 1,
-        * the 'add new' button. Warning: if ch == nullptr we are working with
-        * master in/master out stacks. */
-
-       int numPlugins = pluginHost::countPlugins(stackType, ch);
-       int i = 0;
-
-       while (i<numPlugins) {
-               Plugin   *pPlugin = pluginHost::getPluginByIndex(i, stackType, ch);
-               gdPlugin *gdp     = new gdPlugin(this, pPlugin, list->x(), list->y()-list->yposition()+(i*24), 800);
-               list->add(gdp);
-               i++;
-       }
-
-       int addPlugY = numPlugins == 0 ? 90 : list->y()-list->yposition()+(i*24);
-       addPlugin = new geButton(8, addPlugY, 452, 20, "-- add new plugin --");
-       addPlugin->callback(cb_addPlugin, (void*)this);
-       list->add(addPlugin);
-
-       /* if num(plugins) > 7 make room for the side scrollbar.
-        * Scrollbar.width = 20 + 4(margin) */
-
-       if (i>7)
-               size(492, h());
-       else
-               size(468, h());
-
-       redraw();
-
-  /* set 'full' flag to FX button */
-
-  /* TODO - awful stuff... we should subclass into gdPluginListChannel and
-  gdPluginListMaster */
-
-       if (stackType == pluginHost::MASTER_OUT) {
-    G_MainWin->mainIO->setMasterFxOutFull(
-                       pluginHost::countPlugins(stackType, ch) > 0);
-  }
-       else
-       if (stackType == pluginHost::MASTER_IN) {
-    G_MainWin->mainIO->setMasterFxInFull(
-                       pluginHost::countPlugins(stackType, ch) > 0);
-  }
-       else {
-    ch->guiChannel->fx->status = pluginHost::countPlugins(stackType, ch) > 0;
-    ch->guiChannel->fx->redraw();
-  }
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gdPlugin::gdPlugin(gdPluginList *gdp, Plugin *p, int X, int Y, int W)
-       : Fl_Group(X, Y, W, 20), pParent(gdp), pPlugin (p)
-{
-       begin();
-       button    = new geIdButton(8, y(), 220, 20);
-       program   = new geChoice(button->x()+button->w()+4, y(), 132, 20);
-       bypass    = new geIdButton(program->x()+program->w()+4, y(), 20, 20);
-       shiftUp   = new geIdButton(bypass->x()+bypass->w()+4, y(), 20, 20, "", fxShiftUpOff_xpm, fxShiftUpOn_xpm);
-       shiftDown = new geIdButton(shiftUp->x()+shiftUp->w()+4, y(), 20, 20, "", fxShiftDownOff_xpm, fxShiftDownOn_xpm);
-       remove    = new geIdButton(shiftDown->x()+shiftDown->w()+4, y(), 20, 20, "", fxRemoveOff_xpm, fxRemoveOn_xpm);
-       end();
-
-       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++)
-    program->add(gu_removeFltkChars(pPlugin->getProgramName(i)).c_str());
-
-       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);
-       remove->callback(cb_removePlugin, (void*)this);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::cb_removePlugin    (Fl_Widget *v, void *p)    { ((gdPlugin*)p)->__cb_removePlugin(); }
-void gdPlugin::cb_openPluginWindow(Fl_Widget *v, void *p)    { ((gdPlugin*)p)->__cb_openPluginWindow(); }
-void gdPlugin::cb_setBypass       (Fl_Widget *v, void *p)    { ((gdPlugin*)p)->__cb_setBypass(); }
-void gdPlugin::cb_shiftUp         (Fl_Widget *v, void *p)    { ((gdPlugin*)p)->__cb_shiftUp(); }
-void gdPlugin::cb_shiftDown       (Fl_Widget *v, void *p)    { ((gdPlugin*)p)->__cb_shiftDown(); }
-void gdPlugin::cb_setProgram      (Fl_Widget *v, void *p)    { ((gdPlugin*)p)->__cb_setProgram(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::__cb_shiftUp()
-{
-       /*nothing to do if there's only one plugin */
-
-       if (pluginHost::countPlugins(pParent->stackType, pParent->ch) == 1)
-               return;
-
-       int pluginIndex = pluginHost::getPluginIndex(pPlugin->getId(),
-    pParent->stackType, pParent->ch);
-
-       if (pluginIndex == 0)  // first of the stack, do nothing
-               return;
-
-  glue_swapPlugins(pParent->ch, pluginIndex, pluginIndex-1, pParent->stackType);
-       pParent->refreshList();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::__cb_shiftDown()
-{
-       /*nothing to do if there's only one plugin */
-
-       if (pluginHost::countPlugins(pParent->stackType, pParent->ch) == 1)
-               return;
-
-       unsigned pluginIndex = pluginHost::getPluginIndex(pPlugin->getId(), pParent->stackType, pParent->ch);
-       unsigned stackSize   = (pluginHost::getStack(pParent->stackType, pParent->ch))->size();
-
-       if (pluginIndex == stackSize-1)  // last one in the stack, do nothing
-               return;
-
-  glue_swapPlugins(pParent->ch, pluginIndex, pluginIndex+1, pParent->stackType);
-       pParent->refreshList();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::__cb_removePlugin()
-{
-       /* any subwindow linked to the plugin must be destroyed first */
-
-       pParent->delSubWindow(pPlugin->getId());
-  glue_freePlugin(pParent->ch, pPlugin->getId(), pParent->stackType);
-  pParent->refreshList();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::__cb_openPluginWindow()
-{
-  /* the new pluginWindow has id = id_plugin + 1, because id=0 is reserved
-  * for the parent window 'add plugin'. */
-
-  gdWindow *w;
-  if (pPlugin->hasEditor()) {
-    if (pPlugin->isEditorOpen()) {
-      gu_log("[gdPlugin::__cb_openPluginWindow] plugin has editor but it's already visible\n");
-      return;
-    }
-
-    int pwid = pPlugin->getId()+1;
-
-    gu_log("[gdPlugin::__cb_openPluginWindow] plugin has editor, open window id=%d\n", pwid);
-
-    if (pParent->hasWindow(pwid))
-      pParent->delSubWindow(pwid);
-    w = new gdPluginWindowGUI(pPlugin);
-    w->setId(pwid);
-               pParent->addSubWindow(w);
-  }
-  else {
-    w = new gdPluginWindow(pPlugin);
-  }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::__cb_setBypass()
-{
-       pPlugin->toggleBypass();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPlugin::__cb_setProgram()
-{
-       pPlugin->setCurrentProgram(program->value());
-}
-
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginList.h b/src/gui/dialogs/gd_pluginList.h
deleted file mode 100644 (file)
index c8e88ce..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-#ifndef GD_PLUGINLIST_H
-#define GD_PLUGINLIST_H
-
-#include <FL/Fl.H>
-#include <FL/Fl_Scroll.H>
-#include "window.h"
-
-
-class Plugin;
-class Channel;
-class geButton;
-class gdPluginList;
-class geIdButton;
-class geChoice;
-
-
-class gdPluginList : public gdWindow
-{
-private:
-
-  geButton  *addPlugin;
-       Fl_Scroll *list;
-
-       static void cb_addPlugin  (Fl_Widget *v, void *p);
-       inline void __cb_addPlugin();
-
-public:
-
-       Channel *ch;      // ch == nullptr ? masterOut
-       int stackType;
-
-       gdPluginList(int stackType, Channel *ch=nullptr);
-       ~gdPluginList();
-
-       /* special callback, passed to browser. When closed (i.e. plugin
-        * has been selected) the same browser will refresh this window. */
-
-       static void cb_refreshList(Fl_Widget*, void*);
-
-       void refreshList();
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class gdPlugin : public Fl_Group
-{
-private:
-
-  gdPluginList *pParent;
-  Plugin       *pPlugin;
-
-       static void cb_removePlugin       (Fl_Widget *v, void *p);
-       static void cb_openPluginWindow   (Fl_Widget *v, void *p);
-       static void cb_setBypass          (Fl_Widget *v, void *p);
-       static void cb_shiftUp            (Fl_Widget *v, void *p);
-       static void cb_shiftDown          (Fl_Widget *v, void *p);
-       static void cb_setProgram         (Fl_Widget *v, void *p);
-       inline void __cb_removePlugin     ();
-       inline void __cb_openPluginWindow ();
-       inline void __cb_setBypass        ();
-       inline void __cb_shiftUp          ();
-       inline void __cb_shiftDown        ();
-       inline void __cb_setProgram       ();
-
-public:
-
-       geIdButton *button;
-       geChoice    *program;
-       geIdButton *bypass;
-       geIdButton *shiftUp;
-       geIdButton *shiftDown;
-       geIdButton *remove;
-
-       gdPlugin(gdPluginList *gdp, Plugin *p, int x, int y, int w);
-};
-
-#endif
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginWindow.cpp b/src/gui/dialogs/gd_pluginWindow.cpp
deleted file mode 100644 (file)
index 23316df..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-
-#include <FL/Fl_Scroll.H>
-#include "../../utils/gui.h"
-#include "../../core/plugin.h"
-#include "../elems/basics/boxtypes.h"
-#include "../elems/basics/box.h"
-#include "../elems/basics/liquidScroll.h"
-#include "../elems/basics/slider.h"
-#include "gd_pluginWindow.h"
-
-
-using std::string;
-
-
-Parameter::Parameter(int paramIndex, Plugin *p, int X, int Y, int W)
-       : Fl_Group(X, Y, W-24, 20), paramIndex(paramIndex), pPlugin(p)
-{
-       begin();
-
-               label = new geBox(x(), y(), 60, 20);
-               label->copy_label(pPlugin->getParameterName(paramIndex).c_str());
-               label->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
-
-               slider = new geSlider(label->x()+label->w()+8, y(), W-200, 20);
-               slider->value(pPlugin->getParameter(paramIndex));
-               slider->callback(cb_setValue, (void *)this);
-
-               value = new geBox(slider->x()+slider->w()+8, y(), 100, 20);
-               value->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
-               value->box(G_CUSTOM_BORDER_BOX);
-               updateValue();
-
-               resizable(slider);
-
-       end();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void Parameter::cb_setValue(Fl_Widget *v, void *p)  { ((Parameter*)p)->__cb_setValue(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void Parameter::__cb_setValue()
-{
-       pPlugin->setParameter(paramIndex, slider->value());
-       updateValue();
-       value->redraw();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void Parameter::updateValue()
-{
-       string v = pPlugin->getParameterText(paramIndex) + " " +
-                       pPlugin->getParameterLabel(paramIndex);
-       value->copy_label(v.c_str());
-}
-
-
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-/* -------------------------------------------------------------------------- */
-
-
-gdPluginWindow::gdPluginWindow(Plugin *p)
- : gdWindow(400, 156), pPlugin(p) // 350
-{
-       set_non_modal();
-
-       geLiquidScroll *list = new geLiquidScroll(8, 8, w()-16, h()-16);
-       list->type(Fl_Scroll::VERTICAL_ALWAYS);
-       list->begin();
-
-       int numParams = pPlugin->getNumParameters();
-       for (int i=0; i<numParams; i++)
-               new Parameter(i, pPlugin, list->x(), list->y()+(i*24), list->w());
-       list->end();
-
-       end();
-
-       label(pPlugin->getName().c_str());
-
-       size_range(400, (24*1)+12);
-       resizable(list);
-
-       gu_setFavicon(this);
-       show();
-}
-
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginWindow.h b/src/gui/dialogs/gd_pluginWindow.h
deleted file mode 100644 (file)
index ff399ab..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-#ifdef WITH_VST
-
-#ifndef GD_PLUGIN_WINDOW_H
-#define GD_PLUGIN_WINDOW_H
-
-
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include "window.h"
-
-
-class Plugin;
-class geBox;
-class geSlider;
-
-
-class gdPluginWindow : public gdWindow
-{
-private:
-
-  Plugin *pPlugin;
-
-public:
-
-  int id;
-
-       gdPluginWindow(Plugin *pPlugin);
-};
-
-
-/* -------------------------------------------------------------------------- */
-
-
-class Parameter : public Fl_Group
-{
-private:
-
-  int paramIndex;
-       Plugin *pPlugin;
-
-       static void cb_setValue(Fl_Widget *v, void *p);
-       inline void __cb_setValue();
-
-       void updateValue();
-
-public:
-
-  geBox    *label;
-       geSlider *slider;
-       geBox    *value;
-
-       Parameter(int paramIndex, Plugin *p, int x, int y, int w);
-};
-
-
-#endif
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginWindowGUI.cpp b/src/gui/dialogs/gd_pluginWindowGUI.cpp
deleted file mode 100644 (file)
index afd5cb8..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-
-#include <FL/x.H>
-#include "../../utils/log.h"
-#include "../../utils/gui.h"
-#include "../../core/pluginHost.h"
-#include "../../core/plugin.h"
-#include "../../core/const.h"
-#include "gd_pluginWindowGUI.h"
-
-#ifdef __APPLE__
-#import "../../utils/cocoa.h" // objective-c
-#endif
-
-
-using namespace giada::m;
-
-
-gdPluginWindowGUI::gdPluginWindowGUI(Plugin *pPlugin)
- : gdWindow(450, 300), pPlugin(pPlugin)
-{
-  show();
-
-#ifndef __APPLE__
-
-  Fl::check();
-
-#endif
-
-  gu_log("[gdPluginWindowGUI] opening GUI, this=%p, xid=%p\n",
-    (void*) this, (void*) fl_xid(this));
-
-#if defined(__APPLE__)
-
-  void *cocoaWindow = (void*) fl_xid(this);
-  cocoa_setWindowSize(cocoaWindow, pPlugin->getEditorW(), pPlugin->getEditorH());
-  pPlugin->showEditor(cocoa_getViewFromWindow(cocoaWindow));
-
-#else
-
-  pPlugin->showEditor((void*) fl_xid(this));
-
-#endif
-
-  int pluginW = pPlugin->getEditorW();
-  int pluginH = pPlugin->getEditorH();
-
-  resize((Fl::w() - pluginW) / 2, (Fl::h() - pluginH) / 2, pluginW, pluginH);
-
-  Fl::add_timeout(G_GUI_PLUGIN_RATE, cb_refresh, (void*) this);
-
-  copy_label(pPlugin->getName().c_str());
-
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginWindowGUI::cb_close(Fl_Widget *v, void *p)   { ((gdPluginWindowGUI*)p)->__cb_close(); }
-void gdPluginWindowGUI::cb_refresh(void *data) { ((gdPluginWindowGUI*)data)->__cb_refresh(); }
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginWindowGUI::__cb_close()
-{
-  Fl::remove_timeout(cb_refresh);
-  pPlugin->closeEditor();
-  gu_log("[gdPluginWindowGUI::__cb_close] GUI closed, this=%p\n", (void*) this);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gdPluginWindowGUI::__cb_refresh()
-{
-  pluginHost::runDispatchLoop();
-  Fl::repeat_timeout(G_GUI_PLUGIN_RATE, cb_refresh, (void*) this);
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-gdPluginWindowGUI::~gdPluginWindowGUI()
-{
-  __cb_close();
-}
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/gd_pluginWindowGUI.h b/src/gui/dialogs/gd_pluginWindowGUI.h
deleted file mode 100644 (file)
index f19f083..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-
-/* ---------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * gd_pluginWindowGUI
- *
- * ---------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * ------------------------------------------------------------------ */
-
-
-#ifdef WITH_VST
-
-
-#ifndef GD_PLUGIN_WINDOW_GUI_H
-#define GD_PLUGIN_WINDOW_GUI_H
-
-
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include "window.h"
-#if defined(__APPLE__)
-       #include <Carbon/Carbon.h>
-#endif
-
-
-class Plugin;
-
-
-class gdPluginWindowGUI : public gdWindow
-{
-private:
-
-       Plugin *pPlugin;
-
-       static void cb_close    (Fl_Widget *v, void *p);
-       static void cb_refresh  (void *data);
-       inline void __cb_close  ();
-       inline void __cb_refresh();
-
-public:
-
-       gdPluginWindowGUI(Plugin *pPlugin);
-       ~gdPluginWindowGUI();
-};
-
-
-#endif // include guard
-
-#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginChooser.cpp b/src/gui/dialogs/pluginChooser.cpp
new file mode 100644 (file)
index 0000000..b7adc89
--- /dev/null
@@ -0,0 +1,138 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include "../../glue/plugin.h"
+#include "../../utils/gui.h"
+#include "../../core/channel.h"
+#include "../../core/conf.h"
+#include "../../core/pluginHost.h"
+#include "../elems/plugin/pluginBrowser.h"
+#include "../elems/basics/button.h"
+#include "../elems/basics/choice.h"
+#include "../elems/basics/box.h"
+#include "pluginChooser.h"
+
+
+using namespace giada::m;
+using namespace giada::c;
+
+
+gdPluginChooser::gdPluginChooser(int X, int Y, int W, int H, int stackType, Channel *ch)
+  : gdWindow(X, Y, W, H, "Available plugins"), ch(ch), stackType(stackType)
+{
+  /* top area */
+  Fl_Group *group_top = new Fl_Group(8, 8, w()-16, 20);
+  sortMethod = new geChoice(group_top->x() + 45, group_top->y(), 100, 20, "Sort by");
+    geBox *b1 = new geBox(sortMethod->x()+sortMethod->w(), group_top->y(), 100, 20);   // spacer window border <-> menu
+  group_top->resizable(b1);
+  group_top->end();
+
+  /* center browser */
+  browser = new gePluginBrowser(8, 36, w()-16, h()-70);
+
+  /* ok/cancel buttons */
+  Fl_Group *group_btn = new Fl_Group(8, browser->y()+browser->h()+8, w()-16, h()-browser->h()-16);
+    geBox *b2 = new geBox(8, browser->y()+browser->h(), 100, 20);      // spacer window border <-> buttons
+    addBtn = new geButton(w()-88, group_btn->y(), 80, 20, "Add");
+    cancelBtn = new geButton(addBtn->x()-88, group_btn->y(), 80, 20, "Cancel");
+  group_btn->resizable(b2);
+  group_btn->end();
+
+  end();
+
+  sortMethod->add("Name");
+  sortMethod->add("Category");
+  sortMethod->add("Manufacturer");
+  sortMethod->callback(cb_sort, (void*) this);
+  sortMethod->value(conf::pluginSortMethod);
+
+  addBtn->callback(cb_add, (void*) this);
+  addBtn->shortcut(FL_Enter);
+  cancelBtn->callback(cb_close, (void*) this);
+
+  resizable(browser);
+       gu_setFavicon(this);
+  show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdPluginChooser::~gdPluginChooser()
+{
+  conf::pluginChooserX = x();
+  conf::pluginChooserY = y();
+  conf::pluginChooserW = w();
+  conf::pluginChooserH = h();
+  conf::pluginSortMethod = sortMethod->value();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginChooser::cb_close(Fl_Widget *v, void *p) { ((gdPluginChooser*)p)->__cb_close(); }
+void gdPluginChooser::cb_add(Fl_Widget *v, void *p)   { ((gdPluginChooser*)p)->__cb_add(); }
+void gdPluginChooser::cb_sort(Fl_Widget *v, void *p)  { ((gdPluginChooser*)p)->__cb_sort(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginChooser::__cb_close()
+{
+       do_callback();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginChooser::__cb_sort()
+{
+       pluginHost::sortPlugins(sortMethod->value());
+  browser->refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginChooser::__cb_add()
+{
+  int index = browser->value() - 3; // subtract header lines
+  if (index < 0)
+    return;
+  plugin::addPlugin(ch, index, stackType);
+  do_callback();
+}
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginChooser.h b/src/gui/dialogs/pluginChooser.h
new file mode 100644 (file)
index 0000000..f74c374
--- /dev/null
@@ -0,0 +1,74 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+#ifndef GD_PLUGIN_CHOOSER_H
+#define GD_PLUGIN_CHOOSER_H
+
+
+#include <FL/Fl.H>
+#include <FL/Fl_Scroll.H>
+#include "window.h"
+
+
+class Channel;
+class geChoice;
+class geButton;
+class geButton;
+class gePluginBrowser;
+
+
+class gdPluginChooser : public gdWindow
+{
+private:
+
+  Channel *ch;      // ch == nullptr ? masterOut
+       int stackType;
+
+  geChoice         *sortMethod;
+  geButton        *addBtn;
+  geButton        *cancelBtn;
+  gePluginBrowser *browser;
+
+       static void cb_close(Fl_Widget *w, void *p);
+       static void cb_add  (Fl_Widget *w, void *p);
+       static void cb_sort (Fl_Widget *w, void *p);
+  inline void __cb_close();
+  inline void __cb_add  ();
+  inline void __cb_sort ();
+
+public:
+
+       gdPluginChooser(int x, int y, int w, int h, int stackType, Channel *ch=nullptr);
+  ~gdPluginChooser();
+};
+
+
+#endif
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginList.cpp b/src/gui/dialogs/pluginList.cpp
new file mode 100644 (file)
index 0000000..8b4cfb9
--- /dev/null
@@ -0,0 +1,376 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include "../../utils/gui.h"
+#include "../../utils/fs.h"
+#include "../../core/conf.h"
+#include "../../core/const.h"
+#include "../../core/graphics.h"
+#include "../../core/pluginHost.h"
+#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/basics/boxtypes.h"
+#include "../elems/basics/idButton.h"
+#include "../elems/basics/statusButton.h"
+#include "../elems/basics/choice.h"
+#include "../elems/mainWindow/mainIO.h"
+#include "../elems/mainWindow/keyboard/channel.h"
+#include "pluginChooser.h"
+#include "pluginWindow.h"
+#include "pluginWindowGUI.h"
+#include "gd_mainWindow.h"
+#include "pluginList.h"
+
+
+extern gdMainWindow* G_MainWin;
+
+
+using std::string;
+using namespace giada::m;
+using namespace giada::c;
+
+
+gdPluginList::gdPluginList(int stackType, Channel* ch)
+       : gdWindow(468, 204), ch(ch), stackType(stackType)
+{
+       if (conf::pluginListX)
+               resize(conf::pluginListX, conf::pluginListY, w(), h());
+
+       list = new Fl_Scroll(8, 8, 476, 188);
+       list->type(Fl_Scroll::VERTICAL);
+       list->scrollbar.color(G_COLOR_GREY_2);
+       list->scrollbar.selection_color(G_COLOR_GREY_4);
+       list->scrollbar.labelcolor(G_COLOR_LIGHT_1);
+       list->scrollbar.slider(G_CUSTOM_BORDER_BOX);
+
+       list->begin();
+               refreshList();
+       list->end();
+
+       end();
+       set_non_modal();
+
+       /* TODO - awful stuff... we should subclass into gdPluginListChannel and
+       gdPluginListMaster */
+
+       if (stackType == pluginHost::MASTER_OUT)
+               label("Master Out Plugins");
+       else
+       if (stackType == pluginHost::MASTER_IN)
+               label("Master In Plugins");
+       else {
+               string l = "Channel " + gu_toString(ch->index+1) + " Plugins";
+               copy_label(l.c_str());
+       }
+
+       gu_setFavicon(this);
+       show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdPluginList::~gdPluginList()
+{
+       conf::pluginListX = x();
+       conf::pluginListY = y();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginList::cb_addPlugin(Fl_Widget* v, void* p)   { ((gdPluginList*)p)->__cb_addPlugin(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+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). */
+
+       gdWindow *child = (gdWindow*) v;
+       if (child->getParent() != nullptr)
+               (child->getParent())->delSubWindow(child);
+
+       /* finally refresh plugin list: void *p is a pointer to gdPluginList.
+        * This callback works even when you click 'x' to close the window...
+        * well, who cares */
+
+       ((gdPluginList*)p)->refreshList();
+       ((gdPluginList*)p)->redraw();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginList::__cb_addPlugin()
+{
+       /* the usual callback that gdWindow 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
+        * we add to gdPluginChooser. It does exactly what we need. */
+
+       gdPluginChooser* pc = new gdPluginChooser(conf::pluginChooserX,
+                       conf::pluginChooserY, conf::pluginChooserW, conf::pluginChooserH,
+                       stackType, ch);
+       addSubWindow(pc);
+       pc->callback(cb_refreshList, (void*)this);      // 'this' refers to gdPluginList
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginList::refreshList()
+{
+       /* delete the previous list */
+
+       list->clear();
+       list->scroll_to(0, 0);
+
+       /* add new buttons, as many as the plugin in pluginHost::stack + 1,
+        * the 'add new' button. Warning: if ch == nullptr we are working with
+        * master in/master out stacks. */
+
+       int numPlugins = pluginHost::countPlugins(stackType, ch);
+       int i = 0;
+
+       while (i<numPlugins) {
+               Plugin   *pPlugin = pluginHost::getPluginByIndex(i, stackType, ch);
+               gdPlugin *gdp     = new gdPlugin(this, pPlugin, list->x(), list->y()-list->yposition()+(i*24), 800);
+               list->add(gdp);
+               i++;
+       }
+
+       int addPlugY = numPlugins == 0 ? 90 : list->y()-list->yposition()+(i*24);
+       addPlugin = new geButton(8, addPlugY, 452, 20, "-- add new plugin --");
+       addPlugin->callback(cb_addPlugin, (void*)this);
+       list->add(addPlugin);
+
+       /* if num(plugins) > 7 make room for the side scrollbar.
+        * Scrollbar.width = 20 + 4(margin) */
+
+       if (i>7)
+               size(492, h());
+       else
+               size(468, h());
+
+       redraw();
+
+       /* set 'full' flag to FX button */
+
+       /* TODO - awful stuff... we should subclass into gdPluginListChannel and
+       gdPluginListMaster */
+
+       if (stackType == pluginHost::MASTER_OUT) {
+               G_MainWin->mainIO->setMasterFxOutFull(
+                       pluginHost::countPlugins(stackType, ch) > 0);
+       }
+       else
+       if (stackType == pluginHost::MASTER_IN) {
+               G_MainWin->mainIO->setMasterFxInFull(
+                       pluginHost::countPlugins(stackType, ch) > 0);
+       }
+       else {
+               ch->guiChannel->fx->status = pluginHost::countPlugins(stackType, ch) > 0;
+               ch->guiChannel->fx->redraw();
+       }
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+
+gdPlugin::gdPlugin(gdPluginList* gdp, Plugin* p, int X, int Y, int W)
+       : Fl_Group(X, Y, W, 20), pParent(gdp), pPlugin (p)
+{
+       begin();
+       button    = new geIdButton(8, y(), 220, 20);
+       program   = new geChoice(button->x()+button->w()+4, y(), 132, 20);
+       bypass    = new geIdButton(program->x()+program->w()+4, y(), 20, 20);
+       shiftUp   = new geIdButton(bypass->x()+bypass->w()+4, y(), 20, 20, "", fxShiftUpOff_xpm, fxShiftUpOn_xpm);
+       shiftDown = new geIdButton(shiftUp->x()+shiftUp->w()+4, y(), 20, 20, "", fxShiftDownOff_xpm, fxShiftDownOn_xpm);
+       remove    = new geIdButton(shiftDown->x()+shiftDown->w()+4, y(), 20, 20, "", fxRemoveOff_xpm, fxRemoveOn_xpm);
+       end();
+
+       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++)
+               program->add(gu_removeFltkChars(pPlugin->getProgramName(i)).c_str());
+
+       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);
+       remove->callback(cb_removePlugin, (void*)this);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::cb_removePlugin    (Fl_Widget* v, void* p) { ((gdPlugin*)p)->__cb_removePlugin(); }
+void gdPlugin::cb_openPluginWindow(Fl_Widget* v, void* p) { ((gdPlugin*)p)->__cb_openPluginWindow(); }
+void gdPlugin::cb_setBypass       (Fl_Widget* v, void* p) { ((gdPlugin*)p)->__cb_setBypass(); }
+void gdPlugin::cb_shiftUp         (Fl_Widget* v, void* p) { ((gdPlugin*)p)->__cb_shiftUp(); }
+void gdPlugin::cb_shiftDown       (Fl_Widget* v, void* p) { ((gdPlugin*)p)->__cb_shiftDown(); }
+void gdPlugin::cb_setProgram      (Fl_Widget* v, void* p) { ((gdPlugin*)p)->__cb_setProgram(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::__cb_shiftUp()
+{
+       /*nothing to do if there's only one plugin */
+
+       if (pluginHost::countPlugins(pParent->stackType, pParent->ch) == 1)
+               return;
+
+       int pluginIndex = pluginHost::getPluginIndex(pPlugin->getId(),
+               pParent->stackType, pParent->ch);
+
+       if (pluginIndex == 0)  // first of the stack, do nothing
+               return;
+
+       plugin::swapPlugins(pParent->ch, pluginIndex, pluginIndex-1, pParent->stackType);
+       pParent->refreshList();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::__cb_shiftDown()
+{
+       /*nothing to do if there's only one plugin */
+
+       if (pluginHost::countPlugins(pParent->stackType, pParent->ch) == 1)
+               return;
+
+       unsigned pluginIndex = pluginHost::getPluginIndex(pPlugin->getId(), pParent->stackType, pParent->ch);
+       unsigned stackSize   = (pluginHost::getStack(pParent->stackType, pParent->ch))->size();
+
+       if (pluginIndex == stackSize-1)  // last one in the stack, do nothing
+               return;
+
+       plugin::swapPlugins(pParent->ch, pluginIndex, pluginIndex+1, pParent->stackType);
+       pParent->refreshList();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::__cb_removePlugin()
+{
+       /* any subwindow linked to the plugin must be destroyed first */
+
+       pParent->delSubWindow(pPlugin->getId());
+       plugin::freePlugin(pParent->ch, pPlugin->getId(), pParent->stackType);
+       pParent->refreshList();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::__cb_openPluginWindow()
+{
+       /* the new pluginWindow has id = id_plugin + 1, because id=0 is reserved
+       * for the parent window 'add plugin'. */
+
+       int pwid = pPlugin->getId() + 1;
+       
+       gdWindow* w;
+       if (pPlugin->hasEditor()) {
+               if (pPlugin->isEditorOpen()) {
+                       gu_log("[gdPlugin::__cb_openPluginWindow] Plug-in has editor but it's already visible\n");
+                       pParent->getChild(pwid)->show();  // Raise it to top
+                       return;
+               }
+               gu_log("[gdPlugin::__cb_openPluginWindow] Plug-in has editor, window id=%d\n", pwid);
+               w = new gdPluginWindowGUI(pPlugin);
+       }
+       else
+               w = new gdPluginWindow(pPlugin);
+
+       gu_log("[gdPlugin::__cb_openPluginWindow] Plug-in has no editor, window id=%d\n", pwid);
+
+       if (pParent->hasWindow(pwid))
+               pParent->delSubWindow(pwid);
+       w->setId(pwid);
+       pParent->addSubWindow(w);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::__cb_setBypass()
+{
+       pPlugin->toggleBypass();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPlugin::__cb_setProgram()
+{
+       pPlugin->setCurrentProgram(program->value());
+}
+
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginList.h b/src/gui/dialogs/pluginList.h
new file mode 100644 (file)
index 0000000..c8e88ce
--- /dev/null
@@ -0,0 +1,110 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+#ifndef GD_PLUGINLIST_H
+#define GD_PLUGINLIST_H
+
+#include <FL/Fl.H>
+#include <FL/Fl_Scroll.H>
+#include "window.h"
+
+
+class Plugin;
+class Channel;
+class geButton;
+class gdPluginList;
+class geIdButton;
+class geChoice;
+
+
+class gdPluginList : public gdWindow
+{
+private:
+
+  geButton  *addPlugin;
+       Fl_Scroll *list;
+
+       static void cb_addPlugin  (Fl_Widget *v, void *p);
+       inline void __cb_addPlugin();
+
+public:
+
+       Channel *ch;      // ch == nullptr ? masterOut
+       int stackType;
+
+       gdPluginList(int stackType, Channel *ch=nullptr);
+       ~gdPluginList();
+
+       /* special callback, passed to browser. When closed (i.e. plugin
+        * has been selected) the same browser will refresh this window. */
+
+       static void cb_refreshList(Fl_Widget*, void*);
+
+       void refreshList();
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+
+class gdPlugin : public Fl_Group
+{
+private:
+
+  gdPluginList *pParent;
+  Plugin       *pPlugin;
+
+       static void cb_removePlugin       (Fl_Widget *v, void *p);
+       static void cb_openPluginWindow   (Fl_Widget *v, void *p);
+       static void cb_setBypass          (Fl_Widget *v, void *p);
+       static void cb_shiftUp            (Fl_Widget *v, void *p);
+       static void cb_shiftDown          (Fl_Widget *v, void *p);
+       static void cb_setProgram         (Fl_Widget *v, void *p);
+       inline void __cb_removePlugin     ();
+       inline void __cb_openPluginWindow ();
+       inline void __cb_setBypass        ();
+       inline void __cb_shiftUp          ();
+       inline void __cb_shiftDown        ();
+       inline void __cb_setProgram       ();
+
+public:
+
+       geIdButton *button;
+       geChoice    *program;
+       geIdButton *bypass;
+       geIdButton *shiftUp;
+       geIdButton *shiftDown;
+       geIdButton *remove;
+
+       gdPlugin(gdPluginList *gdp, Plugin *p, int x, int y, int w);
+};
+
+#endif
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginWindow.cpp b/src/gui/dialogs/pluginWindow.cpp
new file mode 100644 (file)
index 0000000..ede116e
--- /dev/null
@@ -0,0 +1,97 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include <FL/fl_draw.H>
+#include "../../utils/gui.h"
+#include "../../core/plugin.h"
+#include "../../core/const.h"
+#include "../elems/basics/liquidScroll.h"
+#include "../elems/plugin/pluginParameter.h"
+#include "pluginWindow.h"
+
+
+gdPluginWindow::gdPluginWindow(Plugin* p)
+ : gdWindow(450, 156), m_plugin(p)
+{
+       set_non_modal();
+
+       m_list = new geLiquidScroll(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, 
+               w()-(G_GUI_OUTER_MARGIN*2), h()-(G_GUI_OUTER_MARGIN*2));
+
+       m_list->type(Fl_Scroll::VERTICAL_ALWAYS);
+       m_list->begin();
+               int labelWidth = getLabelWidth();
+               int numParams = m_plugin->getNumParameters();
+               for (int i=0; i<numParams; i++) {
+                       int py = m_list->y() + (i * (G_GUI_UNIT + G_GUI_INNER_MARGIN));
+                       int pw = m_list->w() - m_list->scrollbar_size() - (G_GUI_OUTER_MARGIN*3);
+                       new gePluginParameter(i, m_plugin, m_list->x(), py, pw, labelWidth);
+               }
+       m_list->end();
+
+       end();
+
+       label(m_plugin->getName().c_str());
+
+       size_range(450, (G_GUI_UNIT + (G_GUI_OUTER_MARGIN*2)));
+       resizable(m_list);
+
+       gu_setFavicon(this);
+       show();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginWindow::updateParameter(int index, bool changeSlider)
+{
+       static_cast<gePluginParameter*>(m_list->child(index))->update(changeSlider);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int gdPluginWindow::getLabelWidth() const
+{
+       int width = 0;
+       int numParams = m_plugin->getNumParameters();
+       for (int i=0; i<numParams; i++) {
+               int wl = 0, hl = 0;   
+               fl_measure(m_plugin->getParameterName(i).c_str(), wl, hl);
+               if (wl > width)
+                       width = wl;
+       }
+       return width;
+}
+
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginWindow.h b/src/gui/dialogs/pluginWindow.h
new file mode 100644 (file)
index 0000000..1e0f922
--- /dev/null
@@ -0,0 +1,63 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+#ifndef GD_PLUGIN_WINDOW_H
+#define GD_PLUGIN_WINDOW_H
+
+
+#include "window.h"
+
+
+class Plugin;
+class geBox;
+class geSlider;
+class geLiquidScroll;
+
+
+class gdPluginWindow : public gdWindow
+{
+private:
+
+       Plugin* m_plugin;
+
+       geLiquidScroll* m_list;
+
+       int getLabelWidth() const;
+
+public:
+
+       gdPluginWindow(Plugin* p);
+
+       void updateParameter(int index, bool changeSlider=false);
+};
+
+
+#endif
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginWindowGUI.cpp b/src/gui/dialogs/pluginWindowGUI.cpp
new file mode 100644 (file)
index 0000000..ed11987
--- /dev/null
@@ -0,0 +1,121 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include <FL/x.H>
+#include "../../utils/log.h"
+#include "../../utils/gui.h"
+#include "../../core/pluginHost.h"
+#include "../../core/plugin.h"
+#include "../../core/const.h"
+#include "pluginWindowGUI.h"
+
+#ifdef __APPLE__
+#import "../../utils/cocoa.h" // objective-c
+#endif
+
+
+using namespace giada::m;
+
+
+gdPluginWindowGUI::gdPluginWindowGUI(Plugin *pPlugin)
+ : gdWindow(450, 300), pPlugin(pPlugin)
+{
+  show();
+
+#ifndef __APPLE__
+
+  Fl::check();
+
+#endif
+
+  gu_log("[gdPluginWindowGUI] opening GUI, this=%p, xid=%p\n",
+    (void*) this, (void*) fl_xid(this));
+
+#if defined(__APPLE__)
+
+  void *cocoaWindow = (void*) fl_xid(this);
+  cocoa_setWindowSize(cocoaWindow, pPlugin->getEditorW(), pPlugin->getEditorH());
+  pPlugin->showEditor(cocoa_getViewFromWindow(cocoaWindow));
+
+#else
+
+  pPlugin->showEditor((void*) fl_xid(this));
+
+#endif
+
+  int pluginW = pPlugin->getEditorW();
+  int pluginH = pPlugin->getEditorH();
+
+  resize((Fl::w() - pluginW) / 2, (Fl::h() - pluginH) / 2, pluginW, pluginH);
+
+  Fl::add_timeout(G_GUI_PLUGIN_RATE, cb_refresh, (void*) this);
+
+  copy_label(pPlugin->getName().c_str());
+
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginWindowGUI::cb_close(Fl_Widget *v, void *p)   { ((gdPluginWindowGUI*)p)->__cb_close(); }
+void gdPluginWindowGUI::cb_refresh(void *data) { ((gdPluginWindowGUI*)data)->__cb_refresh(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginWindowGUI::__cb_close()
+{
+  Fl::remove_timeout(cb_refresh);
+  pPlugin->closeEditor();
+  gu_log("[gdPluginWindowGUI::__cb_close] GUI closed, this=%p\n", (void*) this);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gdPluginWindowGUI::__cb_refresh()
+{
+  pluginHost::runDispatchLoop();
+  Fl::repeat_timeout(G_GUI_PLUGIN_RATE, cb_refresh, (void*) this);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+gdPluginWindowGUI::~gdPluginWindowGUI()
+{
+  __cb_close();
+}
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/dialogs/pluginWindowGUI.h b/src/gui/dialogs/pluginWindowGUI.h
new file mode 100644 (file)
index 0000000..54731a3
--- /dev/null
@@ -0,0 +1,69 @@
+
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * gd_pluginWindowGUI
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#ifndef GD_PLUGIN_WINDOW_GUI_H
+#define GD_PLUGIN_WINDOW_GUI_H
+
+
+#include <FL/Fl.H>
+#include <FL/Fl_Window.H>
+#include "window.h"
+#if defined(__APPLE__)
+       #include <Carbon/Carbon.h>
+#endif
+
+
+class Plugin;
+
+
+class gdPluginWindowGUI : public gdWindow
+{
+private:
+
+       Plugin *pPlugin;
+
+       static void cb_close    (Fl_Widget *v, void *p);
+       static void cb_refresh  (void *data);
+       inline void __cb_close  ();
+       inline void __cb_refresh();
+
+public:
+
+       gdPluginWindowGUI(Plugin *pPlugin);
+       ~gdPluginWindowGUI();
+};
+
+
+#endif // include guard
+
+#endif // #ifdef WITH_VST
index 6c250f6fcb1c77296ec19691fdedec286004a570..ea80d9f341660b482354a54371eb4afb51958340 100644 (file)
@@ -53,6 +53,7 @@
 #include "../elems/sampleEditor/panTool.h"
 #include "../elems/sampleEditor/pitchTool.h"
 #include "../elems/sampleEditor/rangeTool.h"
+#include "../elems/sampleEditor/shiftTool.h"
 #include "../elems/mainWindow/keyboard/channel.h"
 #include "gd_warnings.h"
 #include "sampleEditor.h"
@@ -69,10 +70,10 @@ gdSampleEditor::gdSampleEditor(SampleChannel* ch)
 {
   Fl_Group* upperBar = createUpperBar();
   
-  waveTools = new geWaveTools(8, upperBar->y()+upperBar->h()+8, w()-16, h()-128
-       ch);
+  waveTools = new geWaveTools(G_GUI_OUTER_MARGIN, upperBar->y()+upperBar->h()+G_GUI_OUTER_MARGIN
+    w()-16, h()-128, ch);
   
-  Fl_Group* bottomBar = createBottomBar(8, waveTools->y()+waveTools->h()+8
+  Fl_Group* bottomBar = createBottomBar(G_GUI_OUTER_MARGIN, waveTools->y()+waveTools->h()+G_GUI_OUTER_MARGIN
        h()-waveTools->h()-upperBar->h()-32);
 
   add(upperBar);
@@ -83,7 +84,7 @@ gdSampleEditor::gdSampleEditor(SampleChannel* ch)
 
   gu_setFavicon(this);
   set_non_modal();
-  copy_label(ch->wave->getName().c_str());
+  copy_label(ch->getName().c_str());
 
   size_range(720, 480);
   if (conf::sampleEditorX)
@@ -115,13 +116,13 @@ gdSampleEditor::~gdSampleEditor()
 
 Fl_Group* gdSampleEditor::createUpperBar()
 {
-  Fl_Group* g = new Fl_Group(8, 8, w()-16, 20);
+  Fl_Group* g = new Fl_Group(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN, w()-16, G_GUI_UNIT);
   g->begin();
-    grid    = new geChoice(g->x(), g->y(), 50, 20);
+    grid    = new geChoice(g->x(), g->y(), 50, G_GUI_UNIT);
     snap    = new geCheck(grid->x()+grid->w()+4, g->y()+3, 12, 12, "Snap");
-    sep1    = new geBox(snap->x()+snap->w()+4, g->y(), 506, 20);
-    zoomOut = new geButton(sep1->x()+sep1->w()+4, g->y(), 20, 20, "", zoomOutOff_xpm, zoomOutOn_xpm);
-    zoomIn  = new geButton(zoomOut->x()+zoomOut->w()+4, g->y(), 20, 20, "", zoomInOff_xpm, zoomInOn_xpm);
+    sep1    = new geBox(snap->x()+snap->w()+4, g->y(), 506, G_GUI_UNIT);
+    zoomOut = new geButton(sep1->x()+sep1->w()+4, g->y(), G_GUI_UNIT, G_GUI_UNIT, "", zoomOutOff_xpm, zoomOutOn_xpm);
+    zoomIn  = new geButton(zoomOut->x()+zoomOut->w()+4, g->y(), G_GUI_UNIT, G_GUI_UNIT, "", zoomInOff_xpm, zoomInOn_xpm);
   g->end();
   g->resizable(sep1);
 
@@ -167,7 +168,8 @@ Fl_Group* gdSampleEditor::createOpTools(int x, int y, int h)
     pitchTool = new gePitchTool(g->x(), panTool->y()+panTool->h()+8, ch);
 
     rangeTool = new geRangeTool(g->x(), pitchTool->y()+pitchTool->h()+8, ch);
-    reload    = new geButton(g->x()+g->w()-70, rangeTool->y(), 70, 20, "Reload");
+    shiftTool = new geShiftTool(rangeTool->x()+rangeTool->w()+4, pitchTool->y()+pitchTool->h()+8, ch);
+    reload    = new geButton(g->x()+g->w()-70, shiftTool->y(), 70, 20, "Reload");
   g->end();
 
   if (ch->wave->isLogical()) // Logical samples (aka takes) cannot be reloaded.
@@ -249,19 +251,19 @@ Fl_Group* gdSampleEditor::createBottomBar(int x, int y, int h)
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::cb_reload       (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_reload(); }
-void gdSampleEditor::cb_zoomIn       (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_zoomIn(); }
-void gdSampleEditor::cb_zoomOut      (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_zoomOut(); }
-void gdSampleEditor::cb_changeGrid   (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_changeGrid(); }
-void gdSampleEditor::cb_enableSnap   (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_enableSnap(); }
-void gdSampleEditor::cb_togglePreview(Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_togglePreview(); }
-void gdSampleEditor::cb_rewindPreview(Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->__cb_rewindPreview(); }
+void gdSampleEditor::cb_reload       (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_reload(); }
+void gdSampleEditor::cb_zoomIn       (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_zoomIn(); }
+void gdSampleEditor::cb_zoomOut      (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_zoomOut(); }
+void gdSampleEditor::cb_changeGrid   (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_changeGrid(); }
+void gdSampleEditor::cb_enableSnap   (Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_enableSnap(); }
+void gdSampleEditor::cb_togglePreview(Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_togglePreview(); }
+void gdSampleEditor::cb_rewindPreview(Fl_Widget* w, void* p) { ((gdSampleEditor*)p)->cb_rewindPreview(); }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::__cb_enableSnap()
+void gdSampleEditor::cb_enableSnap()
 {
   waveTools->waveform->setSnap(!waveTools->waveform->getSnap());
 }
@@ -270,7 +272,7 @@ void gdSampleEditor::__cb_enableSnap()
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::__cb_togglePreview()
+void gdSampleEditor::cb_togglePreview()
 {
        if (play->value())
        sampleEditor::setPreview(ch, G_PREVIEW_NONE);
@@ -279,7 +281,7 @@ void gdSampleEditor::__cb_togglePreview()
 }
 
 
-void gdSampleEditor::__cb_rewindPreview()
+void gdSampleEditor::cb_rewindPreview()
 {
        sampleEditor::rewindPreview(ch);
 }
@@ -288,7 +290,7 @@ void gdSampleEditor::__cb_rewindPreview()
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::__cb_reload()
+void gdSampleEditor::cb_reload()
 {
   /* TODO - move to glue::sampleEditor */
   if (!gdConfirmWin("Warning", "Reload sample: are you sure?"))
@@ -316,7 +318,7 @@ void gdSampleEditor::__cb_reload()
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::__cb_zoomIn()
+void gdSampleEditor::cb_zoomIn()
 {
   waveTools->waveform->setZoom(-1);
   waveTools->redraw();
@@ -326,7 +328,7 @@ void gdSampleEditor::__cb_zoomIn()
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::__cb_zoomOut()
+void gdSampleEditor::cb_zoomOut()
 {
   waveTools->waveform->setZoom(0);
   waveTools->redraw();
@@ -336,7 +338,7 @@ void gdSampleEditor::__cb_zoomOut()
 /* -------------------------------------------------------------------------- */
 
 
-void gdSampleEditor::__cb_changeGrid()
+void gdSampleEditor::cb_changeGrid()
 {
   waveTools->waveform->setGridLevel(atoi(grid->text()));
 }
index dc09694f9e5cbecf656e7d2898bfc0bd02342565..43ac55678898fc0ff1de3be10635ef3905e808bb 100644 (file)
@@ -40,6 +40,8 @@ class geBoostTool;
 class gePanTool;
 class gePitchTool;
 class geRangeTool;
+class geSampleTool;
+class geShiftTool;
 class geChoice;
 class geCheck;
 class geBox;
@@ -66,13 +68,13 @@ private:
        static void cb_enableSnap(Fl_Widget* w, void* p);
        static void cb_togglePreview(Fl_Widget* w, void* p);
        static void cb_rewindPreview(Fl_Widget* w, void* p);
-       void __cb_reload();
-       void __cb_zoomIn();
-       void __cb_zoomOut();
-       void __cb_changeGrid();
-       void __cb_enableSnap();
-       void __cb_togglePreview();
-       void __cb_rewindPreview();
+       void cb_reload();
+       void cb_zoomIn();
+       void cb_zoomOut();
+       void cb_changeGrid();
+       void cb_enableSnap();
+       void cb_togglePreview();
+       void cb_rewindPreview();
 
 public:
 
@@ -96,6 +98,7 @@ public:
        gePitchTool* pitchTool;
 
        geRangeTool* rangeTool;
+       geShiftTool* shiftTool;
        geButton*    reload;
 
        geButton* play;
index ec17e5bbe1c1d565993625c35ff68533e22bb81e..698f51237f39554d7ba60e078737e075a584cd5b 100644 (file)
 /* cb_window_closer
  * callback for when closing windows. Deletes the widget (delete). */
 
-void __cb_window_closer(Fl_Widget *v, void *p);
+void __cb_window_closer(Fl_Widget* v, void* p);
 
 
 class gdWindow : public Fl_Double_Window
 {
 protected:
 
-       std::vector <gdWindow*> subWindows;
+       std::vector<gdWindow*> subWindows;
        int id;
-       gdWindow *parent;
+       gdWindowparent;
 
 public:
 
-       gdWindow(int x, int y, int w, int h, const char *title=0, int id=0);
-       gdWindow(int w, int h, const char *title=0, int id=0);
+       gdWindow(int x, int y, int w, int h, const chartitle=0, int id=0);
+       gdWindow(int w, int h, const chartitle=0, int id=0);
        ~gdWindow();
 
-       static void cb_closeChild(Fl_Widget *v, void *p);
+       static void cb_closeChild(Fl_Widget* v, void* p);
 
-       void addSubWindow(gdWindow *w);
-       void delSubWindow(gdWindow *w);
+       void addSubWindow(gdWindoww);
+       void delSubWindow(gdWindoww);
        void delSubWindow(int id);
 
        int  getId();
        void setId(int id);
        void debug();
 
-       void     setParent(gdWindow *);
-       gdWindow *getParent();
-       gdWindow *getChild(int id);
+       void setParent(gdWindow* w);
+       gdWindowgetParent();
+       gdWindowgetChild(int id);
 
        /* hasWindow
         * true if the window with id 'id' exists in the stack. */
index 7645ab696272da2f92def9af5acd20d8dd0f4004..6640377ab2040baedc020a053886c27fd7c0205f 100644 (file)
 #include "liquidScroll.h"
 
 
-geLiquidScroll::geLiquidScroll(int x, int y, int w, int h, const char *l)
-  : Fl_Scroll(x, y, w, h, l)
+geLiquidScroll::geLiquidScroll(int x, int y, int w, int h, const charl)
+       : Fl_Scroll(x, y, w, h, l)
 {
-  type(Fl_Scroll::VERTICAL);
-  scrollbar.color(G_COLOR_GREY_2);
-  scrollbar.selection_color(G_COLOR_GREY_4);
-  scrollbar.labelcolor(G_COLOR_LIGHT_1);
-  scrollbar.slider(G_CUSTOM_BORDER_BOX);
+       type(Fl_Scroll::VERTICAL);
+       scrollbar.color(G_COLOR_GREY_2);
+       scrollbar.selection_color(G_COLOR_GREY_4);
+       scrollbar.labelcolor(G_COLOR_LIGHT_1);
+       scrollbar.slider(G_CUSTOM_BORDER_BOX);
 }
 
 
@@ -51,11 +51,11 @@ geLiquidScroll::geLiquidScroll(int x, int y, int w, int h, const char *l)
 
 void geLiquidScroll::resize(int X, int Y, int W, int H)
 {
-  int nc = children()-2;                // skip hscrollbar and vscrollbar
-  for ( int t=0; t<nc; t++) {           // tell children to resize to our new width
-    Fl_Widget *c = child(t);
-    c->resize(c->x(), c->y(), W-24, c->h());    // W-24: leave room for scrollbar
-  }
-  init_sizes();   // tell scroll children changed in size
-  Fl_Scroll::resize(X,Y,W,H);
+       int nc = children()-2;                // skip hscrollbar and vscrollbar
+       for ( int t=0; t<nc; t++) {           // tell children to resize to our new width
+               Fl_Widget* c = child(t);
+               c->resize(c->x(), c->y(), W-24, c->h());    // W-24: leave room for scrollbar
+       }
+       init_sizes();   // tell scroll children changed in size
+       Fl_Scroll::resize(X,Y,W,H);
 }
index ae37e9f2921379747a0473a59de58fb5c4bf9153..59963c20c225b5f01e991a311422e79d3ca38cb0 100644 (file)
@@ -48,18 +48,18 @@ geTabAudio::geTabAudio(int X, int Y, int W, int H)
        : Fl_Group(X, Y, W, H, "Sound System")
 {
        begin();
-       soundsys    = new geChoice(x()+92,  y()+9,  253, 20, "System");
-       buffersize  = new geChoice(x()+92,  y()+37, 55,  20, "Buffer size");
-       samplerate  = new geChoice(x()+290, y()+37, 55,  20, "Sample rate");
-       sounddevOut = new geChoice(x()+92,  y()+65, 225, 20, "Output device");
-       devOutInfo  = new geButton (x()+325, y()+65, 20,  20, "?");
-       channelsOut = new geChoice(x()+92,  y()+93, 55,  20, "Output channels");
-       limitOutput = new geCheck (x()+155, y()+97, 55,  20, "Limit output");
-       sounddevIn  = new geChoice(x()+92,  y()+121, 225, 20, "Input device");
-       devInInfo   = new geButton (x()+325, y()+121, 20,  20, "?");
-       channelsIn  = new geChoice(x()+92,  y()+149, 55,  20, "Input channels");
-       delayComp   = new geInput (x()+290, y()+149, 55,  20, "Rec delay comp.");
-       rsmpQuality = new geChoice(x()+92, y()+177, 253, 20, "Resampling");
+       soundsys    = new geChoice(x()+114, y()+9,  250, 20, "System");
+       buffersize  = new geChoice(x()+114, y()+37, 55,  20, "Buffer size");
+       samplerate  = new geChoice(x()+309, y()+37, 55,  20, "Sample rate");
+       sounddevOut = new geChoice(x()+114, y()+65, 222, 20, "Output device");
+       devOutInfo  = new geButton(x()+344, y()+65, 20,  20, "?");
+       channelsOut = new geChoice(x()+114, y()+93, 55,  20, "Output channels");
+       limitOutput = new geCheck (x()+177, y()+97, 55,  20, "Limit output");
+       sounddevIn  = new geChoice(x()+114, y()+121, 222, 20, "Input device");
+       devInInfo   = new geButton(x()+344, y()+121, 20,  20, "?");
+       channelsIn  = new geChoice(x()+114, y()+149, 55,  20, "Input channels");
+       delayComp   = new geInput (x()+309, y()+149, 55,  20, "Rec delay comp.");
+       rsmpQuality = new geChoice(x()+114, y()+177, 250, 20, "Resampling");
                 new geBox(x(), rsmpQuality->y()+rsmpQuality->h()+8, w(), 92,
                                                                                "Restart Giada for the changes to take effect.");
        end();
index 39f2d260a9a9b59ba2e611e0dd56b323ca02763a..31078991e69884f7a0be1f9d50dc005926bc988d 100644 (file)
@@ -46,13 +46,13 @@ geTabMidi::geTabMidi(int X, int Y, int W, int H)
        : Fl_Group(X, Y, W, H, "MIDI")
 {
        begin();
-       system    = new geChoice(x()+92, y()+9, 253, 20, "System");
-       portOut   = new geChoice(x()+92, system->y()+system->h()+8, 253, 20, "Output port");
-       portIn    = new geChoice(x()+92, portOut->y()+portOut->h()+8, 253, 20, "Input port");
-       noNoteOff = new geCheck (x()+92, portIn->y()+portIn->h()+8, 253, 20, "Device does not send NoteOff");
-       midiMap   = new geChoice(x()+92, noNoteOff->y()+noNoteOff->h(), 253, 20, "Output Midi Map");
-       sync        = new geChoice(x()+92, midiMap->y()+midiMap->h()+8, 253, 20, "Sync");
-       new geBox(x(), sync->y()+sync->h()+8, w(), h()-125, "Restart Giada for the changes to take effect.");
+       system    = new geChoice(x()+w()-250, y()+9, 250, 20, "System");
+       portOut   = new geChoice(x()+w()-250, system->y()+system->h()+8, 250, 20, "Output port");
+       portIn    = new geChoice(x()+w()-250, portOut->y()+portOut->h()+8, 250, 20, "Input port");
+       noNoteOff = new geCheck (x()+w()-250, portIn->y()+portIn->h()+8, 230, 20, "Device does not send NoteOff");
+       midiMap   = new geChoice(x()+w()-250, noNoteOff->y()+noNoteOff->h(), 250, 20, "Output Midi Map");
+       sync        = new geChoice(x()+w()-250, midiMap->y()+midiMap->h()+8, 250, 20, "Sync");
+       new geBox(x(), sync->y()+sync->h()+8, w(), h()-150, "Restart Giada for the changes to take effect.");
        end();
 
        labelsize(G_GUI_FONT_SIZE_BASE);
index 57a5087b849b9d8b1dd267b024c7589207bc9e46..875e54af973a8b32a9905d4031b573e328fd8e47 100644 (file)
@@ -38,7 +38,7 @@ geTabMisc::geTabMisc(int X, int Y, int W, int H)
        : Fl_Group(X, Y, W, H, "Misc")
 {
        begin();
-       debugMsg = new geChoice(x()+92,  y()+9, 253, 20, "Debug messages");
+       debugMsg = new geChoice(x()+w()-230, y()+9, 230, 20, "Debug messages");
        end();
 
        debugMsg->add("(disabled)");
index d226c1fdbaadb7918efd16b86a48a6bfe9e58696..a74eda46ca6304ae98d9b15d5a3b839271b452ad 100644 (file)
@@ -33,7 +33,7 @@
 #include "../../../../utils/gui.h"
 #include "../../../../glue/channel.h"
 #include "../../../dialogs/gd_mainWindow.h"
-#include "../../../dialogs/gd_pluginList.h"
+#include "../../../dialogs/pluginList.h"
 #include "../../basics/idButton.h"
 #include "../../basics/dial.h"
 #include "../../basics/statusButton.h"
 #include "channel.h"
 
 
-extern gdMainWindow *G_MainWin;
+extern gdMainWindowG_MainWin;
 
 
 using namespace giada::m;
 
 
-geChannel::geChannel(int X, int Y, int W, int H, int type, Channel *ch)
+geChannel::geChannel(int X, int Y, int W, int H, int type, Channelch)
  : Fl_Group(X, Y, W, H, nullptr),
         ch      (ch),
         type    (type)
@@ -60,19 +60,19 @@ geChannel::geChannel(int X, int Y, int W, int H, int type, Channel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-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(); }
+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(); }
+void geChannel::cb_openFxWindow(Fl_Widget* v, void* p) { ((geChannel*)p)->cb_openFxWindow(); }
 #endif
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void geChannel::__cb_arm()
+void geChannel::cb_arm()
 {
        glue_toggleArm(ch, true);
 }
@@ -81,16 +81,16 @@ void geChannel::__cb_arm()
 /* -------------------------------------------------------------------------- */
 
 
-void geChannel::__cb_mute()
+void geChannel::cb_mute()
 {
-       glue_setMute(ch);
+       glue_toggleMute(ch);
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void geChannel::__cb_solo()
+void geChannel::cb_solo()
 {
        solo->value() ? glue_setSoloOn(ch) : glue_setSoloOff(ch);
 }
@@ -99,7 +99,7 @@ void geChannel::__cb_solo()
 /* -------------------------------------------------------------------------- */
 
 
-void geChannel::__cb_changeVol()
+void geChannel::cb_changeVol()
 {
        glue_setVolume(ch, vol->value());
 }
@@ -109,7 +109,7 @@ void geChannel::__cb_changeVol()
 
 
 #ifdef WITH_VST
-void geChannel::__cb_openFxWindow()
+void geChannel::cb_openFxWindow()
 {
        gu_openSubWindow(G_MainWin, new gdPluginList(pluginHost::CHANNEL, ch), WID_FX_LIST);
 }
@@ -131,7 +131,7 @@ int geChannel::keyPress(int e)
 
 int geChannel::getColumnIndex()
 {
-       return ((geColumn*)parent())->getIndex();
+       return static_cast<geColumn*>(parent())->getIndex();
 }
 
 
index 04cbfdd8a6229bc36541accd5b779eb8caf1deb5..7314a36b84947441de914a79968305eb12239358 100644 (file)
@@ -63,20 +63,19 @@ protected:
 
        static const int MIN_ELEM_W = 20;
 
-       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);
+       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();
+       void cb_mute();
+       void cb_arm();
+       void cb_solo();
+       void cb_changeVol();
 #ifdef WITH_VST
-               inline void __cb_openFxWindow();
+               void cb_openFxWindow();
 #endif
 
        /* blink
index 6eb8d625d46666290ea9024c2962585d90b216a3..c70371ef236ddb9f563fc6adb73e169afff8a94e 100644 (file)
 using std::string;
 
 
-geChannelButton::geChannelButton(int x, int y, int w, int h, const char *l)
-  : geButton(x, y, w, h, l), key("") {}
+geChannelButton::geChannelButton(int x, int y, int w, int h, const char* l)
+       : geButton(x, y, w, h, l), 
+         m_key   ("") 
+{
+}
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void geChannelButton::setKey(const string &k)
+void geChannelButton::setKey(const stringk)
 {
-  key = k;
+       m_key = k;
 }
 
 
@@ -51,13 +54,13 @@ void geChannelButton::setKey(const string &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;
-  }
+       if (k == 0)
+               m_key = "";
+       else {
+               // FIXME - this crap won't work with unicode/utf-8
+               char c = (char) k;
+               m_key = c;
+       }
 }
 
 
@@ -66,20 +69,20 @@ void geChannelButton::setKey(int k)
 
 void geChannelButton::draw()
 {
-  geButton::draw();
+       geButton::draw();
 
-  if (key == "")
-    return;
+       if (m_key == "")
+               return;
 
-  /* draw background */
+       /* draw background */
 
-  fl_rectf(x()+1, y()+1, 18, h()-2, bgColor0);
+       fl_rectf(x()+1, y()+1, 18, h()-2, bgColor0);
 
-  /* draw key */
+       /* draw m_key */
 
-  fl_color(G_COLOR_LIGHT_2);
-  fl_font(FL_HELVETICA, 11);
-  fl_draw(key.c_str(), x(), y(), 18, h(), FL_ALIGN_CENTER);
+       fl_color(G_COLOR_LIGHT_2);
+       fl_font(FL_HELVETICA, 11);
+       fl_draw(m_key.c_str(), x(), y(), 18, h(), FL_ALIGN_CENTER);
 }
 
 
@@ -88,7 +91,7 @@ void geChannelButton::draw()
 
 void geChannelButton::setInputRecordMode()
 {
-  bgColor0 = G_COLOR_RED;
+       bgColor0 = G_COLOR_RED;
 }
 
 
@@ -97,21 +100,21 @@ void geChannelButton::setInputRecordMode()
 
 void geChannelButton::setActionRecordMode()
 {
-  bgColor0 = G_COLOR_BLUE;
-  txtColor = G_COLOR_LIGHT_2;
+       bgColor0 = G_COLOR_BLUE;
+       txtColor = G_COLOR_LIGHT_2;
 }
 
 
 /* -------------------------------------------------------------------------- */
 
 
-void geChannelButton::setDefaultMode(const char *l)
+void geChannelButton::setDefaultMode(const charl)
 {
-  bgColor0 = G_COLOR_GREY_2;
+       bgColor0 = G_COLOR_GREY_2;
        bdColor  = G_COLOR_GREY_4;
        txtColor = G_COLOR_LIGHT_2;
-  if (l)
-    label(l);
+       if (l)
+               label(l);
 }
 
 
@@ -120,9 +123,9 @@ void geChannelButton::setDefaultMode(const char *l)
 
 void geChannelButton::setPlayMode()
 {
-  bgColor0 = G_COLOR_LIGHT_1;
-  bdColor  = G_COLOR_LIGHT_1;
-  txtColor = G_COLOR_GREY_1;
+       bgColor0 = G_COLOR_LIGHT_1;
+       bdColor  = G_COLOR_LIGHT_1;
+       txtColor = G_COLOR_GREY_1;
 }
 
 
@@ -131,5 +134,5 @@ void geChannelButton::setPlayMode()
 
 void geChannelButton::setEndingMode()
 {
-  bgColor0 = G_COLOR_GREY_4;
+       bgColor0 = G_COLOR_GREY_4;
 }
index 78c6f68c86f460305ce96e86b4dc61b3a600118f..b2cef9edaa7eb44f5b103f0720cc358c07bad13a 100644 (file)
@@ -36,21 +36,21 @@ class geChannelButton : public geButton
 {
 private:
 
-       std::string key;
+       std::string m_key;
 
 public:
 
-       geChannelButton(int x, int y, int w, int h, const char *l=0);
+       geChannelButton(int x, int y, int w, int h, const charl=0);
 
        virtual int handle(int e) = 0;
 
        void draw() override;
   
-       void setKey(const std::string &k);
+       void setKey(const std::stringk);
        void setKey(int k);
        void setPlayMode();
        void setEndingMode();
-       void setDefaultMode(const char *l=0);
+       void setDefaultMode(const charl=0);
        void setInputRecordMode();
        void setActionRecordMode();
 };
index ff94d684fd4ec88a0ccb438a418f8a02f5b8f994..49accc334ae682625c70c4debb188af6eaf7ca0a 100644 (file)
@@ -63,7 +63,7 @@ void geChannelStatus::draw()
       fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_GREY_2);     // status empty
 
 
-    if (mixer::recording && ch->armed)
+    if (mixer::recording && ch->isArmed())
       fl_rectf(x()+1, y()+1, w()-2, h()-2, G_COLOR_RED);     // take in progress
     else
     if (recorder::active && recorder::canRec(ch, clock::isRunning(), mixer::recording))
index 64e9b9db9adc55a37fa96b8b251c0f518f08c8eb..7c4a11312b834aa54c92e4909f3356eaeaa4669d 100644 (file)
 #include "../../../../core/graphics.h"
 #include "../../../../core/midiChannel.h"
 #include "../../../../utils/gui.h"
+#include "../../../../utils/string.h"
 #include "../../../../glue/channel.h"
 #include "../../../../glue/io.h"
 #include "../../../../glue/recorder.h"
 #include "../../../dialogs/gd_mainWindow.h"
-#include "../../../dialogs/sampleEditor.h"
+#include "../../../dialogs/channelNameInput.h"
 #include "../../../dialogs/gd_actionEditor.h"
 #include "../../../dialogs/gd_warnings.h"
 #include "../../../dialogs/gd_keyGrabber.h"
-#include "../../../dialogs/gd_pluginList.h"
+#include "../../../dialogs/pluginList.h"
 #include "../../../dialogs/midiIO/midiInputChannel.h"
 #include "../../../dialogs/midiIO/midiOutputMidiCh.h"
 #include "../../basics/boxtypes.h"
 #include "../../basics/statusButton.h"
 #include "../../basics/dial.h"
 #include "column.h"
+#include "midiChannelButton.h"
 #include "midiChannel.h"
 
 
-extern gdMainWindow *G_MainWin;
+extern gdMainWindowG_MainWin;
 
 
+using std::string;
 using namespace giada::m;
 
 
@@ -72,6 +75,7 @@ enum class Menu
        RESIZE_H3,
        RESIZE_H4,
        __END_RESIZE_SUBMENU__,
+       RENAME_CHANNEL,
        CLONE_CHANNEL,
        DELETE_CHANNEL
 };
@@ -80,9 +84,9 @@ enum class Menu
 /* -------------------------------------------------------------------------- */
 
 
-void menuCallback(Fl_Widget *w, void *v)
+void menuCallback(Fl_Widget* w, void* v)
 {
-       geMidiChannel *gch = static_cast<geMidiChannel*>(w);
+       geMidiChannelgch = static_cast<geMidiChannel*>(w);
        Menu selectedItem = (Menu) (intptr_t) v;
 
        switch (selectedItem)
@@ -126,6 +130,9 @@ void menuCallback(Fl_Widget *w, void *v)
                        break;
                case Menu::CLONE_CHANNEL:
                        glue_cloneChannel(gch->ch);
+                       break;          
+               case Menu::RENAME_CHANNEL:
+                       gu_openSubWindow(G_MainWin, new gdChannelNameInput(gch->ch), WID_SAMPLE_NAME);
                        break;
                case Menu::DELETE_CHANNEL:
                        glue_deleteChannel(gch->ch);
@@ -139,7 +146,7 @@ void menuCallback(Fl_Widget *w, void *v)
 /* -------------------------------------------------------------------------- */
 
 
-geMidiChannel::geMidiChannel(int X, int Y, int W, int H, MidiChannel *ch)
+geMidiChannel::geMidiChannel(int X, int Y, int W, int H, MidiChannelch)
        : geChannel(X, Y, W, H, CHANNEL_MIDI, ch)
 {
        begin();
@@ -197,14 +204,14 @@ geMidiChannel::geMidiChannel(int X, int Y, int W, int H, MidiChannel *ch)
 /* -------------------------------------------------------------------------- */
 
 
-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  (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()
+void geMidiChannel::cb_button()
 {
        if (button->value())
                glue_keyPress(ch, Fl::event_ctrl(), Fl::event_shift());
@@ -214,7 +221,7 @@ void geMidiChannel::__cb_button()
 /* -------------------------------------------------------------------------- */
 
 
-void geMidiChannel::__cb_openMenu()
+void geMidiChannel::cb_openMenu()
 {
        Fl_Menu_Item rclick_menu[] = {
                {"Edit actions...", 0, menuCallback, (void*) Menu::EDIT_ACTIONS},
@@ -230,6 +237,7 @@ void geMidiChannel::__cb_openMenu()
                        {"Large",   0, menuCallback, (void*) Menu::RESIZE_H3},
                        {"X-Large", 0, menuCallback, (void*) Menu::RESIZE_H4},
                        {0},
+               {"Rename channel",  0, menuCallback, (void*) Menu::RENAME_CHANNEL},
                {"Clone channel",  0, menuCallback, (void*) Menu::CLONE_CHANNEL},
                {"Delete channel", 0, menuCallback, (void*) Menu::DELETE_CHANNEL},
                {0}
@@ -240,13 +248,13 @@ void geMidiChannel::__cb_openMenu()
        if (!ch->hasActions)
                rclick_menu[(int)Menu::CLEAR_ACTIONS].deactivate();
 
-       Fl_Menu_Button *b = new Fl_Menu_Button(0, 0, 100, 50);
+       Fl_Menu_Buttonb = new Fl_Menu_Button(0, 0, 100, 50);
        b->box(G_CUSTOM_BORDER_BOX);
        b->textsize(G_GUI_FONT_SIZE_BASE);
        b->textcolor(G_COLOR_LIGHT_2);
        b->color(G_COLOR_GREY_2);
 
-       const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
+       const Fl_Menu_Itemm = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, b);
        if (m)
                m->do_callback(this, m->user_data());
        return;
@@ -278,22 +286,29 @@ void geMidiChannel::reset()
 
 void geMidiChannel::update()
 {
-       if (((MidiChannel*) ch)->midiOut) {
-               char tmp[32];
-               sprintf(tmp, "-- MIDI (channel %d) --", ((MidiChannel*) ch)->midiOutChan+1);
-               mainButton->copy_label(tmp);
-       }
+       const MidiChannel* mch = static_cast<const MidiChannel*>(ch);
+
+       string label; 
+       if (mch->getName().empty())
+               label = "-- MIDI --";
        else
-               mainButton->label("-- MIDI --");
+               label = mch->getName().c_str();
+
+       if (mch->midiOut) 
+               label += " (ch " + gu_toString(mch->midiOutChan + 1) + " out)";
+
+       mainButton->label(label.c_str());
+
+       vol->value(mch->volume);
+       mute->value(mch->mute);
+       solo->value(mch->solo);
 
-       vol->value(ch->volume);
-       mute->value(ch->mute);
-       solo->value(ch->solo);
+       mainButton->setKey(mch->key);
 
-       mainButton->setKey(ch->key);
+       arm->value(mch->isArmed());
 
 #ifdef WITH_VST
-       fx->status = ch->plugins.size() > 0;
+       fx->status = mch->plugins.size() > 0;
        fx->redraw();
 #endif
 }
@@ -319,23 +334,4 @@ void geMidiChannel::resize(int X, int Y, int W, int H)
 #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 geButton::handle(e);
-}
+}
\ No newline at end of file
index 8ed63f0ad5611aa11d54f0f726cc699f5d334376..881c6102594b9de9d198558055470fa8e128e9bb 100644 (file)
@@ -40,16 +40,14 @@ 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 ();
+       static void cb_button(Fl_Widget* v, void* p);
+       static void cb_openMenu(Fl_Widget* v, void* p);
+       void cb_button();
+       void cb_openMenu();
 
 public:
 
-       geMidiChannel(int x, int y, int w, int h, MidiChannel *ch);
+       geMidiChannel(int x, int y, int w, int h, MidiChannelch);
 
        void resize(int x, int y, int w, int h) override;
 
@@ -61,15 +59,4 @@ public:
 };
 
 
-/* -------------------------------------------------------------------------- */
-
-
-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/midiChannelButton.cpp b/src/gui/elems/mainWindow/keyboard/midiChannelButton.cpp
new file mode 100644 (file)
index 0000000..b1ed9b4
--- /dev/null
@@ -0,0 +1,44 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include "midiChannelButton.h"
+
+
+geMidiChannelButton::geMidiChannelButton(int x, int y, int w, int h, const char* l)
+       : geChannelButton(x, y, w, h, l)
+{
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+int geMidiChannelButton::handle(int e)
+{
+       // Currently MIDI drag-n-drop does nothing.
+       return geButton::handle(e);
+}
diff --git a/src/gui/elems/mainWindow/keyboard/midiChannelButton.h b/src/gui/elems/mainWindow/keyboard/midiChannelButton.h
new file mode 100644 (file)
index 0000000..f1bf9dd
--- /dev/null
@@ -0,0 +1,43 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef GE_MIDI_CHANNEL_BUTTON_H
+#define GE_MIDI_CHANNEL_BUTTON_H
+
+
+#include "channelButton.h"
+
+
+class geMidiChannelButton : public geChannelButton
+{
+public:
+       geMidiChannelButton(int x, int y, int w, int h, const char* l=0);
+       int handle(int e);
+};
+
+
+#endif
\ No newline at end of file
index 15950978e1e2161978d73a6b7e78d802a5018a7e..26a839c1e67f4d2169eb28c3943f4ff32811135b 100644 (file)
@@ -39,6 +39,7 @@
 #include "../../../dialogs/gd_mainWindow.h"
 #include "../../../dialogs/gd_keyGrabber.h"
 #include "../../../dialogs/sampleEditor.h"
+#include "../../../dialogs/channelNameInput.h"
 #include "../../../dialogs/gd_actionEditor.h"
 #include "../../../dialogs/gd_warnings.h"
 #include "../../../dialogs/browser/browserSave.h"
@@ -87,6 +88,7 @@ enum class Menu
        RESIZE_H3,
        RESIZE_H4,
        __END_RESIZE_SUBMENU__,
+       RENAME_CHANNEL,
        CLONE_CHANNEL,
        FREE_CHANNEL,
        DELETE_CHANNEL
@@ -185,6 +187,10 @@ void menuCallback(Fl_Widget* w, void* v)
                        glue_cloneChannel(gch->ch);
                        break;
                }
+               case Menu::RENAME_CHANNEL: {
+                       gu_openSubWindow(G_MainWin, new gdChannelNameInput(gch->ch), WID_SAMPLE_NAME);
+                       break;
+               }
                case Menu::FREE_CHANNEL: {
                        glue_freeChannel(gch->ch);
                        break;
@@ -311,6 +317,7 @@ void geSampleChannel::__cb_openMenu()
                        {"Large",   0, menuCallback, (void*) Menu::RESIZE_H3},
                        {"X-Large", 0, menuCallback, (void*) Menu::RESIZE_H4},
                        {0},
+               {"Rename channel", 0, menuCallback, (void*) Menu::RENAME_CHANNEL},
                {"Clone channel",  0, menuCallback, (void*) Menu::CLONE_CHANNEL},
                {"Free channel",   0, menuCallback, (void*) Menu::FREE_CHANNEL},
                {"Delete channel", 0, menuCallback, (void*) Menu::DELETE_CHANNEL},
@@ -321,11 +328,13 @@ void geSampleChannel::__cb_openMenu()
                rclick_menu[(int) Menu::EXPORT_SAMPLE].deactivate();
                rclick_menu[(int) Menu::EDIT_SAMPLE].deactivate();
                rclick_menu[(int) Menu::FREE_CHANNEL].deactivate();
+               rclick_menu[(int) Menu::RENAME_CHANNEL].deactivate();
        }
 
        if (!ch->hasActions)
                rclick_menu[(int) Menu::CLEAR_ACTIONS].deactivate();
 
+
        /* No 'clear start/stop actions' for those channels in loop mode: they cannot
        have start/stop actions. */
 
@@ -350,7 +359,7 @@ void geSampleChannel::__cb_openMenu()
 
 void geSampleChannel::__cb_readActions()
 {
-       glue_startStopReadingRecs(static_cast<SampleChannel*>(ch));
+       glue_toggleReadingRecs(static_cast<SampleChannel*>(ch));
 }
 
 
@@ -365,7 +374,7 @@ void geSampleChannel::refresh()
        setColorsByStatus(ch->status, ch->recStatus);
 
        if (static_cast<SampleChannel*>(ch)->wave != nullptr) {
-               if (mixer::recording && ch->armed)
+               if (mixer::recording && ch->isArmed())
                        mainButton->setInputRecordMode();
                if (recorder::active) {
                        if (recorder::canRec(ch, clock::isRunning(), mixer::recording))
@@ -394,9 +403,9 @@ void geSampleChannel::reset()
 
 void geSampleChannel::update()
 {
-       /* update sample button's label */
+       const SampleChannel* sch = static_cast<const SampleChannel*>(ch);
 
-       switch (ch->status) {
+       switch (sch->status) {
                case STATUS_EMPTY:
                        mainButton->label("-- no sample --");
                        break;
@@ -405,34 +414,35 @@ void geSampleChannel::update()
                        mainButton->label("* file not found! *");
                        break;
                default:
-                       mainButton->label(static_cast<SampleChannel*>(ch)->wave->getName().c_str());
+                       if (sch->getName().empty())
+                               mainButton->label(sch->wave->getBasename(false).c_str());
+                       else
+                               mainButton->label(sch->getName().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. */
+       /* 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)
+       if (sch->hasActions)
                showActionButton();
        else
                hideActionButton();
 
-       /* updates modebox */
-
-       modeBox->value(static_cast<SampleChannel*>(ch)->mode);
+       modeBox->value(sch->mode);
        modeBox->redraw();
 
-       /* update volumes+mute+solo */
+       vol->value(sch->volume);
+       mute->value(sch->mute);
+       solo->value(sch->solo);
 
-       vol->value(ch->volume);
-       mute->value(ch->mute);
-       solo->value(ch->solo);
+       mainButton->setKey(sch->key);
 
-       mainButton->setKey(ch->key);
+       arm->value(sch->isArmed());
 
 #ifdef WITH_VST
-       fx->status = ch->plugins.size() > 0;
+       fx->status = sch->plugins.size() > 0;
        fx->redraw();
 #endif
 }
index a2a9c3ff2938639a7f347c38d12ecefa4e860b19..9e504df5b956019e52b50c1908c9e65eeeb13534 100644 (file)
 #include "sampleChannelButton.h"
 
 
-extern gdMainWindow *G_MainWin;
+extern gdMainWindowG_MainWin;
 
 
 geSampleChannelButton::geSampleChannelButton(int x, int y, int w, int h,
-       const char *l)
+       const charl)
        : geChannelButton(x, y, w, h, l)
 {
 }
@@ -61,9 +61,9 @@ int geSampleChannelButton::handle(int e)
                        break;
                }
                case FL_PASTE: {
-                       geSampleChannel *gch = static_cast<geSampleChannel*>(parent());
-                       SampleChannel   *ch  = static_cast<SampleChannel*>(gch->ch);
-                       int result = glue_loadChannel(ch, gu_trim(gu_stripFileUrl(Fl::event_text())).c_str());
+                       geSampleChannelgch = static_cast<geSampleChannel*>(parent());
+                       SampleChannel*   ch  = static_cast<SampleChannel*>(gch->ch);
+                       int result = glue_loadChannel(ch, gu_trim(gu_stripFileUrl(Fl::event_text())));
                        if (result != G_RES_OK)
                                G_MainWin->keyboard->printChannelMessage(result);
                        ret = 1;
index 4857c44dbbf05e5721c55cccc478ab7ff8cbb3b4..eb470713be6cd526d95728246ff1d72fd8688adb 100644 (file)
@@ -36,7 +36,7 @@ class geSampleChannelButton : public geChannelButton
 {
 public:
 
-  geSampleChannelButton(int x, int y, int w, int h, const char *l=0);
+       geSampleChannelButton(int x, int y, int w, int h, const char* l=0);
        int handle(int e);
 };
 
index 098785ab0a9a9d3d4927084fffbd43ba2a416d85..67bc074aeb26b488bdc9f8ad5336eb35516cf2d1 100644 (file)
@@ -35,7 +35,7 @@
 #include "../../elems/basics/statusButton.h"
 #include "../../elems/basics/dial.h"
 #include "../../dialogs/gd_mainWindow.h"
-#include "../../dialogs/gd_pluginList.h"
+#include "../../dialogs/pluginList.h"
 #include "mainIO.h"
 
 
index a61f8ed996d67624a155a43c01b82f527b0439a4..2d7269b4237567096b187853a30099767a252868 100644 (file)
@@ -99,7 +99,7 @@ void geMainMenu::__cb_about()
 
 void geMainMenu::__cb_config()
 {
-       gu_openSubWindow(G_MainWin, new gdConfig(380, 370), WID_CONFIG);
+       gu_openSubWindow(G_MainWin, new gdConfig(400, 370), WID_CONFIG);
 }
 
 
index 334d6c850418f5376b872cfb15b1e10c7485061e..ac19b4f9d37eaf49c395c281231992a55d39c8cb 100644 (file)
@@ -34,8 +34,8 @@
 #include "../../elems/basics/button.h"
 #include "../../elems/basics/choice.h"
 #include "../../dialogs/gd_mainWindow.h"
-#include "../../dialogs/gd_bpmInput.h"
-#include "../../dialogs/gd_beatsInput.h"
+#include "../../dialogs/bpmInput.h"
+#include "../../dialogs/beatsInput.h"
 #include "mainTimer.h"
 
 
diff --git a/src/gui/elems/plugin/pluginBrowser.cpp b/src/gui/elems/plugin/pluginBrowser.cpp
new file mode 100644 (file)
index 0000000..11d0882
--- /dev/null
@@ -0,0 +1,124 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include <FL/fl_draw.H>
+#include "../../../core/plugin.h"
+#include "../../../core/const.h"
+#include "../../../core/pluginHost.h"
+#include "../basics/boxtypes.h"
+#include "pluginBrowser.h"
+
+
+using std::vector;
+using std::string;
+using namespace giada::m;
+
+
+gePluginBrowser::gePluginBrowser(int x, int y, int w, int h)
+       : Fl_Browser(x, y, w, h)
+{
+       box(G_CUSTOM_BORDER_BOX);
+       textsize(G_GUI_FONT_SIZE_BASE);
+       textcolor(G_COLOR_LIGHT_2);
+       selection_color(G_COLOR_GREY_4);
+       color(G_COLOR_GREY_2);
+
+       this->scrollbar.color(G_COLOR_GREY_2);
+       this->scrollbar.selection_color(G_COLOR_GREY_4);
+       this->scrollbar.labelcolor(G_COLOR_LIGHT_1);
+       this->scrollbar.slider(G_CUSTOM_BORDER_BOX);
+
+       this->hscrollbar.color(G_COLOR_GREY_2);
+       this->hscrollbar.selection_color(G_COLOR_GREY_4);
+       this->hscrollbar.labelcolor(G_COLOR_LIGHT_1);
+       this->hscrollbar.slider(G_CUSTOM_BORDER_BOX);
+
+       type(FL_HOLD_BROWSER);
+
+       computeWidths();
+
+  column_widths(widths);
+  column_char('\t');       // tabs as column delimiters
+
+       refresh();
+
+       end();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gePluginBrowser::refresh()
+{
+       clear();
+
+       add("NAME\tMANUFACTURER\tCATEGORY\tFORMAT\tUID");
+       add("---\t---\t---\t---\t---");
+
+       for (int i=0; i<pluginHost::countAvailablePlugins(); i++) {
+               pluginHost::PluginInfo pi = pluginHost::getAvailablePluginInfo(i);
+               string m = pluginHost::doesPluginExist(pi.uid) ? "" : "@-";
+               string s = m + pi.name + "\t" + m + pi.manufacturerName + "\t" + m +
+                               pi.category +   "\t" + m + pi.format + "\t" + m + pi.uid;
+               add(s.c_str());
+       }
+
+       for (unsigned i=0; i<pluginHost::countUnknownPlugins(); i++) {
+               string s = "?\t?\t?\t?\t? " + pluginHost::getUnknownPluginInfo(i) + " ?";
+               add(s.c_str());
+       }
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gePluginBrowser::computeWidths()
+{
+       int w0, w1, w3;
+       for (int i=0; i<pluginHost::countAvailablePlugins(); i++) {
+               pluginHost::PluginInfo pi = pluginHost::getAvailablePluginInfo(i);
+               w0 = (int) fl_width(pi.name.c_str());
+               w1 = (int) fl_width(pi.manufacturerName.c_str());
+               w3 = (int) fl_width(pi.format.c_str());
+               if (w0 > widths[0]) widths[0] = w0;
+               if (w1 > widths[1]) widths[1] = w1;
+               if (w3 > widths[3]) widths[3] = w3;
+       }
+       widths[0] += 60;
+       widths[1] += 60;
+       widths[2] = fl_width("CATEGORY") + 60;
+       widths[3] += 60;
+       widths[4] = 0;
+}
+
+
+#endif
diff --git a/src/gui/elems/plugin/pluginBrowser.h b/src/gui/elems/plugin/pluginBrowser.h
new file mode 100644 (file)
index 0000000..4e2287e
--- /dev/null
@@ -0,0 +1,54 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+#ifndef GE_PLUGIN_BROWSER_H
+#define GE_PLUGIN_BROWSER_H
+
+
+#include <FL/Fl_Browser.H>
+
+
+class gePluginBrowser : public Fl_Browser
+{
+private:
+
+       int widths[5] = {0};
+
+       void computeWidths();
+
+public:
+
+       gePluginBrowser(int x, int y, int w, int h);
+
+       void refresh();
+};
+
+#endif
+
+#endif
diff --git a/src/gui/elems/plugin/pluginParameter.cpp b/src/gui/elems/plugin/pluginParameter.cpp
new file mode 100644 (file)
index 0000000..5a6916b
--- /dev/null
@@ -0,0 +1,99 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#include "../../../core/plugin.h"
+#include "../../../core/const.h"
+#include "../../../glue/plugin.h"
+#include "../basics/boxtypes.h"
+#include "../basics/box.h"
+#include "../basics/slider.h"
+#include "pluginParameter.h"
+
+
+using std::string;
+using namespace giada::c;
+
+
+gePluginParameter::gePluginParameter(int paramIndex, Plugin* p, int X, int Y, 
+       int W, int labelWidth)
+       : Fl_Group    (X, Y, W, G_GUI_UNIT), 
+         m_paramIndex(paramIndex), 
+         m_plugin    (p)
+{
+       begin();
+
+               m_label = new geBox(x(), y(), labelWidth, G_GUI_UNIT);
+               m_label->copy_label(m_plugin->getParameterName(m_paramIndex).c_str());
+               m_label->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
+
+               m_slider = new geSlider(m_label->x()+m_label->w()+G_GUI_OUTER_MARGIN, y(), 
+                       w()-(m_label->x()+m_label->w()+G_GUI_OUTER_MARGIN)-VALUE_WIDTH, G_GUI_UNIT);
+               m_slider->value(m_plugin->getParameter(m_paramIndex));
+               m_slider->callback(cb_setValue, (void*)this);
+
+               m_value = new geBox(m_slider->x()+m_slider->w()+G_GUI_OUTER_MARGIN, y(), VALUE_WIDTH, G_GUI_UNIT);
+               m_value->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE);
+               m_value->box(G_CUSTOM_BORDER_BOX);
+
+       end();
+       resizable(m_slider);
+       update(false);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gePluginParameter::cb_setValue(Fl_Widget* v, void* p)  { ((gePluginParameter*)p)->cb_setValue(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gePluginParameter::cb_setValue()
+{
+       plugin::setParameter(m_plugin, m_paramIndex, m_slider->value());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void gePluginParameter::update(bool changeSlider)
+{
+       string v = m_plugin->getParameterText(m_paramIndex) + " " +
+                       m_plugin->getParameterLabel(m_paramIndex);
+       m_value->copy_label(v.c_str());
+       if (changeSlider)
+               m_slider->value(m_plugin->getParameter(m_paramIndex));
+}
+
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/elems/plugin/pluginParameter.h b/src/gui/elems/plugin/pluginParameter.h
new file mode 100644 (file)
index 0000000..268b7e6
--- /dev/null
@@ -0,0 +1,69 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifdef WITH_VST
+
+
+#ifndef GE_PLUGIN_PARAMETER_H
+#define GE_PLUGIN_PARAMETER_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class Plugin;
+class geBox;
+class geSlider;
+
+
+class gePluginParameter : public Fl_Group
+{
+private:
+
+       static const int VALUE_WIDTH = 100;
+
+       int m_paramIndex;
+       Plugin* m_plugin;
+
+       geBox*    m_label;
+       geSlider* m_slider;
+       geBox*    m_value;
+
+       static void cb_setValue(Fl_Widget* v, void* p);
+       void cb_setValue();
+
+public:
+
+       gePluginParameter(int paramIndex, Plugin* p, int x, int y, int w, int labelWidth);
+
+       void update(bool changeSlider);
+};
+
+
+#endif
+
+#endif // #ifdef WITH_VST
diff --git a/src/gui/elems/pluginBrowser.cpp b/src/gui/elems/pluginBrowser.cpp
deleted file mode 100644 (file)
index 46a8bc5..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-
-#include <FL/fl_draw.H>
-#include "../../core/plugin.h"
-#include "../../core/const.h"
-#include "../../core/pluginHost.h"
-#include "basics/boxtypes.h"
-#include "pluginBrowser.h"
-
-
-using std::vector;
-using std::string;
-using namespace giada::m;
-
-
-gePluginBrowser::gePluginBrowser(int x, int y, int w, int h)
-       : Fl_Browser(x, y, w, h)
-{
-       box(G_CUSTOM_BORDER_BOX);
-       textsize(G_GUI_FONT_SIZE_BASE);
-       textcolor(G_COLOR_LIGHT_2);
-       selection_color(G_COLOR_GREY_4);
-       color(G_COLOR_GREY_2);
-
-       this->scrollbar.color(G_COLOR_GREY_2);
-       this->scrollbar.selection_color(G_COLOR_GREY_4);
-       this->scrollbar.labelcolor(G_COLOR_LIGHT_1);
-       this->scrollbar.slider(G_CUSTOM_BORDER_BOX);
-
-       this->hscrollbar.color(G_COLOR_GREY_2);
-       this->hscrollbar.selection_color(G_COLOR_GREY_4);
-       this->hscrollbar.labelcolor(G_COLOR_LIGHT_1);
-       this->hscrollbar.slider(G_CUSTOM_BORDER_BOX);
-
-       type(FL_HOLD_BROWSER);
-
-       computeWidths();
-
-  column_widths(widths);
-  column_char('\t');       // tabs as column delimiters
-
-       refresh();
-
-       end();
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gePluginBrowser::refresh()
-{
-       clear();
-
-       add("NAME\tMANUFACTURER\tCATEGORY\tFORMAT\tUID");
-       add("---\t---\t---\t---\t---");
-
-       for (int i=0; i<pluginHost::countAvailablePlugins(); i++) {
-               pluginHost::PluginInfo pi = pluginHost::getAvailablePluginInfo(i);
-               string m = pluginHost::doesPluginExist(pi.uid) ? "" : "@-";
-               string s = m + pi.name + "\t" + m + pi.manufacturerName + "\t" + m +
-                               pi.category +   "\t" + m + pi.format + "\t" + m + pi.uid;
-               add(s.c_str());
-       }
-
-       for (unsigned i=0; i<pluginHost::countUnknownPlugins(); i++) {
-               string s = "?\t?\t?\t?\t? " + pluginHost::getUnknownPluginInfo(i) + " ?";
-               add(s.c_str());
-       }
-}
-
-
-/* -------------------------------------------------------------------------- */
-
-
-void gePluginBrowser::computeWidths()
-{
-       int w0, w1, w3;
-       for (int i=0; i<pluginHost::countAvailablePlugins(); i++) {
-               pluginHost::PluginInfo pi = pluginHost::getAvailablePluginInfo(i);
-               w0 = (int) fl_width(pi.name.c_str());
-               w1 = (int) fl_width(pi.manufacturerName.c_str());
-               w3 = (int) fl_width(pi.format.c_str());
-               if (w0 > widths[0]) widths[0] = w0;
-               if (w1 > widths[1]) widths[1] = w1;
-               if (w3 > widths[3]) widths[3] = w3;
-       }
-       widths[0] += 60;
-       widths[1] += 60;
-       widths[2] = fl_width("CATEGORY") + 60;
-       widths[3] += 60;
-       widths[4] = 0;
-}
-
-
-#endif
diff --git a/src/gui/elems/pluginBrowser.h b/src/gui/elems/pluginBrowser.h
deleted file mode 100644 (file)
index 4e2287e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-
-#ifdef WITH_VST
-
-#ifndef GE_PLUGIN_BROWSER_H
-#define GE_PLUGIN_BROWSER_H
-
-
-#include <FL/Fl_Browser.H>
-
-
-class gePluginBrowser : public Fl_Browser
-{
-private:
-
-       int widths[5] = {0};
-
-       void computeWidths();
-
-public:
-
-       gePluginBrowser(int x, int y, int w, int h);
-
-       void refresh();
-};
-
-#endif
-
-#endif
index 9bdd59a37d24b477ea1a7e7096a782e30a9b279e..2125294d48a5591e60ce3f5902be80b0918cad94 100644 (file)
@@ -44,27 +44,27 @@ using namespace giada::c;
 
 
 geRangeTool::geRangeTool(int x, int y, SampleChannel* ch)
-       : Fl_Group(x, y, 300, 20),
-         m_ch    (ch)
+       : Fl_Group(x, y, 280, G_GUI_UNIT),
+               m_ch    (ch)
 {
-  begin();
-    m_label = new geBox  (x, y, gu_getStringWidth("Range"), 20, "Range", FL_ALIGN_RIGHT);
-    m_begin = new geInput(m_label->x()+m_label->w()+4, y, 70, 20);
-    m_end   = new geInput(m_begin->x()+m_begin->w()+4, y, 70, 20);
-    m_reset = new geButton(m_end->x()+m_end->w()+4, y, 70, 20, "Reset");
-  end();
-
-  m_begin->type(FL_INT_INPUT);
-  m_begin->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY); // on focus lost or enter key
-  m_begin->callback(cb_setChanPos, this);
-  
-  m_end->type(FL_INT_INPUT);
-  m_end->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY); // on focus lost or enter key
-  m_end->callback(cb_setChanPos, this);
-
-  m_reset->callback(cb_resetStartEnd, this);
-
-  refresh();
+       begin();
+               m_label = new geBox(x, y, gu_getStringWidth("Range"), G_GUI_UNIT, "Range", FL_ALIGN_RIGHT);
+               m_begin = new geInput(m_label->x()+m_label->w()+G_GUI_INNER_MARGIN, y, 70, G_GUI_UNIT);
+               m_end   = new geInput(m_begin->x()+m_begin->w()+G_GUI_INNER_MARGIN, y, 70, G_GUI_UNIT);
+               m_reset = new geButton(m_end->x()+m_end->w()+G_GUI_INNER_MARGIN, y, 70, G_GUI_UNIT, "Reset");
+       end();
+
+       m_begin->type(FL_INT_INPUT);
+       m_begin->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY); // on focus lost or enter key
+       m_begin->callback(cb_setChanPos, this);
+       
+       m_end->type(FL_INT_INPUT);
+       m_end->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY); // on focus lost or enter key
+       m_end->callback(cb_setChanPos, this);
+
+       m_reset->callback(cb_resetStartEnd, this);
+
+       refresh();
 }
 
 
@@ -73,8 +73,8 @@ geRangeTool::geRangeTool(int x, int y, SampleChannel* ch)
 
 void geRangeTool::refresh()
 {
-  m_begin->value(gu_toString(m_ch->getBegin()).c_str());
-  m_end->value(gu_toString(m_ch->getEnd()).c_str());
+       m_begin->value(gu_toString(m_ch->getBegin()).c_str());
+       m_end->value(gu_toString(m_ch->getEnd()).c_str());
 }
 
 
@@ -90,8 +90,8 @@ void geRangeTool::cb_resetStartEnd(Fl_Widget* w, void* p) { ((geRangeTool*)p)->_
 
 void geRangeTool::__cb_setChanPos()
 {
-  sampleEditor::setBeginEnd(m_ch, atoi(m_begin->value()), atoi(m_end->value()));
-  static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform();
+       sampleEditor::setBeginEnd(m_ch, atoi(m_begin->value()), atoi(m_end->value()));
+       static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform(); // TODO - glue's business!
 }
 
 
@@ -100,6 +100,6 @@ void geRangeTool::__cb_setChanPos()
 
 void geRangeTool::__cb_resetStartEnd()
 {
-  sampleEditor::setBeginEnd(m_ch, 0, m_ch->wave->getSize() - 1);
-  static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform();
+       sampleEditor::setBeginEnd(m_ch, 0, m_ch->wave->getSize() - 1);
+       static_cast<gdSampleEditor*>(window())->waveTools->updateWaveform(); // TODO - glue's business!
 }
diff --git a/src/gui/elems/sampleEditor/shiftTool.cpp b/src/gui/elems/sampleEditor/shiftTool.cpp
new file mode 100644 (file)
index 0000000..83e9afe
--- /dev/null
@@ -0,0 +1,107 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#include "../../../core/const.h"
+#include "../../../core/sampleChannel.h"
+#include "../../../utils/gui.h"
+#include "../../../utils/string.h"
+#include "../../../glue/sampleEditor.h"
+#include "../../dialogs/gd_warnings.h"
+#include "../basics/input.h"
+#include "../basics/box.h"
+#include "../basics/button.h"
+#include "shiftTool.h"
+
+
+using namespace giada::c;
+
+
+geShiftTool::geShiftTool(int x, int y, SampleChannel* ch)
+       : Fl_Group(x, y, 300, G_GUI_UNIT),
+               m_ch    (ch)
+{
+       begin();
+               m_label = new geBox(x, y, gu_getStringWidth("Shift"), G_GUI_UNIT, "Shift", FL_ALIGN_RIGHT);
+               m_shift = new geInput(m_label->x()+m_label->w()+G_GUI_INNER_MARGIN, y, 70, G_GUI_UNIT);
+               m_reset = new geButton(m_shift->x()+m_shift->w()+G_GUI_INNER_MARGIN, y, 70, G_GUI_UNIT, "Reset");
+       end();
+
+       m_shift->type(FL_INT_INPUT);
+       m_shift->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY); // on focus lost or enter key
+       m_shift->value(gu_toString(ch->getShift()).c_str());
+       m_shift->callback(cb_setShift, (void*)this);
+
+       m_reset->callback(cb_reset, (void*)this);
+
+       refresh();
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geShiftTool::cb_setShift(Fl_Widget* w, void* p) { ((geShiftTool*)p)->cb_setShift(); }
+void geShiftTool::cb_reset(Fl_Widget* w, void* p) { ((geShiftTool*)p)->cb_reset(); }
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geShiftTool::cb_setShift()
+{
+       shift(atoi(m_shift->value()));
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geShiftTool::cb_reset()
+{
+       shift(0);
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geShiftTool::refresh()
+{
+       m_shift->value(gu_toString(m_ch->getShift()).c_str());
+}
+
+
+/* -------------------------------------------------------------------------- */
+
+
+void geShiftTool::shift(int f)
+{
+       if (m_ch->isPlaying())
+               gdAlert("Can't shift sample while playing.");
+       else
+               sampleEditor::shift(m_ch, f);   
+}
diff --git a/src/gui/elems/sampleEditor/shiftTool.h b/src/gui/elems/sampleEditor/shiftTool.h
new file mode 100644 (file)
index 0000000..17aee46
--- /dev/null
@@ -0,0 +1,66 @@
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2017 Giovanni A. Zuliani | Monocasual
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+
+#ifndef GE_SHIFT_TOOL_H
+#define GE_SHIFT_TOOL_H
+
+
+#include <FL/Fl_Group.H>
+
+
+class SampleChannel;
+class geInput;
+class geButton;
+class geBox;
+
+
+class geShiftTool : public Fl_Group
+{
+private:
+
+       SampleChannel* m_ch;
+
+       geBox*    m_label;
+       geInput*  m_shift;
+       geButton* m_reset;
+
+       static void cb_setShift(Fl_Widget* w, void* p);
+       static void cb_reset(Fl_Widget* w, void* p);
+       void cb_setShift();
+       void cb_reset();
+
+       void shift(int f);
+
+public:
+
+       geShiftTool(int x, int y, SampleChannel* ch);
+
+       void refresh();
+};
+
+
+#endif
index d13b369792d9e97a3cdca5b57fdb872c064f3f70..dc4c980abade0687fa92095d80a2e31a092ed6d4 100644 (file)
@@ -349,7 +349,7 @@ int geWaveform::handle(int e)
 
                case FL_KEYDOWN: {
                        if (Fl::event_key() == ' ')
-                               static_cast<gdSampleEditor*>(window())->__cb_togglePreview();
+                               static_cast<gdSampleEditor*>(window())->cb_togglePreview();
                        else
                        if (Fl::event_key() == FL_BackSpace)
                                sampleEditor::rewindPreview(m_ch);
index cee9c81f9306c6a4d6fff817ee09e38f3faa9ea2..3e84fffe25f10190355123c02a712837a5aec5cf 100644 (file)
 #include <string>
 
 
-bool gu_fileExists(const std::string &path);
-bool gu_dirExists(const std::string &path);
-bool gu_isDir(const std::string &path);
-bool gu_isProject(const std::string &path);
-bool gu_mkdir(const std::string &path);
+bool gu_fileExists(const std::stringpath);
+bool gu_dirExists(const std::stringpath);
+bool gu_isDir(const std::stringpath);
+bool gu_isProject(const std::stringpath);
+bool gu_mkdir(const std::stringpath);
 std::string gu_getCurrentPath();
 std::string gu_getHomePath();
-std::string gu_basename(const std::string &s);
-std::string gu_dirname(const std::string &s);
-std::string gu_getExt(const std::string &s);
-std::string gu_stripExt(const std::string &s);
-std::string gu_stripFileUrl(const std::string &s);
+
+/* gu_basename
+/path/to/file.txt -> file.txt */
+
+std::string gu_basename(const std::string& s);
+
+/* gu_dirname
+/path/to/file.txt -> /path/to */
+
+std::string gu_dirname(const std::string& s);
+
+/* gu_getExt
+/path/to/file.txt -> txt */
+
+std::string gu_getExt(const std::string& s);
+
+/* gu_stripExt
+/path/to/file.txt -> /path/to/file */
+
+std::string gu_stripExt(const std::string& s);
+
+std::string gu_stripFileUrl(const std::string& s);
 
 
 #endif
index 92df941176dd4080b691d019612b6aac9ef2678a..e19c235760e70774ca894566ff85b35c7b335581 100644 (file)
@@ -37,7 +37,7 @@ using std::string;
 using std::vector;
 
 
-string gu_getRealPath(const string &path)
+string gu_getRealPath(const stringpath)
 {
        string out = "";
 
@@ -85,7 +85,7 @@ string gu_toString(int i)
 /* -------------------------------------------------------------------------- */
 
 
-string gu_trim(const string &s)
+string gu_trim(const strings)
 {
        std::size_t first = s.find_first_not_of(" \n\t");
        std::size_t last  = s.find_last_not_of(" \n\t");
@@ -96,7 +96,7 @@ string gu_trim(const string &s)
 /* -------------------------------------------------------------------------- */
 
 
-string gu_replace(string in, const string &search, const string &replace)
+string gu_replace(string in, const string& search, const string& replace)
 {
        size_t pos = 0;
        while ((pos = in.find(search, pos)) != string::npos) {
@@ -110,7 +110,7 @@ string gu_replace(string in, const string &search, const string &replace)
 /* -------------------------------------------------------------------------- */
 
 
-void gu_split(string in, string sep, vector<string> *v)
+void gu_split(string in, string sep, vector<string>v)
 {
        string full  = in;
        string token = "";
index 401b773476e9ff4d66dcee340800b5708e2e2f83..17b446c627ac52065dd3d23db57c3069a7e0d63f 100644 (file)
 #include <vector>
 
 
-std::string gu_getRealPath(const std::string &path);
+std::string gu_getRealPath(const std::stringpath);
 
-std::string gu_replace(std::string in, const std::string &search,
-  const std::string &replace);
+std::string gu_replace(std::string in, const std::stringsearch,
+  const std::stringreplace);
 
-std::string gu_trim(const std::string &s);
+std::string gu_trim(const std::strings);
 
 std::string gu_toString(int i);
 
-void gu_split(std::string in, std::string sep, std::vector<std::string> *v);
+void gu_split(std::string in, std::string sep, std::vector<std::string>v);
 
 
 #endif
index e28a706ed4e228014f925be699838bb5381cf18b..3318258b93ce630a5e79c4888b68c0f09bc0d617 100644 (file)
  * -------------------------------------------------------------------------- */
 
 
-#include <chrono>
-#include <thread>
+#include "../core/const.h"
+#ifndef G_OS_MAC
+       #include <chrono>
+       #include <thread>
+#else
+       #include <unistd.h>
+#endif
 #include "time.h"
 
 
@@ -38,6 +43,10 @@ namespace time
 {
 void sleep(int millisecs)
 {
+#ifndef G_OS_MAC
        std::this_thread::sleep_for(std::chrono::milliseconds(millisecs));
+#else
+       usleep(millisecs * 1000);
+#endif
 }
 }}};  // giada::u::time::
index 4f2e18aa0ea759bf40fea6b53016cdb28038a676..77290240c7da0b74350157fe130ba47078e0fe85 100644 (file)
@@ -13,42 +13,55 @@ TEST_CASE("Test Wave class")
        static const int CHANNELS = 2;
        static const int BIT_DEPTH = 32;
 
-  /* Each SECTION the TEST_CASE is executed from the start. Any code between 
-  this comment and the first SECTION macro is exectuted before each SECTION. */
-
-  std::unique_ptr<Wave> wave;
-  
-  SECTION("test basename")
-  {
-    wave = std::unique_ptr<Wave>(new Wave(nullptr, BUFFER_SIZE, CHANNELS, 
-      SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
-
-    REQUIRE(wave->getPath() == "path/to/sample.wav");
-    REQUIRE(wave->getBasename() == "sample");
-    REQUIRE(wave->getBasename(true) == "sample.wav");
-  }  
-
-  SECTION("test change name")
-  {
-    wave = std::unique_ptr<Wave>(new Wave(nullptr, BUFFER_SIZE, CHANNELS, 
-      SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
-    wave->setName("waveform");
-
-    REQUIRE(wave->getPath() == "path/to/waveform.wav");
-    REQUIRE(wave->getBasename() == "waveform");
-    REQUIRE(wave->getBasename(true) == "waveform.wav");
-  }
-
-  SECTION("test memory cleanup")
-  {
-    float* data = new float[BUFFER_SIZE];
-
-    wave = std::unique_ptr<Wave>(new Wave(data, BUFFER_SIZE, CHANNELS, 
-      SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
-    wave->clear();
-
-    REQUIRE(wave->getData() == nullptr);
-    REQUIRE(wave->getPath() == "");
-    REQUIRE(wave->getSize() == 0);
-  }
+       /* Each SECTION the TEST_CASE is executed from the start. Any code between 
+       this comment and the first SECTION macro is exectuted before each SECTION. */
+
+       std::unique_ptr<Wave> wave;
+       
+       SECTION("test basename")
+       {
+               wave = std::unique_ptr<Wave>(new Wave(nullptr, BUFFER_SIZE, CHANNELS, 
+                       SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
+
+               REQUIRE(wave->getPath() == "path/to/sample.wav");
+               REQUIRE(wave->getBasename() == "sample");
+               REQUIRE(wave->getBasename(true) == "sample.wav");
+       }
+
+       SECTION("test path")
+       {
+               wave = std::unique_ptr<Wave>(new Wave(nullptr, BUFFER_SIZE, CHANNELS, 
+                       SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
+
+               wave->setPath("path/is/now/different.mp3");
+
+               REQUIRE(wave->getPath() == "path/is/now/different.mp3");
+
+               wave->setPath("path/is/now/different.mp3", 5);
+
+               REQUIRE(wave->getPath() == "path/is/now/different-5.mp3");
+       }  
+
+       SECTION("test change name")
+       {
+               wave = std::unique_ptr<Wave>(new Wave(nullptr, BUFFER_SIZE, CHANNELS, 
+                       SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
+
+               REQUIRE(wave->getPath() == "path/to/sample.wav");
+               REQUIRE(wave->getBasename() == "sample");
+               REQUIRE(wave->getBasename(true) == "sample.wav");
+       }
+
+       SECTION("test memory cleanup")
+       {
+               float* data = new float[BUFFER_SIZE];
+
+               wave = std::unique_ptr<Wave>(new Wave(data, BUFFER_SIZE, CHANNELS, 
+                       SAMPLE_RATE, BIT_DEPTH, "path/to/sample.wav"));
+               wave->clear();
+
+               REQUIRE(wave->getData() == nullptr);
+               REQUIRE(wave->getPath() == "");
+               REQUIRE(wave->getSize() == 0);
+       }
 }