src/gui/dialogs/sampleEditor.cpp
src/gui/dialogs/pluginWindowGUI.cpp
src/gui/dialogs/pluginChooser.cpp
+ src/gui/dialogs/missingAssets.cpp
src/gui/dialogs/actionEditor/baseActionEditor.cpp
src/gui/dialogs/actionEditor/sampleActionEditor.cpp
src/gui/dialogs/actionEditor/midiActionEditor.cpp
src/gui/dialogs/midiIO/midiInputMaster.cpp
src/gui/elems/midiIO/midiLearner.cpp
src/gui/elems/midiIO/midiLearnerPack.cpp
- src/gui/elems/browser.cpp
+ src/gui/elems/fileBrowser.cpp
src/gui/elems/soundMeter.cpp
src/gui/elems/plugin/pluginBrowser.cpp
src/gui/elems/plugin/pluginParameter.cpp
src/gui/elems/mainWindow/keyboard/channel.cpp
src/gui/elems/mainWindow/keyboard/sampleChannelButton.cpp
src/gui/elems/mainWindow/keyboard/midiChannelButton.cpp
+ src/gui/elems/mainWindow/keyboard/midiActivity.cpp
src/gui/elems/config/tabMisc.cpp
src/gui/elems/config/tabMidi.cpp
src/gui/elems/config/tabAudio.cpp
src/gui/elems/basics/progress.cpp
src/gui/elems/basics/check.cpp
src/gui/elems/basics/split.cpp
+ src/gui/elems/basics/browser.cpp
+ src/gui/elems/basics/flex.cpp
src/utils/log.cpp
src/utils/time.cpp
src/utils/math.cpp
--------------------------------------------------------------------------------
+0.20.1 --- 2022 . 02 . 21
+- New MIDI I/O activity LEDs on channels (#143)
+- New "Missing Assets" alert window (#344)
+- Many smaller improvements and cleanups in UI code
+- Add ability to sort installed plug-ins by Format (VST, VST3, ...)
+- Update JUCE to 6.1.5
+- Update custom RtAudio submodule (now pointing to 6.0.0beta1)
+- Optimize internal buffer Giada <-> JUCE conversion
+- Remove old plug-in parameter storage used in old patches
+- Fix deadlock when using JACK transport
+- Fix Action Editor grid refresh when changing BPM while the editor window is open (#547)
+- Fix plug-in clone operation while cloning a channel (#551)
+
+
0.20.0 --- 2022 . 01 . 24
- Show progress bar for long operations
- Improved rendering algorithm for sample channels
## Copyright
-Giada is Copyright (C) 2010-2021 by Giovanni A. Zuliani | Monocasual Laboratories
+Giada is Copyright (C) 2010-2022 by Giovanni A. Zuliani | Monocasual Laboratories
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.
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
if (id == Mixer::MASTER_OUT_CHANNEL_ID)
renderMasterOut(*out);
-#ifdef WITH_VST
else if (id == Mixer::MASTER_IN_CHANNEL_ID)
renderMasterIn(*in);
-#endif
else
renderChannel(*out, *in, audible);
}
/* -------------------------------------------------------------------------- */
-#ifdef WITH_VST
-
void Channel::renderMasterIn(mcl::AudioBuffer& in) const
{
+#ifdef WITH_VST
if (plugins.size() > 0)
g_engine.pluginHost.processStack(in, plugins, nullptr);
-}
-
+#else
+ (void)in;
#endif
+}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/plugins/plugin.h"
#include "core/plugins/pluginHost.h"
#include "core/wave.h"
+#include "glue/channel.h"
#include <cassert>
+#include <memory>
namespace giada::m
{
if (out.audioReceiver)
out.audioReceiver->overdubProtection = m_conf.overdubProtectionDefaultOn;
+ c::channel::setCallbacks(out); // UI callbacks
+
return out;
}
out.id = m_channelId.generate();
out.shared = &makeShared(o.type, bufferSize);
+ c::channel::setCallbacks(out); // UI callbacks
+
return out;
}
Channel ChannelManager::deserializeChannel(const Patch::Channel& pch, float samplerateRatio, int bufferSize)
{
m_channelId.set(pch.id);
- return Channel(pch, makeShared(pch.type, bufferSize), samplerateRatio, m_model.findShared<Wave>(pch.waveId));
+
+ Channel out = Channel(pch, makeShared(pch.type, bufferSize), samplerateRatio, m_model.findShared<Wave>(pch.waveId));
+ c::channel::setCallbacks(out); // UI callbacks
+
+ return out;
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
template <typename KernelMidiI>
MidiLighter<KernelMidiI>::MidiLighter(MidiMapper<KernelMidiI>& m)
: enabled(false)
+, onSend(nullptr)
, m_midiMapper(&m)
{
}
switch (status)
{
case ChannelStatus::OFF:
- m_midiMapper->sendMidiLightning(l_playing, midiMap.stopped);
+ send(l_playing, midiMap.stopped);
break;
case ChannelStatus::WAIT:
- m_midiMapper->sendMidiLightning(l_playing, midiMap.waiting);
+ send(l_playing, midiMap.waiting);
break;
case ChannelStatus::ENDING:
- m_midiMapper->sendMidiLightning(l_playing, midiMap.stopping);
+ send(l_playing, midiMap.stopping);
break;
case ChannelStatus::PLAY:
- m_midiMapper->sendMidiLightning(l_playing, audible ? midiMap.playing : midiMap.playingInaudible);
+ send(l_playing, audible ? midiMap.playing : midiMap.playingInaudible);
break;
default:
const uint32_t l_mute = mute.getValue();
if (l_mute != 0x0)
- m_midiMapper->sendMidiLightning(l_mute, isMuted ? midiMap.muteOn : midiMap.muteOff);
+ send(l_mute, isMuted ? midiMap.muteOn : midiMap.muteOff);
}
/* -------------------------------------------------------------------------- */
const uint32_t l_solo = solo.getValue();
if (l_solo != 0x0)
- m_midiMapper->sendMidiLightning(l_solo, isSoloed ? midiMap.soloOn : midiMap.soloOff);
+ send(l_solo, isSoloed ? midiMap.soloOn : midiMap.soloOff);
+}
+
+/* -------------------------------------------------------------------------- */
+
+template <typename KernelMidiI>
+void MidiLighter<KernelMidiI>::send(uint32_t learnt, const MidiMap::Message& msg)
+{
+ assert(onSend != nullptr);
+
+ m_midiMapper->sendMidiLightning(learnt, msg);
+ onSend();
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
MidiLearnParam mute;
MidiLearnParam solo;
+ /* onSend
+ Callback fired when a MIDI signal has been sent. */
+
+ std::function<void()> onSend;
+
private:
+ void send(uint32_t learnt, const MidiMap::Message&);
+
MidiMapper<KernelMidiI>* m_midiMapper;
};
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
: kernelMidi(&k)
, enabled(false)
, filter(0)
+, onSend(nullptr)
{
}
void MidiSender::send(MidiEvent e) const
{
+ assert(onSend != nullptr);
+
e.setChannel(filter);
kernelMidi->send(e.getRaw());
+ onSend();
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
int filter;
+ /* onSend
+ Callback fired when a MIDI signal has been sent. */
+
+ std::function<void()> onSend;
+
private:
void send(MidiEvent e) const;
void parseActions(const Channel& ch, const std::vector<Action>& as) const;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
/* -- version --------------------------------------------------------------- */
constexpr auto G_APP_NAME = "Giada";
-constexpr auto G_VERSION_STR = "0.20.0";
+constexpr auto G_VERSION_STR = "0.20.1";
constexpr int G_VERSION_MAJOR = 0;
constexpr int G_VERSION_MINOR = 20;
-constexpr int G_VERSION_PATCH = 0;
+constexpr int G_VERSION_PATCH = 1;
constexpr auto CONF_FILENAME = "giada.conf";
constexpr int G_EVENT_DISPATCHER_RATE_MS = 5;
/* -- GUI ------------------------------------------------------------------- */
-constexpr float G_GUI_REFRESH_RATE = 1 / 30.0f; // 30 fps
-constexpr float G_GUI_PLUGIN_RATE = 1 / 30.0f; // 30 fps
+constexpr int G_GUI_FPS = 30;
+constexpr float G_GUI_REFRESH_RATE = 1 / static_cast<float>(G_GUI_FPS);
constexpr int G_GUI_FONT_SIZE_BASE = 12;
constexpr int G_GUI_INNER_MARGIN = 4;
constexpr int G_GUI_OUTER_MARGIN = 8;
/* -- unique IDs of mainWin's subwindows ------------------------------------ */
/* -- wid > 0 are reserved by gg_keyboard ----------------------------------- */
-constexpr int WID_BEATS = -1;
-constexpr int WID_BPM = -2;
-constexpr int WID_ABOUT = -3;
-constexpr int WID_FILE_BROWSER = -4;
-constexpr int WID_CONFIG = -5;
-constexpr int WID_FX_LIST = -6;
-constexpr int WID_ACTION_EDITOR = -7;
-constexpr int WID_SAMPLE_EDITOR = -8;
-constexpr int WID_FX = -9;
-constexpr int WID_KEY_GRABBER = -10;
-constexpr int WID_SAMPLE_NAME = -11;
-constexpr int WID_FX_CHOOSER = -12;
-constexpr int WID_MIDI_INPUT = -13;
-constexpr int WID_MIDI_OUTPUT = -14;
+constexpr int WID_BEATS = -1;
+constexpr int WID_BPM = -2;
+constexpr int WID_ABOUT = -3;
+constexpr int WID_FILE_BROWSER = -4;
+constexpr int WID_CONFIG = -5;
+constexpr int WID_FX_LIST = -6;
+constexpr int WID_ACTION_EDITOR = -7;
+constexpr int WID_SAMPLE_EDITOR = -8;
+constexpr int WID_FX = -9;
+constexpr int WID_KEY_GRABBER = -10;
+constexpr int WID_SAMPLE_NAME = -11;
+constexpr int WID_FX_CHOOSER = -12;
+constexpr int WID_MIDI_INPUT = -13;
+constexpr int WID_MIDI_OUTPUT = -14;
+constexpr int WID_MISSING_ASSETS = -15;
/* -- patch signals --------------------------------------------------------- */
constexpr int G_PATCH_UNSUPPORTED = -2;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/model/storage.h"
#include "utils/fs.h"
#include "utils/log.h"
+#include <memory>
namespace giada::m
{
+bool LoadState::isGood() const
+{
+ return patch == G_PATCH_OK && missingWaves.empty() && missingPlugins.empty();
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
Engine::Engine()
: midiMapper(kernelMidi)
, channelManager(conf.data, model)
kernelMidi.onMidiReceived = [this](uint32_t msg) { midiDispatcher.dispatch(msg); };
#ifdef WITH_AUDIO_JACK
- if (kernelAudio.getAPI() == G_SYS_API_JACK)
- jackTransport.setHandle(kernelAudio.getJackHandle());
-
- synchronizer.onJackRewind = [this]() { sequencer.rawRewind(); };
- synchronizer.onJackChangeBpm = [this](float bpm) { sequencer.rawSetBpm(bpm, kernelAudio.getSampleRate()); };
- synchronizer.onJackStart = [this]() { sequencer.rawStart(); };
- synchronizer.onJackStop = [this]() { sequencer.rawStop(); };
+ synchronizer.onJackRewind = [this]() {
+ eventDispatcher.pumpMidiEvent({EventDispatcher::EventType::SEQUENCER_REWIND_JACK});
+ };
+ synchronizer.onJackChangeBpm = [this](float bpm) {
+ eventDispatcher.pumpMidiEvent({EventDispatcher::EventType::SEQUENCER_BPM_JACK, 0, 0, bpm});
+ };
+ synchronizer.onJackStart = [this]() {
+ eventDispatcher.pumpMidiEvent({EventDispatcher::EventType::SEQUENCER_START_JACK});
+ };
+ synchronizer.onJackStop = [this]() {
+ eventDispatcher.pumpMidiEvent({EventDispatcher::EventType::SEQUENCER_STOP_JACK});
+ };
#endif
eventDispatcher.onMidiLearn = [this](const MidiEvent& e) { midiDispatcher.learn(e); };
model.swap(model::SwapType::SOFT);
};
eventDispatcher.onProcessSequencer = [this](const EventDispatcher::EventBuffer& eb) {
- sequencer.react(eb);
+ sequencer.react(eb, kernelAudio.getSampleRate());
};
eventDispatcher.onMixerSignalCallback = [this]() {
recorder.startInputRecOnCallback();
if (!kernelAudio.isReady())
return;
+#ifdef WITH_AUDIO_JACK
+ if (kernelAudio.getAPI() == G_SYS_API_JACK)
+ jackTransport.setHandle(kernelAudio.getJackHandle());
+#endif
+
mixerHandler.reset(sequencer.getMaxFramesInLoop(kernelAudio.getSampleRate()),
kernelAudio.getBufferSize(), channelManager);
sequencer.reset(kernelAudio.getSampleRate());
/* -------------------------------------------------------------------------- */
-int Engine::load(const std::string& projectPath, const std::string& patchPath,
+LoadState Engine::load(const std::string& projectPath, const std::string& patchPath,
std::function<void(float)> progress)
{
u::log::print("[Engine::load] Load project from %s\n", projectPath);
patch.reset();
if (int res = patch.read(patchPath, projectPath); res != G_PATCH_OK)
- return res;
+ return {res};
progress(0.3f);
mixer.disable();
reset();
- m::model::load(patch.data);
+ LoadState state = m::model::load(patch.data);
progress(0.6f);
progress(1.0f);
- return G_PATCH_OK;
+ state.patch = G_PATCH_OK;
+ return state;
}
-} // namespace giada::m
\ No newline at end of file
+} // namespace giada::m
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::m
{
+struct LoadState
+{
+ bool isGood() const;
+
+ int patch = G_PATCH_OK;
+ std::vector<std::string> missingWaves = {};
+ std::vector<std::string> missingPlugins = {};
+};
+
class Engine final
{
public:
/* load
Reads a Patch from file and then de-serialize its content into the model.
- Returns G_PATCH_OK on success or any G_PATCH_* on failure. */
+ Returns a LoadState object. */
- int load(const std::string& projectPath, const std::string& patchPath,
+ LoadState load(const std::string& projectPath, const std::string& patchPath,
std::function<void(float)> progress);
/* updateMixerModel
SEQUENCER_START,
SEQUENCER_STOP,
SEQUENCER_REWIND,
+#ifdef WITH_AUDIO_JACK
+ SEQUENCER_START_JACK,
+ SEQUENCER_STOP_JACK,
+ SEQUENCER_REWIND_JACK,
+ SEQUENCER_BPM_JACK,
+#endif
MIDI,
MIDI_DISPATCHER_LEARN,
MIDI_DISPATCHER_PROCESS,
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/const.h"
#include "utils/log.h"
#include <cassert>
+#include <memory>
namespace giada::m
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#ifdef WITH_VST
-void MidiDispatcher::processPlugins(const std::vector<Plugin*>& plugins, const MidiEvent& midiEvent)
+void MidiDispatcher::processPlugins(ID channelId, const std::vector<Plugin*>& plugins,
+ const MidiEvent& midiEvent)
{
uint32_t pure = midiEvent.getRawNoVelocity();
float vf = u::math::map(midiEvent.getVelocity(), G_MAX_VELOCITY, 1.0f);
{
if (pure != param.getValue())
continue;
- c::events::setPluginParameter(p->id, param.getIndex(), vf, /*gui=*/false);
+ c::events::setPluginParameter(channelId, p->id, param.getIndex(), vf, Thread::MIDI);
u::log::print(" >>> [pluginId=%d paramIndex=%d] (pure=0x%X, value=%d, float=%f)\n",
p->id, param.getIndex(), pure, midiEvent.getVelocity(), vf);
}
#ifdef WITH_VST
/* Process learned plugins parameters. */
- processPlugins(c.plugins, midiEvent);
+ processPlugins(c.id, c.plugins, midiEvent);
#endif
/* Redirect raw MIDI message (pure + velocity) to plug-ins in armed
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void learnMaster(MidiEvent e, int param, std::function<void()> doneCb);
#ifdef WITH_VST
- void processPlugins(const std::vector<Plugin*>& plugins, const MidiEvent& midiEvent);
- void learnPlugin(MidiEvent e, std::size_t paramIndex, ID pluginId, std::function<void()> doneCb);
+ void processPlugins(ID channelId, const std::vector<Plugin*>& plugins,
+ const MidiEvent& midiEvent);
+ void learnPlugin(MidiEvent e, std::size_t paramIndex, ID pluginId,
+ std::function<void()> doneCb);
#endif
/* cb_midiLearn
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
if (!isMessageDefined(m))
{
- u::log::print("[MidiMapper::sendMidiLightning] message skipped (not defined in midiMap)");
+ u::log::print("[MidiMapper::sendMidiLightning] message skipped (not defined in midiMap)\n");
return;
}
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void Mixer::renderMasterIn(const Channel& ch, mcl::AudioBuffer& in) const
{
+#ifdef WITH_VST
ch.render(nullptr, &in, true);
+#else
+ (void)ch;
+ (void)in;
+#endif
}
void Mixer::renderMasterOut(const Channel& ch, mcl::AudioBuffer& out) const
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/vector.h"
#include <algorithm>
#include <cassert>
+#include <memory>
#include <vector>
namespace giada::m
}
#ifdef WITH_VST
+
+ /* Overwrite existing plug-ins in new channel with a new vector of plug-ins,
+ as currently new channel has cloned plug-ins from the old one (with same ID). */
+
+ std::vector<Plugin*> newPlugins;
for (const Plugin* plugin : oldChannel.plugins)
{
m_model.addShared(pluginManager.makePlugin(*plugin, sampleRate, bufferSize, sequencer));
- newChannel.plugins.push_back(&m_model.backShared<Plugin>());
+ newPlugins.push_back(&m_model.backShared<Plugin>());
}
+ newChannel.plugins = newPlugins;
+
#endif
/* Then push the new channel in the channels vector. */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/model/model.h"
#include <cassert>
+#include <memory>
#ifdef G_DEBUG_MODE
#include "core/channels/channelManager.h"
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "deps/mcl-audio-buffer/src/audioBuffer.hpp"
#include "src/core/actions/actions.h"
#include "utils/vector.h"
+#include <memory>
namespace giada::m::model
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/waveManager.h"
#include "src/core/actions/actionRecorder.h"
#include <cassert>
+#include <memory>
extern giada::m::Engine g_engine;
/* -------------------------------------------------------------------------- */
-void load(const Patch::Data& patch)
+LoadState load(const Patch::Data& patch)
{
DataLock lock = g_engine.model.lockData();
g_engine.model.get().channels = {};
g_engine.model.getAllShared<ChannelSharedPtrs>().clear();
+ LoadState state;
+
/* Load external data first: plug-ins and waves. */
#ifdef WITH_VST
g_engine.model.getAllShared<PluginPtrs>().clear();
for (const Patch::Plugin& pplugin : patch.plugins)
- g_engine.model.getAllShared<PluginPtrs>().push_back(g_engine.pluginManager.deserializePlugin(
- pplugin, patch.version, g_engine.kernelAudio.getSampleRate(), g_engine.kernelAudio.getBufferSize(), g_engine.sequencer));
+ {
+ std::unique_ptr<Plugin> p = g_engine.pluginManager.deserializePlugin(
+ pplugin, g_engine.kernelAudio.getSampleRate(), g_engine.kernelAudio.getBufferSize(), g_engine.sequencer);
+
+ if (!p->valid)
+ state.missingPlugins.push_back(pplugin.path);
+
+ g_engine.model.getAllShared<PluginPtrs>().push_back(std::move(p));
+ }
#endif
g_engine.model.getAllShared<WavePtrs>().clear();
{
std::unique_ptr<Wave> w = g_engine.waveManager.deserializeWave(pwave, g_engine.kernelAudio.getSampleRate(),
g_engine.conf.data.rsmpQuality);
+
if (w != nullptr)
g_engine.model.getAllShared<WavePtrs>().push_back(std::move(w));
+ else
+ state.missingWaves.push_back(pwave.path);
}
/* Then load up channels, actions and global properties. */
g_engine.model.get().sequencer.beats = patch.beats;
g_engine.model.get().sequencer.bpm = patch.bpm;
g_engine.model.get().sequencer.quantize = patch.quantize;
+
+ return state;
}
/* -------------------------------------------------------------------------- */
#ifndef G_MODEL_STORAGE_H
#define G_MODEL_STORAGE_H
-#include "core/patch.h"
#include "core/conf.h"
+#include "core/engine.h"
+#include "core/patch.h"
namespace giada::m::model
{
-void store(Conf::Data& c);
-void store(Patch::Data& p);
-void load(const Patch::Data& p);
-void load(const Conf::Data& c);
+void store(Conf::Data& c);
+void store(Patch::Data& p);
+LoadState load(const Patch::Data& p);
+void load(const Conf::Data& c);
} // namespace giada::m::model
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/time.h"
#include <FL/Fl.H>
#include <cassert>
+#include <memory>
namespace giada::m
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/plugins/pluginHost.h"
#include "core/plugins/pluginState.h"
#include "deps/juce-config.h"
+#include <memory>
#include <vector>
namespace giada::m
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/log.h"
#include "utils/vector.h"
#include <cassert>
+#include <memory>
namespace giada::m
{
void PluginHost::giadaToJuceTempBuf(const mcl::AudioBuffer& outBuf)
{
- for (int i = 0; i < outBuf.countFrames(); i++)
- for (int j = 0; j < outBuf.countChannels(); j++)
- m_audioBuffer.setSample(j, i, outBuf[i][j]);
-}
+ assert(outBuf.countChannels() == m_audioBuffer.getNumChannels());
+
+ using namespace juce;
+ using Format = AudioData::Format<AudioData::Float32, AudioData::BigEndian>;
-/* juceToGiadaOutBuf
-Converts 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. */
+ AudioData::deinterleaveSamples(
+ AudioData::InterleavedSource<Format>{outBuf[0], outBuf.countChannels()},
+ AudioData::NonInterleavedDest<Format>{m_audioBuffer.getArrayOfWritePointers(), m_audioBuffer.getNumChannels()},
+ outBuf.countFrames());
+}
void PluginHost::juceToGiadaOutBuf(mcl::AudioBuffer& outBuf) const
{
- for (int i = 0; i < outBuf.countFrames(); i++)
- for (int j = 0; j < outBuf.countChannels(); j++)
- outBuf[i][j] = m_audioBuffer.getSample(j, i);
+ assert(outBuf.countChannels() == m_audioBuffer.getNumChannels());
+
+ using namespace juce;
+ using Format = AudioData::Format<AudioData::Float32, AudioData::BigEndian>;
+
+ AudioData::interleaveSamples(
+ AudioData::NonInterleavedSource<Format>{m_audioBuffer.getArrayOfReadPointers(), m_audioBuffer.getNumChannels()},
+ AudioData::InterleavedDest<Format>{outBuf[0], outBuf.countChannels()},
+ outBuf.countFrames());
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/types.h"
#include "deps/juce-config.h"
#include <functional>
+#include <memory>
namespace mcl
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/log.h"
#include "utils/string.h"
#include <cassert>
+#include <memory>
namespace giada::m
{
int PluginManager::scanDirs(const std::string& dirs, const std::function<void(float)>& cb)
{
u::log::print("[pluginManager::scanDir] requested directories: '%s'\n", dirs);
- u::log::print("[pluginManager::scanDir] current plug-in types: %d\n", m_knownPluginList.getNumTypes());
+ u::log::print("[pluginManager::scanDir] currently known plug-ins: %d\n", m_knownPluginList.getNumTypes());
m_knownPluginList.clear(); // clear up previous plugins
/* -------------------------------------------------------------------------- */
std::unique_ptr<Plugin> PluginManager::deserializePlugin(const Patch::Plugin& p,
- Patch::Version version, int sampleRate, int bufferSize, const Sequencer& sequencer)
+ int sampleRate, int bufferSize, const Sequencer& sequencer)
{
std::unique_ptr<Plugin> plugin = makePlugin(p.path, sampleRate, bufferSize, sequencer, p.id);
if (!plugin->valid)
return plugin; // Return invalid version
- /* Fill plug-in parameters. */
plugin->setBypass(p.bypass);
-
- if (version < Patch::Version{0, 17, 0}) // TODO - to be removed in 0.18.0
- for (unsigned j = 0; j < p.params.size(); j++)
- plugin->setParameter(j, p.params.at(j));
- else
- plugin->setState(PluginState(p.state));
+ plugin->setState(PluginState(p.state));
/* Fill plug-in MidiIn parameters. Don't fill Plugin::midiInParam if
Patch::midiInParams are zero: it would wipe out the current default 0x0
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/patch.h"
#include "deps/juce-config.h"
#include "plugin.h"
+#include <memory>
namespace giada::m::patch
{
Transforms patch data into a Plugin object and vice versa. */
const Patch::Plugin serializePlugin(const Plugin& p) const;
- std::unique_ptr<Plugin> deserializePlugin(const Patch::Plugin& p, Patch::Version version, int sampleRate, int bufferSize, const Sequencer&);
+ std::unique_ptr<Plugin> deserializePlugin(const Patch::Plugin&, int sampleRate, int bufferSize, const Sequencer&);
std::vector<Plugin*> hydratePlugins(std::vector<ID> pluginIds, model::Model& model);
void sortPlugins(SortMethod sortMethod);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
/* -------------------------------------------------------------------------- */
-void Sequencer::react(const EventDispatcher::EventBuffer& events)
+void Sequencer::react(const EventDispatcher::EventBuffer& events, int sampleRate)
{
for (const EventDispatcher::Event& e : events)
{
- if (e.type == EventDispatcher::EventType::SEQUENCER_START)
+ switch (e.type)
{
+ case EventDispatcher::EventType::SEQUENCER_START:
if (!m_jackTransport.start())
rawStart();
break;
- }
- if (e.type == EventDispatcher::EventType::SEQUENCER_STOP)
- {
+
+ case EventDispatcher::EventType::SEQUENCER_STOP:
if (!m_jackTransport.stop())
rawStop();
break;
- }
- if (e.type == EventDispatcher::EventType::SEQUENCER_REWIND)
- {
+
+ case EventDispatcher::EventType::SEQUENCER_REWIND:
if (!m_jackTransport.setPosition(0))
rawRewind();
break;
+
+#ifdef WITH_AUDIO_JACK
+ case EventDispatcher::EventType::SEQUENCER_START_JACK:
+ rawStart();
+ break;
+
+ case EventDispatcher::EventType::SEQUENCER_STOP_JACK:
+ rawStop();
+ break;
+
+ case EventDispatcher::EventType::SEQUENCER_REWIND_JACK:
+ rawRewind();
+ break;
+
+ case EventDispatcher::EventType::SEQUENCER_BPM_JACK:
+ rawSetBpm(std::get<float>(e.data), sampleRate);
+ break;
+#endif
+
+ default:
+ break;
}
}
}
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
/* react
Reacts to live events coming from the EventDispatcher (human events). */
- void react(const EventDispatcher::EventBuffer&);
+ void react(const EventDispatcher::EventBuffer&, int sampleRate);
/* advance
Parses sequencer events that might occur in a block and advances the internal
void render(mcl::AudioBuffer& outBuf);
- /* raw[*]
- Raw functions to start, stop and rewind the sequencer. These functions must
- be called only when the JACK signal is received. Other modules should send
- a SEQUENCER_* event to the Event Dispatcher. */
-
- void rawStart();
- void rawStop();
- void rawRewind();
-
- /* rawSetBpm
- Raw function to set the bpm, bypassing any JACK instruction. This function
- must be called only by the Synchronizer when the JACK signal is received.
- Other modules should use the non-raw version below. */
-
- void rawSetBpm(float v, int sampleRate);
-
void rewind();
void toggleMetronome();
void setMetronome(bool v);
void rewindQ(Frame delta);
+ /* raw[*]
+ Raw functions to start, stop and rewind the sequencer. These functions must
+ be called only when the JACK signal is received. Other modules should send
+ a SEQUENCER_* event to the Event Dispatcher. */
+
+ void rawStart();
+ void rawStop();
+ void rawRewind();
+
+ /* rawSetBpm
+ Raw function to set the bpm, bypassing any JACK instruction. This function
+ must be called only by the Synchronizer when the JACK signal is received.
+ Other modules should use the public, non-raw version setBpm(...). */
+
+ void rawSetBpm(float v, int sampleRate);
+
model::Model& m_model;
Synchronizer& m_synchronizer;
JackTransport& m_jackTransport;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "wave.h"
#include "waveFx.h"
#include <cmath>
+#include <memory>
#include <samplerate.h>
#include <sndfile.h>
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void addChannel(ID columnId, ChannelType type)
{
- g_engine.mixerHandler.addChannel(type, columnId, g_engine.kernelAudio.getBufferSize(), g_engine.channelManager);
+ m::Channel& ch = g_engine.mixerHandler.addChannel(type, columnId,
+ g_engine.kernelAudio.getBufferSize(), g_engine.channelManager);
+
+ auto onSendMidiCb = [channelId = ch.id]() { g_ui.mainWindow->keyboard->notifyMidiOut(channelId); };
+
+ ch.midiLighter.onSend = onSendMidiCb;
+ if (ch.midiSender)
+ ch.midiSender->onSend = onSendMidiCb;
}
/* -------------------------------------------------------------------------- */
{
g_engine.mixerHandler.renameChannel(channelId, name);
}
+
+/* -------------------------------------------------------------------------- */
+
+void setCallbacks(m::Channel& ch)
+{
+ auto onSendMidiCb = [channelId = ch.id]() { g_ui.mainWindow->keyboard->notifyMidiOut(channelId); };
+
+ ch.midiLighter.onSend = onSendMidiCb;
+ if (ch.midiSender)
+ ch.midiSender->onSend = onSendMidiCb;
+}
} // namespace giada::c::channel
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void setHeight(ID channelId, Pixel p);
void setSamplePlayerMode(ID channelId, SamplePlayerMode m);
+
+/* setCallbacks
+Install callbacks to a m::Channel object in order to communicate with the UI.
+Call this whenever you add a new channel. */
+
+void setCallbacks(m::Channel&);
} // namespace giada::c::channel
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
if (g_engine.kernelAudio.hasAPI(RtAudio::LINUX_ALSA))
audioData.apis[G_SYS_API_ALSA] = "ALSA";
if (g_engine.kernelAudio.hasAPI(RtAudio::UNIX_JACK))
- audioData.apis[G_SYS_API_JACK] = "Jack";
+ audioData.apis[G_SYS_API_JACK] = "JACK";
if (g_engine.kernelAudio.hasAPI(RtAudio::LINUX_PULSE))
audioData.apis[G_SYS_API_PULSE] = "PulseAudio";
#elif defined(G_OS_FREEBSD)
if (g_engine.kernelAudio.hasAPI(RtAudio::UNIX_JACK))
- audioData.apis[G_SYS_API_JACK] = "Jack";
+ audioData.apis[G_SYS_API_JACK] = "JACK";
if (g_engine.kernelAudio.hasAPI(RtAudio::LINUX_PULSE))
audioData.apis[G_SYS_API_PULSE] = "PulseAudio";
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
bool res = true;
if (t == Thread::MAIN)
+ {
res = g_engine.eventDispatcher.UIevents.push(e);
+ }
else if (t == Thread::MIDI)
+ {
res = g_engine.eventDispatcher.MidiEvents.push(e);
+ u::gui::ScopedLock lock;
+ g_ui.mainWindow->keyboard->notifyMidiIn(e.channelId);
+ }
else
+ {
assert(false);
+ }
if (!res)
G_DEBUG("[events] Queue full!\n");
pushEvent_({m::EventDispatcher::EventType::CHANNEL_VOLUME, 0, channelId, v}, t);
- sampleEditor::onRefresh(t == Thread::MAIN, [v](v::gdSampleEditor& e) { e.volumeTool->update(v); });
+ sampleEditor::onRefresh(t, [v](v::gdSampleEditor& e) { e.volumeTool->update(v); });
if (t != Thread::MAIN)
{
- Fl::lock();
- g_ui.mainWindow->keyboard->getChannel(channelId)->vol->value(v);
- Fl::unlock();
+ u::gui::ScopedLock lock;
+ g_ui.mainWindow->keyboard->setChannelVolume(channelId, v);
}
}
pushEvent_({m::EventDispatcher::EventType::CHANNEL_PITCH, 0, channelId, v}, t);
- sampleEditor::onRefresh(t == Thread::MAIN, [v](v::gdSampleEditor& e) { e.pitchTool->update(v); });
+ sampleEditor::onRefresh(t, [v](v::gdSampleEditor& e) { e.pitchTool->update(v); });
}
/* -------------------------------------------------------------------------- */
/* Pan event is currently triggered only by the main thread. */
pushEvent_({m::EventDispatcher::EventType::CHANNEL_PAN, 0, channelId, v}, Thread::MAIN);
- sampleEditor::onRefresh(/*gui=*/true, [v](v::gdSampleEditor& e) { e.panTool->update(v); });
+ sampleEditor::onRefresh(Thread::MAIN, [v](v::gdSampleEditor& e) { e.panTool->update(v); });
}
/* -------------------------------------------------------------------------- */
if (t != Thread::MAIN)
{
- Fl::lock();
+ u::gui::ScopedLock lock;
g_ui.mainWindow->mainIO->setInVol(v);
- Fl::unlock();
}
}
if (t != Thread::MAIN)
{
- Fl::lock();
+ u::gui::ScopedLock lock;
g_ui.mainWindow->mainIO->setOutVol(v);
- Fl::unlock();
}
}
/* -------------------------------------------------------------------------- */
#ifdef WITH_VST
-void setPluginParameter(ID pluginId, int paramIndex, float value, bool gui)
+void setPluginParameter(ID channelId, ID pluginId, int paramIndex, float value, Thread t)
{
+ if (t == Thread::MIDI)
+ {
+ u::gui::ScopedLock lock;
+ g_ui.mainWindow->keyboard->notifyMidiIn(channelId);
+ }
g_engine.pluginHost.setPluginParameter(pluginId, paramIndex, value);
- c::plugin::updateWindow(pluginId, gui);
+ c::plugin::updateWindow(pluginId, t);
}
#endif
} // namespace giada::c::events
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
/* Plug-ins. */
#ifdef WITH_VST
-void setPluginParameter(ID pluginId, int paramIndex, float value, bool gui);
+void setPluginParameter(ID channelId, ID pluginId, int paramIndex, float value, Thread);
#endif
} // namespace giada::c::events
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/dialogs/midiIO/midiInputMaster.h"
#include "gui/dialogs/midiIO/midiOutputMidiCh.h"
#include "gui/dialogs/midiIO/midiOutputSampleCh.h"
+#include "gui/dialogs/missingAssets.h"
#include "gui/dialogs/pluginChooser.h"
#include "gui/dialogs/pluginList.h"
#include "gui/dialogs/sampleEditor.h"
void openSampleActionEditor(ID channelId)
{
g_ui.openSubWindow(*g_ui.mainWindow.get(),
- new v::gdSampleActionEditor(channelId, g_engine.conf.data, g_engine.sequencer.getFramesInBeat()),
- WID_ACTION_EDITOR);
+ new v::gdSampleActionEditor(channelId, g_engine.conf.data), WID_ACTION_EDITOR);
}
/* -------------------------------------------------------------------------- */
void openMidiActionEditor(ID channelId)
{
g_ui.openSubWindow(*g_ui.mainWindow.get(),
- new v::gdMidiActionEditor(channelId, g_engine.conf.data, g_engine.sequencer.getFramesInBeat()),
- WID_ACTION_EDITOR);
+ new v::gdMidiActionEditor(channelId, g_engine.conf.data), WID_ACTION_EDITOR);
}
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
+void openMissingAssetsWindow(const m::LoadState& state)
+{
+ g_ui.openSubWindow(*g_ui.mainWindow.get(), new v::gdMissingAssets(state),
+ WID_MISSING_ASSETS);
+}
+
+/* -------------------------------------------------------------------------- */
+
#ifdef WITH_VST
void openBrowserForPlugins(v::gdWindow& parent)
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/types.h"
#include <string>
+namespace giada::m
+{
+struct LoadState;
+}
+
namespace giada::v
{
class gdWindow;
void openMidiActionEditor(ID channelId);
void openSampleEditor(ID channelId);
void openRenameChannelWindow(const c::channel::Data&);
+void openMissingAssetsWindow(const m::LoadState&);
#ifdef WITH_VST
void openBrowserForPlugins(v::gdWindow& parent);
void openChannelPluginListWindow(ID channelId);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/gui.h"
#include <FL/Fl.H>
#include <cassert>
+#include <memory>
extern giada::v::Ui g_ui;
extern giada::m::Engine g_engine;
/* -------------------------------------------------------------------------- */
-void updateWindow(ID pluginId, bool gui)
+void updateWindow(ID pluginId, Thread t)
{
m::Plugin* p = g_engine.model.findShared<m::Plugin>(pluginId);
if (child == nullptr)
return;
- if (!gui)
- Fl::lock();
- child->updateParameters(!gui);
- if (!gui)
- Fl::unlock();
+ if (t != Thread::MAIN)
+ u::gui::ScopedLock lock;
+ child->updateParameters(t != Thread::MAIN);
}
/* -------------------------------------------------------------------------- */
void setProgram(ID pluginId, int programIndex)
{
g_engine.pluginHost.setPluginProgram(pluginId, programIndex);
- updateWindow(pluginId, /*gui=*/true);
+ updateWindow(pluginId, Thread::MAIN);
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
Updates the editor-less plug-in window. This is useless if the plug-in has an
editor. */
-void updateWindow(ID pluginId, bool gui);
+void updateWindow(ID pluginId, Thread);
void addPlugin(int pluginListIndex, ID channelId);
void swapPlugins(const m::Plugin& p1, const m::Plugin& p2, ID channelId);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/log.h"
#include <FL/Fl.H>
#include <cassert>
+#include <memory>
extern giada::v::Ui g_ui;
extern giada::m::Engine g_engine;
/* -------------------------------------------------------------------------- */
-void onRefresh(bool gui, std::function<void(v::gdSampleEditor&)> f)
+void onRefresh(Thread t, std::function<void(v::gdSampleEditor&)> f)
{
v::gdSampleEditor* se = static_cast<v::gdSampleEditor*>(g_ui.getSubwindow(*g_ui.mainWindow.get(), WID_SAMPLE_EDITOR));
if (se == nullptr)
return;
- if (!gui)
- Fl::lock();
+ if (t != Thread::MAIN)
+ u::gui::ScopedLock lock;
f(*se);
- if (!gui)
- Fl::unlock();
}
v::gdSampleEditor* getSampleEditorWindow()
void toNewChannel(ID channelId, Frame a, Frame b)
{
- ID columnId = g_ui.mainWindow->keyboard->getChannel(channelId)->getColumnId();
+ ID columnId = g_ui.mainWindow->keyboard->getChannelColumnId(channelId);
g_engine.mixerHandler.addAndLoadChannel(columnId, g_engine.waveManager.createFromWave(getWave_(channelId), a, b),
g_engine.kernelAudio.getBufferSize(), g_engine.channelManager);
}
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
/* onRefresh --- TODO - wrong name */
-void onRefresh(bool gui, std::function<void(v::gdSampleEditor&)> f);
+void onRefresh(Thread, std::function<void(v::gdSampleEditor&)> f);
/* getData
Returns a Data object filled with data from a channel. */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/sequencer.h"
#include "core/wave.h"
#include "core/waveManager.h"
+#include "glue/layout.h"
+#include "glue/main.h"
#include "gui/dialogs/browser/browserLoad.h"
#include "gui/dialogs/browser/browserSave.h"
#include "gui/dialogs/mainWindow.h"
#include "gui/elems/mainWindow/keyboard/column.h"
#include "gui/elems/mainWindow/keyboard/keyboard.h"
#include "gui/ui.h"
-#include "main.h"
#include "src/core/actions/actionRecorder.h"
#include "storage.h"
#include "utils/fs.h"
p.setProgress(v);
};
- if (int res = g_engine.load(projectPath, patchPath, progressCb); res != G_PATCH_OK)
+ m::LoadState state = g_engine.load(projectPath, patchPath, progressCb);
+
+ if (state.patch != G_PATCH_OK)
{
- if (res == G_PATCH_UNREADABLE)
+ if (state.patch == G_PATCH_UNREADABLE)
v::gdAlert("This patch is unreadable.");
- else if (res == G_PATCH_INVALID)
+ else if (state.patch == G_PATCH_INVALID)
v::gdAlert("This patch is not valid.");
- else if (res == G_PATCH_UNSUPPORTED)
+ else if (state.patch == G_PATCH_UNSUPPORTED)
v::gdAlert("This patch format is no longer supported.");
return;
}
g_ui.load(g_engine.patch.data);
-#ifdef WITH_VST
-
- if (g_engine.pluginManager.hasMissingPlugins())
- v::gdAlert("Some plug-ins were not loaded successfully.\nCheck the Plug-in Browser to know more.");
-
-#endif
+ if (!state.isGood())
+ layout::openMissingAssetsWindow(state);
browser->do_callback();
}
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
, vstLogo(8, 265, 324, 50)
#endif
{
- end();
set_modal();
std::string version = G_VERSION_STR;
"www.giadamusic.com")
.c_str());
+ add(logo);
+ add(text);
+ add(close);
+
#ifdef WITH_VST
vstLogo.image(new Fl_Pixmap(vstLogo_xpm));
"VST is a trademark of Steinberg\nMedia Technologies GmbH");
vstText.position(vstText.x(), vstLogo.y() + vstLogo.h());
+ add(vstLogo);
+ add(vstText);
+
#endif
close.callback(cb_close, (void*)this);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::v
{
-gdBaseActionEditor::gdBaseActionEditor(ID channelId, m::Conf::Data& conf, Frame framesInBeat)
+gdBaseActionEditor::gdBaseActionEditor(ID channelId, m::Conf::Data& conf)
: gdWindow(conf.actionEditorX, conf.actionEditorY, conf.actionEditorW, conf.actionEditorH)
, channelId(channelId)
-, gridTool(0, 0, conf, framesInBeat)
+, gridTool(0, 0, conf)
, zoomInBtn(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", zoomInOff_xpm, zoomInOn_xpm)
, zoomOutBtn(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", zoomOutOff_xpm, zoomOutOn_xpm)
, m_barTop(0, 0, Direction::HORIZONTAL)
return f / m_ratio;
}
-Frame gdBaseActionEditor::pixelToFrame(Pixel p, bool snap) const
+Frame gdBaseActionEditor::pixelToFrame(Pixel p, Frame framesInBeat, bool snap) const
{
- return snap ? gridTool.getSnapFrame(p * m_ratio) : p * m_ratio;
+ return snap ? gridTool.getSnapFrame(p * m_ratio, framesInBeat) : p * m_ratio;
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void draw() override;
Pixel frameToPixel(Frame f) const;
- Frame pixelToFrame(Pixel p, bool snap = true) const;
+ Frame pixelToFrame(Pixel p, Frame framesInBeat, bool snap = true) const;
ID channelId;
static constexpr float MAX_RATIO = 40000.0f;
static constexpr float RATIO_STEP = 1.5f;
- gdBaseActionEditor(ID channelId, m::Conf::Data&, Frame framesInBeat);
+ gdBaseActionEditor(ID channelId, m::Conf::Data&);
/* getMouseOverContent
Returns mouse x-position relative to the viewport content. */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::v
{
-gdMidiActionEditor::gdMidiActionEditor(ID channelId, m::Conf::Data& conf, Frame framesInBeat)
-: gdBaseActionEditor(channelId, conf, framesInBeat)
+gdMidiActionEditor::gdMidiActionEditor(ID channelId, m::Conf::Data& conf)
+: gdBaseActionEditor(channelId, conf)
, m_barPadding(0, 0, w() - 150, G_GUI_UNIT)
, m_pianoRoll(0, 0, this)
, m_velocityEditor(0, 0, this)
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
class gdMidiActionEditor : public gdBaseActionEditor
{
public:
- gdMidiActionEditor(ID channelId, m::Conf::Data&, Frame framesInBeat);
+ gdMidiActionEditor(ID channelId, m::Conf::Data&);
~gdMidiActionEditor();
void rebuild() override;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::v
{
-gdSampleActionEditor::gdSampleActionEditor(ID channelId, m::Conf::Data& conf, Frame framesInBeat)
-: gdBaseActionEditor(channelId, conf, framesInBeat)
+gdSampleActionEditor::gdSampleActionEditor(ID channelId, m::Conf::Data& conf)
+: gdBaseActionEditor(channelId, conf)
, m_barPadding(0, 0, w() - 232, G_GUI_UNIT)
, m_sampleActionEditor(0, 0, this)
, m_envelopeEditor(0, 0, "Volume", this)
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
class gdSampleActionEditor : public gdBaseActionEditor
{
public:
- gdSampleActionEditor(ID channelId, m::Conf::Data&, Frame framesInBeat);
+ gdSampleActionEditor(ID channelId, m::Conf::Data&);
~gdSampleActionEditor();
void rebuild() override;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
set_modal();
+ begin();
m_beats = new geInput(8, 8, 43, G_GUI_UNIT);
m_bars = new geInput(m_beats->x() + m_beats->w() + 4, 8, 43, G_GUI_UNIT);
m_ok = new geButton(m_bars->x() + m_bars->w() + 4, 8, 70, G_GUI_UNIT, "Ok");
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "window.h"
class geInput;
-class geButton;
class geCheck;
namespace giada::v
{
+class geButton;
class gdBeatsInput : public gdWindow
{
public:
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
set_modal();
+ begin();
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");
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "window.h"
class geInput;
-class geButton;
namespace giada::v
{
+class geButton;
class gdBpmInput : public gdWindow
{
public:
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/elems/basics/check.h"
#include "gui/elems/basics/input.h"
#include "gui/elems/basics/progress.h"
-#include "gui/elems/browser.h"
+#include "gui/elems/fileBrowser.h"
#include "utils/fs.h"
#include "utils/gui.h"
{
set_non_modal();
+ begin();
+
groupTop = new Fl_Group(8, 8, w() - 16, 48);
hiddenFiles = new geCheck(groupTop->x(), groupTop->y(), 400, 20, "Show hidden files");
where = new geInput(groupTop->x(), hiddenFiles->y() + hiddenFiles->h() + 8, 20, 20);
updir->callback(cb_up, (void*)this);
- browser = new geBrowser(8, groupTop->y() + groupTop->h() + 8, w() - 16, h() - 101);
+ browser = new geFileBrowser(8, groupTop->y() + groupTop->h() + 8, w() - 16, h() - 101);
browser->loadDir(path);
if (path == m_conf.browserLastPath)
browser->preselect(m_conf.browserPosition, m_conf.browserLastValue);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
class Fl_Group;
class geCheck;
-class geButton;
class geInput;
namespace giada::m
namespace giada::v
{
-class geBrowser;
+class geButton;
+class geFileBrowser;
class gdBrowserBase : public gdWindow
{
public:
m::Conf::Data& m_conf;
ID m_channelId;
- Fl_Group* groupTop;
- geCheck* hiddenFiles;
- geBrowser* browser;
- geButton* ok;
- geButton* cancel;
- geInput* where;
- geButton* updir;
+ Fl_Group* groupTop;
+ geCheck* hiddenFiles;
+ geFileBrowser* browser;
+ geButton* ok;
+ geButton* cancel;
+ geInput* where;
+ geButton* updir;
};
} // namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "browserDir.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/input.h"
-#include "gui/elems/browser.h"
+#include "gui/elems/fileBrowser.h"
#include "utils/fs.h"
namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "browserLoad.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/input.h"
-#include "gui/elems/browser.h"
+#include "gui/elems/fileBrowser.h"
#include "utils/fs.h"
namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "browserSave.h"
#include "gui/elems/basics/button.h"
#include "gui/elems/basics/input.h"
-#include "gui/elems/browser.h"
+#include "gui/elems/fileBrowser.h"
#include "utils/fs.h"
namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
set_modal();
+ begin();
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");
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "window.h"
class geInput;
-class geButton;
namespace giada::c::channel
{
struct Data;
}
+
namespace giada::v
{
+class geButton;
class gdChannelNameInput : public gdWindow
{
public:
gdChannelNameInput(const c::channel::Data& d);
- private:
+private:
static void cb_update(Fl_Widget* /*w*/, void* p);
static void cb_cancel(Fl_Widget* /*w*/, void* p);
void cb_update();
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
gdConfig::gdConfig(int w, int h, m::Conf::Data& conf)
: gdWindow(u::gui::centerWindowX(w), u::gui::centerWindowY(h), w, h, "Configuration")
{
+ begin();
+
Fl_Tabs* tabs = new Fl_Tabs(8, 8, w - 16, h - 44);
tabs->box(G_CUSTOM_BORDER_BOX);
tabs->labelcolor(G_COLOR_LIGHT_2);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/conf.h"
#include "window.h"
-class geButton;
class geCheck;
class geInput;
class geBox;
namespace giada::v
{
+class geButton;
class geChoice;
class geTabAudio;
class geTabBehaviors;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <FL/Fl.H>
class geBox;
-class geButton;
namespace giada::c::channel
{
namespace giada::v
{
+class geButton;
class gdKeyGrabber : public gdWindow
{
public:
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "core/const.h"
#include "core/init.h"
#include "gui/elems/basics/boxtypes.h"
+#include "gui/elems/basics/flex.h"
#include "gui/elems/mainWindow/keyboard/keyboard.h"
#include "gui/elems/mainWindow/mainIO.h"
#include "gui/elems/mainWindow/mainMenu.h"
: gdWindow(W, H, title)
, m_conf(c)
{
-
Fl::visible_focus(0);
Fl::background(25, 25, 25); // TODO use G_COLOR_GREY_1
size_range(G_MIN_GUI_WIDTH, G_MIN_GUI_HEIGHT);
- mainMenu = new v::geMainMenu(8, 0);
-#if defined(WITH_VST)
- mainIO = new v::geMainIO(412, 8);
-#else
- mainIO = new v::geMainIO(460, 8);
-#endif
+ mainMenu = new v::geMainMenu(0, 0);
+ mainIO = new v::geMainIO(0, 0, 0, 0);
mainTransport = new v::geMainTransport(8, 39);
mainTimer = new v::geMainTimer(571, 44);
sequencer = new v::geSequencer(100, 78, 609, 30);
/* zone 1 - menus, and I/O tools */
- Fl_Group* zone1 = new Fl_Group(8, 0, W - 16, 28);
- zone1->add(mainMenu);
- zone1->resizable(new Fl_Box(300, 8, 80, 20));
- zone1->add(mainIO);
+ geFlex* zone1 = new geFlex(getContentBounds().reduced(G_GUI_OUTER_MARGIN).withH(G_GUI_UNIT),
+ Direction::HORIZONTAL, G_GUI_INNER_MARGIN);
+ zone1->add(mainMenu, 300);
+ zone1->add(new Fl_Box(0, 0, 0, 0));
+ zone1->add(mainIO, 430);
+ zone1->end();
/* zone 2 - mainTransport and timing tools */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void clearKeyboard();
- ScopedProgress getScopedProgress(const char* msg);
+ [[nodiscard]] ScopedProgress getScopedProgress(const char* msg);
geKeyboard* keyboard;
geSequencer* sequencer;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/dialogs/window.h"
#include "gui/elems/midiIO/midiLearner.h"
-class geButton;
class geCheck;
namespace giada::v
{
+class geButton;
class geChoice;
class gdMidiInputBase : public gdWindow
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
setCallbacks(
[channelId = channel.channelId](int param) { c::io::channel_startMidiLearn(param, channelId); },
[channelId = channel.channelId](int param) { c::io::channel_clearMidiLearn(param, channelId); });
- addMidiLearner("keyPress", G_MIDI_IN_KEYPRESS);
+ addMidiLearner("key press", G_MIDI_IN_KEYPRESS);
addMidiLearner("key release", G_MIDI_IN_KEYREL);
addMidiLearner("key kill", G_MIDI_IN_KILL);
addMidiLearner("arm", G_MIDI_IN_ARM);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/elems/midiIO/midiLearner.h"
#include "gui/elems/midiIO/midiLearnerPack.h"
-class geButton;
class geCheck;
/* There's no such thing as a gdMidiOutputMaster vs gdMidiOutputChannel. MIDI
{
namespace v
{
+class geButton;
class geLightningLearnerPack : public geMidiLearnerPack
{
public:
gdMidiOutputBase(int w, int h, ID channelId);
~gdMidiOutputBase();
- protected:
+protected:
/* cb_close
close current window. */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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 "gui/dialogs/missingAssets.h"
+#include "core/engine.h"
+#include "gui/elems/basics/box.h"
+#include "gui/elems/basics/browser.h"
+#include "gui/elems/basics/button.h"
+#include "gui/elems/basics/flex.h"
+#include "utils/gui.h"
+#include <FL/Fl_Group.H>
+
+namespace giada::v
+{
+gdMissingAssets::gdMissingAssets(const m::LoadState& state)
+: gdWindow(u::gui::getCenterWinBounds(400, 300), "Warning")
+{
+ geFlex* container = new geFlex(getContentBounds().reduced({G_GUI_OUTER_MARGIN}), Direction::VERTICAL, G_GUI_OUTER_MARGIN);
+ {
+ geFlex* body = new geFlex(Direction::VERTICAL, G_GUI_INNER_MARGIN);
+ {
+ geBox* textIntro = new geBox("This project contains missing assets.", FL_ALIGN_LEFT);
+ textIntro->color(G_COLOR_BLUE);
+
+ body->add(textIntro, G_GUI_UNIT);
+
+ if (state.missingWaves.size() > 0)
+ {
+ geBrowser* waves = new geBrowser();
+ for (const std::string& s : state.missingWaves)
+ waves->add(s.c_str());
+ body->add(new geBox("Audio files not found in the project folder:", FL_ALIGN_LEFT), G_GUI_UNIT);
+ body->add(waves);
+ }
+
+ if (state.missingPlugins.size() > 0)
+ {
+ geBrowser* plugins = new geBrowser();
+ for (const std::string& s : state.missingPlugins)
+ plugins->add(s.c_str());
+ body->add(new geBox("Audio plug-ins not found globally:", FL_ALIGN_LEFT), G_GUI_UNIT);
+ body->add(plugins);
+ }
+ body->end();
+ }
+
+ geFlex* footer = new geFlex(Direction::HORIZONTAL);
+ {
+ geButton* close = new geButton("Close");
+ close->onClick = [this]() { do_callback(); };
+ footer->add(new geBox()); // Spacer
+ footer->add(close, 80);
+ footer->end();
+ }
+
+ container->add(body);
+ container->add(footer, G_GUI_UNIT);
+ container->end();
+ }
+
+ add(container);
+ resizable(container);
+
+ set_modal();
+ u::gui::setFavicon(this);
+ show();
+}
+} // namespace giada::v
\ No newline at end of file
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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_MISSING_ASSETS_H
+#define GD_MISSING_ASSETS_H
+
+#include "gui/dialogs/window.h"
+
+namespace giada::m
+{
+struct LoadState;
+}
+
+namespace giada::v
+{
+class gdMissingAssets : public gdWindow
+{
+public:
+ gdMissingAssets(const m::LoadState&);
+};
+} // namespace giada::v
+
+#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
, m_conf(c)
, m_channelId(channelId)
{
+ begin();
+
/* 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");
sortMethod->add("Name");
sortMethod->add("Category");
sortMethod->add("Manufacturer");
+ sortMethod->add("Format");
sortMethod->callback(cb_sort, (void*)this);
sortMethod->value(m_conf.pluginSortMethod);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <FL/Fl.H>
#include <FL/Fl_Scroll.H>
-class geButton;
-class geButton;
-
namespace giada::v
{
+class geButton;
class geChoice;
class gePluginBrowser;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "glue/plugin.h"
#include "window.h"
-class geButton;
-
namespace giada::v
{
+class geButton;
class geLiquidScroll;
class gePluginElement;
class gdPluginList : public gdWindow
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
set_non_modal();
+ begin();
+
m_list = new geLiquidScroll(G_GUI_OUTER_MARGIN, G_GUI_OUTER_MARGIN,
w() - (G_GUI_OUTER_MARGIN * 2), h() - (G_GUI_OUTER_MARGIN * 2),
Direction::VERTICAL);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "window.h"
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
+#include <memory>
namespace giada::c::plugin
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#ifndef GD_EDITOR_H
#define GD_EDITOR_H
-#include "core/types.h"
#include "core/conf.h"
+#include "core/types.h"
#include "glue/sampleEditor.h"
#include "window.h"
-class geButton;
class geCheck;
class geBox;
-class geButton;
class geStatusButton;
namespace giada::m
namespace giada::v
{
+class geButton;
class geChoice;
class gePack;
class geGroup;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
-namespace giada
+namespace giada::v
{
-namespace v
+namespace
{
-void gdAlert(const char* c)
+bool confirmRet_ = false;
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+void gdAlert(const char* msg)
{
- gdWindow* modal = new gdWindow(
- (Fl::w() / 2) - 150,
- (Fl::h() / 2) - 47,
- 300, 90, "Alert");
- modal->set_modal();
- modal->begin();
- geBox* box = new geBox(10, 10, 280, 40, c);
+ gdWindow win(u::gui::getCenterWinBounds(300, 90), "Alert");
+ win.set_modal();
+ win.begin();
+ geBox* box = new geBox(10, 10, 280, 40, msg);
geButton* b = new geButton(210, 60, 80, 20, "Close");
- modal->end();
+ win.end();
box->labelsize(G_GUI_FONT_SIZE_BASE);
- b->callback(cb_window_closer, (void*)modal);
+
b->shortcut(FL_Enter);
- u::gui::setFavicon(modal);
- modal->show();
+ b->onClick = [&win]() { win.hide(); };
+
+ u::gui::setFavicon(&win);
+ win.show();
+
+ while (win.shown())
+ Fl::wait();
}
+/* -------------------------------------------------------------------------- */
+
int gdConfirmWin(const char* title, const char* msg)
{
- gdWindow* win = new gdWindow(
- (Fl::w() / 2) - 150,
- (Fl::h() / 2) - 47,
- 300, 90, title);
- win->set_modal();
- win->begin();
+ gdWindow win(u::gui::getCenterWinBounds(300, 90), title);
+ win.set_modal();
+ win.begin();
new geBox(10, 10, 280, 40, msg);
geButton* ok = new geButton(212, 62, 80, 20, "Ok");
geButton* ko = new geButton(124, 62, 80, 20, "Cancel");
- win->end();
+ win.end();
+
ok->shortcut(FL_Enter);
- u::gui::setFavicon(win);
- win->show();
+ ok->onClick = [&win]() { confirmRet_ = true; win.hide(); };
+
+ ko->onClick = [&win]() { confirmRet_ = false; win.hide(); };
+
+ u::gui::setFavicon(&win);
+ win.show();
- /* no callbacks here. readqueue() check the event stack. */
+ while (win.shown())
+ Fl::wait();
- int r = 0;
- while (true)
- {
- Fl_Widget* o = Fl::readqueue();
- if (!o)
- Fl::wait();
- else if (o == ok)
- {
- r = 1;
- break;
- }
- else if (o == ko)
- {
- r = 0;
- break;
- }
- }
- //delete win;
- win->hide();
- return r;
+ return confirmRet_;
}
-} // namespace v
-} // namespace giada
\ No newline at end of file
+} // namespace giada::v
\ No newline at end of file
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#ifndef GD_WARNINGS_H
#define GD_WARNINGS_H
-namespace giada
-{
-namespace v
+namespace giada::v
{
void gdAlert(const char* c);
int gdConfirmWin(const char* title, const char* msg);
} // namespace v
-} // namespace giada
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::v
{
-void cb_window_closer(Fl_Widget* /*v*/, void* p)
-{
- delete (Fl_Window*)p;
-}
-
-/* -------------------------------------------------------------------------- */
-
gdWindow::gdWindow(int x, int y, int w, int h, const char* title, int id)
: Fl_Double_Window(x, y, w, h, title)
, id(id)
, parent(nullptr)
{
+ end();
}
/* -------------------------------------------------------------------------- */
: Fl_Double_Window(w, h, title)
, id(id)
, parent(nullptr)
+{
+ end();
+}
+
+/* -------------------------------------------------------------------------- */
+
+gdWindow::gdWindow(geompp::Rect<int> r, const char* title, int id)
+: gdWindow(r.x, r.y, r.w, r.h, title, id)
{
}
/* -------------------------------------------------------------------------- */
+geompp::Rect<int> gdWindow::getContentBounds() const
+{
+ return {0, 0, w(), h()};
+}
+
+/* -------------------------------------------------------------------------- */
+
gdWindow* gdWindow::getParent()
{
return parent;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#ifndef GD_WINDOW_H
#define GD_WINDOW_H
+#include "deps/geompp/src/rect.hpp"
#include <FL/Fl_Double_Window.H>
#include <vector>
namespace giada::v
{
-/* cb_window_closer
-Callback for closing windows. Deletes the widget (delete). */
-
-void cb_window_closer(Fl_Widget* /*w*/, void* p);
-
class gdWindow : public Fl_Double_Window
{
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(geompp::Rect<int>, const char* title = 0, int id = 0);
~gdWindow();
static void cb_closeChild(Fl_Widget* /*w*/, void* p);
int getId() const;
void debug() const;
+ geompp::Rect<int> getContentBounds() const;
+
void addSubWindow(gdWindow* w);
void delSubWindow(gdWindow* w);
void delSubWindow(int id);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
if (m_base->gridTool.getValue() > 1)
{
fl_color(G_COLOR_GREY_3);
- drawVerticals(m_base->gridTool.getCellSize());
+ drawVerticals(m_base->gridTool.getCellSize(m_data->framesInBeat));
}
fl_color(G_COLOR_GREY_4);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void geEnvelopeEditor::onAddAction()
{
- Frame f = m_base->pixelToFrame(Fl::event_x() - x());
+ Frame f = m_base->pixelToFrame(Fl::event_x() - x(), m_data->framesInBeat);
int v = yToValue(Fl::event_y() - y());
c::actionEditor::recordEnvelopeAction(m_data->channelId, f, v);
void geEnvelopeEditor::onRefreshAction()
{
- Frame f = m_base->pixelToFrame((m_action->x() - x()) + geEnvelopePoint::SIDE / 2);
- float v = yToValue(m_action->y() - y(), geEnvelopePoint::SIDE);
- c::actionEditor::updateEnvelopeAction(m_data->channelId, m_action->a1, f, v);
+ const Frame f = (m_action->x() - x()) + geEnvelopePoint::SIDE / 2;
+ const Frame fq = m_base->pixelToFrame(f, m_data->framesInBeat);
+ const float v = yToValue(m_action->y() - y(), geEnvelopePoint::SIDE);
+ c::actionEditor::updateEnvelopeAction(m_data->channelId, m_action->a1, fq, v);
m_base->rebuild();
}
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* ------------------------------------------------------------------------------
*
-* Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+* Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::v
{
-geGridTool::geGridTool(Pixel x, Pixel y, m::Conf::Data& c, Frame framesInBeat)
+geGridTool::geGridTool(Pixel x, Pixel y, m::Conf::Data& c)
: Fl_Group(x, y, 80, 20)
, m_conf(c)
-, m_framesInBeat(framesInBeat)
{
gridType = new geChoice(x, y, 40, 20);
gridType->add("1");
/* -------------------------------------------------------------------------- */
-Frame geGridTool::getSnapFrame(Frame v) const
+Frame geGridTool::getSnapFrame(Frame v, Frame framesInBeat) const
{
if (!isOn())
return v;
- return u::math::quantize(v, getCellSize());
+ return u::math::quantize(v, getCellSize(framesInBeat));
}
/* -------------------------------------------------------------------------- */
-Frame geGridTool::getCellSize() const
+Frame geGridTool::getCellSize(Frame framesInBeat) const
{
- return m_framesInBeat / getValue();
+ return framesInBeat / getValue();
}
} // namespace giada::v
\ No newline at end of file
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
class geGridTool : public Fl_Group
{
public:
- geGridTool(Pixel x, Pixel y, m::Conf::Data&, Frame framesInBeat);
+ geGridTool(Pixel x, Pixel y, m::Conf::Data&);
~geGridTool();
int getValue() const;
bool isOn() const;
- Frame getSnapFrame(Frame f) const;
+ Frame getSnapFrame(Frame f, Frame framesInBeat) const;
/* getCellSize
Returns the size in frames of a single cell of the grid. */
- Frame getCellSize() const;
+ Frame getCellSize(Frame framesInBeat) const;
private:
m::Conf::Data& m_conf;
- Frame m_framesInBeat;
geChoice* gridType;
geCheck* active;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void gePianoRoll::onAddAction()
{
- Frame frame = m_base->pixelToFrame(Fl::event_x() - x());
+ Frame frame = m_base->pixelToFrame(Fl::event_x() - x(), m_data->framesInBeat);
int note = yToNote(Fl::event_y() - y());
c::actionEditor::recordMidiAction(m_data->channelId, note, G_MAX_VELOCITY,
frame);
if (!m_action->isOnEdges())
{
- f1 = m_base->pixelToFrame(p1);
- f2 = m_base->pixelToFrame(p2, /*snap=*/false) - (m_base->pixelToFrame(p1, /*snap=*/false) - f1);
+ f1 = m_base->pixelToFrame(p1, m_data->framesInBeat);
+ f2 = m_base->pixelToFrame(p2, m_data->framesInBeat, /*snap=*/false) - (m_base->pixelToFrame(p1, m_data->framesInBeat, /*snap=*/false) - f1);
}
else if (m_action->onLeftEdge)
{
- f1 = m_base->pixelToFrame(p1);
+ f1 = m_base->pixelToFrame(p1, m_data->framesInBeat);
f2 = m_action->a2.frame;
if (f1 == f2) // If snapping makes an action fall onto the other
f1 -= G_DEFAULT_ACTION_SIZE;
else if (m_action->onRightEdge)
{
f1 = m_action->a1.frame;
- f2 = m_base->pixelToFrame(p2);
+ f2 = m_base->pixelToFrame(p2, m_data->framesInBeat);
if (f1 == f2) // If snapping makes an action fall onto the other
f2 += G_DEFAULT_ACTION_SIZE;
}
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
for (const m::Action& a1 : m_data->actions)
{
-
if (a1.event.getStatus() == m::MidiEvent::ENVELOPE || isNoteOffSinglePress(a1))
continue;
void geSampleActionEditor::onAddAction()
{
- Frame f = m_base->pixelToFrame(Fl::event_x() - x());
+ Frame f = m_base->pixelToFrame(Fl::event_x() - x(), m_data->framesInBeat);
c::actionEditor::recordSampleAction(m_data->channelId, static_cast<gdSampleActionEditor*>(m_base)->getActionType(), f);
}
if (!m_action->isOnEdges())
{
- f1 = m_base->pixelToFrame(p1);
- f2 = m_base->pixelToFrame(p2, /*snap=*/false) - (m_base->pixelToFrame(p1, /*snap=*/false) - f1);
+ f1 = m_base->pixelToFrame(p1, m_data->framesInBeat);
+ f2 = m_base->pixelToFrame(p2, m_data->framesInBeat, /*snap=*/false) - (m_base->pixelToFrame(p1, m_data->framesInBeat, /*snap=*/false) - f1);
}
else if (m_action->onLeftEdge)
{
- f1 = m_base->pixelToFrame(p1);
+ f1 = m_base->pixelToFrame(p1, m_data->framesInBeat);
f2 = m_action->a2.frame;
}
else if (m_action->onRightEdge)
{
f1 = m_action->a1.frame;
- f2 = m_base->pixelToFrame(p2);
+ f2 = m_base->pixelToFrame(p2, m_data->framesInBeat);
}
ca::updateSampleAction(m_data->channelId, m_action->a1, type, f1, f2);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* ------------------------------------------------------------------------------
*
-* Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+* Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
copy_label(l);
box(FL_NO_BOX);
+ color(G_COLOR_GREY_1);
align(al | FL_ALIGN_INSIDE);
}
/* -------------------------------------------------------------------------- */
+geBox::geBox(const char* l, Fl_Align al)
+: geBox(0, 0, 0, 0, l, al)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
void geBox::draw()
{
- fl_rectf(x(), y(), w(), h(), G_COLOR_GREY_1); // Clear background
+ fl_rectf(x(), y(), w(), h(), color()); // Clear background
if (box() != FL_NO_BOX)
fl_rect(x(), y(), w(), h(), G_COLOR_GREY_4); // Border
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
public:
geBox(int x, int y, int w, int h, const char* l = nullptr, Fl_Align al = FL_ALIGN_CENTER);
+ geBox(const char* l = nullptr, Fl_Align al = FL_ALIGN_CENTER);
void draw() override;
};
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * geScroll
+ * Custom scroll with nice scrollbars and something else.
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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 "gui/elems/basics/browser.h"
+#include "core/const.h"
+#include "gui/elems/basics/boxtypes.h"
+
+namespace giada::v
+{
+geBrowser::geBrowser(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);
+
+ scrollbar.color(G_COLOR_GREY_2);
+ scrollbar.selection_color(G_COLOR_GREY_4);
+ scrollbar.labelcolor(G_COLOR_LIGHT_1);
+ scrollbar.slider(G_CUSTOM_BORDER_BOX);
+
+ hscrollbar.color(G_COLOR_GREY_2);
+ hscrollbar.selection_color(G_COLOR_GREY_4);
+ hscrollbar.labelcolor(G_COLOR_LIGHT_1);
+ hscrollbar.slider(G_CUSTOM_BORDER_BOX);
+}
+
+/* -------------------------------------------------------------------------- */
+
+geBrowser::geBrowser()
+: geBrowser(0, 0, 0, 0)
+{
+}
+} // namespace giada::v
\ No newline at end of file
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * This file is part of Giada - Your Hardcore Loopmachine.
+ *
+ * Giada - Your Hardcore Loopmachine is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Giada - Your Hardcore Loopmachine is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Giada - Your Hardcore Loopmachine. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * -------------------------------------------------------------------------- */
+
+#ifndef GE_BROWSER_H
+#define GE_BROWSER_H
+
+#include <FL/Fl_Browser.H>
+
+namespace giada::v
+{
+class geBrowser : public Fl_Browser
+{
+public:
+ geBrowser(int x, int y, int w, int h);
+ geBrowser();
+};
+} // namespace giada::v
+
+#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "utils/gui.h"
#include <FL/fl_draw.H>
+namespace giada::v
+{
geButton::geButton(int x, int y, int w, int h, const char* l,
const char** imgOff, const char** imgOn, const char** imgDisabled)
: Fl_Button(x, y, w, h, l)
+, onClick(nullptr)
, imgOff(imgOff)
, imgOn(imgOn)
, imgDisabled(imgDisabled)
, bgColor1(G_COLOR_GREY_4)
, bdColor(G_COLOR_GREY_4)
, txtColor(G_COLOR_LIGHT_2)
+{
+ callback(cb_click);
+}
+
+/* -------------------------------------------------------------------------- */
+
+geButton::geButton(const char* l, const char** imgOff, const char** imgOn, const char** imgDisabled)
+: geButton(0, 0, 0, 0, l, imgOff, imgOn, imgDisabled)
{
}
/* -------------------------------------------------------------------------- */
+void geButton::cb_click(Fl_Widget* w, void*)
+{
+ geButton* b = static_cast<geButton*>(w);
+ if (b->onClick != nullptr)
+ b->onClick();
+}
+
+/* -------------------------------------------------------------------------- */
+
void geButton::draw()
{
//Fl_Button::draw();
fl_font(FL_HELVETICA, G_GUI_FONT_SIZE_BASE);
fl_draw(giada::u::gui::truncate(label(), w() - 16).c_str(), x() + 2, y(), w() - 2, h(), FL_ALIGN_CENTER);
}
-}
\ No newline at end of file
+}
+} // namespace giada::v
\ No newline at end of file
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#define GE_BUTTON_H
#include <FL/Fl_Button.H>
+#include <functional>
+namespace giada::v
+{
class geButton : public Fl_Button
{
public:
const char** imgOff = nullptr, const char** imgOn = nullptr,
const char** imgDisabled = nullptr);
+ geButton(const char* l = nullptr, const char** imgOff = nullptr,
+ const char** imgOn = nullptr, const char** imgDisabled = nullptr);
+
void draw() override;
- protected:
+ std::function<void()> onClick;
+
+protected:
+ static void cb_click(Fl_Widget*, void*);
+
void draw(const char** img, Fl_Color bgColor, Fl_Color textColor);
const char** imgOff;
Fl_Color bdColor; // border
Fl_Color txtColor; // text
};
+} // namespace giada::v
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -------------------------------------------------------------------------- */
-#include "dial.h"
-#include "../../../core/const.h"
+#include "gui/elems/basics/dial.h"
+#include "core/const.h"
#include <FL/fl_draw.H>
+namespace giada::v
+{
geDial::geDial(int x, int y, int w, int h, const char* l)
: Fl_Dial(x, y, w, h, l)
+, onChange(nullptr)
{
labelsize(G_GUI_FONT_SIZE_BASE);
labelcolor(G_COLOR_LIGHT_2);
angles(0, 360);
color(G_COLOR_GREY_2); // background
selection_color(G_COLOR_GREY_4); // selection
+ callback(cb_change);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geDial::cb_change(Fl_Widget* w, void*)
+{
+ geDial* d = static_cast<geDial*>(w);
+ if (d->onChange != nullptr)
+ d->onChange(d->value());
}
/* -------------------------------------------------------------------------- */
fl_arc(x(), y(), w(), h(), 0, 360);
fl_pie(x(), y(), w(), h(), 270 - angle, 270 - angle1());
}
+} // namespace giada::v
\ No newline at end of file
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#define GE_DIAL_H
#include <FL/Fl_Dial.H>
+#include <functional>
+namespace giada::v
+{
class geDial : public Fl_Dial
{
public:
geDial(int x, int y, int w, int h, const char* l = 0);
- void draw();
+ void draw() override;
+
+ std::function<void(float)> onChange;
+
+private:
+ static void cb_change(Fl_Widget*, void*);
};
+} // namespace giada::v
#endif
--- /dev/null
+#include "flex.h"
+#include <numeric>
+
+namespace giada::v
+{
+geFlex::Elem::Elem(Fl_Widget& w, geFlex& parent, Direction d, int size, geompp::Border<int> pad)
+: size(size)
+, m_w(w)
+, m_parent(parent)
+, m_dir(d)
+, m_pad(pad)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
+int geFlex::Elem::getSize() const
+{
+ if (isFixed())
+ return size;
+ return m_dir == Direction::VERTICAL ? m_w.h() : m_w.w();
+}
+
+/* -------------------------------------------------------------------------- */
+
+bool geFlex::Elem::isFixed() const
+{
+ return size != -1;
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFlex::Elem::resize(int pos, int newSize)
+{
+ geompp::Rect<int> bounds;
+
+ if (m_dir == Direction::VERTICAL)
+ bounds = geompp::Rect<int>(m_parent.x(), pos, m_parent.w(), newSize).reduced(m_pad);
+ else
+ bounds = geompp::Rect<int>(pos, m_parent.y(), newSize, m_parent.h()).reduced(m_pad);
+
+ m_w.resize(bounds.x, bounds.y, bounds.w, bounds.h);
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+geFlex::geFlex(int x, int y, int w, int h, Direction d, int gutter)
+: Fl_Group(x, y, w, h, 0)
+, m_direction(d)
+, m_gutter(gutter)
+, m_numFixed(0)
+{
+ Fl_Group::end();
+}
+
+/* -------------------------------------------------------------------------- */
+
+geFlex::geFlex(geompp::Rect<int> r, Direction d, int gutter)
+: geFlex(r.x, r.y, r.w, r.h, d, gutter)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
+geFlex::geFlex(Direction d, int gutter)
+: geFlex(0, 0, 0, 0, d, gutter)
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFlex::add(Fl_Widget& w, int size, geompp::Border<int> pad)
+{
+ Fl_Group::add(w);
+ m_elems.push_back({w, *this, m_direction, size, pad});
+ if (size != -1)
+ m_numFixed++;
+}
+
+void geFlex::add(Fl_Widget* w, int size, geompp::Border<int> pad)
+{
+ geFlex::add(*w, size, pad);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFlex::resize(int X, int Y, int W, int H)
+{
+ Fl_Group::resize(X, Y, W, H);
+
+ const size_t numAllElems = m_elems.size();
+ const size_t numLiquidElems = numAllElems - m_numFixed;
+
+ const int pos = m_direction == Direction::VERTICAL ? y() : x();
+ const int size = m_direction == Direction::VERTICAL ? h() : w();
+
+ /* No fancy computations if there are no liquid elements. Just lay children
+ according to their fixed size. */
+
+ if (numLiquidElems == 0)
+ {
+ layWidgets(pos);
+ return;
+ }
+
+ const int fixedElemsSize = std::accumulate(m_elems.begin(), m_elems.end(), 0, [](int acc, const Elem& e) {
+ return e.isFixed() ? acc + e.getSize() : acc;
+ });
+ const int availableSize = size - (m_gutter * (numAllElems - 1)); // Total size - gutters
+ const int liquidElemSize = (availableSize - fixedElemsSize) / numLiquidElems;
+
+ layWidgets(pos, liquidElemSize);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFlex::layWidgets(int startPos, int sizeIfLiquid)
+{
+ int nextElemPos = startPos;
+ for (Elem& e : m_elems)
+ {
+ e.resize(nextElemPos, e.isFixed() ? e.size : sizeIfLiquid);
+ nextElemPos += e.getSize() + m_gutter;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFlex::end()
+{
+ Fl_Group::end();
+ resize(x(), y(), w(), h());
+}
+} // namespace giada::v
\ No newline at end of file
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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_FLEX_H
+#define GE_FLEX_H
+
+#include "deps/geompp/src/border.hpp"
+#include "deps/geompp/src/rect.hpp"
+#include "gui/types.h"
+#include <FL/Fl_Group.H>
+#include <vector>
+
+namespace giada::v
+{
+/* geFlex
+Like a FlexBox item, it's a group that contains widgets that can be stretched
+to fill the area. Inspired by https://github.com/osen/FL_Flex. */
+
+class geFlex : public Fl_Group
+{
+public:
+ geFlex(int x, int y, int w, int h, Direction d, int gutter = 0);
+ geFlex(geompp::Rect<int>, Direction d, int gutter = 0);
+ geFlex(Direction d, int gutter = 0);
+
+ /* add
+ Adds an existing widget to the Flex layout. If 'size' == -1, the widget
+ will be stretched to take up the available space. WARNING: like Fl_Group,
+ geFlex owns widgets! */
+
+ void add(Fl_Widget&, int size = -1, geompp::Border<int> pad = {});
+ void add(Fl_Widget*, int size = -1, geompp::Border<int> pad = {});
+
+ /* end
+ Finalize the Flex item. Call this when you're done add()ing widgets. */
+
+ void end();
+
+private:
+ class Elem
+ {
+ public:
+ Elem(Fl_Widget&, geFlex& parent, Direction, int size, geompp::Border<int> pad);
+
+ int getSize() const;
+ bool isFixed() const;
+
+ void resize(int pos, int size);
+
+ int size;
+
+ private:
+ Fl_Widget& m_w;
+ geFlex& m_parent;
+ Direction m_dir;
+ geompp::Border<int> m_pad;
+ };
+
+ void resize(int x, int y, int w, int h) override;
+
+ void layWidgets(int startPos, int sizeIfLiquid = 0);
+
+ Direction m_direction;
+ int m_gutter;
+ std::vector<Elem> m_elems;
+ int m_numFixed;
+};
+} // namespace giada::v
+
+#endif
\ No newline at end of file
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2021 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 "browser.h"
-#include "basics/boxtypes.h"
-#include "core/const.h"
-#include "gui/dialogs/browser/browserBase.h"
-#include "utils/fs.h"
-#include "utils/string.h"
-
-namespace giada
-{
-namespace v
-{
-geBrowser::geBrowser(int x, int y, int w, int h)
-: Fl_File_Browser(x, y, w, h)
-, m_showHiddenFiles(false)
-{
- 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);
- type(FL_SELECT_BROWSER);
-
- 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);
-
- take_focus(); // let it have focus on startup
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBrowser::toggleHiddenFiles()
-{
- m_showHiddenFiles = !m_showHiddenFiles;
- loadDir(m_currentDir);
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBrowser::loadDir(const std::string& dir)
-{
- m_currentDir = dir;
- load(m_currentDir.c_str());
-
- /* Clean up unwanted elements. Hide "../" first, it just screws up things.
- Also remove hidden files, if requested. */
-
- for (int i = size(); i >= 0; i--)
- {
- if (text(i) == nullptr)
- continue;
- if (strcmp(text(i), "../") == 0 || (!m_showHiddenFiles && strncmp(text(i), ".", 1) == 0))
- remove(i);
- }
-}
-
-/* -------------------------------------------------------------------------- */
-
-int geBrowser::handle(int e)
-{
- int ret = Fl_File_Browser::handle(e);
- switch (e)
- {
- case FL_FOCUS:
- case FL_UNFOCUS:
- ret = 1; // enables receiving Keyboard events
- break;
- case FL_KEYDOWN: // keyboard
- if (Fl::event_key(FL_Down))
- select(value() + 1);
- else if (Fl::event_key(FL_Up))
- select(value() - 1);
- else if (Fl::event_key(FL_Enter))
- static_cast<v::gdBrowserBase*>(parent())->fireCallback();
- ret = 1;
- break;
- case FL_PUSH: // mouse
- if (Fl::event_clicks() > 0) // double click
- static_cast<v::gdBrowserBase*>(parent())->fireCallback();
- ret = 1;
- break;
- case FL_RELEASE: // mouse
- /* nasty trick to keep the selection on mouse release */
- if (value() > 1)
- {
- select(value() - 1);
- select(value() + 1);
- }
- else
- {
- select(value() + 1);
- select(value() - 1);
- }
- ret = 1;
- break;
- }
- return ret;
-}
-
-/* -------------------------------------------------------------------------- */
-
-std::string geBrowser::getCurrentDir()
-{
- return normalize(u::fs::getRealPath(m_currentDir));
-}
-
-/* -------------------------------------------------------------------------- */
-
-std::string geBrowser::getSelectedItem(bool fullPath)
-{
- if (!fullPath) // no full path requested? return the selected text
- return normalize(text(value()));
- else if (value() == 0) // no rows selected? return current directory
- return normalize(m_currentDir);
- else
- {
-#ifdef G_OS_WINDOWS
- std::string sep = m_currentDir != "" ? G_SLASH_STR : "";
-#else
- std::string sep = G_SLASH_STR;
-#endif
- return normalize(u::fs::getRealPath(m_currentDir + sep + normalize(text(value()))));
- }
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geBrowser::preselect(int pos, int line)
-{
- position(pos);
- select(line);
-}
-
-/* -------------------------------------------------------------------------- */
-
-std::string geBrowser::normalize(const std::string& s)
-{
- std::string out = s;
-
- /* If std::string ends with G_SLASH, remove it. Don't do it if is the root dir,
- that is '/' on Unix or '[x]:\' on Windows. */
-
- //if (out.back() == G_SLASH && out.length() > 1)
- if (out.back() == G_SLASH && !u::fs::isRootDir(s))
- out = out.substr(0, out.size() - 1);
- return out;
-}
-} // namespace v
-} // namespace giada
\ No newline at end of file
+++ /dev/null
-/* -----------------------------------------------------------------------------
- *
- * Giada - Your Hardcore Loopmachine
- *
- * ge_browser
- *
- * -----------------------------------------------------------------------------
- *
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
- *
- * This file is part of Giada - Your Hardcore Loopmachine.
- *
- * Giada - Your Hardcore Loopmachine is free software: you can
- * redistribute it and/or modify it under the terms of the GNU General
- * Public License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * Giada - Your Hardcore Loopmachine is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Giada - Your Hardcore Loopmachine. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * -------------------------------------------------------------------------- */
-
-#ifndef GE_BROWSER_H
-#define GE_BROWSER_H
-
-#include <FL/Fl_File_Browser.H>
-#include <string>
-
-namespace giada
-{
-namespace v
-{
-class geBrowser : public Fl_File_Browser
-{
-public:
- geBrowser(int x, int y, int w, int h);
-
- void toggleHiddenFiles();
-
- /* init
- Initializes browser and show 'dir' as initial directory. */
-
- void loadDir(const std::string& dir);
-
- /* getSelectedItem
- Returns the full path or just the displayed name of the i-th selected item.
- Always with the trailing slash! */
-
- std::string getSelectedItem(bool fullPath = true);
-
- std::string getCurrentDir();
-
- void preselect(int position, int line);
-
- int handle(int e);
-
- private:
- /* normalize
- Makes sure the std::string never ends with a trailing slash. */
-
- std::string normalize(const std::string& s);
-
- std::string m_currentDir;
- bool m_showHiddenFiles;
-};
-} // namespace v
-} // namespace giada
-
-#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <FL/Fl_Group.H>
class geCheck;
-class geButton;
class geInput;
namespace giada::v
{
+class geButton;
class geTabAudio : public Fl_Group
{
public:
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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 "fileBrowser.h"
+#include "basics/boxtypes.h"
+#include "core/const.h"
+#include "gui/dialogs/browser/browserBase.h"
+#include "utils/fs.h"
+#include "utils/string.h"
+
+namespace giada
+{
+namespace v
+{
+geFileBrowser::geFileBrowser(int x, int y, int w, int h)
+: Fl_File_Browser(x, y, w, h)
+, m_showHiddenFiles(false)
+{
+ 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);
+ type(FL_SELECT_BROWSER);
+
+ 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);
+
+ take_focus(); // let it have focus on startup
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFileBrowser::toggleHiddenFiles()
+{
+ m_showHiddenFiles = !m_showHiddenFiles;
+ loadDir(m_currentDir);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFileBrowser::loadDir(const std::string& dir)
+{
+ m_currentDir = dir;
+ load(m_currentDir.c_str());
+
+ /* Clean up unwanted elements. Hide "../" first, it just screws up things.
+ Also remove hidden files, if requested. */
+
+ for (int i = size(); i >= 0; i--)
+ {
+ if (text(i) == nullptr)
+ continue;
+ if (strcmp(text(i), "../") == 0 || (!m_showHiddenFiles && strncmp(text(i), ".", 1) == 0))
+ remove(i);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+int geFileBrowser::handle(int e)
+{
+ int ret = Fl_File_Browser::handle(e);
+ switch (e)
+ {
+ case FL_FOCUS:
+ case FL_UNFOCUS:
+ ret = 1; // enables receiving Keyboard events
+ break;
+ case FL_KEYDOWN: // keyboard
+ if (Fl::event_key(FL_Down))
+ select(value() + 1);
+ else if (Fl::event_key(FL_Up))
+ select(value() - 1);
+ else if (Fl::event_key(FL_Enter))
+ static_cast<v::gdBrowserBase*>(parent())->fireCallback();
+ ret = 1;
+ break;
+ case FL_PUSH: // mouse
+ if (Fl::event_clicks() > 0) // double click
+ static_cast<v::gdBrowserBase*>(parent())->fireCallback();
+ ret = 1;
+ break;
+ case FL_RELEASE: // mouse
+ /* nasty trick to keep the selection on mouse release */
+ if (value() > 1)
+ {
+ select(value() - 1);
+ select(value() + 1);
+ }
+ else
+ {
+ select(value() + 1);
+ select(value() - 1);
+ }
+ ret = 1;
+ break;
+ }
+ return ret;
+}
+
+/* -------------------------------------------------------------------------- */
+
+std::string geFileBrowser::getCurrentDir()
+{
+ return normalize(u::fs::getRealPath(m_currentDir));
+}
+
+/* -------------------------------------------------------------------------- */
+
+std::string geFileBrowser::getSelectedItem(bool fullPath)
+{
+ if (!fullPath) // no full path requested? return the selected text
+ return normalize(text(value()));
+ else if (value() == 0) // no rows selected? return current directory
+ return normalize(m_currentDir);
+ else
+ {
+#ifdef G_OS_WINDOWS
+ std::string sep = m_currentDir != "" ? G_SLASH_STR : "";
+#else
+ std::string sep = G_SLASH_STR;
+#endif
+ return normalize(u::fs::getRealPath(m_currentDir + sep + normalize(text(value()))));
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geFileBrowser::preselect(int pos, int line)
+{
+ position(pos);
+ select(line);
+}
+
+/* -------------------------------------------------------------------------- */
+
+std::string geFileBrowser::normalize(const std::string& s)
+{
+ std::string out = s;
+
+ /* If std::string ends with G_SLASH, remove it. Don't do it if is the root dir,
+ that is '/' on Unix or '[x]:\' on Windows. */
+
+ //if (out.back() == G_SLASH && out.length() > 1)
+ if (out.back() == G_SLASH && !u::fs::isRootDir(s))
+ out = out.substr(0, out.size() - 1);
+ return out;
+}
+} // namespace v
+} // namespace giada
\ No newline at end of file
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * ge_browser
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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_FILE_BROWSER_H
+#define GE_FILE_BROWSER_H
+
+#include <FL/Fl_File_Browser.H>
+#include <string>
+
+namespace giada
+{
+namespace v
+{
+class geFileBrowser : public Fl_File_Browser
+{
+public:
+ geFileBrowser(int x, int y, int w, int h);
+
+ void toggleHiddenFiles();
+
+ /* init
+ Initializes browser and show 'dir' as initial directory. */
+
+ void loadDir(const std::string& dir);
+
+ /* getSelectedItem
+ Returns the full path or just the displayed name of the i-th selected item.
+ Always with the trailing slash! */
+
+ std::string getSelectedItem(bool fullPath = true);
+
+ std::string getCurrentDir();
+
+ void preselect(int position, int line);
+
+ int handle(int e);
+
+ private:
+ /* normalize
+ Makes sure the std::string never ends with a trailing slash. */
+
+ std::string normalize(const std::string& s);
+
+ std::string m_currentDir;
+ bool m_showHiddenFiles;
+};
+} // namespace v
+} // namespace giada
+
+#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/elems/mainWindow/keyboard/channelButton.h"
#include "gui/elems/mainWindow/keyboard/channelStatus.h"
#include "gui/elems/mainWindow/keyboard/column.h"
+#include "gui/elems/mainWindow/keyboard/midiActivity.h"
#include "gui/ui.h"
#include <FL/Fl.H>
#include <FL/fl_draw.H>
blink();
playButton->setStatus(playStatus == ChannelStatus::PLAY || playStatus == ChannelStatus::ENDING);
+ midiActivity->redraw();
mute->setStatus(m_channel.getMute());
solo->setStatus(m_channel.getSolo());
}
/* -------------------------------------------------------------------------- */
-int geChannel::getColumnId()
+int geChannel::getColumnId() const
{
return static_cast<geColumn*>(parent())->id;
}
void geChannel::packWidgets()
{
- /* Count visible widgets and resize mainButton according to how many widgets
- are visible. */
+ /* Compute how much space is visible for the main button, then resize it
+ according to that amount. */
- int visibles = 0;
+ int visible = w();
for (int i = 0; i < children(); i++)
{
- child(i)->size(MIN_ELEM_W, child(i)->h()); // also normalize widths
- if (child(i)->visible())
- visibles++;
+ if (child(i)->visible() && child(i) != mainButton)
+ visible -= child(i)->w() + G_GUI_INNER_MARGIN;
}
- mainButton->size(w() - ((visibles - 1) * (MIN_ELEM_W + G_GUI_INNER_MARGIN)), // -1: exclude itself
- mainButton->h());
+
+ mainButton->size(visible, mainButton->h());
/* Reposition everything else */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "glue/channel.h"
#include <FL/Fl_Group.H>
-class geButton;
-class geDial;
-
namespace giada::v
{
+class geDial;
+class geButton;
class geChannelStatus;
class geStatusButton;
class geChannelButton;
+class geMidiActivity;
class geChannel : public Fl_Group
{
public:
/* getColumnId
Returns the ID of the column this channel resides in. */
- ID getColumnId();
+ ID getColumnId() const;
/* handleKey
Performs some UI-related operations when the bound key is pressed. Returns
geButton* arm;
geChannelStatus* status;
geChannelButton* mainButton;
+ geMidiActivity* midiActivity;
geStatusButton* mute;
geStatusButton* solo;
geDial* vol;
static const int BREAK_ARM = 168;
#endif
- static const int MIN_ELEM_W = 20;
-
static void cb_arm(Fl_Widget* /*w*/, void* p);
static void cb_mute(Fl_Widget* /*w*/, void* p);
static void cb_solo(Fl_Widget* /*w*/, void* p);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <functional>
#include <vector>
-class geButton;
-
namespace giada::v
{
+class geButton;
class geResizerBar;
class geKeyboard;
class geChannel;
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -------------------------------------------------------------------------- */
-#include "keyboard.h"
-#include "channelButton.h"
-#include "column.h"
+#include "gui/elems/mainWindow/keyboard/keyboard.h"
#include "glue/channel.h"
#include "glue/io.h"
#include "gui/dialogs/warnings.h"
#include "gui/dispatcher.h"
#include "gui/elems/basics/boxtypes.h"
+#include "gui/elems/basics/dial.h"
#include "gui/elems/basics/resizerBar.h"
+#include "gui/elems/mainWindow/keyboard/channelButton.h"
+#include "gui/elems/mainWindow/keyboard/column.h"
+#include "gui/elems/mainWindow/keyboard/midiActivity.h"
+#include "gui/elems/mainWindow/keyboard/sampleChannel.h"
#include "gui/ui.h"
-#include "sampleChannel.h"
#include "utils/fs.h"
#include "utils/log.h"
#include "utils/string.h"
/* -------------------------------------------------------------------------- */
+ID geKeyboard::getChannelColumnId(ID channelId) const
+{
+ return getChannel(channelId)->getColumnId();
+}
+
+/* -------------------------------------------------------------------------- */
+
void geKeyboard::init()
{
m_columnId = m::IdManager();
/* -------------------------------------------------------------------------- */
+void geKeyboard::setChannelVolume(ID channelId, float v)
+{
+ getChannel(channelId)->vol->value(v);
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geKeyboard::notifyMidiIn(ID channelId)
+{
+ getChannel(channelId)->midiActivity->in->lit();
+}
+
+void geKeyboard::notifyMidiOut(ID channelId)
+{
+ getChannel(channelId)->midiActivity->out->lit();
+}
+
+/* -------------------------------------------------------------------------- */
+
void geKeyboard::cb_addColumn(Fl_Widget* /*w*/, void* p)
{
((geKeyboard*)p)->cb_addColumn();
/* -------------------------------------------------------------------------- */
-geChannel* geKeyboard::getChannel(ID channelId)
+const geChannel* geKeyboard::getChannel(ID channelId) const
{
for (geColumn* column : m_columns)
{
return nullptr;
}
+geChannel* geKeyboard::getChannel(ID channelId)
+{
+ return const_cast<geChannel*>(const_cast<const geKeyboard*>(this)->getChannel(channelId));
+}
+
/* -------------------------------------------------------------------------- */
std::vector<std::string> geKeyboard::getDroppedFilePaths() const
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <functional>
#include <vector>
-class geButton;
-
namespace giada::v
{
+class geButton;
class geResizerBar;
class geColumn;
class geChannel;
int handle(int e) override;
void draw() override;
+ /* getChannelColumnId
+ Given a channel ID, returns the ID of the column it belongs to. */
+
+ ID getChannelColumnId(ID channelId) const;
+
/* rebuild
Rebuilds this widget from scratch. Used when the model has changed. */
void deleteAllColumns();
- /* getChannel
- Given a channel ID returns the UI channel it belongs to. */
-
- geChannel* getChannel(ID channelId);
+ void setChannelVolume(ID channelId, float v);
+ void notifyMidiIn(ID channelId);
+ void notifyMidiOut(ID channelId);
/* init
Builds the default setup of empty columns. */
geColumn* getColumnAtCursor(Pixel x);
+ /* getChannel
+ Given a channel ID returns the UI channel it belongs to. */
+
+ geChannel* getChannel(ID channelId);
+ const geChannel* getChannel(ID channelId) const;
+
/* storeLayout
Stores the current column layout into the layout vector. */
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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 "gui/elems/mainWindow/keyboard/midiActivity.h"
+#include "core/const.h"
+#include "gui/elems/basics/flex.h"
+#include <FL/fl_draw.H>
+
+namespace giada::v
+{
+geMidiActivity::geLed::geLed()
+: Fl_Button(0, 0, 0, 0)
+, m_decay(0) // decay > 0: led is on
+{
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geMidiActivity::geLed::draw()
+{
+ int bgColor = G_COLOR_GREY_2;
+ int bdColor = G_COLOR_GREY_4;
+
+ if (m_decay > 0) // If led is on
+ {
+ m_decay = (m_decay + 1) % (G_GUI_FPS / 4);
+
+ bgColor = G_COLOR_LIGHT_2;
+ bdColor = G_COLOR_LIGHT_2;
+ }
+
+ fl_rectf(x(), y(), w(), h(), bgColor); // background
+ fl_rect(x(), y(), w(), h(), bdColor); // border
+}
+
+/* -------------------------------------------------------------------------- */
+
+void geMidiActivity::geLed::lit()
+{
+ m_decay = 1;
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
+geMidiActivity::geMidiActivity(int x, int y, int w, int h)
+: Fl_Group(x, y, w, h)
+{
+ end();
+
+ geFlex* container = new geFlex(x, y, w, h, Direction::VERTICAL, G_GUI_INNER_MARGIN);
+ {
+ out = new geLed();
+ in = new geLed();
+
+ container->add(out);
+ container->add(in);
+ container->end();
+ }
+
+ add(container);
+ resizable(container);
+
+ copy_tooltip("MIDI I/O activity\n\nNotifies MIDI messages sent (top) or "
+ "received (bottom) by this channel.");
+}
+} // namespace giada::v
\ No newline at end of file
--- /dev/null
+/* -----------------------------------------------------------------------------
+ *
+ * Giada - Your Hardcore Loopmachine
+ *
+ * -----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
+ *
+ * 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_ACTIVITY_H
+#define GE_MIDI_ACTIVITY_H
+
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Group.H>
+
+namespace giada::v
+{
+class geMidiActivity : public Fl_Group
+{
+public:
+ class geLed : public Fl_Button
+ {
+ public:
+ geLed();
+
+ void draw() override;
+ void lit();
+
+ private:
+ int m_decay;
+ };
+
+ geMidiActivity(int x, int y, int w, int h);
+
+ geLed* out;
+ geLed* in;
+};
+} // namespace giada::v
+
+#endif
#include "gui/elems/basics/dial.h"
#include "gui/elems/basics/statusButton.h"
#include "gui/elems/mainWindow/keyboard/column.h"
+#include "gui/elems/mainWindow/keyboard/midiActivity.h"
#include "gui/elems/mainWindow/keyboard/midiChannelButton.h"
#include "utils/gui.h"
#include "utils/string.h"
: geChannel(X, Y, W, H, d)
, m_data(d)
{
-#if defined(WITH_VST)
- constexpr int delta = 6 * (G_GUI_UNIT + G_GUI_INNER_MARGIN);
-#else
- constexpr int delta = 5 * (G_GUI_UNIT + G_GUI_INNER_MARGIN);
-#endif
-
- playButton = new geStatusButton(x(), y(), G_GUI_UNIT, G_GUI_UNIT, channelStop_xpm, channelPlay_xpm);
- arm = new geButton(playButton->x() + playButton->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, "", armOff_xpm, armOn_xpm);
- mainButton = new geMidiChannelButton(arm->x() + arm->w() + G_GUI_INNER_MARGIN, y(), w() - delta, H, m_channel);
- mute = new geStatusButton(mainButton->x() + mainButton->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, muteOff_xpm, muteOn_xpm);
- solo = new geStatusButton(mute->x() + mute->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, soloOff_xpm, soloOn_xpm);
+ playButton = new geStatusButton(x(), y(), G_GUI_UNIT, G_GUI_UNIT, channelStop_xpm, channelPlay_xpm);
+ arm = new geButton(playButton->x() + playButton->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, "", armOff_xpm, armOn_xpm);
+ mainButton = new geMidiChannelButton(arm->x() + arm->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, H, m_channel);
+ midiActivity = new geMidiActivity(mainButton->x() + mainButton->w() + G_GUI_INNER_MARGIN, y(), 10, h());
+ mute = new geStatusButton(midiActivity->x() + midiActivity->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, muteOff_xpm, muteOn_xpm);
+ solo = new geStatusButton(mute->x() + mute->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, soloOff_xpm, soloOn_xpm);
#if defined(WITH_VST)
fx = new geStatusButton(solo->x() + solo->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, fxOff_xpm, fxOn_xpm);
vol = new geDial(fx->x() + fx->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT);
#else
- vol = new geDial(solo->x() + solo->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT);
+ vol = new geDial(solo->x() + solo->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT);
#endif
end();
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/elems/mainWindow/keyboard/channelStatus.h"
#include "gui/elems/mainWindow/keyboard/column.h"
#include "gui/elems/mainWindow/keyboard/keyboard.h"
+#include "gui/elems/mainWindow/keyboard/midiActivity.h"
#include "gui/elems/mainWindow/keyboard/sampleChannelButton.h"
#include "utils/gui.h"
geSampleChannel::geSampleChannel(int X, int Y, int W, int H, c::channel::Data d)
: geChannel(X, Y, W, H, d)
{
-#if defined(WITH_VST)
- constexpr int delta = 9 * (G_GUI_UNIT + G_GUI_INNER_MARGIN);
-#else
- constexpr int delta = 8 * (G_GUI_UNIT + G_GUI_INNER_MARGIN);
-#endif
-
- playButton = new geStatusButton(x(), y(), G_GUI_UNIT, G_GUI_UNIT, channelStop_xpm, channelPlay_xpm);
- arm = new geButton(playButton->x() + playButton->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, "", armOff_xpm, armOn_xpm, armDisabled_xpm);
- status = new geChannelStatus(arm->x() + arm->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, H, m_channel);
- mainButton = new geSampleChannelButton(status->x() + status->w() + G_GUI_INNER_MARGIN, y(), w() - delta, H, m_channel);
- readActions = new geStatusButton(mainButton->x() + mainButton->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, readActionOff_xpm, readActionOn_xpm, readActionDisabled_xpm);
- modeBox = new geChannelMode(readActions->x() + readActions->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, m_channel);
- mute = new geStatusButton(modeBox->x() + modeBox->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, muteOff_xpm, muteOn_xpm);
- solo = new geStatusButton(mute->x() + mute->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, soloOff_xpm, soloOn_xpm);
+ playButton = new geStatusButton(x(), y(), G_GUI_UNIT, G_GUI_UNIT, channelStop_xpm, channelPlay_xpm);
+ arm = new geButton(playButton->x() + playButton->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, "", armOff_xpm, armOn_xpm, armDisabled_xpm);
+ status = new geChannelStatus(arm->x() + arm->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, h(), m_channel);
+ mainButton = new geSampleChannelButton(status->x() + status->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, H, m_channel);
+ midiActivity = new geMidiActivity(mainButton->x() + mainButton->w() + G_GUI_INNER_MARGIN, y(), 10, h());
+ readActions = new geStatusButton(midiActivity->x() + midiActivity->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, readActionOff_xpm, readActionOn_xpm, readActionDisabled_xpm);
+ modeBox = new geChannelMode(readActions->x() + readActions->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, m_channel);
+ mute = new geStatusButton(modeBox->x() + modeBox->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, muteOff_xpm, muteOn_xpm);
+ solo = new geStatusButton(mute->x() + mute->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, soloOff_xpm, soloOn_xpm);
#if defined(WITH_VST)
fx = new geStatusButton(solo->x() + solo->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT, fxOff_xpm, fxOn_xpm);
vol = new geDial(fx->x() + fx->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT);
#else
- vol = new geDial(solo->x() + solo->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT);
+ vol = new geDial(solo->x() + solo->w() + G_GUI_INNER_MARGIN, y(), G_GUI_UNIT, G_GUI_UNIT);
#endif
end();
{
const int ny = y() + (h() / 2) - (G_GUI_UNIT / 2);
- status->resize(status->x(), ny, G_GUI_UNIT, G_GUI_UNIT);
modeBox->resize(modeBox->x(), ny, G_GUI_UNIT, G_GUI_UNIT);
readActions->resize(readActions->x(), ny, G_GUI_UNIT, G_GUI_UNIT);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* ------------------------------------------------------------------------------
*
-* Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+* Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "glue/events.h"
#include "glue/layout.h"
#include "glue/main.h"
+#include "gui/elems/basics/button.h"
#include "gui/elems/basics/dial.h"
#include "gui/elems/basics/statusButton.h"
#include "gui/elems/soundMeter.h"
#include "utils/gui.h"
+#ifdef WITH_VST
+#include "gui/elems/basics/statusButton.h"
+#endif
namespace giada::v
{
-geMainIO::geMainIO(int x, int y)
-: gePack(x, y, Direction::HORIZONTAL)
-, outMeter(0, 0, 140, G_GUI_UNIT)
-, inMeter(0, 0, 140, G_GUI_UNIT)
-, outVol(0, 0, G_GUI_UNIT, G_GUI_UNIT)
-, inVol(0, 0, G_GUI_UNIT, G_GUI_UNIT)
-, inToOut(0, 0, 12, G_GUI_UNIT, "")
-#ifdef WITH_VST
-, masterFxOut(0, 0, G_GUI_UNIT, G_GUI_UNIT, fxOff_xpm, fxOn_xpm)
-, masterFxIn(0, 0, G_GUI_UNIT, G_GUI_UNIT, fxOff_xpm, fxOn_xpm)
-#endif
+geMainIO::geMainIO(int x, int y, int w, int h)
+: geFlex(x, y, w, h, Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
{
+ m_outMeter = new geSoundMeter(0, 0, 0, 0);
+ m_inMeter = new geSoundMeter(0, 0, 0, 0);
+ m_outVol = new geDial(0, 0, 0, 0);
+ m_inVol = new geDial(0, 0, 0, 0);
+ m_inToOut = new geButton();
#ifdef WITH_VST
- add(&masterFxIn);
+ m_masterFxOut = new geStatusButton(0, 0, 0, 0, fxOff_xpm, fxOn_xpm);
+ m_masterFxIn = new geStatusButton(0, 0, 0, 0, fxOff_xpm, fxOn_xpm);
#endif
- add(&inVol);
- add(&inMeter);
- add(&inToOut);
- add(&outMeter);
- add(&outVol);
-#ifdef WITH_VST
- add(&masterFxOut);
-#endif
-
- resizable(nullptr); // don't resize any widget
- outMeter.copy_tooltip("Main output meter");
- inMeter.copy_tooltip("Main input meter");
- outVol.copy_tooltip("Main output volume");
- inVol.copy_tooltip("Main input volume");
- inToOut.copy_tooltip("Stream linker\n\nConnects input to output to enable \"hear what you're playing\" mode.");
#ifdef WITH_VST
- masterFxOut.copy_tooltip("Main output plug-ins");
- masterFxIn.copy_tooltip("Main input plug-ins");
+ add(m_masterFxIn, G_GUI_UNIT);
#endif
-
- outVol.callback(cb_outVol, (void*)this);
- inVol.callback(cb_inVol, (void*)this);
-
- inToOut.callback(cb_inToOut, (void*)this);
- inToOut.type(FL_TOGGLE_BUTTON);
-
+ add(m_inVol, G_GUI_UNIT);
+ add(m_inMeter);
+ add(m_inToOut, 12);
+ add(m_outMeter);
+ add(m_outVol, G_GUI_UNIT);
#ifdef WITH_VST
- masterFxOut.callback(cb_masterFxOut, (void*)this);
- masterFxIn.callback(cb_masterFxIn, (void*)this);
+ add(m_masterFxOut, G_GUI_UNIT);
#endif
-}
+ end();
-/* -------------------------------------------------------------------------- */
-
-void geMainIO::cb_outVol(Fl_Widget* /*w*/, void* p) { ((geMainIO*)p)->cb_outVol(); }
-void geMainIO::cb_inVol(Fl_Widget* /*w*/, void* p) { ((geMainIO*)p)->cb_inVol(); }
-void geMainIO::cb_inToOut(Fl_Widget* /*w*/, void* p) { ((geMainIO*)p)->cb_inToOut(); }
+ m_outMeter->copy_tooltip("Main output meter");
+ m_inMeter->copy_tooltip("Main input meter");
+ m_outVol->copy_tooltip("Main output volume");
+ m_inVol->copy_tooltip("Main input volume");
+ m_inToOut->copy_tooltip("Stream linker\n\nConnects input to output to enable \"hear what you're playing\" mode.");
#ifdef WITH_VST
-void geMainIO::cb_masterFxOut(Fl_Widget* /*w*/, void* p)
-{
- ((geMainIO*)p)->cb_masterFxOut();
-}
-void geMainIO::cb_masterFxIn(Fl_Widget* /*w*/, void* p) { ((geMainIO*)p)->cb_masterFxIn(); }
+ m_masterFxOut->copy_tooltip("Main output plug-ins");
+ m_masterFxIn->copy_tooltip("Main input plug-ins");
#endif
-/* -------------------------------------------------------------------------- */
+ m_outVol->onChange = [](float v) {
+ c::events::setMasterOutVolume(v, Thread::MAIN);
+ };
-void geMainIO::cb_outVol()
-{
- c::events::setMasterOutVolume(outVol.value(), Thread::MAIN);
-}
+ m_inVol->onChange = [](float v) {
+ c::events::setMasterInVolume(v, Thread::MAIN);
+ };
-void geMainIO::cb_inVol()
-{
- c::events::setMasterInVolume(inVol.value(), Thread::MAIN);
-}
-
-void geMainIO::cb_inToOut()
-{
- c::main::setInToOut(inToOut.value());
-}
-
-/* -------------------------------------------------------------------------- */
+ m_inToOut->type(FL_TOGGLE_BUTTON);
+ m_inToOut->onClick = [v = m_inToOut->value()]() {
+ c::main::setInToOut(v);
+ };
#ifdef WITH_VST
-
-void geMainIO::cb_masterFxOut()
-{
- c::layout::openMasterOutPluginListWindow();
-}
-
-void geMainIO::cb_masterFxIn()
-{
- c::layout::openMasterInPluginListWindow();
-}
-
+ m_masterFxOut->onClick = [] { c::layout::openMasterOutPluginListWindow(); };
+ m_masterFxIn->onClick = [] { c::layout::openMasterInPluginListWindow(); };
#endif
+}
/* -------------------------------------------------------------------------- */
-void geMainIO::setOutVol(float v)
-{
- outVol.value(v);
-}
-
-void geMainIO::setInVol(float v)
-{
- inVol.value(v);
-}
+void geMainIO::setOutVol(float v) { m_outVol->value(v); }
+void geMainIO::setInVol(float v) { m_inVol->value(v); }
/* -------------------------------------------------------------------------- */
void geMainIO::setMasterFxOutFull(bool v)
{
- masterFxOut.setStatus(v);
+ m_masterFxOut->setStatus(v);
}
void geMainIO::setMasterFxInFull(bool v)
{
- masterFxIn.setStatus(v);
+ m_masterFxIn->setStatus(v);
}
#endif
void geMainIO::refresh()
{
- outMeter.peak = m_io.getMasterOutPeak();
- outMeter.ready = m_io.isKernelReady();
- inMeter.peak = m_io.getMasterInPeak();
- inMeter.ready = m_io.isKernelReady();
- outMeter.redraw();
- inMeter.redraw();
+ m_outMeter->peak = m_io.getMasterOutPeak();
+ m_outMeter->ready = m_io.isKernelReady();
+ m_inMeter->peak = m_io.getMasterInPeak();
+ m_inMeter->ready = m_io.isKernelReady();
+ m_outMeter->redraw();
+ m_inMeter->redraw();
}
/* -------------------------------------------------------------------------- */
{
m_io = c::main::getIO();
- outVol.value(m_io.masterOutVol);
- inVol.value(m_io.masterInVol);
+ m_outVol->value(m_io.masterOutVol);
+ m_inVol->value(m_io.masterInVol);
#ifdef WITH_VST
- masterFxOut.setStatus(m_io.masterOutHasPlugins);
- masterFxIn.setStatus(m_io.masterInHasPlugins);
- inToOut.value(m_io.inToOut);
+ m_masterFxOut->setStatus(m_io.masterOutHasPlugins);
+ m_masterFxIn->setStatus(m_io.masterInHasPlugins);
+ m_inToOut->value(m_io.inToOut);
#endif
}
} // namespace giada::v
\ No newline at end of file
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#ifndef GE_MAIN_IO_H
#define GE_MAIN_IO_H
-#include "gui/elems/basics/button.h"
-#include "gui/elems/basics/dial.h"
-#include "gui/elems/basics/pack.h"
-#include "gui/elems/soundMeter.h"
-#ifdef WITH_VST
-#include "gui/elems/basics/statusButton.h"
-#endif
#include "glue/main.h"
+#include "gui/elems/basics/flex.h"
namespace giada::v
{
-class geMainIO : public gePack
+class geDial;
+class geSoundMeter;
+class geButton;
+class geStatusButton;
+class geMainIO : public geFlex
{
public:
- geMainIO(int x, int y);
+ geMainIO(int x, int y, int w, int h);
void refresh();
void rebuild();
#endif
private:
- static void cb_outVol(Fl_Widget* /*w*/, void* p);
- static void cb_inVol(Fl_Widget* /*w*/, void* p);
- static void cb_inToOut(Fl_Widget* /*w*/, void* p);
- void cb_outVol();
- void cb_inVol();
- void cb_inToOut();
-#ifdef WITH_VST
- static void cb_masterFxOut(Fl_Widget* /*w*/, void* p);
- static void cb_masterFxIn(Fl_Widget* /*w*/, void* p);
- void cb_masterFxOut();
- void cb_masterFxIn();
-#endif
-
c::main::IO m_io;
- geSoundMeter outMeter;
- geSoundMeter inMeter;
- geDial outVol;
- geDial inVol;
- geButton inToOut;
+ geSoundMeter* m_outMeter;
+ geSoundMeter* m_inMeter;
+ geDial* m_outVol;
+ geDial* m_inVol;
+ geButton* m_inToOut;
#ifdef WITH_VST
- geStatusButton masterFxOut;
- geStatusButton masterFxIn;
+ geStatusButton* m_masterFxOut;
+ geStatusButton* m_masterFxIn;
#endif
};
} // namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::v
{
geMainMenu::geMainMenu(int x, int y)
-: gePack(x, y, Direction::HORIZONTAL)
+: gePack(x, y, Direction::HORIZONTAL, G_GUI_INNER_MARGIN)
{
- file = new geButton(0, 0, 70, 21, "file");
- edit = new geButton(0, 0, 70, 21, "edit");
- config = new geButton(0, 0, 70, 21, "config");
- about = new geButton(0, 0, 70, 21, "about");
+ geButton* file = new geButton(0, 0, 70, G_GUI_UNIT, "File");
+ geButton* edit = new geButton(0, 0, 70, G_GUI_UNIT, "Edit");
+ geButton* config = new geButton(0, 0, 70, G_GUI_UNIT, "Config");
+ geButton* about = new geButton(0, 0, 70, G_GUI_UNIT, "About");
add(file);
add(edit);
add(config);
add(about);
- resizable(nullptr); // don't resize any widget
+ resizable(nullptr);
- file->callback(cb_file, (void*)this);
- edit->callback(cb_edit, (void*)this);
-
- about->callback([](Fl_Widget* /*w*/, void* /*v*/) {
- c::layout::openAboutWindow();
- });
- config->callback([](Fl_Widget* /*w*/, void* /*v*/) {
- c::layout::openConfigWindow();
- });
+ file->onClick = [this]() { cb_file(); };
+ edit->onClick = [this]() { cb_edit(); };
+ about->onClick = []() { c::layout::openAboutWindow(); };
+ config->onClick = []() { c::layout::openConfigWindow(); };
}
/* -------------------------------------------------------------------------- */
-void geMainMenu::cb_file(Fl_Widget* /*w*/, void* p) { ((geMainMenu*)p)->cb_file(); }
-void geMainMenu::cb_edit(Fl_Widget* /*w*/, void* p) { ((geMainMenu*)p)->cb_edit(); }
-
-/* -------------------------------------------------------------------------- */
-
void geMainMenu::cb_file()
{
- using namespace giada::m;
-
- /* An Fl_Menu_Button is made of many Fl_Menu_Item */
-
Fl_Menu_Item menu[] = {
u::gui::makeMenuItem("Open project..."),
u::gui::makeMenuItem("Save project..."),
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include "gui/elems/basics/pack.h"
-class geButton;
-
namespace giada::v
{
class geMainMenu : public gePack
geMainMenu(int x, int y);
private:
- static void cb_file(Fl_Widget* /*w*/, void* p);
- static void cb_edit(Fl_Widget* /*w*/, void* p);
- void cb_file();
- void cb_edit();
-
- geButton* file;
- geButton* edit;
- geButton* config;
- geButton* about;
+ void cb_file();
+ void cb_edit();
};
} // namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{
geMainTimer::geMainTimer(int x, int y)
: gePack(x, y, Direction::HORIZONTAL)
-, m_bpm(0, 0, 60, G_GUI_UNIT)
-, m_meter(0, 0, 60, G_GUI_UNIT)
-, m_quantizer(0, 0, 60, G_GUI_UNIT, "", false)
-, m_multiplier(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", multiplyOff_xpm, multiplyOn_xpm)
-, m_divider(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", divideOff_xpm, divideOn_xpm)
{
- add(&m_quantizer);
- add(&m_bpm);
- add(&m_meter);
- add(&m_multiplier);
- add(&m_divider);
+ m_bpm = new geButton(0, 0, 60, G_GUI_UNIT);
+ m_meter = new geButton(0, 0, 60, G_GUI_UNIT);
+ m_quantizer = new geChoice(0, 0, 60, G_GUI_UNIT, "", false);
+ m_multiplier = new geButton(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", multiplyOff_xpm, multiplyOn_xpm);
+ m_divider = new geButton(0, 0, G_GUI_UNIT, G_GUI_UNIT, "", divideOff_xpm, divideOn_xpm);
+ add(m_quantizer);
+ add(m_bpm);
+ add(m_meter);
+ add(m_multiplier);
+ add(m_divider);
resizable(nullptr); // don't resize any widget
- m_bpm.copy_tooltip("Beats per minute (BPM)");
- m_meter.copy_tooltip("Beats and bars");
- m_quantizer.copy_tooltip("Live quantizer");
- m_multiplier.copy_tooltip("Beat multiplier");
- m_divider.copy_tooltip("Beat divider");
-
- m_bpm.callback(cb_bpm, (void*)this);
- m_meter.callback(cb_meter, (void*)this);
- m_multiplier.callback(cb_multiplier, (void*)this);
- m_divider.callback(cb_divider, (void*)this);
-
- m_quantizer.add("off", 0, cb_quantizer, (void*)this);
- m_quantizer.add("1\\/1", 0, cb_quantizer, (void*)this);
- m_quantizer.add("1\\/2", 0, cb_quantizer, (void*)this);
- m_quantizer.add("1\\/3", 0, cb_quantizer, (void*)this);
- m_quantizer.add("1\\/4", 0, cb_quantizer, (void*)this);
- m_quantizer.add("1\\/6", 0, cb_quantizer, (void*)this);
- m_quantizer.add("1\\/8", 0, cb_quantizer, (void*)this);
- m_quantizer.value(0); // "off" by default
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geMainTimer::cb_bpm(Fl_Widget* /*w*/, void* p) { ((geMainTimer*)p)->cb_bpm(); }
-void geMainTimer::cb_meter(Fl_Widget* /*w*/, void* p) { ((geMainTimer*)p)->cb_meter(); }
-void geMainTimer::cb_quantizer(Fl_Widget* /*w*/, void* p) { ((geMainTimer*)p)->cb_quantizer(); }
-void geMainTimer::cb_multiplier(Fl_Widget* /*w*/, void* p) { ((geMainTimer*)p)->cb_multiplier(); }
-void geMainTimer::cb_divider(Fl_Widget* /*w*/, void* p) { ((geMainTimer*)p)->cb_divider(); }
-
-/* -------------------------------------------------------------------------- */
-
-void geMainTimer::cb_bpm()
-{
- c::layout::openBpmWindow(m_bpm.label());
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geMainTimer::cb_meter()
-{
- c::layout::openBeatsWindow(m_timer.beats, m_timer.bars);
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geMainTimer::cb_quantizer()
-{
- c::main::quantize(m_quantizer.value());
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geMainTimer::cb_multiplier()
-{
- c::events::multiplyBeats();
-}
-
-/* -------------------------------------------------------------------------- */
-
-void geMainTimer::cb_divider()
-{
- c::events::divideBeats();
+ m_bpm->copy_tooltip("Beats per minute (BPM)");
+ m_meter->copy_tooltip("Beats and bars");
+ m_quantizer->copy_tooltip("Live quantizer");
+ m_multiplier->copy_tooltip("Beat multiplier");
+ m_divider->copy_tooltip("Beat divider");
+
+ m_bpm->onClick = [&bpm = m_bpm]() { c::layout::openBpmWindow(bpm->label()); };
+ m_meter->onClick = [&timer = m_timer]() { c::layout::openBeatsWindow(timer.beats, timer.bars); };
+ m_multiplier->onClick = []() { c::events::multiplyBeats(); };
+ m_divider->onClick = []() { c::events::divideBeats(); };
+
+ m_quantizer->addItem("off");
+ m_quantizer->addItem("1\\/1");
+ m_quantizer->addItem("1\\/2");
+ m_quantizer->addItem("1\\/3");
+ m_quantizer->addItem("1\\/4");
+ m_quantizer->addItem("1\\/6");
+ m_quantizer->addItem("1\\/8");
+ m_quantizer->showItem(1); // "off" by default
+ m_quantizer->onChange = [](ID value) { c::main::quantize(value); };
}
/* -------------------------------------------------------------------------- */
if (m_timer.isRecordingInput)
{
- m_bpm.deactivate();
- m_meter.deactivate();
- m_multiplier.deactivate();
- m_divider.deactivate();
+ m_bpm->deactivate();
+ m_meter->deactivate();
+ m_multiplier->deactivate();
+ m_divider->deactivate();
}
else
{
- m_bpm.activate();
- m_meter.activate();
- m_multiplier.activate();
- m_divider.activate();
+ m_bpm->activate();
+ m_meter->activate();
+ m_multiplier->activate();
+ m_divider->activate();
}
}
void geMainTimer::setBpm(const char* v)
{
- m_bpm.copy_label(v);
+ m_bpm->copy_label(v);
}
void geMainTimer::setBpm(float v)
{
- m_bpm.copy_label(u::string::fToString(v, 1).c_str()); // Only 1 decimal place (e.g. 120.0)
+ m_bpm->copy_label(u::string::fToString(v, 1).c_str()); // Only 1 decimal place (e.g. 120.0)
}
/* -------------------------------------------------------------------------- */
{
if (v)
{
- m_bpm.deactivate();
- m_meter.deactivate();
- m_multiplier.deactivate();
- m_divider.deactivate();
+ m_bpm->deactivate();
+ m_meter->deactivate();
+ m_multiplier->deactivate();
+ m_divider->deactivate();
}
else
{
- m_bpm.activate();
- m_meter.activate();
- m_multiplier.activate();
- m_divider.activate();
+ m_bpm->activate();
+ m_meter->activate();
+ m_multiplier->activate();
+ m_divider->activate();
}
}
void geMainTimer::setQuantizer(int q)
{
- m_quantizer.value(q);
+ m_quantizer->value(q);
}
/* -------------------------------------------------------------------------- */
void geMainTimer::setMeter(int beats, int bars)
{
std::string s = std::to_string(beats) + "/" + std::to_string(bars);
- m_meter.copy_label(s.c_str());
+ m_meter->copy_label(s.c_str());
}
} // namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#define GE_MAIN_TIMER_H
#include "glue/main.h"
-#include "gui/elems/basics/button.h"
-#include "gui/elems/basics/choice.h"
#include "gui/elems/basics/pack.h"
-class geButton;
-
namespace giada::v
{
+class geButton;
class geChoice;
class geMainTimer : public gePack
{
void setLock(bool v);
- private:
- static void cb_bpm(Fl_Widget* /*w*/, void* p);
- static void cb_meter(Fl_Widget* /*w*/, void* p);
- static void cb_quantizer(Fl_Widget* /*w*/, void* p);
- static void cb_multiplier(Fl_Widget* /*w*/, void* p);
- static void cb_divider(Fl_Widget* /*w*/, void* p);
- void cb_bpm();
- void cb_meter();
- void cb_quantizer();
- void cb_multiplier();
- void cb_divider();
-
+private:
c::main::Timer m_timer;
- geButton m_bpm;
- geButton m_meter;
- geChoice m_quantizer;
- geButton m_multiplier;
- geButton m_divider;
+ geButton* m_bpm;
+ geButton* m_meter;
+ geChoice* m_quantizer;
+ geButton* m_multiplier;
+ geButton* m_divider;
};
} // namespace giada::v
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void geSequencer::draw()
{
m_background = geompp::Rect(x(), y(), w(), h());
- m_cell = geompp::Rect(x(), y(), w() / G_MAX_BEATS, h()).reduced(0, REC_BARS_H);
+ m_cell = geompp::Rect(x(), y(), w() / G_MAX_BEATS, h()).reduced({0, REC_BARS_H});
/* Cleanup */
drawRectf(m_background, FL_BACKGROUND_COLOR);
void geSequencer::drawBody() const
{
- const geompp::Rect body = m_background.reduced(0, REC_BARS_H);
+ const geompp::Rect body = m_background.reduced({0, REC_BARS_H});
const geompp::Line line = m_cell.getHeightAsLine();
/* Background and borders. */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <string>
class geBox;
-class geButton;
namespace giada
{
namespace v
{
+class geButton;
class geMidiLearner : public gePack
{
public:
std::function<void()> onStopLearn;
std::function<void(uint32_t)> onClearLearn;
- protected:
+protected:
/* m_param
Parameter index to be learnt. */
geButton m_valueBtn;
geButton m_button;
- private:
+private:
static void cb_button(Fl_Widget* /*w*/, void* p);
static void cb_value(Fl_Widget* /*w*/, void* p);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
void gePluginParameter::cb_setValue()
{
- c::events::setPluginParameter(m_param.pluginId, m_param.index,
- m_slider->value(), /*gui=*/true);
+ c::events::setPluginParameter(0, m_param.pluginId, m_param.index,
+ m_slider->value(), Thread::MAIN);
}
/* -------------------------------------------------------------------------- */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <FL/Fl_Pack.H>
-class geDial;
class geInput;
-class geButton;
class geBox;
namespace giada
{
namespace v
{
+class geDial;
+class geButton;
class geBoostTool : public Fl_Pack
{
public:
void rebuild();
- private:
+private:
static void cb_setBoost(Fl_Widget* /*w*/, void* p);
static void cb_setBoostNum(Fl_Widget* /*w*/, void* p);
static void cb_normalize(Fl_Widget* /*w*/, void* p);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
bool Ui::shouldBlink() const
{
- return m_blinker > 6; // TODO magic numbers
+ return m_blinker > BLINK_RATE / 2;
}
/* -------------------------------------------------------------------------- */
/* Compute timer for blinker. */
- m_blinker = (m_blinker + 1) % 12; // TODO magic numbers
+ m_blinker = (m_blinker + 1) % BLINK_RATE;
/* Refresh Sample Editor and Action Editor for dynamic playhead. */
void Ui::startJuceDispatchLoop()
{
- Fl::add_timeout(G_GUI_PLUGIN_RATE, juceDispatchLoop);
+ Fl::add_timeout(G_GUI_REFRESH_RATE, juceDispatchLoop);
}
void Ui::stopJuceDispatchLoop()
juce::MessageManager* mm = juce::MessageManager::getInstanceWithoutCreating();
assert(mm != nullptr);
mm->runDispatchLoopUntil(1);
- Fl::add_timeout(G_GUI_PLUGIN_RATE, juceDispatchLoop);
+ Fl::add_timeout(G_GUI_REFRESH_RATE, juceDispatchLoop);
}
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
Dispatcher dispatcher;
private:
+ static constexpr int BLINK_RATE = G_GUI_FPS / 2;
+
#ifdef WITH_VST
static void juceDispatchLoop(void*);
#endif
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
/* This callback is fired by the updater thread, so it requires
synchronization with the main one. */
- Fl::lock();
+ u::gui::ScopedLock lock;
type == m::model::SwapType::HARD ? m_ui.rebuild() : m_ui.refresh();
- Fl::unlock();
};
Fl::add_timeout(G_GUI_REFRESH_RATE, update, this);
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::u::gui
{
+ScopedLock::ScopedLock()
+{
+ Fl::lock();
+}
+
+/* -------------------------------------------------------------------------- */
+
+ScopedLock::~ScopedLock()
+{
+ Fl::unlock();
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+
void setFavicon(v::gdWindow* w)
{
#if defined(__linux__) || defined(__FreeBSD__)
/* -------------------------------------------------------------------------- */
+geompp::Rect<int> getCenterWinBounds(int w, int h)
+{
+ return {centerWindowX(w), centerWindowY(h), w, h};
+}
+
+/* -------------------------------------------------------------------------- */
+
std::string removeFltkChars(const std::string& s)
{
std::string out = u::string::replace(s, "/", "-");
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
namespace giada::u::gui
{
+/* ScopedLock
+ScopedLock for locking the main FLTK thread when the UI must be updated from a
+secondary thread. */
+
+class ScopedLock
+{
+public:
+ ScopedLock();
+ ~ScopedLock();
+};
+
void setFavicon(v::gdWindow* w);
/* removeFltkChars
geompp::Rect<int> getStringRect(const std::string& s);
+/* getCenterWinBounds
+Returns the bounding box to be used for a centered window. */
+
+geompp::Rect<int> getCenterWinBounds(int w, int h);
+
/* truncate
Adds ellipsis to a string 's' if it longer than 'width' pixels. */
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
#include <climits>
#include <cstdarg>
#include <iomanip>
+#include <memory>
namespace giada
{
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
*
* -----------------------------------------------------------------------------
*
- * Copyright (C) 2010-2021 Giovanni A. Zuliani | Monocasual
+ * Copyright (C) 2010-2022 Giovanni A. Zuliani | Monocasual Laboratories
*
* This file is part of Giada - Your Hardcore Loopmachine.
*
{0, "0x000009", 0, 0x000009}, // playingInaudible
};
+ midiLighter.onSend = []() {};
+
midiLighter.playing = {0x000010, 0};
midiLighter.mute = {0x000011, 0};
midiLighter.solo = {0x000012, 0};